public override IEnumerable <(ICandle, ITradingAdviceCode)> AllForecasts(IEnumerable <ICandle> candles) { if (candles.Count() < MinNumberOfCandles) { throw new Exception("Number of candles less then expected"); } RedWeddingPreset preset = null; if (!string.IsNullOrWhiteSpace(Preset)) { preset = JsonConvert.DeserializeObject <RedWeddingPreset>(Preset); } List <(ICandle, ITradingAdviceCode)> result = new List <(ICandle, ITradingAdviceCode)>(); decimal fastEnd = 0.666m; int smaPeriod = preset?.Sma ?? 6; List <decimal?> open = candles.Open().Sma(smaPeriod); List <decimal?> close = candles.Close().Sma(smaPeriod); List <decimal?> high = candles.High().Sma(smaPeriod); List <decimal?> low = candles.Low().Sma(smaPeriod); List <decimal> closes = candles.Close(); List <decimal> highs = candles.High(); List <decimal> opens = candles.Open(); // Calculate the vClose List <decimal?> vClose = new List <decimal?>(); for (int i = 0; i < open.Count; i++) { if (open[i].HasValue && close[i].HasValue && low[i].HasValue && high[i].HasValue) { vClose.Add((open[i].Value + close[i].Value + low[i].Value + high[i].Value) / 4); } else { vClose.Add(null); } } // Calculate the vOpen decimal smooth = fastEnd * fastEnd; List <decimal?> vOpen = new List <decimal?>(); for (int i = 0; i < vClose.Count; i++) { decimal?prev_close = i == 0 ? null : vClose[i - 1]; decimal?prev_open = i == 0 ? null : vOpen[i - 1]; if (prev_close == null && prev_open == null) { vOpen.Add(null); } else { vOpen.Add((prev_open == null ? prev_close : prev_open) + smooth * (prev_close - (prev_open == null ? prev_close : prev_open))); } } List <decimal?> snow_high = new List <decimal?>(); for (int i = 0; i < vClose.Count; i++) { if (high[i].HasValue && vClose[i].HasValue && vOpen[i].HasValue) { snow_high.Add(Math.Max(high[i].Value, Math.Max(vClose[i].Value, vOpen[i].Value))); } else { snow_high.Add(null); } } List <decimal?> snow_low = new List <decimal?>(); for (int i = 0; i < vClose.Count; i++) { if (low[i].HasValue && vClose[i].HasValue && vOpen[i].HasValue) { snow_low.Add(Math.Min(low[i].Value, Math.Min(vClose[i].Value, vOpen[i].Value))); } else { snow_low.Add(null); } } List <decimal?> fish = candles.Fisher(9); for (int i = 0; i < candles.Count(); i++) { if (i <= 2) { result.Add((candles.ElementAt(i), TradingAdviceCode.HOLD)); } else if (fish[i] >= fish[i - 1] && fish[i - 1] >= fish[i - 2] && fish[i - 2] >= fish[i - 3] && closes[i] < snow_low[i] && opens[i] < snow_low[i]) { result.Add((candles.ElementAt(i), TradingAdviceCode.BUY)); } else if (closes[i] > snow_high[i]) { result.Add((candles.ElementAt(i), TradingAdviceCode.SELL)); } else { result.Add((candles.ElementAt(i), TradingAdviceCode.HOLD)); } } return(result); }
public override IEnumerable <(ICandle, ITradingAdviceCode)> AllForecasts(IEnumerable <ICandle> candles) { if (candles.Count() < MinNumberOfCandles) { throw new Exception("Number of candles less then expected"); } RedWeddingPreset preset = null; if (!string.IsNullOrWhiteSpace(Preset)) { preset = JsonConvert.DeserializeObject <RedWeddingPreset>(Preset); } List <(ICandle, ITradingAdviceCode)> result = new List <(ICandle, ITradingAdviceCode)>(); decimal fastEnd = 0.666m; int smaPeriod = preset?.Sma ?? 6; List <decimal?> open = candles.Open().Sma(smaPeriod); List <decimal?> close = candles.Close().Sma(smaPeriod); List <decimal?> high = candles.High().Sma(smaPeriod); List <decimal?> low = candles.Low().Sma(smaPeriod); List <decimal> closes = candles.Close(); // Calculate the vClose List <decimal?> vClose = new List <decimal?>(); for (int i = 0; i < open.Count; i++) { if (open[i].HasValue && close[i].HasValue && low[i].HasValue && high[i].HasValue) { vClose.Add((open[i].Value + close[i].Value + low[i].Value + high[i].Value) / 4); } else { vClose.Add(null); } } // Calculate the vOpen decimal smooth = fastEnd * fastEnd; List <decimal?> vOpen = new List <decimal?>(); List <decimal?> shiftedvClose = new List <decimal?> { null }; foreach (decimal?item in vClose) { if (item != vClose.Last()) { shiftedvClose.Add(item); } } for (int i = 0; i < vClose.Count; i++) { if (shiftedvClose[i] != null) { if (vClose[i] == null) { vOpen.Add(shiftedvClose[i]); } else if (vOpen[i - 1] == null) { vOpen.Add(shiftedvClose[i]); } else { vOpen.Add(vOpen[i - 1] + smooth * (shiftedvClose[i] - vOpen[i - 1])); } } } List <decimal?> snow_high = new List <decimal?>(); for (int i = 0; i < vClose.Count; i++) { if (high[i].HasValue && vClose[i].HasValue && vOpen[i].HasValue) { snow_high.Add(Math.Max(high[i].Value, Math.Max(vClose[i].Value, vOpen[i].Value))); } else { snow_high.Add(null); } } List <decimal?> snow_low = new List <decimal?>(); for (int i = 0; i < vClose.Count; i++) { if (low[i].HasValue && vClose[i].HasValue && vOpen[i].HasValue) { snow_low.Add(Math.Min(low[i].Value, Math.Min(vClose[i].Value, vOpen[i].Value))); } else { snow_low.Add(null); } } List <decimal?> long_sma = vClose.Sma(10); List <decimal?> short_sma = vClose.Sma(3); StochItem stoch = candles.Stoch(); List <decimal?> fish = candles.Fisher(); List <bool> sma_crossover = short_sma.Crossover(long_sma); List <bool> sma_crossunder = short_sma.Crossunder(long_sma); List <bool> snow_cross = vClose.Crossunder(vOpen); List <bool> stoch_cross = stoch.K.Crossunder(80); List <bool> stoch_cross2 = stoch.K.Crossunder(stoch.D); for (int i = 0; i < candles.Count(); i++) { if (i <= 1) { result.Add((candles.ElementAt(i), TradingAdviceCode.HOLD)); } else if (fish[i] >= fish[i - 1] && closes[i] < snow_high[i] && sma_crossover[i]) { result.Add((candles.ElementAt(i), TradingAdviceCode.BUY)); } else if (fish[i] < fish[i - 1] && fish[i - 1] >= fish[i - 2] || sma_crossunder[i] || snow_cross[i] || stoch_cross[i] || stoch_cross2[i] && stoch.K[i - 1] > 80) { result.Add((candles.ElementAt(i), TradingAdviceCode.SELL)); } else { result.Add((candles.ElementAt(i), TradingAdviceCode.HOLD)); } } return(result); }