public Price CalcRSI(MarketData mktData, DateTime updateTime) { if (updateTime >= _nextRsiTime) { if (mktData.TimeSeries.Count < 2) return null; if (_nextRsiTime == DateTime.MinValue) _nextRsiTime = updateTime.AddSeconds(_subPeriodSeconds); else _nextRsiTime = _nextRsiTime.AddSeconds(_subPeriodSeconds); DateTime rsiTime = _nextRsiTime.AddSeconds(-_subPeriodSeconds); if (mktData.TimeSeries.StartTime() > rsiTime) return null; if (_rsiCandles.Count == _nbPeriods) _rsiCandles.RemoveAt(0); if (_history.Count == 120) _history.RemoveAt(0); if (_rsiCandles.Count > 0){ _curCandle.EndTime = updateTime; var curStartRsi = _rsiCandles[_rsiCandles.Count - 1].StartRsiValue + (_rsiCandles[_rsiCandles.Count - 1].GainRsi ? _rsiCandles[_rsiCandles.Count - 1].DiffRsi: -_rsiCandles[_rsiCandles.Count - 1].DiffRsi); _curCandle = new RsiCandle(curStartRsi, mktData.TimeSeries.Last().Mid()); } else _curCandle = new RsiCandle(50m, mktData.TimeSeries.Last().Mid()); _rsiCandles.Add(_curCandle); _history.Add(_curCandle); } else _curCandle = _rsiCandles.Last(); DateTime startTime = _nextRsiTime.AddSeconds(-_subPeriodSeconds); if (mktData.TimeSeries.StartTime() > startTime) return null; var prevValStart = mktData.TimeSeries.PrevValue(startTime); if (!prevValStart.HasValue) return null; Price valStart = prevValStart.Value.Value; Price valEnd = mktData.TimeSeries.Last(); Price valRsiStart = prevValStart.Value.Value; Price valRsiEnd = mktData.TimeSeries.Last(); if (valEnd > valStart) { _curCandle.GainAsset = true; _curCandle.DiffAsset = valEnd.Mid() - valStart.Mid(); } else { _curCandle.GainAsset = false; _curCandle.DiffAsset = valStart.Mid() - valEnd.Mid(); } var sumGain = 0m; var sumLosses = 0m; var nbGain = 0; var nbLoss = 0; foreach (var candle in _rsiCandles) { if (candle.GainAsset) { sumGain += candle.DiffAsset; nbGain++; } else { sumLosses += candle.DiffAsset; nbLoss++; } } var avgGain = nbGain == 0 ? 0 : sumGain / nbGain; var avgLoss = nbLoss == 0 ? 0 : sumLosses / nbLoss; var stdDevGain = 0m; var stdDevLoss = 0m; foreach (var candle in _rsiCandles) { if (candle.GainAsset) stdDevGain += (decimal)Math.Pow((double)(candle.DiffAsset - avgGain), 2.0); else stdDevLoss += (decimal)Math.Pow((double)(candle.DiffAsset - avgLoss), 2.0); } _curCandle.StdDevGain = nbGain == 0 ? 0m : (decimal)Math.Sqrt((double)stdDevGain / nbGain); _curCandle.StdDevLoss = nbLoss == 0 ? 0m : (decimal)Math.Sqrt((double)stdDevLoss / nbLoss); decimal rs = Math.Abs(sumLosses) < 0.1m ? (Math.Abs(sumGain) < 0.1m ? 1m : 1000m) : sumGain / sumLosses; Price rsi = new Price(100m - 100m / (1m + rs)); if (rsi.Bid > _curCandle.StartRsiValue){ _curCandle.GainRsi = true; _curCandle.DiffRsi = rsi.Bid - _curCandle.StartRsiValue; } else{ _curCandle.GainRsi = false; _curCandle.DiffRsi = _curCandle.StartRsiValue - rsi.Bid; } return rsi; }
public Price CalcRSI(MarketData mktData, DateTime updateTime) { if (updateTime >= _nextRsiTime) { if (mktData.TimeSeries.Count < 2) { return(null); } if (_nextRsiTime == DateTime.MinValue) { _nextRsiTime = updateTime.AddSeconds(_subPeriodSeconds); } else { _nextRsiTime = _nextRsiTime.AddSeconds(_subPeriodSeconds); } DateTime rsiTime = _nextRsiTime.AddSeconds(-_subPeriodSeconds); if (mktData.TimeSeries.StartTime() > rsiTime) { return(null); } if (_rsiCandles.Count == _nbPeriods) { _rsiCandles.RemoveAt(0); } if (_history.Count == 120) { _history.RemoveAt(0); } if (_rsiCandles.Count > 0) { _curCandle.EndTime = updateTime; var curStartRsi = _rsiCandles[_rsiCandles.Count - 1].StartRsiValue + (_rsiCandles[_rsiCandles.Count - 1].GainRsi ? _rsiCandles[_rsiCandles.Count - 1].DiffRsi: -_rsiCandles[_rsiCandles.Count - 1].DiffRsi); _curCandle = new RsiCandle(curStartRsi, mktData.TimeSeries.Last().Mid()); } else { _curCandle = new RsiCandle(50m, mktData.TimeSeries.Last().Mid()); } _rsiCandles.Add(_curCandle); _history.Add(_curCandle); } else { _curCandle = _rsiCandles.Last(); } DateTime startTime = _nextRsiTime.AddSeconds(-_subPeriodSeconds); if (mktData.TimeSeries.StartTime() > startTime) { return(null); } var prevValStart = mktData.TimeSeries.PrevValue(startTime); if (!prevValStart.HasValue) { return(null); } Price valStart = prevValStart.Value.Value; Price valEnd = mktData.TimeSeries.Last(); Price valRsiStart = prevValStart.Value.Value; Price valRsiEnd = mktData.TimeSeries.Last(); if (valEnd > valStart) { _curCandle.GainAsset = true; _curCandle.DiffAsset = valEnd.Mid() - valStart.Mid(); } else { _curCandle.GainAsset = false; _curCandle.DiffAsset = valStart.Mid() - valEnd.Mid(); } var sumGain = 0m; var sumLosses = 0m; var nbGain = 0; var nbLoss = 0; foreach (var candle in _rsiCandles) { if (candle.GainAsset) { sumGain += candle.DiffAsset; nbGain++; } else { sumLosses += candle.DiffAsset; nbLoss++; } } var avgGain = nbGain == 0 ? 0 : sumGain / nbGain; var avgLoss = nbLoss == 0 ? 0 : sumLosses / nbLoss; var stdDevGain = 0m; var stdDevLoss = 0m; foreach (var candle in _rsiCandles) { if (candle.GainAsset) { stdDevGain += (decimal)Math.Pow((double)(candle.DiffAsset - avgGain), 2.0); } else { stdDevLoss += (decimal)Math.Pow((double)(candle.DiffAsset - avgLoss), 2.0); } } _curCandle.StdDevGain = nbGain == 0 ? 0m : (decimal)Math.Sqrt((double)stdDevGain / nbGain); _curCandle.StdDevLoss = nbLoss == 0 ? 0m : (decimal)Math.Sqrt((double)stdDevLoss / nbLoss); decimal rs = Math.Abs(sumLosses) < 0.1m ? (Math.Abs(sumGain) < 0.1m ? 1m : 1000m) : sumGain / sumLosses; Price rsi = new Price(100m - 100m / (1m + rs)); if (rsi.Bid > _curCandle.StartRsiValue) { _curCandle.GainRsi = true; _curCandle.DiffRsi = rsi.Bid - _curCandle.StartRsiValue; } else { _curCandle.GainRsi = false; _curCandle.DiffRsi = _curCandle.StartRsiValue - rsi.Bid; } return(rsi); }