Thank you for the great order book implementation. Recently I have been playing with it to compare different approaches to order book creations with NYSE Arca data. Your approach was generic, so I have been tempted to adapt it.
At this moment I've been mostly interested in having L1 updates (specifically top of the book for each instrument). Implemented auxilliary structure to track if each update price changed worked just fine, e.g.:
uint64_t orig_best_ask_price = 0;
uint64_t orig_best_ask_vol = 0;
if (orderBookPtr->best_ask())
{
orig_best_ask_price = orderBookPtr->best_ask()->Price;
orig_best_ask_vol = orderbookPtr->best_ask()->TotalVolume;
}
// Perform order book calculation e.g.
market.AddOrder(Order::Limit(1234567890, GetInstId("WMT"), OrderSide::SELL, 120000, 25);
if (orig_best_ask_price != orderBookPtr->best_ask()->Price || orig_best_ask_vol != orderBookPtr->best_ask()->TotalVolume)
{
// Update top of book
}
`
The code above works perfectly at least for the following updates: 'Modify', 'Execute', 'Delete', 'Add', and 'Replace'. However, it introduces latency, each check is required if the top of the book has been changed.
Is this expected?
I have made some modifications for this code to work for L1 top of book updates and the moment still under testing (and at this moment isn't best effort implementation). But I was more wondering, if I missing a point here what is meant by 'LevelUpdate' member 'top', is it for multiple level depth? It's not clear though, how to know which LevelUpdate 'top' is relating to during callback... Or is it not expected & simply a bug?
To replicate a problem (currently only using NYSE data):
class NYSEMarketHandler: public MarketHandler
{
public:
void onUpdateOrderBook(const OrderBook& orderBook, bool isTop) override
{
if (isTop)
{
static int num{ 0 };
printf("top of the book update! %i\n", num++);
}
}
};
Hi chronoxor,
Thank you for the great order book implementation. Recently I have been playing with it to compare different approaches to order book creations with NYSE Arca data. Your approach was generic, so I have been tempted to adapt it. At this moment I've been mostly interested in having L1 updates (specifically top of the book for each instrument). Implemented auxilliary structure to track if each update price changed worked just fine, e.g.:
` OrderBook orderBookPtr = (OrderBook)market.GetOrderBook(instrument_id);
uint64_t orig_best_ask_price = 0; uint64_t orig_best_ask_vol = 0; if (orderBookPtr->best_ask()) { orig_best_ask_price = orderBookPtr->best_ask()->Price; orig_best_ask_vol = orderbookPtr->best_ask()->TotalVolume; } // Perform order book calculation e.g. market.AddOrder(Order::Limit(1234567890, GetInstId("WMT"), OrderSide::SELL, 120000, 25);
if (orig_best_ask_price != orderBookPtr->best_ask()->Price || orig_best_ask_vol != orderBookPtr->best_ask()->TotalVolume) { // Update top of book } ` The code above works perfectly at least for the following updates: 'Modify', 'Execute', 'Delete', 'Add', and 'Replace'. However, it introduces latency, each check is required if the top of the book has been changed.
Investigating code by examples, I've been intrigued, if MarketHandler interface could be used to make code faster - https://github.com/chronoxor/CppTrader/blob/master/include/trader/matching/market_handler.h
However testing code, looks like 'UpdateLevel' https://github.com/chronoxor/CppTrader/blob/5cd250a65a9b09740e8830ed80d19a82d147d677/source/trader/matching/market_manager.cpp#L1741 method 'LevelUpdate' structure 'Top' member is 'true' for non L1 data. Specifically looking at: https://github.com/chronoxor/CppTrader/blob/5cd250a65a9b09740e8830ed80d19a82d147d677/source/trader/matching/order_book.cpp#L215 Any Level, which to be deleted (even not top of the book), if there is no prices at this level will make 'Top' member as 'true'.
Is this expected? I have made some modifications for this code to work for L1 top of book updates and the moment still under testing (and at this moment isn't best effort implementation). But I was more wondering, if I missing a point here what is meant by 'LevelUpdate' member 'top', is it for multiple level depth? It's not clear though, how to know which LevelUpdate 'top' is relating to during callback... Or is it not expected & simply a bug?
To replicate a problem (currently only using NYSE data):
`
ifndef NYSEFH_SRC_ORDERBOOK_MARKET_HANDLER_EXAMPLE
define NYSEFH_SRC_ORDERBOOK_MARKET_HANDLER_EXAMPLE
include
include \<string>
include "trader/matching/market_manager.h"
using namespace CppTrader::Matching;
class NYSEMarketHandler: public MarketHandler { public: void onUpdateOrderBook(const OrderBook& orderBook, bool isTop) override { if (isTop) { static int num{ 0 }; printf("top of the book update! %i\n", num++); } } };
NYSEMarketHandler marketHandler; MarketManager market(marketHandler);
int main() { printf("Start cpptrader testing\n"); std::unordered_map<std::string, uint32_t> instKey { { "WMT", 1 } };
}
endif
`
Output:
Expected output:
Thanks