protected override void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { if (!mktData.Levels.HasValue) { return; } Publish(updateTime, new Price(GetNearestLevel(value.Mid(), mktData.Levels.Value))); }
protected override bool Sell(Signal signal, DateTime time, Price stockValue) { if (!_ptf.BookTrade(signal.Trade, signal.TradingAsset.Name)) { Reset(time, stockValue.Mid(), true); return(false); } string tradeRef = signal.Trade == null ? "" : " " + signal.Trade.Reference; Log.Instance.WriteEntry(time + tradeRef + " Signal " + signal.Id + ": SELL " + signal.TradingAsset.Id + " " + stockValue.Bid + " spread: " + (stockValue.Offer - stockValue.Bid), EventLogEntryType.Information); return(true); }
protected override Price IndicatorFunc(MarketData mktData, DateTime updateTime, Price value) { var curEma = 0m; if (_prevEma.HasValue) { var curPeriod = (decimal)(updateTime - _startTime).TotalMilliseconds; if (curPeriod > _periodMilliSeconds) { curPeriod = _periodMilliSeconds; } var timeDecay = _timeDecayWeight * (decimal)(updateTime - _startTime).TotalSeconds; var k = (curPeriod + timeDecay) / _periodMilliSeconds; curEma = value.Mid() * k + _prevEma.Value * (1m - k); } else { curEma = value.Mid(); } _prevEma = curEma; _startTime = updateTime; return(new Price(curEma)); }
protected virtual bool OnSell(Signal signal, DateTime time, Price stockValue) { if (FilterSignal(signal, time)) { var pos = _ptf.GetPosition(signal.TradingAsset.Id); if (pos == null) { Reset(time, stockValue.Mid(), true); return(false); } if (pos.Quantity < 0) { Log.Instance.WriteEntry(time + " Signal " + signal.Id + ": Some trades are still open. last trade: " + signal.Trade.Id + " " + stockValue.Bid + ". Closing all positions...", EventLogEntryType.Error); _ptf.CloseAllPositions(time, signal.TradingAsset.Id, stockValue.Offer); return(false); } signal.Trade = new Trade(time, signal.TradingAsset.Id, SIGNAL_CODE.SELL, _amount, stockValue.Bid, 0); return(Sell(signal, time, stockValue)); } return(false); }
public Price CalcWMVol(MarketData mktData, DateTime updateTime, Price value) { Price avg = base.IndicatorFunc(mktData, updateTime, value); var curWMVol = 0m; if (_prevWMVol.HasValue) { var curPeriod = (decimal)(updateTime - _startVolTime).TotalMilliseconds; if (curPeriod > _periodMilliSeconds) { curPeriod = _periodMilliSeconds; } var timeDecay = _timeDecayWeight * (decimal)(updateTime - _startTime).TotalSeconds; var k = (curPeriod + timeDecay) / _periodMilliSeconds; curWMVol = Math.Abs(value.Mid() - _ema.TimeSeries.Last().Mid()) * k + _prevWMVol.Value * (1m - k); } else { curWMVol = 0m; } _prevWMVol = curWMVol; _startVolTime = updateTime; return(new Price(curWMVol)); }
public bool Update(DateTime updateTime, Price value, Price rsi) { var curValue = value.Mid(); if (StartValue == decimal.MinValue) { StartValue = curValue; } if (GlobalTrend == SIGNAL_CODE.BUY) { if (ReachedExtremum) { if (curValue > LastValue) { PoolTrend = LastValue < StartValue ? SIGNAL_CODE.SELL : SIGNAL_CODE.BUY; Depth = LastValue < StartValue ? ExtremumValue - StartValue : ExtremumValue - LastValue; return(true); } } else { if (curValue > ExtremumValue) { ExtremumValue = curValue; ExtremumTime = updateTime; } else if (curValue < ExtremumValue) { ReachedExtremum = true; } } } else { if (ReachedExtremum) { if (curValue < LastValue) { PoolTrend = LastValue < StartValue ? SIGNAL_CODE.SELL : SIGNAL_CODE.BUY; Depth = LastValue < StartValue ? LastValue - ExtremumValue : StartValue - ExtremumValue; return(true); } } else { if (curValue < ExtremumValue) { ExtremumValue = curValue; ExtremumTime = updateTime; } else if (curValue > ExtremumValue) { ReachedExtremum = true; } } } LastTime = updateTime; LastValue = curValue; LastRsi = rsi.Bid; return(false); }
public static int comparison(Price p1, Price p2) { // precision is set to 1/10000 of bp return (int)(10000m * (p1.Mid() - p2.Mid())); }
protected override bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder) { if (_calendar == null) { _calendar = new Calendar(updateTime); } IndicatorRSI rsi = (IndicatorRSI)indicator; if (indicator.TimeSeries.TotalMinutes(updateTime) < _timeFrameMn) { return(false); } if (!_startValue.HasValue) { _startValue = value.Mid(); } Price curRsi = rsi.TimeSeries.Last(); Price prevRsi = rsi.TimeSeries.PrevValue(updateTime).Value.Value; if ((prevRsi.Bid <= 50m && curRsi.Bid >= 50m) || (curRsi.Bid <= 50m && prevRsi.Bid >= 50m)) { _rsi_loss_reset = true; } //_rsiSellThreshold += Math.Max(0m, curRsi.Bid - (decimal)getSellThreshold()) / 2m; //_rsiBuyThreshold += Math.Min(0m, curRsi.Bid - (decimal)getBuyThreshold()) / 2m; var minVal = _asset.TimeSeries.Min(updateTime.AddMinutes(-_timeFrameStopLossMn), updateTime); var maxVal = _asset.TimeSeries.Max(updateTime.AddMinutes(-_timeFrameStopLossMn), updateTime); if (maxVal - minVal > _maxVol) { //WriteBlockReason(updateTime, string.Format("reset due to vol > {0}", _maxVol)); _rsi_loss_reset = false; } minVal = _asset.TimeSeries.Min(updateTime.AddMinutes(-_timeFrameBottomMn), updateTime); maxVal = _asset.TimeSeries.Max(updateTime.AddMinutes(-_timeFrameBottomMn), updateTime); if (maxVal - minVal > _maxLongVol) { //WriteBlockReason(updateTime, string.Format("reset due to long vol > {0}", _maxLongVol)); _rsi_loss_reset = false; } if (Math.Abs(value.Mid() - _startValue.Value) > _maxTotalVol) { WriteBlockReason(updateTime, string.Format("stopped trading due to vol > {0}", _maxTotalVol)); _stopTrading = true; } if (_tradingStart > DateTime.MinValue) { if ((decimal)(updateTime - _tradingStart).TotalMilliseconds > _timeFrameStopLossMn * 60000m) { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to timeout, AssetStart = {0}, Value = {1}", _tradingStartValue, value.Bid), ref tradingOrder)); } else { int idxStopLoss = -1; decimal ratio = 0m; foreach (var interval in stopLossTimes) { idxStopLoss++; if (interval.IsInside((int)(updateTime - _tradingStart).TotalMinutes)) { ratio = interval.Ratio((decimal)(updateTime - _tradingStart).TotalMinutes); break; } } if (_signalCode == SIGNAL_CODE.BUY) { var assetMin = rsi.MinAsset((int)(updateTime - _tradingStart).TotalMinutes + 1); var stopWin = stopWinValues[idxStopLoss].Value(ratio); var stopBigLoss = bigStopLossValues[idxStopLoss].Value(ratio); if (value.Bid >= _tradingStartValue + stopWin && curRsi.Bid >= getBuyThreshold() + 10) { return(close(_id + string.Format(" close event due to stop win. SELL AssetStart = {0}, LastValue = {1}, StopWin = {2}", _tradingStartValue, value.Bid, stopWin), ref tradingOrder)); } else if (value.Bid - assetMin >= stopWin && curRsi.Bid >= getBuyThreshold() + 10) { if (value.Bid > _tradingStartValue) { return(close(_id + string.Format(" close event due to stop win. SELL AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Bid), ref tradingOrder)); } else { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to stop loss. SELL AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Bid), ref tradingOrder)); } } else if (value.Bid - _tradingStartValue >= stopBigLoss) { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to stop loss. SELL AssetMin = {0}, LastValue = {1}, StopLoss = {2}", assetMin, value.Bid, stopBigLoss), ref tradingOrder)); }/* * else if (_trend.TimeSeries.Last().Bid <= _tradingTrend - 5m && curRsi.Bid >= getBuyThreshold() + 10) * { * if (value.Offer > _tradingStartValue) * return close(_id + string.Format(" close event due to stop win forced by trend. SELL AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Offer), ref tradingOrder); * else * { * _rsi_loss_reset = false; * return close(_id + string.Format(" close event due to stop loss forced by trend. SELL AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Offer), ref tradingOrder); * } * }*/ else { var stopLoss = stopLossValues[idxStopLoss].Value(ratio); var bigStopLoss = bigStopLossValues[idxStopLoss].Value(ratio); if ((_tradingStartValue - value.Bid >= stopLoss && curRsi.Bid >= getBuyThreshold() + 20) || (_tradingStartValue - value.Bid >= bigStopLoss)) { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to stop loss. SELL AssetStart = {0}, LastValue = {1}, StopLoss = {2}", _tradingStartValue, value.Bid, stopLoss), ref tradingOrder)); } } } else { var assetMax = rsi.MaxAsset((int)(updateTime - _tradingStart).TotalMinutes + 1); var stopWin = stopWinValues[idxStopLoss].Value(ratio); var stopBigLoss = bigStopLossValues[idxStopLoss].Value(ratio); if (value.Offer <= _tradingStartValue - stopWin && curRsi.Bid <= getSellThreshold() - 10) { return(close(_id + string.Format(" close event due to stop win. BUY AssetStart = {0}, LastValue = {1}, StopWin = {2}", _tradingStartValue, value.Offer, stopWin), ref tradingOrder)); } else if (assetMax - value.Offer >= stopWin && curRsi.Bid <= getSellThreshold() - 10) { if (value.Offer < _tradingStartValue) { return(close(_id + string.Format(" close event due to stop win. BUY AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Offer), ref tradingOrder)); } else { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to stop loss. BUY AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Offer), ref tradingOrder)); } } else if (assetMax - value.Offer >= stopBigLoss) { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to stop loss. BUY AssetMax = {0}, LastValue = {1}, StopLoss = {2}", assetMax, value.Offer, stopBigLoss), ref tradingOrder)); }/* * else if (_trend.TimeSeries.Last().Bid >= _tradingTrend + 5m && curRsi.Bid <= getSellThreshold() - 10) * { * if (value.Offer < _tradingStartValue) * return close(_id + string.Format(" close event due to stop win forced by trend. BUY AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Offer), ref tradingOrder); * else * { * _rsi_loss_reset = false; * return close(_id + string.Format(" close event due to stop loss forced by trend. BUY AssetStart = {0}, LastValue = {1}", _tradingStartValue, value.Offer), ref tradingOrder); * } * }*/ else { var stopLoss = stopLossValues[idxStopLoss].Value(ratio); var bigStopLoss = bigStopLossValues[idxStopLoss].Value(ratio); if ((value.Offer - _tradingStartValue >= stopLoss && curRsi.Bid <= getSellThreshold() - 20) || (value.Offer - _tradingStartValue >= bigStopLoss)) { _rsi_loss_reset = false; return(close(_id + string.Format(" close event due to stop loss. BUY AssetStart = {0}, LastValue = {1}, StopLoss = {2}", _tradingStartValue, value.Offer, stopLoss), ref tradingOrder)); } } } } } else { if (!_rsi_loss_reset || _stopTrading || maxVal - minVal < _minVol || value.Offer - value.Bid > _maxSpread) { return(false); } /* * foreach (var rsiRef in _rsiRefs) * { * if (rsiRef.TimeSeries.Count > 0) * { * if (Math.Abs(curRsi.Mid() - 50m) < Math.Abs(rsiRef.TimeSeries.Last().Mid() - 50m)) * return false; * } * }*/ string eventName = ""; if (_calendar.IsNearEvent(_asset.Name, updateTime, ref eventName)) { WriteBlockReason(updateTime, "deal blocked by event: " + eventName); _rsi_loss_reset = false; return(false); } var rsiMax = rsi.MaxRsi(_timeFramePeakMn); var rsiMin = rsi.MinRsi(_timeFramePeakMn); //var rsiLongMax = _rsiLong.MaxRsi(_timeFrameRsiLongMn); //var rsiLongMin = _rsiLong.MinRsi(_timeFrameRsiLongMn); var rsiAdjustment = Math.Max(0, rsi.MaxRsi(_timeFrameBottomMn) - getSellThreshold()) - Math.Max(0, getBuyThreshold() - rsi.MinRsi(_timeFrameBottomMn)); var curEmaVeryShort = _emaVeryShort.TimeSeries.Last(); var curEmaShort = _emaShort.TimeSeries.Last(); var curEmaLong = _emaLong.TimeSeries.Last(); var curVol = _wmvol.TimeSeries.Last().Bid; if (curVol < _maxWmVol) { WriteBlockReason(updateTime, "deal blocked due to vol < " + _maxWmVol); return(false); } var curVolAvg = (_wmvol.Min() + _wmvol.Max()) / 2m; if (curVol < curVolAvg) { WriteBlockReason(updateTime, "deal blocked due to vol < vol average"); return(false); } if ((curRsi.Bid >= getSellThreshold()) && //(curRsi.Bid - rsiAdjustment >= getSellThreshold() && curRsi.Bid >= (getSellThreshold() - 10))) && (rsiLongMax >= getSellThreshold() - 15m) && (curRsi.Bid > rsiMax - _startThreshold) && (curEmaVeryShort.Mid() + _maxShortMacDSpread > curEmaLong.Mid()) && (Math.Abs(curEmaShort.Mid() - curEmaLong.Mid()) < _maxLongMacDSpread)) { var curVolTrend = _volTrend.TimeSeries.Last().Bid; if (curVolTrend > 0.5m || curVolTrend < 0m) { WriteBlockReason(updateTime, "deal blocked due to vol not within 0 < trend < 0.5"); return(false); } if (!_volTrendTrend.IsMin(2, curVolTrend, 0.01m) || _volTrendTrend.IsMax(2, curVolTrend, 0.02m)) { WriteBlockReason(updateTime, "sell event blocked due to vol trend not 1mn minimum"); return(false); } tradingOrder = _onSell; _signalCode = SIGNAL_CODE.SELL; _tradingStart = updateTime; _tradingStartValue = value.Bid; _tradingTrend = _trend.TimeSeries.Last().Bid; if (curRsi.Bid >= getSellThreshold()) { Log.Instance.WriteEntry(_id + " sell event due to RSI >= getSellThreshold()"); } // else if (Math.Abs(curRsi.Bid - rsiMax) < _startThreshold) // Log.Instance.WriteEntry(_id + " sell event due highest RSI peak reached"); else { Log.Instance.WriteEntry(_id + " sell event due to adjusted RSI >= getSellThreshold()"); } return(true); } else if ((curRsi.Bid <= getBuyThreshold()) && //(curRsi.Bid + rsiAdjustment <= getBuyThreshold() && curRsi.Bid <= (getBuyThreshold() + 10))) && (rsiLongMin <= getBuyThreshold() + 15m) && (curRsi.Bid < rsiMin + _startThreshold) && (curEmaVeryShort.Mid() - _maxShortMacDSpread < curEmaLong.Mid()) && (Math.Abs(curEmaShort.Mid() - curEmaLong.Mid()) < _maxLongMacDSpread)) { var curVolTrend = _volTrend.TimeSeries.Last().Bid; if (curVolTrend < -0.5m || curVolTrend > 0m) { WriteBlockReason(updateTime, "deal blocked due to vol not within -0.5 < trend < 0"); return(false); } if (!_volTrendTrend.IsMax(2, curVolTrend, 0.01m) || _volTrendTrend.IsMin(2, curVolTrend, 0.02m)) { WriteBlockReason(updateTime, "buy event blocked due to vol trend not 1mn maximum"); return(false); } tradingOrder = _onBuy; _signalCode = SIGNAL_CODE.BUY; _tradingStart = updateTime; _tradingStartValue = value.Offer; _tradingTrend = _trend.TimeSeries.Last().Bid; if (curRsi.Bid <= getBuyThreshold()) { Log.Instance.WriteEntry(_id + " buy event due to RSI <= getBuyThreshold()"); } // else if (Math.Abs(curRsi.Bid - rsiMin) < _startThreshold) // Log.Instance.WriteEntry(_id + " buy event due lowest RSI peak reached"); else { Log.Instance.WriteEntry(_id + " buy event due to adjusted RSI <= getBuyThreshold()"); } return(true); } else { _signalCode = SIGNAL_CODE.HOLD; _tradingStart = DateTime.MinValue; _tradingStartValue = 0m; } } return(false); }
public Price CalcCurve(MarketData mktData, DateTime updateTime) { /* * var topValues = new List<KeyValuePair<decimal, decimal>>(); * var bottomValues = new List<KeyValuePair<decimal, decimal>>(); * var timeOrig = updateTime.AddSeconds(_periodSec * _nbCandles); * foreach (var candle in _trend.Candles) * { * topValues.Add(new KeyValuePair<decimal, decimal>((decimal)(candle.EndTime - timeOrig).TotalSeconds, candle.Max)); * bottomValues.Add(new KeyValuePair<decimal, decimal>((decimal)(candle.StartTime - timeOrig).TotalSeconds, candle.Min)); * } * var topCurve = curvature(topValues[0].Key, topValues[0].Value, topValues[1].Key, topValues[1].Value, topValues[2].Key, topValues[2].Value); * var bottomCurve = curvature(topValues[0].Key, topValues[0].Value, topValues[1].Key, topValues[1].Value, topValues[2].Key, topValues[2].Value); * * return new Price((topCurve + bottomCurve) / 2m);*/ if (updateTime >= _nextCurveTime) { if (mktData.TimeSeries.Count < 2) { return(null); } if (_nextCurveTime == DateTime.MinValue) { _nextCurveTime = updateTime.AddSeconds(_subPeriodSeconds); } else { _nextCurveTime = _nextCurveTime.AddSeconds(_subPeriodSeconds); } DateTime rsiTime = _nextCurveTime.AddSeconds(-_subPeriodSeconds); if (mktData.TimeSeries.StartTime() > rsiTime) { return(null); } if (_curvCandles.Count == _nbCandles) { _curvCandles.RemoveAt(0); } if (_curvCandles.Count > 0) { _curCandle.EndTime = updateTime; _curCandle = new CurvCandle(mktData.TimeSeries.Last().Mid()); } else { _curCandle = new CurvCandle(mktData.TimeSeries.Last().Mid()); } _curvCandles.Add(_curCandle); } else { _curCandle = _curvCandles.Last(); } DateTime startTime = _nextCurveTime.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 _curvCandles) { 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 _curvCandles) { 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 curv = Math.Abs(sumLosses) < 0.1m ? (Math.Abs(sumGain) < 0.1m ? 1m : 1000m) : sumGain / sumLosses; if (curv > 1m) { curv = 1m / curv; } return(new Price(100m * curv)); }
protected virtual bool OnSell(Signal signal, DateTime time, Price stockValue) { if (_tradingSignals != null) { if (_tradingSignals.Contains(signal.Id)) { var pos = _ptf.GetPosition(signal.TradingAsset.Id); if (pos == null) { Reset(time, stockValue.Mid(), true); return false; } if (pos.Quantity < 0) { Log.Instance.WriteEntry(time + " Signal " + signal.Id + ": Some trades are still open. last trade: " + signal.Trade.Id + " " + stockValue.Bid + ". Closing all positions...", EventLogEntryType.Error); Portfolio.Instance.CloseAllPositions(time, signal.TradingAsset.Id, stockValue.Offer, signal); return false; } signal.Trade = new Trade(time, signal.TradingAsset.Id, SIGNAL_CODE.SELL, _amount, stockValue.Bid, 0, Reset); return Sell(signal, time, stockValue); } } return false; }
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); }
protected override void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { if (!mktData.Levels.HasValue) return; Publish(updateTime, new Price(GetNearestLevel(value.Mid(), mktData.Levels.Value))); }
public static int comparison(Price p1, Price p2) { // precision is set to 1/10000 of bp return((int)(10000m * (p1.Mid() - p2.Mid()))); }