From 11cb3a34bf67ee0f999e20e7bae58f3d3365e69f Mon Sep 17 00:00:00 2001 From: Ding Ye Date: Tue, 5 Nov 2019 16:47:31 +1100 Subject: [PATCH 1/2] Use static dispatch for onMessage() methods in ITCHHandler class. --- examples/itch_handler.cpp | 48 +- examples/market_manager.cpp | 19 +- .../trader/providers/nasdaq/itch_handler.h | 58 +- .../trader/providers/nasdaq/itch_handler.inl | 639 +++++++++++++++++- performance/itch_handler.cpp | 47 +- performance/market_manager.cpp | 47 +- performance/market_manager_optimized.cpp | 47 +- .../market_manager_optimized_aggressive.cpp | 47 +- performance/matching_engine.cpp | 47 +- .../trader/providers/nasdaq/itch_handler.cpp | 625 ----------------- tests/test_itch_handler.cpp | 47 +- tests/test_market_manager.cpp | 47 +- 12 files changed, 867 insertions(+), 851 deletions(-) delete mode 100644 source/trader/providers/nasdaq/itch_handler.cpp diff --git a/examples/itch_handler.cpp b/examples/itch_handler.cpp index 2c3d622f..ae45aa89 100644 --- a/examples/itch_handler.cpp +++ b/examples/itch_handler.cpp @@ -14,31 +14,31 @@ using namespace CppTrader::ITCH; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { -protected: - bool onMessage(const SystemEventMessage& message) override { return OutputMessage(message); } - bool onMessage(const StockDirectoryMessage& message) override { return OutputMessage(message); } - bool onMessage(const StockTradingActionMessage& message) override { return OutputMessage(message); } - bool onMessage(const RegSHOMessage& message) override { return OutputMessage(message); } - bool onMessage(const MarketParticipantPositionMessage& message) override { return OutputMessage(message); } - bool onMessage(const MWCBDeclineMessage& message) override { return OutputMessage(message); } - bool onMessage(const MWCBStatusMessage& message) override { return OutputMessage(message); } - bool onMessage(const IPOQuotingMessage& message) override { return OutputMessage(message); } - bool onMessage(const AddOrderMessage& message) override { return OutputMessage(message); } - bool onMessage(const AddOrderMPIDMessage& message) override { return OutputMessage(message); } - bool onMessage(const OrderExecutedMessage& message) override { return OutputMessage(message); } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { return OutputMessage(message); } - bool onMessage(const OrderCancelMessage& message) override { return OutputMessage(message); } - bool onMessage(const OrderDeleteMessage& message) override { return OutputMessage(message); } - bool onMessage(const OrderReplaceMessage& message) override { return OutputMessage(message); } - bool onMessage(const TradeMessage& message) override { return OutputMessage(message); } - bool onMessage(const CrossTradeMessage& message) override { return OutputMessage(message); } - bool onMessage(const BrokenTradeMessage& message) override { return OutputMessage(message); } - bool onMessage(const NOIIMessage& message) override { return OutputMessage(message); } - bool onMessage(const RPIIMessage& message) override { return OutputMessage(message); } - bool onMessage(const LULDAuctionCollarMessage& message) override { return OutputMessage(message); } - bool onMessage(const UnknownMessage& message) override { return OutputMessage(message); } +public: + bool onMessage(const SystemEventMessage& message) { return OutputMessage(message); } + bool onMessage(const StockDirectoryMessage& message) { return OutputMessage(message); } + bool onMessage(const StockTradingActionMessage& message) { return OutputMessage(message); } + bool onMessage(const RegSHOMessage& message) { return OutputMessage(message); } + bool onMessage(const MarketParticipantPositionMessage& message) { return OutputMessage(message); } + bool onMessage(const MWCBDeclineMessage& message) { return OutputMessage(message); } + bool onMessage(const MWCBStatusMessage& message) { return OutputMessage(message); } + bool onMessage(const IPOQuotingMessage& message) { return OutputMessage(message); } + bool onMessage(const AddOrderMessage& message) { return OutputMessage(message); } + bool onMessage(const AddOrderMPIDMessage& message) { return OutputMessage(message); } + bool onMessage(const OrderExecutedMessage& message) { return OutputMessage(message); } + bool onMessage(const OrderExecutedWithPriceMessage& message) { return OutputMessage(message); } + bool onMessage(const OrderCancelMessage& message) { return OutputMessage(message); } + bool onMessage(const OrderDeleteMessage& message) { return OutputMessage(message); } + bool onMessage(const OrderReplaceMessage& message) { return OutputMessage(message); } + bool onMessage(const TradeMessage& message) { return OutputMessage(message); } + bool onMessage(const CrossTradeMessage& message) { return OutputMessage(message); } + bool onMessage(const BrokenTradeMessage& message) { return OutputMessage(message); } + bool onMessage(const NOIIMessage& message) { return OutputMessage(message); } + bool onMessage(const RPIIMessage& message) { return OutputMessage(message); } + bool onMessage(const LULDAuctionCollarMessage& message) { return OutputMessage(message); } + bool onMessage(const UnknownMessage& message) { return OutputMessage(message); } private: template diff --git a/examples/market_manager.cpp b/examples/market_manager.cpp index 93ac768a..12dc158a 100644 --- a/examples/market_manager.cpp +++ b/examples/market_manager.cpp @@ -49,13 +49,12 @@ class MyMarketHandler : public MarketHandler { std::cout << "Execute order: " << order << " with price " << price << " and quantity " << quantity << std::endl; } }; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: MyITCHHandler(MarketManager& market) : _market(market) {} -protected: - bool onMessage(const StockDirectoryMessage& message) override + bool onMessage(const StockDirectoryMessage& message) { Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); @@ -63,43 +62,43 @@ class MyITCHHandler : public ITCHHandler return true; } - bool onMessage(const AddOrderMessage& message) override + bool onMessage(const AddOrderMessage& message) { _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const AddOrderMPIDMessage& message) override + bool onMessage(const AddOrderMPIDMessage& message) { _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const OrderExecutedMessage& message) override + bool onMessage(const OrderExecutedMessage& message) { _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override + bool onMessage(const OrderExecutedWithPriceMessage& message) { _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } - bool onMessage(const OrderCancelMessage& message) override + bool onMessage(const OrderCancelMessage& message) { _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } - bool onMessage(const OrderDeleteMessage& message) override + bool onMessage(const OrderDeleteMessage& message) { _market.DeleteOrder(message.OrderReferenceNumber); return true; } - bool onMessage(const OrderReplaceMessage& message) override + bool onMessage(const OrderReplaceMessage& message) { _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; diff --git a/include/trader/providers/nasdaq/itch_handler.h b/include/trader/providers/nasdaq/itch_handler.h index 4e06052f..e65e42a7 100644 --- a/include/trader/providers/nasdaq/itch_handler.h +++ b/include/trader/providers/nasdaq/itch_handler.h @@ -13,6 +13,7 @@ #include "utility/iostream.h" #include +#include namespace CppTrader { @@ -384,6 +385,7 @@ struct UnknownMessage Not thread-safe. */ +template class ITCHHandler { public: @@ -415,33 +417,45 @@ class ITCHHandler protected: // Message handlers - virtual bool onMessage(const SystemEventMessage& message) { return true; } - virtual bool onMessage(const StockDirectoryMessage& message) { return true; } - virtual bool onMessage(const StockTradingActionMessage& message) { return true; } - virtual bool onMessage(const RegSHOMessage& message) { return true; } - virtual bool onMessage(const MarketParticipantPositionMessage& message) { return true; } - virtual bool onMessage(const MWCBDeclineMessage& message) { return true; } - virtual bool onMessage(const MWCBStatusMessage& message) { return true; } - virtual bool onMessage(const IPOQuotingMessage& message) { return true; } - virtual bool onMessage(const AddOrderMessage& message) { return true; } - virtual bool onMessage(const AddOrderMPIDMessage& message) { return true; } - virtual bool onMessage(const OrderExecutedMessage& message) { return true; } - virtual bool onMessage(const OrderExecutedWithPriceMessage& message) { return true; } - virtual bool onMessage(const OrderCancelMessage& message) { return true; } - virtual bool onMessage(const OrderDeleteMessage& message) { return true; } - virtual bool onMessage(const OrderReplaceMessage& message) { return true; } - virtual bool onMessage(const TradeMessage& message) { return true; } - virtual bool onMessage(const CrossTradeMessage& message) { return true; } - virtual bool onMessage(const BrokenTradeMessage& message) { return true; } - virtual bool onMessage(const NOIIMessage& message) { return true; } - virtual bool onMessage(const RPIIMessage& message) { return true; } - virtual bool onMessage(const LULDAuctionCollarMessage& message) { return true; } - virtual bool onMessage(const UnknownMessage& message) { return true; } + bool onMessage(const SystemEventMessage& message) { return true; } + bool onMessage(const StockDirectoryMessage& message) { return true; } + bool onMessage(const StockTradingActionMessage& message) { return true; } + bool onMessage(const RegSHOMessage& message) { return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { return true; } + bool onMessage(const MWCBDeclineMessage& message) { return true; } + bool onMessage(const MWCBStatusMessage& message) { return true; } + bool onMessage(const IPOQuotingMessage& message) { return true; } + bool onMessage(const AddOrderMessage& message) { return true; } + bool onMessage(const AddOrderMPIDMessage& message) { return true; } + bool onMessage(const OrderExecutedMessage& message) { return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { return true; } + bool onMessage(const OrderCancelMessage& message) { return true; } + bool onMessage(const OrderDeleteMessage& message) { return true; } + bool onMessage(const OrderReplaceMessage& message) { return true; } + bool onMessage(const TradeMessage& message) { return true; } + bool onMessage(const CrossTradeMessage& message) { return true; } + bool onMessage(const BrokenTradeMessage& message) { return true; } + bool onMessage(const NOIIMessage& message) { return true; } + bool onMessage(const RPIIMessage& message) { return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { return true; } + bool onMessage(const UnknownMessage& message) { return true; } private: size_t _size; std::vector _cache; + template + using OnMessageType = decltype(std::declval().onMessage(std::declval()...)); + + //! Call the corresponding message handler if defined (as a public method) in SubClass, otherwise the default implementation. + template + bool onMessageWrapper(T&& message) { + if constexpr (std::experimental::is_detected::value) + return static_cast(this)->onMessage(std::forward(message)); + else + return onMessage(std::forward(message)); + } + bool ProcessSystemEventMessage(void* buffer, size_t size); bool ProcessStockDirectoryMessage(void* buffer, size_t size); bool ProcessStockTradingActionMessage(void* buffer, size_t size); diff --git a/include/trader/providers/nasdaq/itch_handler.inl b/include/trader/providers/nasdaq/itch_handler.inl index 65642321..6d2720f9 100644 --- a/include/trader/providers/nasdaq/itch_handler.inl +++ b/include/trader/providers/nasdaq/itch_handler.inl @@ -335,15 +335,650 @@ inline TOutputStream& operator<<(TOutputStream& stream, const UnknownMessage& me return stream; } +template +bool ITCHHandler::Process(void* buffer, size_t size) +{ + size_t index = 0; + uint8_t* data = (uint8_t*)buffer; + + while (index < size) + { + if (_size == 0) + { + size_t remaining = size - index; + + // Collect message size into the cache + if (((_cache.size() == 0) && (remaining < 3)) || (_cache.size() == 1)) + { + _cache.push_back(data[index++]); + continue; + } + + // Read a new message size + uint16_t message_size; + if (_cache.empty()) + { + // Read the message size directly from the input buffer + index += CppCommon::Endian::ReadBigEndian(&data[index], message_size); + } + else + { + // Read the message size from the cache + CppCommon::Endian::ReadBigEndian(_cache.data(), message_size); + + // Clear the cache + _cache.clear(); + } + _size = message_size; + } + + // Read a new message + if (_size > 0) + { + size_t remaining = size - index; + + // Complete or place the message into the cache + if (!_cache.empty()) + { + size_t tail = _size - _cache.size(); + if (tail > remaining) + tail = remaining; + _cache.insert(_cache.end(), &data[index], &data[index + tail]); + index += tail; + if (_cache.size() < _size) + continue; + } + else if (_size > remaining) + { + _cache.reserve(_size); + _cache.insert(_cache.end(), &data[index], &data[index + remaining]); + index += remaining; + continue; + } + + // Process the current message + if (_cache.empty()) + { + // Process the current message size directly from the input buffer + if (!ProcessMessage(&data[index], _size)) + return false; + index += _size; + } + else + { + // Process the current message size directly from the cache + if (!ProcessMessage(_cache.data(), _size)) + return false; + + // Clear the cache + _cache.clear(); + } + + // Process the next message + _size = 0; + } + } + + return true; +} + +template +bool ITCHHandler::ProcessMessage(void* buffer, size_t size) +{ + // Message is empty + if (size == 0) + return false; + + uint8_t* data = (uint8_t*)buffer; + + switch (*data) + { + case 'S': + return ProcessSystemEventMessage(data, size); + case 'R': + return ProcessStockDirectoryMessage(data, size); + case 'H': + return ProcessStockTradingActionMessage(data, size); + case 'Y': + return ProcessRegSHOMessage(data, size); + case 'L': + return ProcessMarketParticipantPositionMessage(data, size); + case 'V': + return ProcessMWCBDeclineMessage(data, size); + case 'W': + return ProcessMWCBStatusMessage(data, size); + case 'K': + return ProcessIPOQuotingMessage(data, size); + case 'A': + return ProcessAddOrderMessage(data, size); + case 'F': + return ProcessAddOrderMPIDMessage(data, size); + case 'E': + return ProcessOrderExecutedMessage(data, size); + case 'C': + return ProcessOrderExecutedWithPriceMessage(data, size); + case 'X': + return ProcessOrderCancelMessage(data, size); + case 'D': + return ProcessOrderDeleteMessage(data, size); + case 'U': + return ProcessOrderReplaceMessage(data, size); + case 'P': + return ProcessTradeMessage(data, size); + case 'Q': + return ProcessCrossTradeMessage(data, size); + case 'B': + return ProcessBrokenTradeMessage(data, size); + case 'I': + return ProcessNOIIMessage(data, size); + case 'N': + return ProcessRPIIMessage(data, size); + case 'J': + return ProcessLULDAuctionCollarMessage(data, size); + default: + return ProcessUnknownMessage(data, size); + } +} + +template +void ITCHHandler::Reset() +{ + _size = 0; + _cache.clear(); +} + +template +bool ITCHHandler::ProcessSystemEventMessage(void* buffer, size_t size) +{ + assert((size == 12) && "Invalid size of the ITCH message type 'S'"); + if (size != 12) + return false; + + uint8_t* data = (uint8_t*)buffer; + + SystemEventMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + message.EventCode = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessStockDirectoryMessage(void* buffer, size_t size) +{ + assert((size == 39) && "Invalid size of the ITCH message type 'R'"); + if (size != 39) + return false; + + uint8_t* data = (uint8_t*)buffer; + + StockDirectoryMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.Stock); + message.MarketCategory = *data++; + message.FinancialStatusIndicator = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.RoundLotSize); + message.RoundLotsOnly = *data++; + message.IssueClassification = *data++; + data += ReadString(data, message.IssueSubType); + message.Authenticity = *data++; + message.ShortSaleThresholdIndicator = *data++; + message.IPOFlag = *data++; + message.LULDReferencePriceTier = *data++; + message.ETPFlag = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.ETPLeverageFactor); + message.InverseIndicator = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessStockTradingActionMessage(void* buffer, size_t size) +{ + assert((size == 25) && "Invalid size of the ITCH message type 'H'"); + if (size != 25) + return false; + + uint8_t* data = (uint8_t*)buffer; + + StockTradingActionMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.Stock); + message.TradingState = *data++; + message.Reserved = *data++; + message.Reason = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessRegSHOMessage(void* buffer, size_t size) +{ + assert((size == 20) && "Invalid size of the ITCH message type 'Y'"); + if (size != 20) + return false; + + uint8_t* data = (uint8_t*)buffer; + + RegSHOMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.Stock); + message.RegSHOAction = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessMarketParticipantPositionMessage(void* buffer, size_t size) +{ + assert((size == 26) && "Invalid size of the ITCH message type 'L'"); + if (size != 26) + return false; + + uint8_t* data = (uint8_t*)buffer; + + MarketParticipantPositionMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.MPID); + data += ReadString(data, message.Stock); + message.PrimaryMarketMaker = *data++; + message.MarketMakerMode = *data++; + message.MarketParticipantState = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessMWCBDeclineMessage(void* buffer, size_t size) +{ + assert((size == 35) && "Invalid size of the ITCH message type 'V'"); + if (size != 35) + return false; + + uint8_t* data = (uint8_t*)buffer; + + MWCBDeclineMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.Level1); + data += CppCommon::Endian::ReadBigEndian(data, message.Level2); + data += CppCommon::Endian::ReadBigEndian(data, message.Level3); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessMWCBStatusMessage(void* buffer, size_t size) +{ + assert((size == 12) && "Invalid size of the ITCH message type 'W'"); + if (size != 12) + return false; + + uint8_t* data = (uint8_t*)buffer; + + MWCBStatusMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + message.BreachedLevel = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessIPOQuotingMessage(void* buffer, size_t size) +{ + assert((size == 28) && "Invalid size of the ITCH message type 'W'"); + if (size != 28) + return false; + + uint8_t* data = (uint8_t*)buffer; + + IPOQuotingMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.IPOReleaseTime); + message.IPOReleaseQualifier = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.IPOPrice); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessAddOrderMessage(void* buffer, size_t size) +{ + assert((size == 36) && "Invalid size of the ITCH message type 'A'"); + if (size != 36) + return false; + + uint8_t* data = (uint8_t*)buffer; + + AddOrderMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + message.BuySellIndicator = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.Shares); + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.Price); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessAddOrderMPIDMessage(void* buffer, size_t size) +{ + assert((size == 40) && "Invalid size of the ITCH message type 'F'"); + if (size != 40) + return false; + + uint8_t* data = (uint8_t*)buffer; + + AddOrderMPIDMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + message.BuySellIndicator = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.Shares); + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.Price); + message.Attribution = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessOrderExecutedMessage(void* buffer, size_t size) +{ + assert((size == 31) && "Invalid size of the ITCH message type 'E'"); + if (size != 31) + return false; + + uint8_t* data = (uint8_t*)buffer; + + OrderExecutedMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + data += CppCommon::Endian::ReadBigEndian(data, message.ExecutedShares); + data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessOrderExecutedWithPriceMessage(void* buffer, size_t size) +{ + assert((size == 36) && "Invalid size of the ITCH message type 'C'"); + if (size != 36) + return false; + + uint8_t* data = (uint8_t*)buffer; + + OrderExecutedWithPriceMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + data += CppCommon::Endian::ReadBigEndian(data, message.ExecutedShares); + data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); + message.Printable = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.ExecutionPrice); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessOrderCancelMessage(void* buffer, size_t size) +{ + assert((size == 23) && "Invalid size of the ITCH message type 'X'"); + if (size != 23) + return false; + + uint8_t* data = (uint8_t*)buffer; + + OrderCancelMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + data += CppCommon::Endian::ReadBigEndian(data, message.CanceledShares); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessOrderDeleteMessage(void* buffer, size_t size) +{ + assert((size == 19) && "Invalid size of the ITCH message type 'D'"); + if (size != 19) + return false; + + uint8_t* data = (uint8_t*)buffer; + + OrderDeleteMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessOrderReplaceMessage(void* buffer, size_t size) +{ + assert((size == 35) && "Invalid size of the ITCH message type 'U'"); + if (size != 35) + return false; + + uint8_t* data = (uint8_t*)buffer; + + OrderReplaceMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OriginalOrderReferenceNumber); + data += CppCommon::Endian::ReadBigEndian(data, message.NewOrderReferenceNumber); + data += CppCommon::Endian::ReadBigEndian(data, message.Shares); + data += CppCommon::Endian::ReadBigEndian(data, message.Price); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessTradeMessage(void* buffer, size_t size) +{ + assert((size == 44) && "Invalid size of the ITCH message type 'P'"); + if (size != 44) + return false; + + uint8_t* data = (uint8_t*)buffer; + + TradeMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); + message.BuySellIndicator = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.Shares); + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.Price); + data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessCrossTradeMessage(void* buffer, size_t size) +{ + assert((size == 40) && "Invalid size of the ITCH message type 'Q'"); + if (size != 40) + return false; + + uint8_t* data = (uint8_t*)buffer; + + CrossTradeMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.Shares); + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.CrossPrice); + data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); + message.CrossType = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessBrokenTradeMessage(void* buffer, size_t size) +{ + assert((size == 19) && "Invalid size of the ITCH message type 'B'"); + if (size != 19) + return false; + + uint8_t* data = (uint8_t*)buffer; + + BrokenTradeMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessNOIIMessage(void* buffer, size_t size) +{ + assert((size == 50) && "Invalid size of the ITCH message type 'I'"); + if (size != 50) + return false; + + uint8_t* data = (uint8_t*)buffer; + + NOIIMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += CppCommon::Endian::ReadBigEndian(data, message.PairedShares); + data += CppCommon::Endian::ReadBigEndian(data, message.ImbalanceShares); + message.ImbalanceDirection = *data++; + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.FarPrice); + data += CppCommon::Endian::ReadBigEndian(data, message.NearPrice); + data += CppCommon::Endian::ReadBigEndian(data, message.CurrentReferencePrice); + message.CrossType = *data++; + message.PriceVariationIndicator = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessRPIIMessage(void* buffer, size_t size) +{ + assert((size == 20) && "Invalid size of the ITCH message type 'N'"); + if (size != 20) + return false; + + uint8_t* data = (uint8_t*)buffer; + + RPIIMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.Stock); + message.InterestFlag = *data++; + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessLULDAuctionCollarMessage(void* buffer, size_t size) +{ + assert((size == 35) && "Invalid size of the ITCH message type 'J'"); + if (size != 35) + return false; + + uint8_t* data = (uint8_t*)buffer; + + LULDAuctionCollarMessage message; + message.Type = *data++; + data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); + data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); + data += ReadTimestamp(data, message.Timestamp); + data += ReadString(data, message.Stock); + data += CppCommon::Endian::ReadBigEndian(data, message.AuctionCollarReferencePrice); + data += CppCommon::Endian::ReadBigEndian(data, message.UpperAuctionCollarPrice); + data += CppCommon::Endian::ReadBigEndian(data, message.LowerAuctionCollarPrice); + data += CppCommon::Endian::ReadBigEndian(data, message.AuctionCollarExtension); + + return onMessageWrapper(message); +} + +template +bool ITCHHandler::ProcessUnknownMessage(void* buffer, size_t size) +{ + assert((size > 0) && "Invalid size of the unknown ITCH message!"); + if (size == 0) + return false; + + uint8_t* data = (uint8_t*)buffer; + + UnknownMessage message; + message.Type = *data; + + return onMessageWrapper(message); +} + +template template -inline size_t ITCHHandler::ReadString(const void* buffer, char (&str)[N]) +inline size_t ITCHHandler::ReadString(const void* buffer, char (&str)[N]) { std::memcpy(str, buffer, N); return N; } -inline size_t ITCHHandler::ReadTimestamp(const void* buffer, uint64_t& value) +template +inline size_t ITCHHandler::ReadTimestamp(const void* buffer, uint64_t& value) { if (CppCommon::Endian::IsBigEndian()) { diff --git a/performance/itch_handler.cpp b/performance/itch_handler.cpp index 6d27dca5..90a333e8 100644 --- a/performance/itch_handler.cpp +++ b/performance/itch_handler.cpp @@ -14,7 +14,7 @@ using namespace CppCommon; using namespace CppTrader::ITCH; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: MyITCHHandler() @@ -25,29 +25,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: size_t _messages; diff --git a/performance/market_manager.cpp b/performance/market_manager.cpp index f1b022d2..de4ad560 100644 --- a/performance/market_manager.cpp +++ b/performance/market_manager.cpp @@ -76,7 +76,7 @@ class MyMarketHandler : public MarketHandler size_t _execute_orders; }; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: MyITCHHandler(MarketManager& market) @@ -88,29 +88,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: MarketManager& _market; diff --git a/performance/market_manager_optimized.cpp b/performance/market_manager_optimized.cpp index 59be449d..d6845ff8 100644 --- a/performance/market_manager_optimized.cpp +++ b/performance/market_manager_optimized.cpp @@ -663,7 +663,7 @@ class MarketManagerOptimized } }; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: explicit MyITCHHandler(MarketManagerOptimized& market) @@ -675,29 +675,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares); return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares); return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares); return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares); return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: MarketManagerOptimized& _market; diff --git a/performance/market_manager_optimized_aggressive.cpp b/performance/market_manager_optimized_aggressive.cpp index f2a9c50f..ffe8506e 100644 --- a/performance/market_manager_optimized_aggressive.cpp +++ b/performance/market_manager_optimized_aggressive.cpp @@ -360,7 +360,7 @@ class MarketManagerOptimized std::vector _orders; }; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: explicit MyITCHHandler(MarketManagerOptimized& market) @@ -372,29 +372,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; _market.AddOrderBook(message.StockLocate); return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? (int32_t)message.Price : -((int32_t)message.Price), message.Shares); return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? (int32_t)message.Price : -((int32_t)message.Price), message.Shares); return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; _market.AddOrderBook(message.StockLocate); return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? (int32_t)message.Price : -((int32_t)message.Price), message.Shares); return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; _market.AddOrder(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? (int32_t)message.Price : -((int32_t)message.Price), message.Shares); return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: MarketManagerOptimized& _market; diff --git a/performance/matching_engine.cpp b/performance/matching_engine.cpp index 36e233f5..1919ad7c 100644 --- a/performance/matching_engine.cpp +++ b/performance/matching_engine.cpp @@ -76,7 +76,7 @@ class MyMarketHandler : public MarketHandler size_t _execute_orders; }; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: explicit MyITCHHandler(MarketManager& market) @@ -88,29 +88,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: MarketManager& _market; diff --git a/source/trader/providers/nasdaq/itch_handler.cpp b/source/trader/providers/nasdaq/itch_handler.cpp deleted file mode 100644 index b65bd7b1..00000000 --- a/source/trader/providers/nasdaq/itch_handler.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/*! - \file itch_handler.cpp - \brief NASDAQ ITCH handler implementation - \author Ivan Shynkarenka - \date 21.07.2017 - \copyright MIT License -*/ - -#include "trader/providers/nasdaq/itch_handler.h" - -#include - -namespace CppTrader { -namespace ITCH { - -bool ITCHHandler::Process(void* buffer, size_t size) -{ - size_t index = 0; - uint8_t* data = (uint8_t*)buffer; - - while (index < size) - { - if (_size == 0) - { - size_t remaining = size - index; - - // Collect message size into the cache - if (((_cache.size() == 0) && (remaining < 3)) || (_cache.size() == 1)) - { - _cache.push_back(data[index++]); - continue; - } - - // Read a new message size - uint16_t message_size; - if (_cache.empty()) - { - // Read the message size directly from the input buffer - index += CppCommon::Endian::ReadBigEndian(&data[index], message_size); - } - else - { - // Read the message size from the cache - CppCommon::Endian::ReadBigEndian(_cache.data(), message_size); - - // Clear the cache - _cache.clear(); - } - _size = message_size; - } - - // Read a new message - if (_size > 0) - { - size_t remaining = size - index; - - // Complete or place the message into the cache - if (!_cache.empty()) - { - size_t tail = _size - _cache.size(); - if (tail > remaining) - tail = remaining; - _cache.insert(_cache.end(), &data[index], &data[index + tail]); - index += tail; - if (_cache.size() < _size) - continue; - } - else if (_size > remaining) - { - _cache.reserve(_size); - _cache.insert(_cache.end(), &data[index], &data[index + remaining]); - index += remaining; - continue; - } - - // Process the current message - if (_cache.empty()) - { - // Process the current message size directly from the input buffer - if (!ProcessMessage(&data[index], _size)) - return false; - index += _size; - } - else - { - // Process the current message size directly from the cache - if (!ProcessMessage(_cache.data(), _size)) - return false; - - // Clear the cache - _cache.clear(); - } - - // Process the next message - _size = 0; - } - } - - return true; -} - -bool ITCHHandler::ProcessMessage(void* buffer, size_t size) -{ - // Message is empty - if (size == 0) - return false; - - uint8_t* data = (uint8_t*)buffer; - - switch (*data) - { - case 'S': - return ProcessSystemEventMessage(data, size); - case 'R': - return ProcessStockDirectoryMessage(data, size); - case 'H': - return ProcessStockTradingActionMessage(data, size); - case 'Y': - return ProcessRegSHOMessage(data, size); - case 'L': - return ProcessMarketParticipantPositionMessage(data, size); - case 'V': - return ProcessMWCBDeclineMessage(data, size); - case 'W': - return ProcessMWCBStatusMessage(data, size); - case 'K': - return ProcessIPOQuotingMessage(data, size); - case 'A': - return ProcessAddOrderMessage(data, size); - case 'F': - return ProcessAddOrderMPIDMessage(data, size); - case 'E': - return ProcessOrderExecutedMessage(data, size); - case 'C': - return ProcessOrderExecutedWithPriceMessage(data, size); - case 'X': - return ProcessOrderCancelMessage(data, size); - case 'D': - return ProcessOrderDeleteMessage(data, size); - case 'U': - return ProcessOrderReplaceMessage(data, size); - case 'P': - return ProcessTradeMessage(data, size); - case 'Q': - return ProcessCrossTradeMessage(data, size); - case 'B': - return ProcessBrokenTradeMessage(data, size); - case 'I': - return ProcessNOIIMessage(data, size); - case 'N': - return ProcessRPIIMessage(data, size); - case 'J': - return ProcessLULDAuctionCollarMessage(data, size); - default: - return ProcessUnknownMessage(data, size); - } -} - -void ITCHHandler::Reset() -{ - _size = 0; - _cache.clear(); -} - -bool ITCHHandler::ProcessSystemEventMessage(void* buffer, size_t size) -{ - assert((size == 12) && "Invalid size of the ITCH message type 'S'"); - if (size != 12) - return false; - - uint8_t* data = (uint8_t*)buffer; - - SystemEventMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - message.EventCode = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessStockDirectoryMessage(void* buffer, size_t size) -{ - assert((size == 39) && "Invalid size of the ITCH message type 'R'"); - if (size != 39) - return false; - - uint8_t* data = (uint8_t*)buffer; - - StockDirectoryMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.Stock); - message.MarketCategory = *data++; - message.FinancialStatusIndicator = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.RoundLotSize); - message.RoundLotsOnly = *data++; - message.IssueClassification = *data++; - data += ReadString(data, message.IssueSubType); - message.Authenticity = *data++; - message.ShortSaleThresholdIndicator = *data++; - message.IPOFlag = *data++; - message.LULDReferencePriceTier = *data++; - message.ETPFlag = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.ETPLeverageFactor); - message.InverseIndicator = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessStockTradingActionMessage(void* buffer, size_t size) -{ - assert((size == 25) && "Invalid size of the ITCH message type 'H'"); - if (size != 25) - return false; - - uint8_t* data = (uint8_t*)buffer; - - StockTradingActionMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.Stock); - message.TradingState = *data++; - message.Reserved = *data++; - message.Reason = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessRegSHOMessage(void* buffer, size_t size) -{ - assert((size == 20) && "Invalid size of the ITCH message type 'Y'"); - if (size != 20) - return false; - - uint8_t* data = (uint8_t*)buffer; - - RegSHOMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.Stock); - message.RegSHOAction = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessMarketParticipantPositionMessage(void* buffer, size_t size) -{ - assert((size == 26) && "Invalid size of the ITCH message type 'L'"); - if (size != 26) - return false; - - uint8_t* data = (uint8_t*)buffer; - - MarketParticipantPositionMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.MPID); - data += ReadString(data, message.Stock); - message.PrimaryMarketMaker = *data++; - message.MarketMakerMode = *data++; - message.MarketParticipantState = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessMWCBDeclineMessage(void* buffer, size_t size) -{ - assert((size == 35) && "Invalid size of the ITCH message type 'V'"); - if (size != 35) - return false; - - uint8_t* data = (uint8_t*)buffer; - - MWCBDeclineMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.Level1); - data += CppCommon::Endian::ReadBigEndian(data, message.Level2); - data += CppCommon::Endian::ReadBigEndian(data, message.Level3); - - return onMessage(message); -} - -bool ITCHHandler::ProcessMWCBStatusMessage(void* buffer, size_t size) -{ - assert((size == 12) && "Invalid size of the ITCH message type 'W'"); - if (size != 12) - return false; - - uint8_t* data = (uint8_t*)buffer; - - MWCBStatusMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - message.BreachedLevel = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessIPOQuotingMessage(void* buffer, size_t size) -{ - assert((size == 28) && "Invalid size of the ITCH message type 'W'"); - if (size != 28) - return false; - - uint8_t* data = (uint8_t*)buffer; - - IPOQuotingMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.IPOReleaseTime); - message.IPOReleaseQualifier = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.IPOPrice); - - return onMessage(message); -} - -bool ITCHHandler::ProcessAddOrderMessage(void* buffer, size_t size) -{ - assert((size == 36) && "Invalid size of the ITCH message type 'A'"); - if (size != 36) - return false; - - uint8_t* data = (uint8_t*)buffer; - - AddOrderMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - message.BuySellIndicator = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.Shares); - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.Price); - - return onMessage(message); -} - -bool ITCHHandler::ProcessAddOrderMPIDMessage(void* buffer, size_t size) -{ - assert((size == 40) && "Invalid size of the ITCH message type 'F'"); - if (size != 40) - return false; - - uint8_t* data = (uint8_t*)buffer; - - AddOrderMPIDMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - message.BuySellIndicator = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.Shares); - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.Price); - message.Attribution = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessOrderExecutedMessage(void* buffer, size_t size) -{ - assert((size == 31) && "Invalid size of the ITCH message type 'E'"); - if (size != 31) - return false; - - uint8_t* data = (uint8_t*)buffer; - - OrderExecutedMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - data += CppCommon::Endian::ReadBigEndian(data, message.ExecutedShares); - data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); - - return onMessage(message); -} - -bool ITCHHandler::ProcessOrderExecutedWithPriceMessage(void* buffer, size_t size) -{ - assert((size == 36) && "Invalid size of the ITCH message type 'C'"); - if (size != 36) - return false; - - uint8_t* data = (uint8_t*)buffer; - - OrderExecutedWithPriceMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - data += CppCommon::Endian::ReadBigEndian(data, message.ExecutedShares); - data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); - message.Printable = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.ExecutionPrice); - - return onMessage(message); -} - -bool ITCHHandler::ProcessOrderCancelMessage(void* buffer, size_t size) -{ - assert((size == 23) && "Invalid size of the ITCH message type 'X'"); - if (size != 23) - return false; - - uint8_t* data = (uint8_t*)buffer; - - OrderCancelMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - data += CppCommon::Endian::ReadBigEndian(data, message.CanceledShares); - - return onMessage(message); -} - -bool ITCHHandler::ProcessOrderDeleteMessage(void* buffer, size_t size) -{ - assert((size == 19) && "Invalid size of the ITCH message type 'D'"); - if (size != 19) - return false; - - uint8_t* data = (uint8_t*)buffer; - - OrderDeleteMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - - return onMessage(message); -} - -bool ITCHHandler::ProcessOrderReplaceMessage(void* buffer, size_t size) -{ - assert((size == 35) && "Invalid size of the ITCH message type 'U'"); - if (size != 35) - return false; - - uint8_t* data = (uint8_t*)buffer; - - OrderReplaceMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OriginalOrderReferenceNumber); - data += CppCommon::Endian::ReadBigEndian(data, message.NewOrderReferenceNumber); - data += CppCommon::Endian::ReadBigEndian(data, message.Shares); - data += CppCommon::Endian::ReadBigEndian(data, message.Price); - - return onMessage(message); -} - -bool ITCHHandler::ProcessTradeMessage(void* buffer, size_t size) -{ - assert((size == 44) && "Invalid size of the ITCH message type 'P'"); - if (size != 44) - return false; - - uint8_t* data = (uint8_t*)buffer; - - TradeMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber); - message.BuySellIndicator = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.Shares); - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.Price); - data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); - - return onMessage(message); -} - -bool ITCHHandler::ProcessCrossTradeMessage(void* buffer, size_t size) -{ - assert((size == 40) && "Invalid size of the ITCH message type 'Q'"); - if (size != 40) - return false; - - uint8_t* data = (uint8_t*)buffer; - - CrossTradeMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.Shares); - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.CrossPrice); - data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); - message.CrossType = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessBrokenTradeMessage(void* buffer, size_t size) -{ - assert((size == 19) && "Invalid size of the ITCH message type 'B'"); - if (size != 19) - return false; - - uint8_t* data = (uint8_t*)buffer; - - BrokenTradeMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber); - - return onMessage(message); -} - -bool ITCHHandler::ProcessNOIIMessage(void* buffer, size_t size) -{ - assert((size == 50) && "Invalid size of the ITCH message type 'I'"); - if (size != 50) - return false; - - uint8_t* data = (uint8_t*)buffer; - - NOIIMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += CppCommon::Endian::ReadBigEndian(data, message.PairedShares); - data += CppCommon::Endian::ReadBigEndian(data, message.ImbalanceShares); - message.ImbalanceDirection = *data++; - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.FarPrice); - data += CppCommon::Endian::ReadBigEndian(data, message.NearPrice); - data += CppCommon::Endian::ReadBigEndian(data, message.CurrentReferencePrice); - message.CrossType = *data++; - message.PriceVariationIndicator = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessRPIIMessage(void* buffer, size_t size) -{ - assert((size == 20) && "Invalid size of the ITCH message type 'N'"); - if (size != 20) - return false; - - uint8_t* data = (uint8_t*)buffer; - - RPIIMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.Stock); - message.InterestFlag = *data++; - - return onMessage(message); -} - -bool ITCHHandler::ProcessLULDAuctionCollarMessage(void* buffer, size_t size) -{ - assert((size == 35) && "Invalid size of the ITCH message type 'J'"); - if (size != 35) - return false; - - uint8_t* data = (uint8_t*)buffer; - - LULDAuctionCollarMessage message; - message.Type = *data++; - data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate); - data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber); - data += ReadTimestamp(data, message.Timestamp); - data += ReadString(data, message.Stock); - data += CppCommon::Endian::ReadBigEndian(data, message.AuctionCollarReferencePrice); - data += CppCommon::Endian::ReadBigEndian(data, message.UpperAuctionCollarPrice); - data += CppCommon::Endian::ReadBigEndian(data, message.LowerAuctionCollarPrice); - data += CppCommon::Endian::ReadBigEndian(data, message.AuctionCollarExtension); - - return onMessage(message); -} - -bool ITCHHandler::ProcessUnknownMessage(void* buffer, size_t size) -{ - assert((size > 0) && "Invalid size of the unknown ITCH message!"); - if (size == 0) - return false; - - uint8_t* data = (uint8_t*)buffer; - - UnknownMessage message; - message.Type = *data; - - return onMessage(message); -} - -} // namespace ITCH -} // namespace CppTrader diff --git a/tests/test_itch_handler.cpp b/tests/test_itch_handler.cpp index 82d84d48..1f35993b 100644 --- a/tests/test_itch_handler.cpp +++ b/tests/test_itch_handler.cpp @@ -13,7 +13,7 @@ using namespace CppTrader::ITCH; namespace { -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: MyITCHHandler() @@ -24,29 +24,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: size_t _messages; diff --git a/tests/test_market_manager.cpp b/tests/test_market_manager.cpp index 139965fa..fbd52070 100644 --- a/tests/test_market_manager.cpp +++ b/tests/test_market_manager.cpp @@ -77,7 +77,7 @@ class MyMarketHandler : public MarketHandler size_t _execute_orders; }; -class MyITCHHandler : public ITCHHandler +class MyITCHHandler : public ITCHHandler { public: explicit MyITCHHandler(MarketManager& market) @@ -89,29 +89,28 @@ class MyITCHHandler : public ITCHHandler size_t messages() const { return _messages; } size_t errors() const { return _errors; } -protected: - bool onMessage(const SystemEventMessage& message) override { ++_messages; return true; } - bool onMessage(const StockDirectoryMessage& message) override { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } - bool onMessage(const StockTradingActionMessage& message) override { ++_messages; return true; } - bool onMessage(const RegSHOMessage& message) override { ++_messages; return true; } - bool onMessage(const MarketParticipantPositionMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBDeclineMessage& message) override { ++_messages; return true; } - bool onMessage(const MWCBStatusMessage& message) override { ++_messages; return true; } - bool onMessage(const IPOQuotingMessage& message) override { ++_messages; return true; } - bool onMessage(const AddOrderMessage& message) override { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const AddOrderMPIDMessage& message) override { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } - bool onMessage(const OrderExecutedMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } - bool onMessage(const OrderExecutedWithPriceMessage& message) override { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } - bool onMessage(const OrderCancelMessage& message) override { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } - bool onMessage(const OrderDeleteMessage& message) override { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } - bool onMessage(const OrderReplaceMessage& message) override { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } - bool onMessage(const TradeMessage& message) override { ++_messages; return true; } - bool onMessage(const CrossTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const BrokenTradeMessage& message) override { ++_messages; return true; } - bool onMessage(const NOIIMessage& message) override { ++_messages; return true; } - bool onMessage(const RPIIMessage& message) override { ++_messages; return true; } - bool onMessage(const LULDAuctionCollarMessage& message) override { ++_messages; return true; } - bool onMessage(const UnknownMessage& message) override { ++_errors; return true; } + bool onMessage(const SystemEventMessage& message) { ++_messages; return true; } + bool onMessage(const StockDirectoryMessage& message) { ++_messages; Symbol symbol(message.StockLocate, message.Stock); _market.AddSymbol(symbol); _market.AddOrderBook(symbol); return true; } + bool onMessage(const StockTradingActionMessage& message) { ++_messages; return true; } + bool onMessage(const RegSHOMessage& message) { ++_messages; return true; } + bool onMessage(const MarketParticipantPositionMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBDeclineMessage& message) { ++_messages; return true; } + bool onMessage(const MWCBStatusMessage& message) { ++_messages; return true; } + bool onMessage(const IPOQuotingMessage& message) { ++_messages; return true; } + bool onMessage(const AddOrderMessage& message) { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } + bool onMessage(const AddOrderMPIDMessage& message) { ++_messages; _market.AddOrder(Order::Limit(message.OrderReferenceNumber, message.StockLocate, (message.BuySellIndicator == 'B') ? OrderSide::BUY : OrderSide::SELL, message.Price, message.Shares)); return true; } + bool onMessage(const OrderExecutedMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutedShares); return true; } + bool onMessage(const OrderExecutedWithPriceMessage& message) { ++_messages; _market.ExecuteOrder(message.OrderReferenceNumber, message.ExecutionPrice, message.ExecutedShares); return true; } + bool onMessage(const OrderCancelMessage& message) { ++_messages; _market.ReduceOrder(message.OrderReferenceNumber, message.CanceledShares); return true; } + bool onMessage(const OrderDeleteMessage& message) { ++_messages; _market.DeleteOrder(message.OrderReferenceNumber); return true; } + bool onMessage(const OrderReplaceMessage& message) { ++_messages; _market.ReplaceOrder(message.OriginalOrderReferenceNumber, message.NewOrderReferenceNumber, message.Price, message.Shares); return true; } + bool onMessage(const TradeMessage& message) { ++_messages; return true; } + bool onMessage(const CrossTradeMessage& message) { ++_messages; return true; } + bool onMessage(const BrokenTradeMessage& message) { ++_messages; return true; } + bool onMessage(const NOIIMessage& message) { ++_messages; return true; } + bool onMessage(const RPIIMessage& message) { ++_messages; return true; } + bool onMessage(const LULDAuctionCollarMessage& message) { ++_messages; return true; } + bool onMessage(const UnknownMessage& message) { ++_errors; return true; } private: MarketManager& _market; From 369410e52df04d0124634896d876ff51aaf67e29 Mon Sep 17 00:00:00 2001 From: Ding Ye Date: Wed, 6 Nov 2019 16:45:44 +1100 Subject: [PATCH 2/2] Include cassert header. --- include/trader/providers/nasdaq/itch_handler.inl | 1 + 1 file changed, 1 insertion(+) diff --git a/include/trader/providers/nasdaq/itch_handler.inl b/include/trader/providers/nasdaq/itch_handler.inl index 6d2720f9..1fefc59b 100644 --- a/include/trader/providers/nasdaq/itch_handler.inl +++ b/include/trader/providers/nasdaq/itch_handler.inl @@ -5,6 +5,7 @@ \date 21.07.2017 \copyright MIT License */ +#include namespace CppTrader { namespace ITCH {