protected override bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder) { KeyValuePair<DateTime, Price>? timeValueLow = _low.TimeSeries[updateTime]; KeyValuePair<DateTime, Price>? timeValueHigh = _high.TimeSeries[updateTime]; if (timeValueLow == null || timeValueHigh == null) return false; if (_high.TimeSeries.TotalMinutes(updateTime) < _high.Period / 60) return false; Price lowWMA = timeValueLow.Value.Value; Price highWMA = timeValueHigh.Value.Value; var signalValue = lowWMA - highWMA; SIGNAL_CODE oldSignalCode = _signalCode; if (signalValue.Offer > 0) { tradingOrder = _onBuy; _signalCode = SIGNAL_CODE.BUY; } else if (signalValue.Bid < 0) { tradingOrder = _onSell; _signalCode = SIGNAL_CODE.SELL; } else return false; return oldSignalCode != SIGNAL_CODE.UNKNOWN && oldSignalCode != SIGNAL_CODE.HOLD && oldSignalCode != _signalCode; }
public static Price operator *(Price p, decimal factor) { Price mult = new Price(p); mult.Bid *= factor; mult.Offer *= factor; return mult; }
protected override bool ComputeOutput() { if (_asset.Levels == null) return false; if (_startAssetPrice == null) _startAssetPrice = _asset.TimeSeries.First(); var updateTime = _indicatorLatestValues.First().Value.Key; var amplitude = 100.0m; decimal curAssetVal = (_asset.TimeSeries[updateTime].Value.Value.Mid() - _asset.Levels.Value.Pivot) / amplitude; _inputValues.Add((double)curAssetVal); var indicatorId = "WMA_2_" + _asset.Id; if (!_indicatorLatestValues.ContainsKey(indicatorId)) return false; _inputValues.Add((double)((_indicatorLatestValues[indicatorId].Value.Mid() - _asset.Levels.Value.Pivot) / amplitude)); indicatorId = "WMA_10_" + _asset.Id; if (!_indicatorLatestValues.ContainsKey(indicatorId)) return false; _inputValues.Add((double)((_indicatorLatestValues[indicatorId].Value.Mid() - _asset.Levels.Value.Pivot) / amplitude)); indicatorId = "WMA_30_" + _asset.Id; if (!_indicatorLatestValues.ContainsKey(indicatorId)) return false; _inputValues.Add((double)((_indicatorLatestValues[indicatorId].Value.Mid() - _asset.Levels.Value.Pivot) / amplitude)); indicatorId = "WMA_90_" + _asset.Id; if (!_indicatorLatestValues.ContainsKey(indicatorId)) return false; _inputValues.Add((double)((_indicatorLatestValues[indicatorId].Value.Mid() - _asset.Levels.Value.Pivot) / amplitude)); return true; }
protected override bool Buy(Signal signal, DateTime time, Price stockValue) { if (base.Buy(signal, time, stockValue)) { Console.WriteLine(time + " Signal " + signal.Id + " buy " + signal.TradingAsset.Id + " " + stockValue.Bid); return true; } return false; }
public override void Publish(DateTime updateTime, Price price) { if (price.Bid != price.Offer) { string error = "Inconsistent indicator " + _name + " values"; Log.Instance.WriteEntry(error, EventLogEntryType.Error); throw new ApplicationException(error); } if (_publishingEnabled) PublisherConnection.Instance.Insert(updateTime, this, price.Bid); }
protected override void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { if (mktData.TimeSeries.TotalMinutes(updateTime) > _interval.TotalMinutes) { decimal? coeff = linearCoeff(updateTime); if (coeff != null) { Price price = new Price(coeff.Value); base.OnUpdate(mktData, updateTime, price); Publish(updateTime, price); } } }
protected override bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder) { if (indicator.TimeSeries.Count == 0) return false; _indicatorLatestValues[indicator.Id] = new KeyValuePair<DateTime, Price>(updateTime, indicator.TimeSeries.Last()); DateTime dt = DateTime.MinValue; foreach (var ind in _indicatorLatestValues) { if (dt == DateTime.MinValue) { dt = ind.Value.Key; continue; } if (dt != ind.Value.Key) return false; } _inputValues.Clear(); if (!ComputeOutput()) return false; _ann.CalculateOutput(_inputValues); var output = _ann.GetOutput()[0]; if (output > 0.5 && _signalCode != SIGNAL_CODE.BUY) { tradingOrder = _onBuy; _signalCode = SIGNAL_CODE.BUY; } else if (output < -0.5 && _signalCode != SIGNAL_CODE.SELL) { tradingOrder = _onSell; _signalCode = SIGNAL_CODE.SELL; } else{ tradingOrder = _onHold; _signalCode = SIGNAL_CODE.HOLD; } return true; }
static void GET(string symbol) { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("{0}?symbol={1}", DATA_SRC, symbol)); request.Method = "GET"; using (var response = (HttpWebResponse)request.GetResponse()) { using (var reader = new StreamReader(response.GetResponseStream())) { JavaScriptSerializer js = new JavaScriptSerializer(); var responseData = reader.ReadToEnd(); var dict = js.Deserialize<dynamic>(responseData.Substring(18, responseData.Length - 19)); var marketData = new MarketData(symbol); var dateComponents = dict["Timestamp"].Split(' '); var timeComponents = dateComponents[3].Split(':'); var month = DateTime.ParseExact(dateComponents[1], "MMM", CultureInfo.CurrentCulture).Month; var updateTime = new DateTime(int.Parse(dateComponents[5]), month, int.Parse(dateComponents[2]), int.Parse(timeComponents[0]), int.Parse(timeComponents[1]), int.Parse(timeComponents[2]), DateTimeKind.Utc); var hourOffset = int.Parse(dateComponents[4].Split('-')[1].Split(':')[0]); updateTime = updateTime.AddHours(hourOffset); if (!stockPriceCache.ContainsKey(symbol)) stockPriceCache[symbol] = new KeyValuePair<DateTime, decimal>(DateTime.MinValue, 0m); if (stockPriceCache[symbol].Key != updateTime && stockPriceCache[symbol].Value != (decimal)dict["LastPrice"]) { stockPriceCache[symbol] = new KeyValuePair<DateTime, decimal>(updateTime, dict["LastPrice"]); var stockPrice = new Price(dict["LastPrice"]); stockPrice.Volume = dict["Volume"]; CassandraConnection.Instance.Insert(updateTime, marketData, stockPrice); } } } } catch (WebException ex) { if (ex.Status != WebExceptionStatus.ProtocolError) Log.Instance.WriteEntry(ex.ToString(), System.Diagnostics.EventLogEntryType.Error); } }
protected override void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { DateTime startTime; if (_curAvg == null) { startTime = updateTime.AddSeconds(-_periodSeconds); if (MarketData.TimeSeries.Count == 0) return; if (MarketData.TimeSeries.StartTime() > startTime) return; _decrementStartTime = startTime; var curAvg = new Price(); MobileVolume(ref curAvg, startTime, updateTime); if (curAvg == null) return; _curAvg = curAvg; } else { startTime = _curAvgTime; var decrementUpdateTime = updateTime.AddSeconds(-_periodSeconds); var decrementAvg = new Price(0m,0m,0m); MobileVolume(ref decrementAvg, _decrementStartTime, decrementUpdateTime); decrementAvg.Bid = decrementAvg.Volume.Value; decrementAvg.Offer = decrementAvg.Volume.Value; _curAvg = _curAvg - decrementAvg + Math.Abs(value.Volume.Value) / (decimal)_periodSeconds; _curAvg.Volume = _curAvg.Bid; _decrementStartTime = decrementUpdateTime; } _curAvg.Bid = _curAvg.Volume.Value; _curAvg.Offer = _curAvg.Volume.Value; _curAvgTime = updateTime; Publish(updateTime, _curAvg.Volume.Value); }
protected override void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { Price rsi = IndicatorFunc(mktData, updateTime, value); if (rsi != null) { _values.Add(updateTime, rsi); Publish(updateTime, rsi.Bid); } }
protected abstract bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder);
public static int comparison(Price p1, Price p2) { // precision is set to 1/10000 of bp return (int)(10000m * (p1.Mid() - p2.Mid())); }
/* public void FireTick(DateTime updateTime, Price livePrice) { if (updateTime > _closePositionTime && !_allPositionsClosed) { Portfolio.Instance.CloseAllPositions(updateTime); _allPositionsClosed = true; } foreach (Tick ticker in this._updateHandlers) ticker(this, updateTime, livePrice); foreach (Tick ticker in this._tickHandlers) ticker(this, updateTime, livePrice); }*/ public virtual void Publish(DateTime updateTime, Price price) { PublisherConnection.Instance.Insert(updateTime, this, price); }
public Price(Price cpy) { this.Bid = cpy.Bid; this.Offer = cpy.Offer; this.Volume = cpy.Volume; }
public virtual void Process(DateTime dt, Price p) { TimeSeries.Add(dt, p); }
public virtual void Publish(DateTime updateTime, Price price) { PublisherConnection.Instance.Insert(updateTime, this, price); }
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 Price IndicatorFunc(MarketData mktData, DateTime updateTime, Price value) { return(CalcRSI(mktData, updateTime)); }
protected bool OnHold(Signal signal, DateTime updateTime, Price value) { // hold your position; do nothing return(false); }
public override void Process(DateTime dt, Price p) { var newValue = IndicatorFunc(SignalStock, dt, p); TimeSeries.Add(dt, newValue); }
static void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { }
protected override bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder) { if (_tradingOrder == _onSell) { tradingOrder = _onBuy; _tradingOrder = _onBuy; return true; } else { tradingOrder = _onSell; _tradingOrder = _onSell; return true; } }
public static Price operator -(Price p1, decimal p2) { Price diff = new Price(p1); diff.Bid -= p2; diff.Offer -= p2; return diff; }
protected void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { if (_signalProcessing) { return; } lock (_mktIndicator) { if (_signalProcessing) { return; } try { _signalProcessing = true; Signal.Tick tradingOrder = _onHold; bool signaled = Process(mktData, updateTime, value, ref tradingOrder); if (signaled) { // send a signal var stockValue = _asset.TimeSeries[updateTime].Value.Value; if (tradingOrder(this, updateTime, stockValue)) { if (_signalCode == SIGNAL_CODE.BUY) { if (_oldSignalCode == SIGNAL_CODE.SELL) { PublisherConnection.Instance.Insert(updateTime.AddSeconds(-1), this, _signalCode, stockValue.Offer); } PublisherConnection.Instance.Insert(updateTime, this, _signalCode, stockValue.Offer); } else if (_signalCode == SIGNAL_CODE.SELL) { if (_oldSignalCode == SIGNAL_CODE.BUY) { PublisherConnection.Instance.Insert(updateTime.AddSeconds(-1), this, _signalCode, stockValue.Bid); } PublisherConnection.Instance.Insert(updateTime, this, _signalCode, stockValue.Bid); } else if (_signalCode == SIGNAL_CODE.HOLD) { if (_oldSignalCode == SIGNAL_CODE.BUY) { PublisherConnection.Instance.Insert(updateTime, this, SIGNAL_CODE.SELL, stockValue.Bid); } else if (_oldSignalCode == SIGNAL_CODE.SELL) { PublisherConnection.Instance.Insert(updateTime, this, SIGNAL_CODE.BUY, stockValue.Offer); } } else if (_signalCode == SIGNAL_CODE.FAILED) { PublisherConnection.Instance.Insert(updateTime, this, _signalCode, stockValue.Bid); } _oldSignalCode = _signalCode; } } } finally { _signalProcessing = false; } } }
protected void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { Signal.Tick tradingOrder = _onHold; bool signaled = Process(mktData, updateTime, value, ref tradingOrder); if (signaled) { // send a signal var stockValue = _asset.TimeSeries[updateTime].Value.Value; if (tradingOrder(this, updateTime, stockValue)) { if (_signalCode == SIGNAL_CODE.BUY) PublisherConnection.Instance.Insert(updateTime, this, _signalCode, stockValue.Offer); else if (_signalCode == SIGNAL_CODE.SELL) PublisherConnection.Instance.Insert(updateTime, this, _signalCode, stockValue.Bid); else if (_signalCode == SIGNAL_CODE.FAILED) PublisherConnection.Instance.Insert(updateTime, this, _signalCode, stockValue.Bid); } } }
public static Price operator +(Price p1, Price p2) { Price sum = new Price(p1); sum += p2.Mid(); return sum; }
protected bool _onHold(Signal signal, DateTime updateTime, Price value) { // hold your position; do nothing return true; }
protected override void OnUpdateIndex(MarketData mktData, DateTime updateTime, Price stockValue) { if (_tradingSet.UpdateIndex(updateTime, stockValue.Offer)) { Console.WriteLine(updateTime + " Signal " + _signal.Id + " buy " + _signal.TradingAsset.Id + " " + stockValue.Offer); } }
protected override void OnUpdate(MarketData mktData, DateTime updateTime, Price value) { Price avgPrice = IndicatorFunc(mktData, updateTime, value); if (avgPrice != null) Publish(_nextCorrelTime, avgPrice.MidPrice()); }
public static Price operator +(Price p1, decimal p2) { Price sum = new Price(p1); sum.Bid += p2; sum.Offer += p2; return sum; }
protected override Price IndicatorFunc(MarketData mktData, DateTime updateTime, Price value) { if (_wma.TimeSeries.Count == 0 || _wmaRef.TimeSeries.Count == 0) return null; if (updateTime > _nextCorrelTime) _nextCorrelTime = (_nextCorrelTime == DateTime.MinValue ? updateTime : _nextCorrelTime).AddSeconds(_periodSeconds); var curCorrel = 0m; var curValue = 0m; var curVar = 0.0; var curVarRef = 0.0; Price priceCurCorrel = null; if (_prevCorrel.HasValue) { if (_wma.TimeSeries.StartTime() > _startTime) return null; if (_wmaRef.TimeSeries.StartTime() > _startTime) return null; if (_wmaRef.TimeSeries.EndTime() != _wma.TimeSeries.EndTime()) return null; var curPeriod = (decimal)(updateTime - _startTime).TotalMilliseconds; if (curPeriod > _periodMilliSeconds) curPeriod = _periodMilliSeconds; var timeDecay = _timeDecayWeight * (decimal)(updateTime - _startTime).TotalSeconds; var k = (curPeriod + timeDecay) / _periodMilliSeconds; var avg = _wma.TimeSeries.Last(); var avgRef = _wmaRef.TimeSeries.Last(); var curVarValue = Math.Pow((double)(value.Bid - avg.Bid), 2); var curVarRefValue = Math.Pow((double)(_wmaRef.SignalStock.TimeSeries.Last().Bid - avgRef.Bid), 2); curVar = (double)(_curVarValue.Bid * k) + _prevVar.Value * (1.0 - (double)k); curVarRef = (double)(_curVarRefValue.Bid * k) + _prevVarRef.Value * (1.0 - (double)k); if (curVar * curVarRef == 0) { if (Math.Abs(curVarValue * curVarRefValue - curVar * curVarRef) < 0.01) curValue = 1m; else curValue = 0m; } else curValue = (decimal)(Math.Sqrt((curVarValue * curVarRefValue) / (curVar * curVarRef))); curCorrel = _curValue.Bid * k + _prevCorrel.Value * (1m - k); _curVarValue = new Price((decimal)curVarValue); _curVarRefValue = new Price((decimal)curVarRefValue); priceCurCorrel = new Price(curCorrel); } else { _curVarValue = new Price(0m); _curVarRefValue = new Price(0m); curValue = 0m; curCorrel = 0m; } _curValue = new Price(curValue); _prevCorrel = curCorrel; _prevVar = curVar; _prevVarRef = curVarRef; _startTime = updateTime; return priceCurCorrel; }
public abstract void Insert(DateTime updateTime, MarketData mktData, Price price);
protected override bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder) { if (base.Process(indicator, updateTime, value, ref tradingOrder)) { if (_trendAssumption != SIGNAL_CODE.BUY && tradingOrder == _onSell) { if (_low.TimeSeries.Count >= 2) { var lowVal = _low.TimeSeries[updateTime].Value.Value; var prevValues = _low.TimeSeries.Values(updateTime, new TimeSpan(0, 1, 0), true); if (prevValues != null) { if (prevValues.Count >= 2) { var prevVal = prevValues[prevValues.Count - 2].Value; if (_cascading) { if (_localMinimum > lowVal.Bid) _localMinimum = lowVal.Bid; if (_localMaximum < lowVal.Bid) _localMaximum = lowVal.Bid; if (_buying) { if (lowVal.Bid < _localMaximum - _threshold) { _pivot = _localMaximum; _localMinimum = _localMaximum; _buying = false; } else if (lowVal.Bid > _pivot + _threshold) { _signalCode = SIGNAL_CODE.BUY; tradingOrder = _onBuy; } } else { if (lowVal.Bid > _localMinimum + _threshold) { _pivot = _localMinimum; _localMaximum = _localMinimum; _signalCode = SIGNAL_CODE.BUY; tradingOrder = _onBuy; _buying = true; } } } else { _cascading = true; _localMinimum = lowVal.Bid; _localMaximum = lowVal.Bid; _pivot = _localMaximum; _buying = false; } return true; } } } } else if (_trendAssumption != SIGNAL_CODE.SELL && tradingOrder == _onBuy) { if (_low.TimeSeries.Count >= 2) { var lowVal = _low.TimeSeries[updateTime].Value.Value; var prevValues = _low.TimeSeries.Values(updateTime, new TimeSpan(0, 1, 0), true); if (prevValues != null) { if (prevValues.Count >= 2) { var prevVal = prevValues[prevValues.Count - 2].Value; if (_cascading) { if (_localMinimum > lowVal.Offer) _localMinimum = lowVal.Offer; if (_localMaximum < lowVal.Offer) _localMaximum = lowVal.Offer; if (_selling) { if (lowVal.Offer > _localMinimum + _threshold) { _pivot = _localMinimum; _localMaximum = _localMinimum; _selling = false; } else if (lowVal.Offer < _pivot - _threshold) { _signalCode = SIGNAL_CODE.SELL; tradingOrder = _onSell; } } else { if (lowVal.Offer < _localMaximum - _threshold) { _pivot = _localMaximum; _localMinimum = _localMaximum; _signalCode = SIGNAL_CODE.SELL; tradingOrder = _onSell; _selling = true; } } } else { _cascading = true; _localMinimum = lowVal.Offer; _localMaximum = lowVal.Offer; _pivot = _localMinimum; _selling = false; } return true; } } } } _cascading = false; _buying = false; _selling = false; return true; } return false; }
protected override Price IndicatorFunc(MarketData mktData, DateTime updateTime, Price value) { return CalcRSI(mktData, updateTime); }
public void FireTick(DateTime updateTime, Price value) { if (!_isReady) return; _values.Add(updateTime, value); if (updateTime > _closePositionTime && !_allPositionsClosed) { Portfolio.Instance.CloseAllPositions(updateTime); _allPositionsClosed = true; } foreach (Tick ticker in this._updateHandlers) ticker(this, updateTime, value); foreach (Tick ticker in this._tickHandlers) ticker(this, updateTime, value); Publish(updateTime, value); /* var curPeriodSec = (decimal)(updateTime - _lastUpdateTime).TotalSeconds; _values.Add(updateTime, value); if (curPeriodSec >= 1m) { FireTick(updateTime, value, true); Publish(updateTime, value); _lastUpdatePrice = new Price(value); _lastUpdatePrice.Volume = 0m; _lastUpdateTime = updateTime; } else { _lastUpdatePrice.Bid = value.Bid; _lastUpdatePrice.Offer = value.Offer; _lastUpdatePrice.Volume += value.Volume; FireTick(updateTime, value); Publish(updateTime, value); }*/ }
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 static int comparison(Price p1, Price p2) { // precision is set to 1/10000 of bp return((int)(10000m * (p1.Mid() - p2.Mid()))); }