Update tg message for synthapi
This commit is contained in:
@@ -334,12 +334,18 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
if (Config.IsForWatchingOnly || (ExecutionCount < 1 && !Config.IsForBacktest))
|
if (Config.IsForWatchingOnly || (ExecutionCount < 1 && !Config.IsForBacktest))
|
||||||
signal.Status = SignalStatus.Expired;
|
signal.Status = SignalStatus.Expired;
|
||||||
|
|
||||||
var signalText = $"{Config.ScenarioName} trigger a signal. Signal told you " +
|
var indicatorNames = Indicators.Select(i => i.Type.ToString()).ToList();
|
||||||
$"to {signal.Direction} {Config.Ticker} on {Config.Timeframe}. The confidence in this signal is {signal.Confidence}. Identifier : {signal.Identifier}";
|
var signalText = $"🎯 **New Trading Signal**\n\n" +
|
||||||
|
$"📊 **Signal Details:**\n" +
|
||||||
|
$"📈 Action: `{signal.Direction}` {Config.Ticker}\n" +
|
||||||
|
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
||||||
|
$"🎯 Confidence: `{signal.Confidence}`\n" +
|
||||||
|
$"🔍 Indicators: `{string.Join(", ", indicatorNames)}`\n" +
|
||||||
|
$"🆔 Signal ID: `{signal.Identifier}`";
|
||||||
|
|
||||||
|
|
||||||
// Apply Synth-based signal filtering if enabled
|
// Apply Synth-based signal filtering if enabled
|
||||||
if (Config.UseSynthApi)
|
if (Config.UseSynthApi || !Config.IsForBacktest)
|
||||||
{
|
{
|
||||||
var currentPrice = Config.IsForBacktest
|
var currentPrice = Config.IsForBacktest
|
||||||
? OptimizedCandles.Last().Close
|
? OptimizedCandles.Last().Close
|
||||||
@@ -352,16 +358,41 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
signalValidationResult.Confidence == Confidence.Low ||
|
signalValidationResult.Confidence == Confidence.Low ||
|
||||||
signalValidationResult.IsBlocked)
|
signalValidationResult.IsBlocked)
|
||||||
{
|
{
|
||||||
signal.Status = SignalStatus.Expired;
|
// TODO : remove this when Synth is stable
|
||||||
await LogInformation(
|
// signal.Status = SignalStatus.Expired;
|
||||||
$"🚫 **Synth Signal Filter** - Signal {signal.Identifier} blocked by Synth risk assessment. Context : {signalValidationResult.ValidationContext}");
|
signalText += $"\n\n🚫 *Synth Signal Filter*\n" +
|
||||||
return;
|
$"Signal `{signal.Identifier}` blocked by Synth risk assessment\n\n" +
|
||||||
|
$"📊 *Risk Analysis Details*\n" +
|
||||||
|
$"SL Probability: `{signalValidationResult.StopLossProbability:P2}`\n" +
|
||||||
|
$"TP Probability: `{signalValidationResult.TakeProfitProbability:P2}`\n" +
|
||||||
|
$"TP/SL Ratio: `{signalValidationResult.TpSlRatio:F2}x`\n" +
|
||||||
|
$"Win/Loss: `{signalValidationResult.WinLossRatio:F2}:1`\n" +
|
||||||
|
$"Expected Value: `${signalValidationResult.ExpectedMonetaryValue:F2}`\n" +
|
||||||
|
$"Expected Utility: `{signalValidationResult.ExpectedUtility:F4}`\n" +
|
||||||
|
$"Kelly Criterion: `{signalValidationResult.KellyFraction:P2}`\n" +
|
||||||
|
$"Kelly Capped: `{signalValidationResult.KellyCappedFraction:P2}`\n" +
|
||||||
|
$"Risk Assessment: `{signalValidationResult.GetUtilityRiskAssessment()}`\n" +
|
||||||
|
$"Time Horizon: `{signalValidationResult.TimeHorizonSeconds / 3600:F1}h`\n\n" +
|
||||||
|
$"📋 *Context*\n`{signalValidationResult.ValidationContext}`";
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
signal.SetConfidence(signalValidationResult.Confidence);
|
signal.SetConfidence(signalValidationResult.Confidence);
|
||||||
signalText +=
|
signalText += $"\n\n✅ *Synth Risk Assessment Passed*\n" +
|
||||||
$" and Synth risk assessment passed. Context : {signalValidationResult.ValidationContext}";
|
$"Confidence: `{signalValidationResult.Confidence}`\n\n" +
|
||||||
|
$"📊 *Risk Analysis Details*\n" +
|
||||||
|
$"SL Probability: `{signalValidationResult.StopLossProbability:P2}`\n" +
|
||||||
|
$"TP Probability: `{signalValidationResult.TakeProfitProbability:P2}`\n" +
|
||||||
|
$"TP/SL Ratio: `{signalValidationResult.TpSlRatio:F2}x`\n" +
|
||||||
|
$"Win/Loss: `{signalValidationResult.WinLossRatio:F2}:1`\n" +
|
||||||
|
$"Expected Value: `${signalValidationResult.ExpectedMonetaryValue:F2}`\n" +
|
||||||
|
$"Expected Utility: `{signalValidationResult.ExpectedUtility:F4}`\n" +
|
||||||
|
$"Kelly Criterion: `{signalValidationResult.KellyFraction:P2}`\n" +
|
||||||
|
$"Kelly Capped: `{signalValidationResult.KellyCappedFraction:P2}`\n" +
|
||||||
|
$"Risk Assessment: `{signalValidationResult.GetUtilityRiskAssessment()}`\n" +
|
||||||
|
$"Time Horizon: `{signalValidationResult.TimeHorizonSeconds / 3600:F1}h`\n\n" +
|
||||||
|
$"📋 *Context*\n`{signalValidationResult.ValidationContext}`";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1316,19 +1347,22 @@ public class TradingBot : Bot, ITradingBot
|
|||||||
// Calculate closing fee based on the actual executed trade's price and quantity
|
// Calculate closing fee based on the actual executed trade's price and quantity
|
||||||
if (position.StopLoss?.Status == TradeStatus.Filled)
|
if (position.StopLoss?.Status == TradeStatus.Filled)
|
||||||
{
|
{
|
||||||
var stopLossPositionSizeUsd = (position.StopLoss.Price * position.StopLoss.Quantity) * position.StopLoss.Leverage;
|
var stopLossPositionSizeUsd =
|
||||||
|
(position.StopLoss.Price * position.StopLoss.Quantity) * position.StopLoss.Leverage;
|
||||||
var uiFeeClose = stopLossPositionSizeUsd * uiFeeRate; // Fee paid on closing via StopLoss
|
var uiFeeClose = stopLossPositionSizeUsd * uiFeeRate; // Fee paid on closing via StopLoss
|
||||||
fees += uiFeeClose;
|
fees += uiFeeClose;
|
||||||
}
|
}
|
||||||
else if (position.TakeProfit1?.Status == TradeStatus.Filled)
|
else if (position.TakeProfit1?.Status == TradeStatus.Filled)
|
||||||
{
|
{
|
||||||
var takeProfit1PositionSizeUsd = (position.TakeProfit1.Price * position.TakeProfit1.Quantity) * position.TakeProfit1.Leverage;
|
var takeProfit1PositionSizeUsd = (position.TakeProfit1.Price * position.TakeProfit1.Quantity) *
|
||||||
|
position.TakeProfit1.Leverage;
|
||||||
var uiFeeClose = takeProfit1PositionSizeUsd * uiFeeRate; // Fee paid on closing via TakeProfit1
|
var uiFeeClose = takeProfit1PositionSizeUsd * uiFeeRate; // Fee paid on closing via TakeProfit1
|
||||||
fees += uiFeeClose;
|
fees += uiFeeClose;
|
||||||
}
|
}
|
||||||
else if (position.TakeProfit2?.Status == TradeStatus.Filled)
|
else if (position.TakeProfit2?.Status == TradeStatus.Filled)
|
||||||
{
|
{
|
||||||
var takeProfit2PositionSizeUsd = (position.TakeProfit2.Price * position.TakeProfit2.Quantity) * position.TakeProfit2.Leverage;
|
var takeProfit2PositionSizeUsd = (position.TakeProfit2.Price * position.TakeProfit2.Quantity) *
|
||||||
|
position.TakeProfit2.Leverage;
|
||||||
var uiFeeClose = takeProfit2PositionSizeUsd * uiFeeRate; // Fee paid on closing via TakeProfit2
|
var uiFeeClose = takeProfit2PositionSizeUsd * uiFeeRate; // Fee paid on closing via TakeProfit2
|
||||||
fees += uiFeeClose;
|
fees += uiFeeClose;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ public static class ScenarioHelpers
|
|||||||
IndicatorType.EmaCross => SignalType.Signal,
|
IndicatorType.EmaCross => SignalType.Signal,
|
||||||
IndicatorType.DualEmaCross => SignalType.Signal,
|
IndicatorType.DualEmaCross => SignalType.Signal,
|
||||||
IndicatorType.ThreeWhiteSoldiers => SignalType.Signal,
|
IndicatorType.ThreeWhiteSoldiers => SignalType.Signal,
|
||||||
IndicatorType.SuperTrend => SignalType.Signal,
|
IndicatorType.SuperTrend => SignalType.Trend,
|
||||||
IndicatorType.ChandelierExit => SignalType.Signal,
|
IndicatorType.ChandelierExit => SignalType.Signal,
|
||||||
IndicatorType.EmaTrend => SignalType.Trend,
|
IndicatorType.EmaTrend => SignalType.Trend,
|
||||||
IndicatorType.Composite => SignalType.Signal,
|
IndicatorType.Composite => SignalType.Signal,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public static class TradingBox
|
|||||||
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IIndicator> strategies,
|
public static Signal GetSignal(HashSet<Candle> newCandles, HashSet<IIndicator> strategies,
|
||||||
HashSet<Signal> previousSignal, IndicatorComboConfig config, int? loopbackPeriod = 1)
|
HashSet<Signal> previousSignal, IndicatorComboConfig config, int? loopbackPeriod = 1)
|
||||||
{
|
{
|
||||||
var signalOnCandles = new HashSet<Signal>();
|
var signalOnCandles = new List<Signal>();
|
||||||
var limitedCandles = newCandles.ToList().TakeLast(600).ToList();
|
var limitedCandles = newCandles.ToList().TakeLast(600).ToList();
|
||||||
|
|
||||||
foreach (var strategy in strategies)
|
foreach (var strategy in strategies)
|
||||||
@@ -141,6 +141,8 @@ public static class TradingBox
|
|||||||
return signalOnCandles.Single();
|
return signalOnCandles.Single();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signalOnCandles = signalOnCandles.OrderBy(s => s.Date).ToHashSet();
|
||||||
|
|
||||||
// Check if all strategies produced signals - this is required for composite signals
|
// Check if all strategies produced signals - this is required for composite signals
|
||||||
var strategyNames = strategies.Select(s => s.Name).ToHashSet();
|
var strategyNames = strategies.Select(s => s.Name).ToHashSet();
|
||||||
var signalIndicatorNames = signalOnCandles.Select(s => s.IndicatorName).ToHashSet();
|
var signalIndicatorNames = signalOnCandles.Select(s => s.IndicatorName).ToHashSet();
|
||||||
|
|||||||
@@ -38,14 +38,20 @@ public class MacdCrossIndicator : Indicator
|
|||||||
var previousCandle = macdCandle[0];
|
var previousCandle = macdCandle[0];
|
||||||
foreach (var currentCandle in macdCandle.Skip(1))
|
foreach (var currentCandle in macdCandle.Skip(1))
|
||||||
{
|
{
|
||||||
if (previousCandle.Histogram > 0 && currentCandle.Histogram < 0 && currentCandle.Macd < 0)
|
// Only trigger signals when Signal line is outside -100 to 100 range (extreme conditions)
|
||||||
|
if (currentCandle.Signal < -200 || currentCandle.Signal > 200)
|
||||||
{
|
{
|
||||||
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
// Check for MACD line crossing below Signal line (bearish cross)
|
||||||
}
|
if (previousCandle.Macd > previousCandle.Signal && currentCandle.Macd < currentCandle.Signal)
|
||||||
|
{
|
||||||
|
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
||||||
|
}
|
||||||
|
|
||||||
if (previousCandle.Histogram < 0 && currentCandle.Histogram > 0 && currentCandle.Macd > 0)
|
// Check for MACD line crossing above Signal line (bullish cross)
|
||||||
{
|
if (previousCandle.Macd < previousCandle.Signal && currentCandle.Macd > currentCandle.Signal)
|
||||||
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
{
|
||||||
|
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previousCandle = currentCandle;
|
previousCandle = currentCandle;
|
||||||
@@ -84,7 +90,8 @@ public class MacdCrossIndicator : Indicator
|
|||||||
Ticker = candle.Ticker,
|
Ticker = candle.Ticker,
|
||||||
Exchange = candle.Exchange,
|
Exchange = candle.Exchange,
|
||||||
Macd = currentMacd.Macd.Value,
|
Macd = currentMacd.Macd.Value,
|
||||||
Histogram = currentMacd.Histogram.Value
|
Histogram = currentMacd.Histogram.Value,
|
||||||
|
Signal = currentMacd.Signal.Value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,17 +38,26 @@ public class SuperTrendIndicator : Indicator
|
|||||||
var previousCandle = superTrendCandle[0];
|
var previousCandle = superTrendCandle[0];
|
||||||
foreach (var currentCandle in superTrendCandle.Skip(1))
|
foreach (var currentCandle in superTrendCandle.Skip(1))
|
||||||
{
|
{
|
||||||
// Short
|
// // Short
|
||||||
if (currentCandle.Close < previousCandle.SuperTrend && previousCandle.Close > previousCandle.SuperTrend)
|
// if (currentCandle.Close < previousCandle.SuperTrend && previousCandle.Close > previousCandle.SuperTrend)
|
||||||
{
|
// {
|
||||||
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
// AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// // Long
|
||||||
|
// if (currentCandle.Close > previousCandle.SuperTrend && previousCandle.Close < previousCandle.SuperTrend)
|
||||||
|
// {
|
||||||
|
// AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
||||||
|
// }
|
||||||
|
|
||||||
// Long
|
if (currentCandle.SuperTrend < currentCandle.Close)
|
||||||
if (currentCandle.Close > previousCandle.SuperTrend && previousCandle.Close < previousCandle.SuperTrend)
|
|
||||||
{
|
{
|
||||||
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
||||||
}
|
}
|
||||||
|
else if (currentCandle.SuperTrend > currentCandle.Close)
|
||||||
|
{
|
||||||
|
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
||||||
|
}
|
||||||
|
|
||||||
previousCandle = currentCandle;
|
previousCandle = currentCandle;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user