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 ChandelierExitIndicator : Indicator { public List Signals { get; set; } public ChandelierExitIndicator(string name, int period, double multiplier) : base(name, IndicatorType.ChandelierExit) { Signals = new List(); Period = period; Multiplier = multiplier; MinimumHistory = 1 + Period.Value; } public override List Run() { if (Candles.Count <= MinimumHistory) { return null; } try { GetSignals(ChandelierType.Long); GetSignals(ChandelierType.Short); return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList(); } catch (RuleException) { return null; } } public override IndicatorsResultBase GetIndicatorValues() { return new IndicatorsResultBase() { ChandelierLong = Candles.GetChandelier(Period.Value, Multiplier.Value, ChandelierType.Long).ToList(), ChandelierShort = Candles.GetChandelier(Period.Value, Multiplier.Value, ChandelierType.Short).ToList() }; } private void GetSignals(ChandelierType chandelierType) { var chandelier = Candles.GetChandelier(Period.Value, Multiplier.Value, chandelierType) .Where(s => s.ChandelierExit.HasValue).ToList(); var chandelierCandle = MapChandelierToCandle(chandelier, Candles.TakeLast(MinimumHistory)); var previousCandle = chandelierCandle[0]; foreach (var currentCandle in chandelierCandle.Skip(1)) { // Short if (currentCandle.Close < previousCandle.ChandelierExit && previousCandle.Close > previousCandle.ChandelierExit && currentCandle.Close < previousCandle.Open && chandelierType == ChandelierType.Short) { AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium); } // Long if (currentCandle.Close > previousCandle.ChandelierExit && previousCandle.Close < previousCandle.ChandelierExit && currentCandle.Close > currentCandle.Open && chandelierType == ChandelierType.Long) { AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium); } previousCandle = currentCandle; } } private List MapChandelierToCandle(List superTrend, IEnumerable candles) { var superTrends = new List(); foreach (var candle in candles) { var currentChandelier = superTrend.Find(candle.Date); if (currentChandelier != null) { superTrends.Add(new CandleChandelier() { Close = candle.Close, Open = candle.Open, Date = candle.Date, Ticker = candle.Ticker, Exchange = candle.Exchange, ChandelierExit = (decimal)currentChandelier.ChandelierExit.Value, }); } } return superTrends; } private void AddSignal(CandleChandelier candleSignal, TradeDirection direction, Confidence confidence) { var signal = new Signal( MiscExtensions.ParseEnum(candleSignal.Ticker), direction, confidence, candleSignal, candleSignal.Date, candleSignal.Exchange, Type, SignalType, Name); if (!Signals.Any(s => s.Identifier == signal.Identifier)) { Signals.AddItem(signal); } } private class CandleChandelier : Candle { public decimal ChandelierExit { get; internal set; } } }