Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions Brokerages/LevelOneOrderBook/LevelOneMarketData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ public LevelOneMarketData(Symbol symbol)
/// <param name="bidSize">The size available at the best bid.</param>
/// <param name="askPrice">The best ask price.</param>
/// <param name="askSize">The size available at the best ask.</param>
public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? bidSize, decimal? askPrice, decimal? askSize)
/// <param name="saleCondition">The sale condition string.</param>
/// <param name="exchange">The exchange identifier.</param>
public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? bidSize, decimal? askPrice, decimal? askSize, string saleCondition, string exchange)
{
if (!IsValidTimestamp(quoteDateTimeUtc))
{
Expand Down Expand Up @@ -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));
}
}

/// <summary>
/// Updates the best bid and ask prices and sizes.
/// Constructs and publishes a quote <see cref="Tick"/> to the <see cref="IDataAggregator"/>.
/// </summary>
/// <param name="quoteDateTimeUtc">The UTC timestamp when the quote was received.</param>
/// <param name="bidPrice">The best bid price.</param>
/// <param name="bidSize">The size available at the best bid.</param>
/// <param name="askPrice">The best ask price.</param>
/// <param name="askSize">The size available at the best ask.</param>
public void UpdateQuote(DateTime? quoteDateTimeUtc, decimal? bidPrice, decimal? bidSize, decimal? askPrice, decimal? askSize)
{
UpdateQuote(quoteDateTimeUtc, bidPrice, bidSize, askPrice, askSize, string.Empty, string.Empty);
}

/// <summary>
/// Updates the last trade price and size.
/// Constructs and publishes a trade <see cref="Tick"/> to the <see cref="Data.IDataAggregator"/>.
Expand Down Expand Up @@ -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);

Expand Down
35 changes: 35 additions & 0 deletions Tests/Brokerages/LevelOneOrderBook/LevelOneMarketDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

using System;
using NUnit.Framework;
using QuantConnect.Data.Market;
using QuantConnect.Brokerages.LevelOneOrderBook;

namespace QuantConnect.Tests.Brokerages.LevelOneOrderBook
Expand Down Expand Up @@ -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)
Expand Down
Loading