/// <summary> /// Initializes a new instance of the <see cref="DepthCandleBuilderSourceValue"/>. /// </summary> /// <param name="message">Messages containing quotes.</param> /// <param name="type">Type of candle depth based data.</param> public QuoteCandleBuilderSourceValue(QuoteChangeMessage message, DepthCandleSourceTypes type) { QuoteChange = message; Type = type; switch (Type) { case DepthCandleSourceTypes.BestBid: { var bid = message.GetBestBid(); if (bid != null) { _price = bid.Price; _volume = bid.Volume; } break; } case DepthCandleSourceTypes.BestAsk: { var ask = message.GetBestAsk(); if (ask != null) { _price = ask.Price; _volume = ask.Volume; } break; } case DepthCandleSourceTypes.Middle: { var bid = message.GetBestBid(); var ask = message.GetBestAsk(); if (bid != null && ask != null) { _price = (ask.Price + bid.Price) / 2; //_volume = pair.Bid.Volume; } break; } default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// To convert quotes. /// </summary> /// <param name="message">Quotes.</param> /// <returns>Stream <see cref="ExecutionMessage"/>.</returns> public IEnumerable <ExecutionMessage> ToExecutionLog(QuoteChangeMessage message) { if (message == null) { throw new ArgumentNullException("message"); } if (!_priceStepUpdated || !_volumeStepUpdated) { var quote = message.GetBestBid() ?? message.GetBestAsk(); if (quote != null) { _securityDefinition.PriceStep = quote.Price.GetDecimalInfo().EffectiveScale.GetPriceStep(); _securityDefinition.VolumeStep = quote.Volume.GetDecimalInfo().EffectiveScale.GetPriceStep(); _priceStepUpdated = true; _volumeStepUpdated = true; } } _lastDepthDate = message.LocalTime.Date; // чтобы склонировать внутренние котировки //message = (QuoteChangeMessage)message.Clone(); // TODO для ускорения идет shallow copy котировок var newBids = message.IsSorted ? message.Bids : message.Bids.OrderByDescending(q => q.Price); var newAsks = message.IsSorted ? message.Asks : message.Asks.OrderBy(q => q.Price); return(ProcessQuoteChange(message.LocalTime, message.ServerTime, newBids.ToArray(), newAsks.ToArray())); }
/// <summary> /// To process the message, containing data on order book. /// </summary> /// <param name="quoteMsg">The message, containing data on order book.</param> public void ProcessQuotes(QuoteChangeMessage quoteMsg) { AskPrice = quoteMsg.GetBestAsk()?.Price; BidPrice = quoteMsg.GetBestBid()?.Price; _recalcUnrealizedPnL = true; }
/// <summary> /// To convert quotes. /// </summary> /// <param name="message">Quotes.</param> /// <returns>Stream <see cref="ExecutionMessage"/>.</returns> public IEnumerable <ExecutionMessage> ToExecutionLog(QuoteChangeMessage message) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (!_priceStepUpdated || !_volumeStepUpdated) { var quote = message.GetBestBid() ?? message.GetBestAsk(); if (quote != null) { var v = quote.Value; if (!_priceStepUpdated) { _securityDefinition.PriceStep = v.Price.GetDecimalInfo().EffectiveScale.GetPriceStep(); _priceStepUpdated = true; } if (!_volumeStepUpdated) { _securityDefinition.VolumeStep = v.Volume.GetDecimalInfo().EffectiveScale.GetPriceStep(); _volumeStepUpdated = true; } } } _lastDepthDate = message.LocalTime.Date; return(ProcessQuoteChange(message.LocalTime, message.ServerTime, message.Bids.ToArray(), message.Asks.ToArray())); }
/// <summary> /// To process the message, containing data on order book. /// </summary> /// <param name="quoteMsg">The message, containing data on order book.</param> public void ProcessQuotes(QuoteChangeMessage quoteMsg) { var ask = quoteMsg.GetBestAsk(); AskPrice = ask != null ? ask.Price : 0; var bid = quoteMsg.GetBestBid(); BidPrice = bid != null ? bid.Price : 0; _unrealizedPnL = null; }
private void ProcessQuotesMessage(Security security, QuoteChangeMessage message, bool fromLevel1) { if (MarketDepthChanged != null || MarketDepthsChanged != null) { var marketDepth = GetMarketDepth(security); message.ToMarketDepth(marketDepth, GetSecurity); if (_subscriptionManager.IsFilteredMarketDepthRegistered(security)) GetFilteredMarketDepthInfo(security).Process(message); RaiseMarketDepthChanged(marketDepth); } else { lock (_marketDepths.SyncRoot) { var info = _marketDepths.SafeAdd(security, key => new MarketDepthInfo(EntityFactory.CreateMarketDepth(security))); info.First.LocalTime = message.LocalTime; info.First.LastChangeTime = message.ServerTime; info.Second = message.Bids; info.Third = message.Asks; } } var bestBid = message.GetBestBid(); var bestAsk = message.GetBestAsk(); if (!fromLevel1 && (bestBid != null || bestAsk != null)) { var values = GetSecurityValues(security); var changes = new List<KeyValuePair<Level1Fields, object>>(4); lock (values.SyncRoot) { if (bestBid != null) { values[(int)Level1Fields.BestBidPrice] = bestBid.Price; changes.Add(new KeyValuePair<Level1Fields, object>(Level1Fields.BestBidPrice, bestBid.Price)); if (bestBid.Volume != 0) { values[(int)Level1Fields.BestBidVolume] = bestBid.Volume; changes.Add(new KeyValuePair<Level1Fields, object>(Level1Fields.BestBidVolume, bestBid.Volume)); } } if (bestAsk != null) { values[(int)Level1Fields.BestAskPrice] = bestAsk.Price; changes.Add(new KeyValuePair<Level1Fields, object>(Level1Fields.BestAskPrice, bestAsk.Price)); if (bestAsk.Volume != 0) { values[(int)Level1Fields.BestAskVolume] = bestAsk.Volume; changes.Add(new KeyValuePair<Level1Fields, object>(Level1Fields.BestAskVolume, bestAsk.Volume)); } } } RaiseValuesChanged(security, changes, message.ServerTime, message.LocalTime); } if (UpdateSecurityLastQuotes) { var updated = false; if (!fromLevel1 || bestBid != null) { updated = true; security.BestBid = bestBid == null ? null : new Quote(security, bestBid.Price, bestBid.Volume, Sides.Buy); } if (!fromLevel1 || bestAsk != null) { updated = true; security.BestAsk = bestAsk == null ? null : new Quote(security, bestAsk.Price, bestAsk.Volume, Sides.Sell); } if (updated) { security.LocalTime = message.LocalTime; security.LastChangeTime = message.ServerTime; RaiseSecurityChanged(security); // стаканы по ALL обновляют BestXXX по конкретным инструментам if (security.Board.Code == AssociatedBoardCode) { var changedSecurities = new Dictionary<Security, RefPair<bool, bool>>(); foreach (var bid in message.Bids) { if (bid.BoardCode.IsEmpty()) continue; var innerSecurity = GetSecurity(new SecurityId { SecurityCode = security.Code, BoardCode = bid.BoardCode }); var info = changedSecurities.SafeAdd(innerSecurity); if (info.First) continue; info.First = true; innerSecurity.BestBid = new Quote(innerSecurity, bid.Price, bid.Volume, Sides.Buy); innerSecurity.LocalTime = message.LocalTime; innerSecurity.LastChangeTime = message.ServerTime; } foreach (var ask in message.Asks) { if (ask.BoardCode.IsEmpty()) continue; var innerSecurity = GetSecurity(new SecurityId { SecurityCode = security.Code, BoardCode = ask.BoardCode }); var info = changedSecurities.SafeAdd(innerSecurity); if (info.Second) continue; info.Second = true; innerSecurity.BestAsk = new Quote(innerSecurity, ask.Price, ask.Volume, Sides.Sell); innerSecurity.LocalTime = message.LocalTime; innerSecurity.LastChangeTime = message.ServerTime; } RaiseSecuritiesChanged(changedSecurities.Keys.ToArray()); } } } if (CreateDepthFromLevel1) GetBuilder(message.SecurityId).HasDepth = true; CreateAssociatedSecurityQuotes(message); }