/// <summary> /// To initialize the generator state. /// </summary> public override void Init() { base.Init(); _lastTradePrice = null; _prevTradePrice = null; _bestAskPrice = null; _bestBidPrice = null; _newTrades = false; _currGenerations = MaxGenerations; _boardDefinition = null; }
/// <summary> /// Process message. /// </summary> /// <param name="message">Message.</param> /// <returns>The result of processing. If <see langword="null" /> is returned, then generator has no sufficient data to generate new message.</returns> protected override Message OnProcess(Message message) { if (_boardDefinition == null) { if (message.Type == MessageTypes.Board) _boardDefinition = (BoardMessage)message.Clone(); return null; } DateTimeOffset time; switch (message.Type) { case MessageTypes.Level1Change: { var l1Msg = (Level1ChangeMessage)message; var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice); if (value != null) _lastTradePrice = (decimal)value; value = l1Msg.Changes.TryGetValue(Level1Fields.BestBidPrice); if (value != null) _bestBidPrice = (decimal)value; value = l1Msg.Changes.TryGetValue(Level1Fields.BestAskPrice); if (value != null) _bestAskPrice = (decimal)value; time = l1Msg.ServerTime; break; } case MessageTypes.Execution: { var execMsg = (ExecutionMessage)message; switch (execMsg.ExecutionType) { case ExecutionTypes.Tick: { var tradePrice = execMsg.TradePrice; if (null == _prevTradePrice) { _prevTradePrice = tradePrice; _bestAskPrice = tradePrice; _bestBidPrice = tradePrice; } switch (execMsg.OriginSide) { case null: { if (tradePrice > _prevTradePrice) { _bestAskPrice = tradePrice; //BestBid = PrevTrade; _prevTradePrice = tradePrice; } else if (tradePrice < _prevTradePrice) { _bestBidPrice = tradePrice; //BestAsk = PrevTrade; _prevTradePrice = tradePrice; } break; } case Sides.Buy: _bestAskPrice = tradePrice; break; default: _bestBidPrice = tradePrice; break; } _lastTradePrice = tradePrice; _newTrades = true; break; } default: return null; } time = execMsg.ServerTime; break; } case MessageTypes.Time: { var timeMsg = (TimeMessage)message; time = timeMsg.ServerTime; break; } default: return null; } if (_currGenerations == 0 || _bestBidPrice == null || _bestAskPrice == null) return null; var isTradeTime = _boardDefinition.IsTradeTime(time); var canProcess = GenerateDepthOnEachTrade && _newTrades ? isTradeTime : (IsTimeToGenerate(time) && isTradeTime); if (!canProcess) return null; _currGenerations = MaxGenerations; var depth = new QuoteChangeMessage { SecurityId = SecurityId, ServerTime = time, LocalTime = time.LocalDateTime, }; if (_bestBidPrice == null || _bestAskPrice == null) { if (_lastTradePrice == null) throw new InvalidOperationException(LocalizedStrings.Str1142); _bestBidPrice = _bestAskPrice = _lastTradePrice; } if (_currGenerations == 0) throw new InvalidOperationException(LocalizedStrings.Str1143); var bidPrice = _bestBidPrice; var askPrice = _bestAskPrice; var minSpred = MinSpreadStepCount * SecurityDefinition.PriceStep; var maxStread = MaxSpreadStepCount * SecurityDefinition.PriceStep; if ((askPrice - bidPrice) < minSpred) { if (_bestBidPrice == _lastTradePrice) // up trend askPrice = bidPrice + minSpred; else bidPrice = askPrice - minSpred; } else if ((askPrice - bidPrice) > maxStread) { if (_bestBidPrice == _lastTradePrice) // down trend askPrice = bidPrice + maxStread; else bidPrice = askPrice - maxStread; } var bids = new List<QuoteChange> { new QuoteChange(Sides.Buy, bidPrice.Value, Volumes.Next()) }; var count = MaxBidsDepth - bids.Count; for (var i = 0; i < count; i++) { var quote = CreateQuote(bidPrice.Value, Sides.Buy); if (quote.Price <= 0) break; bids.Add(quote); bidPrice = quote.Price; } var asks = new List<QuoteChange> { new QuoteChange(Sides.Sell, askPrice.Value, Volumes.Next()) }; count = MaxAsksDepth - asks.Count; for (var i = 0; i < count; i++) { var quote = CreateQuote(askPrice.Value, Sides.Sell); if (quote.Price <= 0) break; asks.Add(quote); askPrice = quote.Price; } depth.Bids = bids; depth.Asks = asks; _newTrades = false; _currGenerations--; return depth; }
public void UpdateBoardDefinition(BoardMessage message) { if (message == null) throw new ArgumentNullException("message"); _timeZoneInfo = message.TimeZoneInfo; }