30template <
typename MsgType>
31auto fill_common(Row& row,
const MsgType& msg) ->
void {
32 row.message_type = msg.message_type;
33 row.timestamp = msg.timestamp;
34 row.stock_locate = msg.stock_locate;
35 row.tracking_number = msg.tracking_number;
39auto field(
const std::string& value) -> std::string {
43 if (value.find(
',') != std::string::npos) {
44 return std::format(
"\"{}\"", value);
49auto build_row(
const Message& message) -> Row {
51 std::visit([&row](
const auto& msg) { fill_common(row, msg); }, message);
53 if (
const auto* add = std::get_if<AddOrderMessage>(&message)) {
55 row.reference_number = std::to_string(add->order_reference_number);
56 row.side = add->buy_sell_indicator;
57 row.shares = std::to_string(add->shares);
59 }
else if (
const auto* add_mpid = std::get_if<AddOrderMPIDAttributionMessage>(&message)) {
61 row.reference_number = std::to_string(add_mpid->order_reference_number);
62 row.side = add_mpid->buy_sell_indicator;
63 row.shares = std::to_string(add_mpid->shares);
65 row.extra = std::format(
"mpid={}",
to_string(add_mpid->attribution, 4));
66 }
else if (
const auto* exec = std::get_if<OrderExecutedMessage>(&message)) {
67 row.reference_number = std::to_string(exec->order_reference_number);
68 row.shares = std::to_string(exec->executed_shares);
69 row.match_number = std::to_string(exec->match_number);
70 }
else if (
const auto* exec_px = std::get_if<OrderExecutedWithPriceMessage>(&message)) {
71 row.reference_number = std::to_string(exec_px->order_reference_number);
72 row.shares = std::to_string(exec_px->executed_shares);
74 row.match_number = std::to_string(exec_px->match_number);
75 row.printable = exec_px->printable;
76 }
else if (
const auto* cancel = std::get_if<OrderCancelMessage>(&message)) {
77 row.reference_number = std::to_string(cancel->order_reference_number);
78 row.shares = std::to_string(cancel->cancelled_shares);
79 }
else if (
const auto* del = std::get_if<OrderDeleteMessage>(&message)) {
80 row.reference_number = std::to_string(del->order_reference_number);
81 }
else if (
const auto* replace = std::get_if<OrderReplaceMessage>(&message)) {
82 row.reference_number = std::to_string(replace->new_order_reference_number);
83 row.shares = std::to_string(replace->shares);
85 row.extra = std::format(
"orig={}", replace->original_order_reference_number);
86 }
else if (
const auto* trade = std::get_if<NonCrossTradeMessage>(&message)) {
88 row.reference_number = std::to_string(trade->order_reference_number);
89 row.side = trade->buy_sell_indicator;
90 row.shares = std::to_string(trade->shares);
92 row.match_number = std::to_string(trade->match_number);
93 }
else if (
const auto* cross = std::get_if<CrossTradeMessage>(&message)) {
95 row.shares = std::to_string(cross->shares);
97 row.match_number = std::to_string(cross->match_number);
98 row.extra = std::format(
"cross={}", cross->cross_type);
99 }
else if (
const auto* event = std::get_if<SystemEventMessage>(&message)) {
100 row.extra = std::format(
"event={}", event->event_code);
101 }
else if (
const auto* directory = std::get_if<StockDirectoryMessage>(&message)) {
103 row.extra = std::format(
"category={}", directory->market_category);
109auto char_field(
char value) -> std::string {
110 return value ==
'\0' ? std::string {} : std::string {value};
117 m_out <<
"message_type,timestamp,stock_locate,tracking_number,symbol,reference_number,"
118 "side,shares,price,match_number,printable,extra\n";
123 const Row row = build_row(message);
124 m_out << std::format(
125 "{},{},{},{},{},{},{},{},{},{},{},{}\n",
131 row.reference_number,
132 char_field(row.side),
136 char_field(row.printable),
auto to_string() const -> std::string
The price as a fixed-precision decimal string.
auto write(const Message &message) -> void override
Writes one message as a CSV row.
auto flush() -> void override
Flushes the underlying stream.
CsvSink(std::ostream &out, bool write_header=true)
Constructs a sink writing to out, emitting the header row unless write_header is false (useful when a...
std::string reference_number
std::uint16_t tracking_number
std::uint16_t stock_locate
CSV output sink for parsed ITCH messages.
std::variant< SystemEventMessage, StockDirectoryMessage, StockTradingActionMessage, RegSHOMessage, MarketParticipantPositionMessage, MWCBDeclineLevelMessage, MWCBStatusMessage, IPOQuotingPeriodUpdateMessage, LULDAuctionCollarMessage, OperationalHaltMessage, AddOrderMessage, AddOrderMPIDAttributionMessage, OrderExecutedMessage, OrderExecutedWithPriceMessage, OrderCancelMessage, OrderDeleteMessage, OrderReplaceMessage, NonCrossTradeMessage, CrossTradeMessage, BrokenTradeMessage, NOIIMessage, RetailPriceImprovementIndicatorMessage, DLCRMessage > Message
A variant able to hold any one of the ITCH 5.0 message structs.
BasicPrice< std::uint32_t, 4 > StandardPrice
Price scale for every ITCH price field except MWCB decline levels.
auto to_string(const char *source, size_t size) -> std::string
Converts a fixed-width character array to a string, trimming trailing spaces and NUL characters.
Strongly typed, fixed-point price representation for ITCH price fields.