chronoxor / CppTrader

High performance components for building Trading Platform such as ultra fast matching engine, order book processor
MIT License
833 stars 254 forks source link

UpdateLevel query (bug?) #38

Open skuch89 opened 10 months ago

skuch89 commented 10 months ago

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 } };

Symbol sym{ instKey["WMT"], "WMT" };
market.AddSymbol(sym);
market.AddOrderBook(sym);
printf("in here#1\n");
market.AddOrder(Order::Limit(1234567890, instKey["WMT"], OrderSide::SELL, 23000, 15));
printf("in here#2\n");
market.AddOrder(Order::Limit(1234567891, instKey["WMT"], OrderSide::SELL, 25000, 25));
printf("in here#3\n");
market.ExecuteOrder(1234567891, 25);
printf("in here#4\n");
printf("Finish cpptrader testing\n");
return EXIT_SUCCESS;

}

endif

`

Output:

Start cpptrader testing in here#1 top of the book update! 0 in here#2 in here#3 top of the book update! 1 in here#4 Finish cpptrader testing

Expected output:

Start cpptrader testing in here#1 top of the book update! 0 in here#2 in here#3 in here#4 Finish cpptrader testing

Thanks