Add new strat DualEmaCross

This commit is contained in:
2025-06-02 21:28:56 +07:00
parent de9f77d5ba
commit 7fce1fa59e
22 changed files with 264 additions and 62 deletions

View File

@@ -60,13 +60,13 @@ public static class TradingBox
{
var signalOnCandles = new HashSet<Signal>();
var limitedCandles = newCandles.ToList().TakeLast(600).ToList();
foreach (var strategy in strategies)
{
strategy.UpdateCandles(limitedCandles.ToHashSet());
var signals = strategy.Run();
if (signals == null || signals.Count == 0)
if (signals == null || signals.Count == 0)
{
// For trend and context strategies, lack of signal might be meaningful
// Signal strategies are expected to be sparse, so we continue
@@ -74,7 +74,7 @@ public static class TradingBox
{
continue;
}
// For trend strategies, no signal might mean neutral trend
// For context strategies, no signal might mean no restrictions
// We'll let the ComputeSignals method handle these cases
@@ -82,6 +82,7 @@ public static class TradingBox
}
// Ensure limitedCandles is ordered chronologically
loopbackPeriod = 20;
var orderedCandles = limitedCandles.OrderBy(c => c.Date).ToList();
var loopback = loopbackPeriod.HasValue && loopbackPeriod > 1 ? loopbackPeriod.Value : 1;
var candleLoopback = orderedCandles.TakeLast(loopback).ToList();
@@ -135,6 +136,13 @@ public static class TradingBox
return signalOnCandles.Single();
}
// Check if all strategies produced signals - this is required for composite signals
if (signalOnCandles.Count != strategies.Count)
{
// Not all strategies produced signals - composite signal requires all strategies to contribute
return null;
}
// Group signals by type for analysis
var signalStrategies = signalOnCandles.Where(s => s.SignalType == SignalType.Signal).ToList();
var trendStrategies = signalOnCandles.Where(s => s.SignalType == SignalType.Trend).ToList();
@@ -153,7 +161,8 @@ public static class TradingBox
var signalDirection = EvaluateSignalDirection(signalStrategies, config);
// Determine final direction and confidence
var (finalDirection, confidence) = DetermineFinalSignal(signalDirection, trendDirection, signalStrategies, trendStrategies, config);
var (finalDirection, confidence) =
DetermineFinalSignal(signalDirection, trendDirection, signalStrategies, trendStrategies, config);
if (finalDirection == TradeDirection.None || confidence < config.MinimumConfidence)
{
@@ -161,8 +170,9 @@ public static class TradingBox
}
// Create composite signal
var lastSignal = signalStrategies.LastOrDefault() ?? trendStrategies.LastOrDefault() ?? contextStrategies.LastOrDefault();
var lastSignal = signalStrategies.LastOrDefault() ??
trendStrategies.LastOrDefault() ?? contextStrategies.LastOrDefault();
return new Signal(
ticker,
finalDirection,
@@ -170,17 +180,18 @@ public static class TradingBox
lastSignal?.Candle,
lastSignal?.Date ?? DateTime.UtcNow,
lastSignal?.Exchange ?? config.DefaultExchange,
StrategyType.Composite,
StrategyType.Composite,
SignalType.Signal);
}
/// <summary>
/// Validates context strategies based on confidence levels indicating market condition quality
/// </summary>
private static bool ValidateContextStrategies(HashSet<IStrategy> allStrategies, List<Signal> contextSignals, StrategyComboConfig config)
private static bool ValidateContextStrategies(HashSet<IStrategy> allStrategies, List<Signal> contextSignals,
StrategyComboConfig config)
{
var contextStrategiesCount = allStrategies.Count(s => s.SignalType == SignalType.Context);
if (contextStrategiesCount == 0)
{
return true; // No context strategies, no restrictions
@@ -256,9 +267,9 @@ public static class TradingBox
/// Determines final signal direction and confidence based on signal and trend analysis
/// </summary>
private static (TradeDirection Direction, Confidence Confidence) DetermineFinalSignal(
TradeDirection signalDirection,
TradeDirection trendDirection,
List<Signal> signalStrategies,
TradeDirection signalDirection,
TradeDirection trendDirection,
List<Signal> signalStrategies,
List<Signal> trendStrategies,
StrategyComboConfig config)
{
@@ -294,12 +305,12 @@ public static class TradingBox
{
// Calculate confidence based on trend strength
var totalTrend = trendStrategies.Count;
var majorityDirection = trendDirection == TradeDirection.Long
var majorityDirection = trendDirection == TradeDirection.Long
? trendStrategies.Count(s => s.Direction == TradeDirection.Long)
: trendStrategies.Count(s => s.Direction == TradeDirection.Short);
var agreementPercentage = (decimal)majorityDirection / totalTrend;
if (agreementPercentage >= 0.8m)
return (trendDirection, Confidence.High);
else if (agreementPercentage >= config.TrendStrongAgreementThreshold)