public void Unsubscribe() { _onBuy = null; _onSell = null; foreach (Indicator indicator in (from i in _mktIndicator select i).Reverse()) { indicator.Unsubscribe(OnUpdate, null); } }
public void Subscribe(Signal.Tick onBuy, Signal.Tick onSell, Signal.Tick onHold) { _onBuy = onBuy; _onSell = onSell; _onHold = onHold == null ? OnHold : onHold; foreach (Indicator indicator in _mktIndicator) { indicator.Subscribe(OnUpdate, null); } }
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); } }
/* * void OnUpdateVolTrendAvg(MarketData mktData, DateTime updateTime, Price value) * { * Price trendVol = _volTrendAvg.Average(updateTime); * if (trendVol != null) * _volTrendAvg.Publish(updateTime, trendVol.Bid); * } * * void OnUpdateVolCurve(MarketData mktData, DateTime updateTime, Price value) * { * Price volCurve = _volCurve.CalcCurve(_volTrend, updateTime); * if (volCurve != null) * _volCurve.Publish(updateTime, volCurve.Bid); * } * * void OnUpdateRsiLong(MarketData mktData, DateTime updateTime, Price value) * { * Price rsi = _rsiLong.CalcRSI(_asset, updateTime); * if (rsi != null) * _rsiLong.Publish(updateTime, rsi.Bid); * } * * void OnUpdateWmVolLong(MarketData mktData, DateTime updateTime, Price value) * { * Price wmvol = _wmvolLong.CalcWMVol(_asset, updateTime, value); * if (wmvol != null) * _wmvolLong.Publish(updateTime, wmvol.Bid); * }*/ bool close(string reason, ref Signal.Tick tradingOrder) { if (_signalCode == SIGNAL_CODE.BUY) { tradingOrder = _onSell; _signalCode = SIGNAL_CODE.SELL; } else if (_signalCode == SIGNAL_CODE.SELL) { tradingOrder = _onBuy; _signalCode = SIGNAL_CODE.BUY; } else { _signalCode = SIGNAL_CODE.FAILED; Log.Instance.WriteEntry(_id + " error detected while attempting to close a position"); return(false); } _tradingStart = DateTime.MinValue; _tradingStartValue = 0m; Log.Instance.WriteEntry(_id + reason); return(true); }
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 void Unsubscribe() { _onBuy = null; _onSell = null; foreach (Indicator indicator in (from i in _mktIndicator select i).Reverse()) indicator.Unsubscribe(OnUpdate, null); }
public void Subscribe(Signal.Tick onBuy, Signal.Tick onSell) { _onBuy = onBuy; _onSell = onSell; foreach (Indicator indicator in _mktIndicator) indicator.Subscribe(OnUpdate, null); }
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 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); }
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); }
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); }
protected abstract bool Process(MarketData indicator, DateTime updateTime, Price value, ref Signal.Tick tradingOrder);
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; } } }