private IIndicatorResult GetInidcatorResult(Rule rule, List <Candle> candles) { // period is the minutes between when the crossing test should be performed // tests on tradingview with bitcoin return best results using a 30 min space on a 5 min chart decimal period = rule.Value.GetValueOrDefault(30); if (candles.Count < 19 || (candles.Last().Timestamp.Minute != 0 && candles.Last().Timestamp.Minute % period != 0)) { return new IndicatorResult { Message = $"IsCrossingOver - within period", Result = false, } } ; Candle lastCandle = candles.ElementAtOrDefault(candles.Count - 1); Candle secondLastCandle = candles.ElementAtOrDefault(candles.Count - 2); switch ((IndicatorRulesEnumerations.CrossingRulesEnum)rule.IndicatorRuleTypeId) { case IndicatorRulesEnumerations.CrossingRulesEnum.IsCrossingOver: if (lastCandle.IsBullish() && secondLastCandle.IsBearish()) { return(new IndicatorResult { Message = $"IsCrossingOver - true lastCandle.IsBullish() && secondLastCandle.IsBearish() {JsonConvert.SerializeObject(lastCandle)} && {JsonConvert.SerializeObject(secondLastCandle)}", Result = true, }); } else { return(new IndicatorResult { Message = $"IsCrossingOver - false lastCandle.IsBullish() && secondLastCandle.IsBearish() {JsonConvert.SerializeObject(lastCandle)} && {JsonConvert.SerializeObject(secondLastCandle)}", Result = false, }); } case IndicatorRulesEnumerations.CrossingRulesEnum.IsCrossingUnder: // To check as having crossed under the last bar close is less than the last bar open // and it was the opposite on the bar immediately preceding it. if (lastCandle.IsBearish() && secondLastCandle.IsBullish()) { return(new IndicatorResult { Message = $"IsCrossingUnder - true lastCandle.IsBearish() && secondLastCandle.IsBullish() {JsonConvert.SerializeObject(lastCandle)} && {JsonConvert.SerializeObject(secondLastCandle)}", Result = true, }); } else { return(new IndicatorResult { Message = $"IsCrossingUnder - false lastCandle.IsBearish() && secondLastCandle.IsBullish() {JsonConvert.SerializeObject(lastCandle)} && {JsonConvert.SerializeObject(secondLastCandle)}", Result = false, }); } default: return(new IndicatorResult { Message = "Error", Result = false }); } }