Add new strat DualEmaCross
This commit is contained in:
@@ -5,6 +5,8 @@ namespace Managing.Domain.Strategies.Base;
|
||||
public class StrategiesResultBase
|
||||
{
|
||||
public List<EmaResult> Ema { get; set; }
|
||||
public List<EmaResult> FastEma { get; set; }
|
||||
public List<EmaResult> SlowEma { get; set; }
|
||||
public List<MacdResult> Macd { get; set; }
|
||||
public List<RsiResult> Rsi { get; set; }
|
||||
public List<StochResult> Stoch { get; set; }
|
||||
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Context;
|
||||
|
||||
public class StDevContext : Strategy
|
||||
{
|
||||
@@ -39,7 +39,7 @@ public class StDevContext : Strategy
|
||||
// Lower absolute Z-score = more normal volatility = higher confidence for trading
|
||||
// Higher absolute Z-score = more extreme volatility = lower confidence for trading
|
||||
Confidence confidence;
|
||||
|
||||
|
||||
if (Math.Abs(zScore) <= 0.5)
|
||||
{
|
||||
// Very low volatility - ideal conditions for trading
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class ChandelierExitStrategy : Strategy
|
||||
{
|
||||
119
src/Managing.Domain/Strategies/Signals/DualEmaCrossStrategy.cs
Normal file
119
src/Managing.Domain/Strategies/Signals/DualEmaCrossStrategy.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Shared.Rules;
|
||||
using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class DualEmaCrossStrategy : EmaBaseStrategy
|
||||
{
|
||||
public List<Signal> Signals { get; set; }
|
||||
|
||||
public DualEmaCrossStrategy(string name, int fastPeriod, int slowPeriod) : base(name, StrategyType.DualEmaCross)
|
||||
{
|
||||
Signals = new List<Signal>();
|
||||
FastPeriods = fastPeriod;
|
||||
SlowPeriods = slowPeriod;
|
||||
MinimumHistory = Math.Max(fastPeriod, slowPeriod) * 2;
|
||||
}
|
||||
|
||||
public override StrategiesResultBase GetStrategyValues()
|
||||
{
|
||||
return new StrategiesResultBase()
|
||||
{
|
||||
FastEma = Candles.GetEma(FastPeriods.Value).ToList(),
|
||||
SlowEma = Candles.GetEma(SlowPeriods.Value).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
public override List<Signal> Run()
|
||||
{
|
||||
if (Candles.Count <= MinimumHistory)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var fastEma = Candles.GetEma(FastPeriods.Value).ToList();
|
||||
var slowEma = Candles.GetEma(SlowPeriods.Value).ToList();
|
||||
|
||||
var dualEmaCandles = MapDualEmaToCandle(fastEma, slowEma, Candles.TakeLast(MinimumHistory));
|
||||
|
||||
if (dualEmaCandles.Count < 2)
|
||||
return null;
|
||||
|
||||
var previousCandle = dualEmaCandles[0];
|
||||
foreach (var currentCandle in dualEmaCandles.Skip(1))
|
||||
{
|
||||
// Short signal: Fast EMA crosses below Slow EMA
|
||||
if (previousCandle.FastEma > previousCandle.SlowEma &&
|
||||
currentCandle.FastEma < currentCandle.SlowEma)
|
||||
{
|
||||
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
||||
}
|
||||
|
||||
// Long signal: Fast EMA crosses above Slow EMA
|
||||
if (previousCandle.FastEma < previousCandle.SlowEma &&
|
||||
currentCandle.FastEma > currentCandle.SlowEma)
|
||||
{
|
||||
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
||||
}
|
||||
|
||||
previousCandle = currentCandle;
|
||||
}
|
||||
|
||||
return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList();
|
||||
}
|
||||
catch (RuleException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<CandleDualEma> MapDualEmaToCandle(List<EmaResult> fastEma, List<EmaResult> slowEma,
|
||||
IEnumerable<Candle> candles)
|
||||
{
|
||||
var dualEmaList = new List<CandleDualEma>();
|
||||
foreach (var candle in candles)
|
||||
{
|
||||
var currentFastEma = fastEma.Find(candle.Date);
|
||||
var currentSlowEma = slowEma.Find(candle.Date);
|
||||
|
||||
if (currentFastEma != null && currentFastEma.Ema.HasValue &&
|
||||
currentSlowEma != null && currentSlowEma.Ema.HasValue)
|
||||
{
|
||||
dualEmaList.Add(new CandleDualEma()
|
||||
{
|
||||
Close = candle.Close,
|
||||
Open = candle.Open,
|
||||
Date = candle.Date,
|
||||
Ticker = candle.Ticker,
|
||||
Exchange = candle.Exchange,
|
||||
FastEma = currentFastEma.Ema.Value,
|
||||
SlowEma = currentSlowEma.Ema.Value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return dualEmaList;
|
||||
}
|
||||
|
||||
private void AddSignal(CandleDualEma candleSignal, TradeDirection direction, Confidence confidence)
|
||||
{
|
||||
var signal = new Signal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
|
||||
candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType);
|
||||
if (!Signals.Any(s => s.Identifier == signal.Identifier))
|
||||
{
|
||||
Signals.AddItem(signal);
|
||||
}
|
||||
}
|
||||
|
||||
public class CandleDualEma : Candle
|
||||
{
|
||||
public double FastEma { get; set; }
|
||||
public double SlowEma { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class EmaCrossStrategy : EmaBaseStrategy
|
||||
{
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
///<summary>
|
||||
/// Lagging STC Strategy: Combines Schaff Trend Cycle with volatility-based confirmation.
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class MacdCrossStrategy : Strategy
|
||||
{
|
||||
@@ -5,13 +5,13 @@ using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
using Candle = Managing.Domain.Candles.Candle;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class RSIDivergenceConfirmStrategy : Strategy
|
||||
public class RsiDivergenceConfirmStrategy : Strategy
|
||||
{
|
||||
public List<Signal> Signals { get; set; }
|
||||
|
||||
public RSIDivergenceConfirmStrategy(string name, int period) : base(name, StrategyType.RsiDivergenceConfirm)
|
||||
public RsiDivergenceConfirmStrategy(string name, int period) : base(name, StrategyType.RsiDivergenceConfirm)
|
||||
{
|
||||
Period = period;
|
||||
Signals = new List<Signal>();
|
||||
@@ -5,16 +5,16 @@ using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
using Candle = Managing.Domain.Candles.Candle;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class RSIDivergenceStrategy : Strategy
|
||||
public class RsiDivergenceStrategy : Strategy
|
||||
{
|
||||
public List<Signal> Signals { get; set; }
|
||||
public TradeDirection Direction { get; set; }
|
||||
private const int UpperBand = 70;
|
||||
private const int LowerBand = 30;
|
||||
|
||||
public RSIDivergenceStrategy(string name, int period) : base(name, StrategyType.RsiDivergence)
|
||||
public RsiDivergenceStrategy(string name, int period) : base(name, StrategyType.RsiDivergence)
|
||||
{
|
||||
Period = period;
|
||||
Signals = new List<Signal>();
|
||||
@@ -5,13 +5,13 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class STCStrategy : Strategy
|
||||
public class StcStrategy : Strategy
|
||||
{
|
||||
public List<Signal> Signals { get; set; }
|
||||
|
||||
public STCStrategy(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, StrategyType.Stc)
|
||||
public StcStrategy(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, StrategyType.Stc)
|
||||
{
|
||||
Signals = new List<Signal>();
|
||||
FastPeriods = fastPeriods;
|
||||
@@ -28,26 +28,32 @@ public class STCStrategy : Strategy
|
||||
|
||||
try
|
||||
{
|
||||
var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
||||
var stcCandles = MapStcToCandle(stc, Candles.TakeLast(CyclePeriods.Value));
|
||||
|
||||
if (stc.Count == 0)
|
||||
return null;
|
||||
|
||||
var previousCandle = stcCandles[0];
|
||||
foreach (var currentCandle in stcCandles.Skip(1))
|
||||
if (FastPeriods != null)
|
||||
{
|
||||
if (previousCandle.Stc > 75 && currentCandle.Stc <= 75)
|
||||
var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
||||
if (CyclePeriods != null)
|
||||
{
|
||||
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
||||
}
|
||||
var stcCandles = MapStcToCandle(stc, Candles.TakeLast(CyclePeriods.Value));
|
||||
|
||||
if (previousCandle.Stc < 25 && currentCandle.Stc >= 25)
|
||||
{
|
||||
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
||||
}
|
||||
if (stc.Count == 0)
|
||||
return null;
|
||||
|
||||
previousCandle = currentCandle;
|
||||
var previousCandle = stcCandles[0];
|
||||
foreach (var currentCandle in stcCandles.Skip(1))
|
||||
{
|
||||
if (previousCandle.Stc > 75 && currentCandle.Stc <= 75)
|
||||
{
|
||||
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
||||
}
|
||||
|
||||
if (previousCandle.Stc < 25 && currentCandle.Stc >= 25)
|
||||
{
|
||||
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
||||
}
|
||||
|
||||
previousCandle = currentCandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList();
|
||||
@@ -60,11 +66,16 @@ public class STCStrategy : Strategy
|
||||
|
||||
public override StrategiesResultBase GetStrategyValues()
|
||||
{
|
||||
var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
||||
return new StrategiesResultBase
|
||||
if (FastPeriods != null && SlowPeriods != null)
|
||||
{
|
||||
Stc = stc
|
||||
};
|
||||
var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
||||
return new StrategiesResultBase
|
||||
{
|
||||
Stc = stc
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<CandleSct> MapStcToCandle(List<StcResult> stc, IEnumerable<Candle> candles)
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class SuperTrendCrossEma : Strategy
|
||||
{
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Signals;
|
||||
|
||||
public class SuperTrendStrategy : Strategy
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Managing.Domain.Strategies.Rules;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies
|
||||
namespace Managing.Domain.Strategies.Signals
|
||||
{
|
||||
public class ThreeWhiteSoldiersStrategy : Strategy
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Trends;
|
||||
|
||||
public class EmaTrendStrategy : EmaBaseStrategy
|
||||
{
|
||||
@@ -5,7 +5,7 @@ using Managing.Domain.Strategies.Base;
|
||||
using Skender.Stock.Indicators;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Domain.Strategies;
|
||||
namespace Managing.Domain.Strategies.Trends;
|
||||
|
||||
public class StochRsiTrendStrategy : Strategy
|
||||
{
|
||||
Reference in New Issue
Block a user