diff --git a/Brokerages/LevelOneOrderBook/LevelOneMarketData.cs b/Brokerages/LevelOneOrderBook/LevelOneMarketData.cs index 0225bdd2040a..8cb097268d80 100644 --- a/Brokerages/LevelOneOrderBook/LevelOneMarketData.cs +++ b/Brokerages/LevelOneOrderBook/LevelOneMarketData.cs @@ -111,7 +111,9 @@ public LevelOneMarketData(Symbol symbol) /// The size available at the best bid. /// The best ask price. /// The size available at the best ask. - public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? bidSize, decimal? askPrice, decimal? askSize) + /// The sale condition string. + /// The exchange identifier. + public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? bidSize, decimal? askPrice, decimal? askSize, string saleCondition, string exchange) { if (!IsValidTimestamp(quoteDateTimeUtc)) { @@ -141,12 +143,26 @@ public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? if (isBidUpdated || isAskUpdated) { - var lastQuoteTick = new Tick(quoteDateTimeUtc.Value.ConvertFromUtc(SymbolDateTimeZone), Symbol, BestBidSize, BestBidPrice, BestAskSize, BestAskPrice); + var lastQuoteTick = new Tick(quoteDateTimeUtc.Value.ConvertFromUtc(SymbolDateTimeZone), Symbol, saleCondition, exchange.GetPrimaryExchange(Symbol.SecurityType), BestBidSize, BestBidPrice, BestAskSize, BestAskPrice); BaseDataReceived?.Invoke(this, new(lastQuoteTick)); } } + /// + /// Updates the best bid and ask prices and sizes. + /// Constructs and publishes a quote to the . + /// + /// The UTC timestamp when the quote was received. + /// The best bid price. + /// The size available at the best bid. + /// The best ask price. + /// The size available at the best ask. + public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? bidSize, decimal? askPrice, decimal? askSize) + { + UpdateQuote(quoteDateTimeUtc, bidPrice, bidSize, askPrice, askSize, string.Empty, string.Empty); + } + /// /// Updates the last trade price and size. /// Constructs and publishes a trade to the . @@ -175,7 +191,7 @@ public void UpdateLastTrade(DateTime? tradeDateTimeUtc, decimal? lastQuantity, d tradeDateTimeUtc.Value.ConvertFromUtc(SymbolDateTimeZone), Symbol, saleCondition, - exchange, + exchange.GetPrimaryExchange(Symbol.SecurityType), LastTradeSize, LastTradePrice); diff --git a/Tests/Brokerages/LevelOneOrderBook/LevelOneMarketDataTests.cs b/Tests/Brokerages/LevelOneOrderBook/LevelOneMarketDataTests.cs index 30fa8f216da8..acfe04474aa1 100644 --- a/Tests/Brokerages/LevelOneOrderBook/LevelOneMarketDataTests.cs +++ b/Tests/Brokerages/LevelOneOrderBook/LevelOneMarketDataTests.cs @@ -15,6 +15,7 @@ using System; using NUnit.Framework; +using QuantConnect.Data.Market; using QuantConnect.Brokerages.LevelOneOrderBook; namespace QuantConnect.Tests.Brokerages.LevelOneOrderBook @@ -176,6 +177,40 @@ public void UpdateQuoteShouldIgnoreZeroSizeUpdatesCorrectly(bool ignoreZeroSizeU } } + [TestCase("T", "NASDAQ")] + [TestCase("Z", "BATS")] + [TestCase("N", "NYSE")] + [TestCase("P", "ARCA")] + [TestCase("", "")] + [TestCase(null, "")] + public void LevelOneMarketDataShouldMapExchangeStringOnPublishedTicks(string exchange, string expectedExchange) + { + var levelOneMarketData = new LevelOneMarketData(_aapl); + var quoteTick = default(Tick); + var tradeTick = default(Tick); + + levelOneMarketData.BaseDataReceived += (_, e) => + { + var tick = (Tick)e.BaseData; + if (tick.TickType == TickType.Quote) + { + quoteTick = tick; + } + else if (tick.TickType == TickType.Trade) + { + tradeTick = tick; + } + }; + + levelOneMarketData.UpdateQuote(_mockDateTime, 1, 1, 1, 1, saleCondition: string.Empty, exchange: exchange); + levelOneMarketData.UpdateLastTrade(_mockDateTime, 1, 1, exchange: exchange); + + Assert.IsNotNull(quoteTick, "Expected BaseDataReceived to publish a quote tick."); + Assert.IsNotNull(tradeTick, "Expected BaseDataReceived to publish a trade tick."); + Assert.AreEqual(expectedExchange, quoteTick.Exchange, "Quote tick exchange mismatch."); + Assert.AreEqual(expectedExchange, tradeTick.Exchange, "Trade tick exchange mismatch."); + } + [TestCase(true, 0, 2)] [TestCase(false, 0, 2)] public void UpdateLastTradeShouldIgnoreZeroSizeUpdatesCorrectly(bool ignoreZeroSizeUpdates, decimal? lastQuantity, decimal? lastPrice)