CppTrader 1.0.5.0
C++ Trader
Loading...
Searching...
No Matches
itch_handler.cpp
Go to the documentation of this file.
1
10
11#include <cassert>
12
13namespace CppTrader {
14namespace ITCH {
15
16bool ITCHHandler::Process(void* buffer, size_t size)
17{
18 size_t index = 0;
19 uint8_t* data = (uint8_t*)buffer;
20
21 while (index < size)
22 {
23 if (_size == 0)
24 {
25 size_t remaining = size - index;
26
27 // Collect message size into the cache
28 if (((_cache.size() == 0) && (remaining < 3)) || (_cache.size() == 1))
29 {
30 _cache.push_back(data[index++]);
31 continue;
32 }
33
34 // Read a new message size
35 uint16_t message_size;
36 if (_cache.empty())
37 {
38 // Read the message size directly from the input buffer
39 index += CppCommon::Endian::ReadBigEndian(&data[index], message_size);
40 }
41 else
42 {
43 // Read the message size from the cache
44 CppCommon::Endian::ReadBigEndian(_cache.data(), message_size);
45
46 // Clear the cache
47 _cache.clear();
48 }
49 _size = message_size;
50 }
51
52 // Read a new message
53 if (_size > 0)
54 {
55 size_t remaining = size - index;
56
57 // Complete or place the message into the cache
58 if (!_cache.empty())
59 {
60 size_t tail = _size - _cache.size();
61 if (tail > remaining)
62 tail = remaining;
63 _cache.insert(_cache.end(), &data[index], &data[index + tail]);
64 index += tail;
65 if (_cache.size() < _size)
66 continue;
67 }
68 else if (_size > remaining)
69 {
70 _cache.reserve(_size);
71 _cache.insert(_cache.end(), &data[index], &data[index + remaining]);
72 index += remaining;
73 continue;
74 }
75
76 // Process the current message
77 if (_cache.empty())
78 {
79 // Process the current message size directly from the input buffer
80 if (!ProcessMessage(&data[index], _size))
81 return false;
82 index += _size;
83 }
84 else
85 {
86 // Process the current message size directly from the cache
87 if (!ProcessMessage(_cache.data(), _size))
88 return false;
89
90 // Clear the cache
91 _cache.clear();
92 }
93
94 // Process the next message
95 _size = 0;
96 }
97 }
98
99 return true;
100}
101
102bool ITCHHandler::ProcessMessage(void* buffer, size_t size)
103{
104 // Message is empty
105 if (size == 0)
106 return false;
107
108 uint8_t* data = (uint8_t*)buffer;
109
110 switch (*data)
111 {
112 case 'S':
113 return ProcessSystemEventMessage(data, size);
114 case 'R':
115 return ProcessStockDirectoryMessage(data, size);
116 case 'H':
117 return ProcessStockTradingActionMessage(data, size);
118 case 'Y':
119 return ProcessRegSHOMessage(data, size);
120 case 'L':
121 return ProcessMarketParticipantPositionMessage(data, size);
122 case 'V':
123 return ProcessMWCBDeclineMessage(data, size);
124 case 'W':
125 return ProcessMWCBStatusMessage(data, size);
126 case 'K':
127 return ProcessIPOQuotingMessage(data, size);
128 case 'A':
129 return ProcessAddOrderMessage(data, size);
130 case 'F':
131 return ProcessAddOrderMPIDMessage(data, size);
132 case 'E':
133 return ProcessOrderExecutedMessage(data, size);
134 case 'C':
135 return ProcessOrderExecutedWithPriceMessage(data, size);
136 case 'X':
137 return ProcessOrderCancelMessage(data, size);
138 case 'D':
139 return ProcessOrderDeleteMessage(data, size);
140 case 'U':
141 return ProcessOrderReplaceMessage(data, size);
142 case 'P':
143 return ProcessTradeMessage(data, size);
144 case 'Q':
145 return ProcessCrossTradeMessage(data, size);
146 case 'B':
147 return ProcessBrokenTradeMessage(data, size);
148 case 'I':
149 return ProcessNOIIMessage(data, size);
150 case 'N':
151 return ProcessRPIIMessage(data, size);
152 case 'J':
153 return ProcessLULDAuctionCollarMessage(data, size);
154 default:
155 return ProcessUnknownMessage(data, size);
156 }
157}
158
160{
161 _size = 0;
162 _cache.clear();
163}
164
165bool ITCHHandler::ProcessSystemEventMessage(void* buffer, size_t size)
166{
167 assert((size == 12) && "Invalid size of the ITCH message type 'S'");
168 if (size != 12)
169 return false;
170
171 uint8_t* data = (uint8_t*)buffer;
172
173 SystemEventMessage message;
174 message.Type = *data++;
175 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
176 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
177 data += ReadTimestamp(data, message.Timestamp);
178 message.EventCode = *data++;
179
180 return onMessage(message);
181}
182
183bool ITCHHandler::ProcessStockDirectoryMessage(void* buffer, size_t size)
184{
185 assert((size == 39) && "Invalid size of the ITCH message type 'R'");
186 if (size != 39)
187 return false;
188
189 uint8_t* data = (uint8_t*)buffer;
190
191 StockDirectoryMessage message;
192 message.Type = *data++;
193 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
194 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
195 data += ReadTimestamp(data, message.Timestamp);
196 data += ReadString(data, message.Stock);
197 message.MarketCategory = *data++;
198 message.FinancialStatusIndicator = *data++;
199 data += CppCommon::Endian::ReadBigEndian(data, message.RoundLotSize);
200 message.RoundLotsOnly = *data++;
201 message.IssueClassification = *data++;
202 data += ReadString(data, message.IssueSubType);
203 message.Authenticity = *data++;
204 message.ShortSaleThresholdIndicator = *data++;
205 message.IPOFlag = *data++;
206 message.LULDReferencePriceTier = *data++;
207 message.ETPFlag = *data++;
208 data += CppCommon::Endian::ReadBigEndian(data, message.ETPLeverageFactor);
209 message.InverseIndicator = *data++;
210
211 return onMessage(message);
212}
213
214bool ITCHHandler::ProcessStockTradingActionMessage(void* buffer, size_t size)
215{
216 assert((size == 25) && "Invalid size of the ITCH message type 'H'");
217 if (size != 25)
218 return false;
219
220 uint8_t* data = (uint8_t*)buffer;
221
222 StockTradingActionMessage message;
223 message.Type = *data++;
224 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
225 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
226 data += ReadTimestamp(data, message.Timestamp);
227 data += ReadString(data, message.Stock);
228 message.TradingState = *data++;
229 message.Reserved = *data++;
230 message.Reason = *data++;
231
232 return onMessage(message);
233}
234
235bool ITCHHandler::ProcessRegSHOMessage(void* buffer, size_t size)
236{
237 assert((size == 20) && "Invalid size of the ITCH message type 'Y'");
238 if (size != 20)
239 return false;
240
241 uint8_t* data = (uint8_t*)buffer;
242
243 RegSHOMessage message;
244 message.Type = *data++;
245 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
246 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
247 data += ReadTimestamp(data, message.Timestamp);
248 data += ReadString(data, message.Stock);
249 message.RegSHOAction = *data++;
250
251 return onMessage(message);
252}
253
254bool ITCHHandler::ProcessMarketParticipantPositionMessage(void* buffer, size_t size)
255{
256 assert((size == 26) && "Invalid size of the ITCH message type 'L'");
257 if (size != 26)
258 return false;
259
260 uint8_t* data = (uint8_t*)buffer;
261
262 MarketParticipantPositionMessage message;
263 message.Type = *data++;
264 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
265 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
266 data += ReadTimestamp(data, message.Timestamp);
267 data += ReadString(data, message.MPID);
268 data += ReadString(data, message.Stock);
269 message.PrimaryMarketMaker = *data++;
270 message.MarketMakerMode = *data++;
271 message.MarketParticipantState = *data++;
272
273 return onMessage(message);
274}
275
276bool ITCHHandler::ProcessMWCBDeclineMessage(void* buffer, size_t size)
277{
278 assert((size == 35) && "Invalid size of the ITCH message type 'V'");
279 if (size != 35)
280 return false;
281
282 uint8_t* data = (uint8_t*)buffer;
283
284 MWCBDeclineMessage message;
285 message.Type = *data++;
286 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
287 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
288 data += ReadTimestamp(data, message.Timestamp);
289 data += CppCommon::Endian::ReadBigEndian(data, message.Level1);
290 data += CppCommon::Endian::ReadBigEndian(data, message.Level2);
291 data += CppCommon::Endian::ReadBigEndian(data, message.Level3);
292
293 return onMessage(message);
294}
295
296bool ITCHHandler::ProcessMWCBStatusMessage(void* buffer, size_t size)
297{
298 assert((size == 12) && "Invalid size of the ITCH message type 'W'");
299 if (size != 12)
300 return false;
301
302 uint8_t* data = (uint8_t*)buffer;
303
304 MWCBStatusMessage message;
305 message.Type = *data++;
306 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
307 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
308 data += ReadTimestamp(data, message.Timestamp);
309 message.BreachedLevel = *data++;
310
311 return onMessage(message);
312}
313
314bool ITCHHandler::ProcessIPOQuotingMessage(void* buffer, size_t size)
315{
316 assert((size == 28) && "Invalid size of the ITCH message type 'W'");
317 if (size != 28)
318 return false;
319
320 uint8_t* data = (uint8_t*)buffer;
321
322 IPOQuotingMessage message;
323 message.Type = *data++;
324 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
325 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
326 data += ReadTimestamp(data, message.Timestamp);
327 data += ReadString(data, message.Stock);
328 data += CppCommon::Endian::ReadBigEndian(data, message.IPOReleaseTime);
329 message.IPOReleaseQualifier = *data++;
330 data += CppCommon::Endian::ReadBigEndian(data, message.IPOPrice);
331
332 return onMessage(message);
333}
334
335bool ITCHHandler::ProcessAddOrderMessage(void* buffer, size_t size)
336{
337 assert((size == 36) && "Invalid size of the ITCH message type 'A'");
338 if (size != 36)
339 return false;
340
341 uint8_t* data = (uint8_t*)buffer;
342
343 AddOrderMessage message;
344 message.Type = *data++;
345 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
346 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
347 data += ReadTimestamp(data, message.Timestamp);
348 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
349 message.BuySellIndicator = *data++;
350 data += CppCommon::Endian::ReadBigEndian(data, message.Shares);
351 data += ReadString(data, message.Stock);
352 data += CppCommon::Endian::ReadBigEndian(data, message.Price);
353
354 return onMessage(message);
355}
356
357bool ITCHHandler::ProcessAddOrderMPIDMessage(void* buffer, size_t size)
358{
359 assert((size == 40) && "Invalid size of the ITCH message type 'F'");
360 if (size != 40)
361 return false;
362
363 uint8_t* data = (uint8_t*)buffer;
364
365 AddOrderMPIDMessage message;
366 message.Type = *data++;
367 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
368 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
369 data += ReadTimestamp(data, message.Timestamp);
370 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
371 message.BuySellIndicator = *data++;
372 data += CppCommon::Endian::ReadBigEndian(data, message.Shares);
373 data += ReadString(data, message.Stock);
374 data += CppCommon::Endian::ReadBigEndian(data, message.Price);
375 message.Attribution = *data++;
376
377 return onMessage(message);
378}
379
380bool ITCHHandler::ProcessOrderExecutedMessage(void* buffer, size_t size)
381{
382 assert((size == 31) && "Invalid size of the ITCH message type 'E'");
383 if (size != 31)
384 return false;
385
386 uint8_t* data = (uint8_t*)buffer;
387
388 OrderExecutedMessage message;
389 message.Type = *data++;
390 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
391 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
392 data += ReadTimestamp(data, message.Timestamp);
393 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
394 data += CppCommon::Endian::ReadBigEndian(data, message.ExecutedShares);
395 data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber);
396
397 return onMessage(message);
398}
399
400bool ITCHHandler::ProcessOrderExecutedWithPriceMessage(void* buffer, size_t size)
401{
402 assert((size == 36) && "Invalid size of the ITCH message type 'C'");
403 if (size != 36)
404 return false;
405
406 uint8_t* data = (uint8_t*)buffer;
407
408 OrderExecutedWithPriceMessage message;
409 message.Type = *data++;
410 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
411 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
412 data += ReadTimestamp(data, message.Timestamp);
413 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
414 data += CppCommon::Endian::ReadBigEndian(data, message.ExecutedShares);
415 data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber);
416 message.Printable = *data++;
417 data += CppCommon::Endian::ReadBigEndian(data, message.ExecutionPrice);
418
419 return onMessage(message);
420}
421
422bool ITCHHandler::ProcessOrderCancelMessage(void* buffer, size_t size)
423{
424 assert((size == 23) && "Invalid size of the ITCH message type 'X'");
425 if (size != 23)
426 return false;
427
428 uint8_t* data = (uint8_t*)buffer;
429
430 OrderCancelMessage message;
431 message.Type = *data++;
432 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
433 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
434 data += ReadTimestamp(data, message.Timestamp);
435 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
436 data += CppCommon::Endian::ReadBigEndian(data, message.CanceledShares);
437
438 return onMessage(message);
439}
440
441bool ITCHHandler::ProcessOrderDeleteMessage(void* buffer, size_t size)
442{
443 assert((size == 19) && "Invalid size of the ITCH message type 'D'");
444 if (size != 19)
445 return false;
446
447 uint8_t* data = (uint8_t*)buffer;
448
449 OrderDeleteMessage message;
450 message.Type = *data++;
451 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
452 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
453 data += ReadTimestamp(data, message.Timestamp);
454 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
455
456 return onMessage(message);
457}
458
459bool ITCHHandler::ProcessOrderReplaceMessage(void* buffer, size_t size)
460{
461 assert((size == 35) && "Invalid size of the ITCH message type 'U'");
462 if (size != 35)
463 return false;
464
465 uint8_t* data = (uint8_t*)buffer;
466
467 OrderReplaceMessage message;
468 message.Type = *data++;
469 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
470 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
471 data += ReadTimestamp(data, message.Timestamp);
472 data += CppCommon::Endian::ReadBigEndian(data, message.OriginalOrderReferenceNumber);
473 data += CppCommon::Endian::ReadBigEndian(data, message.NewOrderReferenceNumber);
474 data += CppCommon::Endian::ReadBigEndian(data, message.Shares);
475 data += CppCommon::Endian::ReadBigEndian(data, message.Price);
476
477 return onMessage(message);
478}
479
480bool ITCHHandler::ProcessTradeMessage(void* buffer, size_t size)
481{
482 assert((size == 44) && "Invalid size of the ITCH message type 'P'");
483 if (size != 44)
484 return false;
485
486 uint8_t* data = (uint8_t*)buffer;
487
488 TradeMessage message;
489 message.Type = *data++;
490 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
491 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
492 data += ReadTimestamp(data, message.Timestamp);
493 data += CppCommon::Endian::ReadBigEndian(data, message.OrderReferenceNumber);
494 message.BuySellIndicator = *data++;
495 data += CppCommon::Endian::ReadBigEndian(data, message.Shares);
496 data += ReadString(data, message.Stock);
497 data += CppCommon::Endian::ReadBigEndian(data, message.Price);
498 data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber);
499
500 return onMessage(message);
501}
502
503bool ITCHHandler::ProcessCrossTradeMessage(void* buffer, size_t size)
504{
505 assert((size == 40) && "Invalid size of the ITCH message type 'Q'");
506 if (size != 40)
507 return false;
508
509 uint8_t* data = (uint8_t*)buffer;
510
511 CrossTradeMessage message;
512 message.Type = *data++;
513 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
514 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
515 data += ReadTimestamp(data, message.Timestamp);
516 data += CppCommon::Endian::ReadBigEndian(data, message.Shares);
517 data += ReadString(data, message.Stock);
518 data += CppCommon::Endian::ReadBigEndian(data, message.CrossPrice);
519 data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber);
520 message.CrossType = *data++;
521
522 return onMessage(message);
523}
524
525bool ITCHHandler::ProcessBrokenTradeMessage(void* buffer, size_t size)
526{
527 assert((size == 19) && "Invalid size of the ITCH message type 'B'");
528 if (size != 19)
529 return false;
530
531 uint8_t* data = (uint8_t*)buffer;
532
533 BrokenTradeMessage message;
534 message.Type = *data++;
535 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
536 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
537 data += ReadTimestamp(data, message.Timestamp);
538 data += CppCommon::Endian::ReadBigEndian(data, message.MatchNumber);
539
540 return onMessage(message);
541}
542
543bool ITCHHandler::ProcessNOIIMessage(void* buffer, size_t size)
544{
545 assert((size == 50) && "Invalid size of the ITCH message type 'I'");
546 if (size != 50)
547 return false;
548
549 uint8_t* data = (uint8_t*)buffer;
550
551 NOIIMessage message;
552 message.Type = *data++;
553 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
554 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
555 data += ReadTimestamp(data, message.Timestamp);
556 data += CppCommon::Endian::ReadBigEndian(data, message.PairedShares);
557 data += CppCommon::Endian::ReadBigEndian(data, message.ImbalanceShares);
558 message.ImbalanceDirection = *data++;
559 data += ReadString(data, message.Stock);
560 data += CppCommon::Endian::ReadBigEndian(data, message.FarPrice);
561 data += CppCommon::Endian::ReadBigEndian(data, message.NearPrice);
562 data += CppCommon::Endian::ReadBigEndian(data, message.CurrentReferencePrice);
563 message.CrossType = *data++;
564 message.PriceVariationIndicator = *data++;
565
566 return onMessage(message);
567}
568
569bool ITCHHandler::ProcessRPIIMessage(void* buffer, size_t size)
570{
571 assert((size == 20) && "Invalid size of the ITCH message type 'N'");
572 if (size != 20)
573 return false;
574
575 uint8_t* data = (uint8_t*)buffer;
576
577 RPIIMessage message;
578 message.Type = *data++;
579 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
580 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
581 data += ReadTimestamp(data, message.Timestamp);
582 data += ReadString(data, message.Stock);
583 message.InterestFlag = *data++;
584
585 return onMessage(message);
586}
587
588bool ITCHHandler::ProcessLULDAuctionCollarMessage(void* buffer, size_t size)
589{
590 assert((size == 35) && "Invalid size of the ITCH message type 'J'");
591 if (size != 35)
592 return false;
593
594 uint8_t* data = (uint8_t*)buffer;
595
596 LULDAuctionCollarMessage message;
597 message.Type = *data++;
598 data += CppCommon::Endian::ReadBigEndian(data, message.StockLocate);
599 data += CppCommon::Endian::ReadBigEndian(data, message.TrackingNumber);
600 data += ReadTimestamp(data, message.Timestamp);
601 data += ReadString(data, message.Stock);
602 data += CppCommon::Endian::ReadBigEndian(data, message.AuctionCollarReferencePrice);
603 data += CppCommon::Endian::ReadBigEndian(data, message.UpperAuctionCollarPrice);
604 data += CppCommon::Endian::ReadBigEndian(data, message.LowerAuctionCollarPrice);
605 data += CppCommon::Endian::ReadBigEndian(data, message.AuctionCollarExtension);
606
607 return onMessage(message);
608}
609
610bool ITCHHandler::ProcessUnknownMessage(void* buffer, size_t size)
611{
612 assert((size > 0) && "Invalid size of the unknown ITCH message!");
613 if (size == 0)
614 return false;
615
616 uint8_t* data = (uint8_t*)buffer;
617
618 UnknownMessage message;
619 message.Type = *data;
620
621 return onMessage(message);
622}
623
624} // namespace ITCH
625} // namespace CppTrader
virtual bool onMessage(const SystemEventMessage &message)
bool ProcessMessage(void *buffer, size_t size)
Process a single message from the given buffer in ITCH format and call corresponding handlers.
bool Process(void *buffer, size_t size)
Process all messages from the given buffer in ITCH format and call corresponding handlers.
void Reset()
Reset ITCH handler.
NASDAQ ITCH handler definition.
C++ Trader project definitions.
Definition errors.h:16