Files
managing-apps/src/Managing.Domain/Strategies/MACDCrossStrategy.cs
Oda c715da8a17 Add indicators to backtest and bot (#14)
* Add indicators to backtest and bot

* Remove
2025-02-28 00:53:25 +07:00

112 lines
3.5 KiB
C#

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;
public class MacdCrossStrategy : Strategy
{
public List<Signal> Signals { get; set; }
public MacdCrossStrategy(string name, int fastPeriods, int slowPeriods, int signalPeriods) :
base(name, StrategyType.MacdCross)
{
Signals = new List<Signal>();
FastPeriods = fastPeriods;
SlowPeriods = slowPeriods;
SignalPeriods = signalPeriods;
}
public override List<Signal> Run()
{
if (Candles.Count <= 2 * (SlowPeriods + SignalPeriods))
{
return null;
}
try
{
var macd = Candles.GetMacd(FastPeriods.Value, SlowPeriods.Value, SignalPeriods.Value).ToList();
var macdCandle = MapMacdToCandle(macd, Candles.TakeLast(SignalPeriods.Value));
if (macd.Count == 0)
return null;
var previousCandle = macdCandle[0];
foreach (var currentCandle in macdCandle.Skip(1))
{
if (previousCandle.Histogram > 0 && currentCandle.Histogram < 0 && currentCandle.Macd < 0)
{
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
if (previousCandle.Histogram < 0 && currentCandle.Histogram > 0 && currentCandle.Macd > 0)
{
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;
}
}
public override StrategiesResultBase GetStrategyValues()
{
return new StrategiesResultBase()
{
Macd = Candles.GetMacd(FastPeriods.Value, SlowPeriods.Value, SignalPeriods.Value).ToList()
};
}
private List<CandleMacd> MapMacdToCandle(List<MacdResult> macd, IEnumerable<Candle> candles)
{
var macdList = new List<CandleMacd>();
foreach (var candle in candles)
{
var currentMacd = macd.Find(candle.Date);
if (currentMacd != null)
{
macdList.Add(new CandleMacd()
{
Close = candle.Close,
Open = candle.Open,
Date = candle.Date,
Ticker = candle.Ticker,
Exchange = candle.Exchange,
Macd = currentMacd.Macd.Value,
Histogram = currentMacd.Histogram.Value
});
}
}
return macdList;
}
private void AddSignal(CandleMacd 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);
}
}
private class CandleMacd : Candle
{
public double Macd { get; set; }
public double Signal { get; set; }
public double Histogram { get; set; }
}
}