libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
messages.hpp
Go to the documentation of this file.
1 #ifndef ISIMUD_EXCHANGES_BATSBOE_common_MESSAGES_HPP
2 #define ISIMUD_EXCHANGES_BATSBOE_common_MESSAGES_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2015 by J.M.McGuiness, isimud@hussar.me.uk
6 **
7 ** This library is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU Lesser General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2.1 of the License, or (at your option) any later version.
11 **
12 ** This library is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ** Lesser General Public License for more details.
16 **
17 ** You should have received a copy of the GNU Lesser General Public
18 ** License along with this library; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
22 #include "types.hpp"
24 
25 #include "../../common/iso_10383_mic_codes.hpp"
26 
27 #include "core/memops.hpp"
28 
29 #include <chrono>
30 
31 namespace isimud { namespace ISIMUD_VER_NAMESPACE { namespace exchanges { namespace BATSBOE {
32 
33 /**
34  From <a href="http://cdn.batstrading.com/resources/participant_resources/BATS_Europe_Binary_Order_Entry_Specification.pdf>"BATS Chi-X Europe Binary Order Entry Specification", Version 1.44, 27 November, 2014</a>
35 */
36 namespace common {
37 
38 const uint16_t msg_start_code=0xBABA;
39 struct logon_args_t {
40  const SeqNum_t sequenceNumber{};
41  const SessionSubID_t sessionSubID{};
42  const UserName_t username{{}};
43  const Password_t password{{}};
44  const bool noUnspec{};
45 };
46 struct logoff_args_t {
47  const SeqNum_t sequenceNumber{};
48 };
49 
50 /**
51  Section: "3.1.1 Login Request"
52 */
53 template<class MsgT, MsgT Msg>
54 class Header {
55 public:
56  using MsgType_t=MsgT;
57  using MsgTypes_t=common::MsgType_t;
58  enum : typename std::underlying_type<MsgType_t>::type {
59  static_type=static_cast<typename std::underlying_type<MsgType_t>::type>(Msg)
60  };
61  enum : bool {
62  has_static_size=false ///< The message is dynamically-sized, not statically, so sizeof(MsgT) is the maximum amount to copy, but it could be less, given by length().
63  };
64 
66 
67 protected:
68  std::uint16_t length_;
69 
70 public:
71  const MsgType_t type_{Msg};
72  const std::uint8_t matchingUnit=0;
73  const SeqNum_t sequenceNumber;
74 
75  explicit Header(std::size_t l) noexcept(true) FORCE_INLINE;
76  Header(std::size_t l, SeqNum_t seqNumber) noexcept(true) FORCE_INLINE;
77 
78  const MsgType_t type() const noexcept(true) {
79  return type_;
80  }
81 
82  /// The actual, not the foolish BATSBOE-specified, length which excludes the start_of_message field.
83  std::uint16_t length() const noexcept(true);
84 
85  bool is_valid() const noexcept(true) {
87  && length()>=sizeof(Header)
88  && matchingUnit==0;
89  }
90 
91 protected:
92  ~Header() noexcept(true)=default;
93 } __attribute__((packed));
94 
95 /**
96  Section: "3.1.1 Login Request"
97 */
98 template<class MsgT, MsgT Msg>
99 struct LogonRequest : public Header<MsgT, Msg> {
101  enum : std::size_t {
102  header_t_size=sizeof(Header_t)
103  };
104 
105  const SessionSubID_t sessionSubID;
106  const UserName_t userName;
107  const Password_t password;
108  const uint8_t noUnspecifiedUnitReplay;
122  const uint8_t reserved[128]={0};
123  const uint8_t numberOfUnits=0;
124 
125  LogonRequest(SeqNum_t seqNum, const SessionSubID_t sessionSubID, const UserName_t &UN, const Password_t &P, const bool noUnspec) noexcept(true) FORCE_INLINE;
126  explicit LogonRequest(logon_args_t const &a) noexcept(true) FORCE_INLINE;
127 
128  /// Create a message from the source message.
129  /**
130  If an error is generated, then this function will need to be specialised for the particular Msg-type.
131 
132  \param msg The source message from which the target message should be created.
133  */
134  template<class SrcMsg> __stdcall
135  LogonRequest(SrcMsg const &msg, SeqNum_t seqNum, const SessionSubID_t sessionSubID, const bool noUnspec)=delete FORCE_INLINE;
136 } __attribute__((packed));
137 
138 /**
139  Section: "3.1.2 Logout request"
140 */
143  enum : std::size_t {
144  header_t_size=sizeof(Header_t)
145  };
146 
147  explicit LogoutRequest(SeqNum_t seqNum) noexcept(true) FORCE_INLINE;
148  explicit LogoutRequest(logoff_args_t const &a) noexcept(true) FORCE_INLINE;
149 
150  /// Create a message from the source message.
151  /**
152  If an error is generated, then this function will need to be specialised for the particular Msg-type.
153 
154  \param msg The source message from which the target message should be created.
155  */
156  template<class SrcMsg> explicit __stdcall
157  LogoutRequest(SrcMsg const &msg, SeqNum_t seqNum) noexcept(true)=delete FORCE_INLINE;
158 } __attribute__((packed));
159 
160 /**
161  Section: "3.1.3 Client Heartbeat" & "2.4 Heartbeats".
162 */
165  enum : std::size_t {
166  header_t_size=sizeof(Header_t)
167  };
168  enum : common::Quantity_t {
169  seq_num=0
170  };
171 
172  explicit ClientHeartbeat(SeqNum_t seqNum) noexcept(true) FORCE_INLINE;
173 
174  /// Create a message from the source message.
175  /**
176  If an error is generated, then this function will need to be specialised for the particular Msg-type.
177 
178  \param msg The source message from which the target message should be created.
179  */
180  template<class SrcMsg> explicit __stdcall
181  ClientHeartbeat(SrcMsg const &msg, SeqNum_t seqNum) noexcept(true)=delete FORCE_INLINE;
182 } __attribute__((packed));
183 
184 /**
185  Section: "3.2.1 Login Response"
186 */
187 template<class MsgT, MsgT Msg>
188 struct LogonReply : public Header<MsgT, Msg> {
190  enum : std::size_t {
191  header_t_size=sizeof(Header_t)
192  };
193  /// Allow a client connected to the exchange to process the LogonReply message.
194  struct respond;
195 
197 
199 
200  LogonReply() noexcept(true) FORCE_INLINE;
201  explicit LogonReply(SeqNum_t seqNum) noexcept(true) FORCE_INLINE;
202 
203  LoginResponseStatus rejectCode() const noexcept(true) FORCE_INLINE {
204  return loginResponseStatus;
205  }
206  void rejectCode(LoginResponseStatus const &rc) noexcept(true) FORCE_INLINE {
208  }
209 } __attribute__((packed));
210 
211 /**
212  Section: "3.2.2 Logout"
213 */
214 struct Logout : public Header<MsgType, MsgType::Logout> {
216  enum : std::size_t {
217  header_t_size=sizeof(Header_t)
218  };
219 
221  LogoutReasonText_t logoutReasonText;
223  const uint8_t numberOfUnits=0;
224 
225  Logout() noexcept(true) FORCE_INLINE;
226  Logout(SeqNum_t seqNum, LogoutReason lr) noexcept(true) FORCE_INLINE;
227 } __attribute__((packed));
228 
229 /**
230  Section: "3.2.3 Server Heartbeat" & "2.4 Heartbeats".
231 */
234  enum : std::size_t {
235  header_t_size=sizeof(Header_t)
236  };
237  enum : common::Quantity_t {
238  seq_num=0
239  };
240 
241  explicit ServerHeartbeat(SeqNum_t seqNum) noexcept(true) FORCE_INLINE;
242 
243  /// Create a message from the source message.
244  /**
245  If an error is generated, then this function will need to be specialised for the particular Msg-type.
246 
247  \param msg The source message from which the target message should be created.
248  */
249  template<class SrcMsg> explicit __stdcall
250  ServerHeartbeat(SrcMsg const &msg, SeqNum_t seqNum) noexcept(true)=delete FORCE_INLINE;
251 } __attribute__((packed));
252 
253 /**
254  Section: "3.2.4 Replay Complete"
255 */
258  enum : std::size_t {
259  header_t_size=sizeof(Header_t)
260  };
261 
262  explicit ReplayComplete(SeqNum_t seqNum) noexcept(true) FORCE_INLINE;
263 } __attribute__((packed));
264 
265 /**
266  Section: "4.1.1 New Order"
267 */
268 struct NewOrder : public Header<MsgType, MsgType::NewOrder> {
272  enum : std::size_t {
273  header_t_size=sizeof(Header_t)
274  };
275 
276  explicit NewOrder(SeqNum_t seqNum, ClientOrderID_t const &clID, OrdType const oT, TIF const t, Side const s, SecurityID_t instID, common::Quantity_t ordQty, Price_t p) noexcept(true) FORCE_INLINE;
277  /// Create a message from the source message.
278  /**
279  If an error is generated, then this function will need to be specialised for the particular Msg-type.
280 
281  \param msg The source message from which the target message should be created.
282  */
283  template<class SrcMsg> explicit __stdcall
284  NewOrder(SrcMsg const &msg, SeqNum_t seqNum) noexcept(true)=delete FORCE_INLINE;
285 
286  ClientOrderID_t const &clientOrderID() const noexcept(true) {
287  return clientOrderID_;
288  }
289  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
290  libjmmcg::memcpy_opt(clID, clientOrderID_);
291  }
292 
293  common::Quantity_t orderQty() const noexcept(true) {
294  return orderQty_;
295  }
296  void orderQty(common::Quantity_t i) noexcept(true) {
297  orderQty_=i;
298  }
299 
300  OrdType const &orderType() const noexcept(true);
301  void orderType(OrdType const &i) noexcept(true);
302 
303  common::Side side() const noexcept(true) {
304  return side_;
305  }
306  void side(common::Side i) noexcept(true) {
307  side_=i;
308  }
309 
310  SecurityID_t const &instrumentID() const noexcept(true);
311  void instrumentID(SecurityID_t const &i) noexcept(true);
312 
313  Price_t limitPrice() const noexcept(true);
314  void limitPrice(Price_t p) noexcept(true);
315 
316  TIF tif() const noexcept(true);
317  void tif(TIF t) noexcept(true);
318 
319 private:
320  ClientOrderID_t clientOrderID_;
321  common::Side side_;
322  common::Quantity_t orderQty_;
323  bitfields_to_type_map bitfields;
324 } __attribute__((packed));
325 
326 /**
327  Section: "4.1.2 Cancel Order"
328 */
333  enum : std::size_t {
334  header_t_size=sizeof(Header_t)
335  };
336 
337  CancelOrder(SeqNum_t seqNum, ClientOrderID_t const &origclID) noexcept(true) FORCE_INLINE;
338  /// Create a message from the source message.
339  /**
340  If an error is generated, then this function will need to be specialised for the particular Msg-type.
341 
342  \param msg The source message from which the target message should be created.
343  */
344  template<class SrcMsg> __stdcall
345  CancelOrder(SrcMsg const &msg, SeqNum_t seqNum) noexcept(true)=delete FORCE_INLINE;
346 
347  ClientOrderID_t const &originalClientOrderID() const noexcept(true) {
348  return originalClientOrderID_;
349  }
350  void originalClientOrderID(ClientOrderID_t const &origclID) noexcept(true) {
351  libjmmcg::memcpy_opt(origclID, originalClientOrderID_);
352  }
353 
354 private:
355  ClientOrderID_t originalClientOrderID_;
356  bitfields_to_type_map bitfields;
357 } __attribute__((packed));
358 
359 /**
360  Section: "4.1.3 Modify Order"
361 */
366  enum : std::size_t {
367  header_t_size=sizeof(Header_t)
368  };
369 
370  ModifyOrder(SeqNum_t seqNum, ClientOrderID_t const &clID, common::Quantity_t ordQty, Price_t p, Side s) noexcept(true) FORCE_INLINE;
371 
372  /// Create a message from the source message.
373  /**
374  If an error is generated, then this function will need to be specialised for the particular Msg-type.
375 
376  \param msg The source message from which the target message should be created.
377  */
378  template<class SrcMsg> explicit __stdcall
379  ModifyOrder(SrcMsg const &msg, SeqNum_t seqNum) noexcept(true)=delete FORCE_INLINE;
380 
381  ClientOrderID_t const &originalClientOrderID() const noexcept(true) {
382  return originalClientOrderID_;
383  }
384  void originalClientOrderID(ClientOrderID_t const &clID) noexcept(true) {
385  libjmmcg::memcpy_opt(clID, originalClientOrderID_);
386  }
387 
388  Price_t limitPrice() const noexcept(true);
389  void limitPrice(Price_t p) noexcept(true);
390 
391  common::Quantity_t orderQty() const noexcept(true);
392  void orderQty(common::Quantity_t i) noexcept(true);
393 
394  Side side() const noexcept(true);
395  void side(Side i) noexcept(true);
396 
397 private:
398  ClientOrderID_t clientOrderID_;
399  ClientOrderID_t originalClientOrderID_;
400  bitfields_to_type_map bitfields;
401 } __attribute__((packed));
402 
403 /**
404  Section: "4.2.1 Order Acknowledgement"
405 */
410  enum : std::size_t {
411  header_t_size=sizeof(Header_t)
412  };
413 
414  const DateTime_t transactionTime;
415 
416  explicit OrderAcknowledgement(SeqNum_t seqNum, ClientOrderID_t const &clID) noexcept(true) FORCE_INLINE;
417 
418  ClientOrderID_t const &clientOrderID() const noexcept(true) {
419  return clientOrderID_;
420  }
421  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
422  libjmmcg::memcpy_opt(clID, clientOrderID_);
423  }
424 
425 private:
426  ClientOrderID_t clientOrderID_;
427  uint64_t orderID;
428  bitfields_to_type_map bitfields;
429 } __attribute__((packed));
430 
431 /**
432  Section: "4.2.2 Order Rejected"
433 */
438  using RejectCode_t=int;
439  enum : std::size_t {
440  header_t_size=sizeof(Header_t)
441  };
443 
444  const DateTime_t transactionTime;
445 
446  OrderRejected() noexcept(true) FORCE_INLINE;
447  OrderRejected(SeqNum_t seqNum, ClientOrderID_t const &clID, OrderRejectReason orr) noexcept(true) FORCE_INLINE;
448 
449  ClientOrderID_t const &clientOrderID() const noexcept(true) {
450  return clientOrderID_;
451  }
452  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
453  libjmmcg::memcpy_opt(clID, clientOrderID_);
454  }
455 
456 private:
457  ClientOrderID_t clientOrderID_;
458 
459 public:
461 
462 private:
463  Text_t text;
464  bitfields_to_type_map bitfields;
465 } __attribute__((packed));
466 
467 /**
468  Section: "4.2.3 Order Modified"
469 */
474  enum : std::size_t {
475  header_t_size=sizeof(Header_t)
476  };
477 
478  const DateTime_t transactionTime;
479 
480  explicit OrderModified() noexcept(true) FORCE_INLINE;
481  explicit OrderModified(SeqNum_t seqNum, ClientOrderID_t const &clID, Price_t p, Side s, common::Quantity_t ordQty) noexcept(true) FORCE_INLINE;
482 
483  ClientOrderID_t const &clientOrderID() const noexcept(true) {
484  return clientOrderID_;
485  }
486  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
487  libjmmcg::memcpy_opt(clID, clientOrderID_);
488  }
489 
490  Price_t limitPrice() const noexcept(true);
491  void limitPrice(Price_t p) noexcept(true);
492 
493  common::Quantity_t orderQty() const noexcept(true);
494  void orderQty(common::Quantity_t i) noexcept(true);
495 
496  Side side() const noexcept(true);
497  void side(Side i) noexcept(true);
498 
499 private:
500  ClientOrderID_t clientOrderID_;
501  uint64_t orderID;
502  bitfields_to_type_map bitfields;
503 } __attribute__((packed));
504 
505 /**
506  Section: "4.2.4 Order Restated"
507 */
512  enum : std::size_t {
513  header_t_size=sizeof(Header_t)
514  };
515 
516  const DateTime_t transactionTime;
517 
518  explicit OrderRestated(SeqNum_t seqNum, ClientOrderID_t const &clID) noexcept(true) FORCE_INLINE;
519 
520  ClientOrderID_t const &clientOrderID() const noexcept(true) {
521  return clientOrderID_;
522  }
523  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
524  libjmmcg::memcpy_opt(clID, clientOrderID_);
525  }
526 
527 private:
528  ClientOrderID_t clientOrderID_;
529  uint64_t orderID;
530  RestatementReason restatementReason;
531  bitfields_to_type_map bitfields;
532 } __attribute__((packed));
533 
534 /**
535  Section: "4.2.5 User Modify Rejected"
536 */
539  using bitfields_to_type_map=optional::UserModifyRejected::bitfields_to_type_map;
540  using bitfields_tags_type=bitfields_to_type_map::bitfields_tags_type;
541  enum : std::size_t {
542  header_t_size=sizeof(Header_t)
543  };
544 
545  const DateTime_t transactionTime;
546 
547  UserModifyRejected() noexcept(true) FORCE_INLINE;
548  explicit UserModifyRejected(SeqNum_t seqNum, ClientOrderID_t const &clID, OrderRejectReason orr) noexcept(true) FORCE_INLINE;
549 
550  ClientOrderID_t const &clientOrderID() const noexcept(true) {
551  return clientOrderID_;
552  }
553  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
554  libjmmcg::memcpy_opt(clID, clientOrderID_);
555  }
556 
557 private:
558  ClientOrderID_t clientOrderID_;
559  uint64_t orderID;
560 
561 public:
563 
564 private:
565  Text_t text;
566  bitfields_to_type_map bitfields;
567 } __attribute__((packed));
568 
569 /**
570  Section: "4.2.6 Order Cancelled"
571 */
576  enum : std::size_t {
577  header_t_size=sizeof(Header_t)
578  };
579 
580  const DateTime_t transactionTime;
581 
582  explicit OrderCancelled() noexcept(true) FORCE_INLINE;
583  explicit OrderCancelled(SeqNum_t seqNum, ClientOrderID_t const &clID, OrderRejectReason orr, Price_t p, Side s, common::Quantity_t ls, common::Quantity_t ordQty) noexcept(true) FORCE_INLINE;
584 
585  ClientOrderID_t const &clientOrderID() const noexcept(true) {
586  return clientOrderID_;
587  }
588  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
589  libjmmcg::memcpy_opt(clID, clientOrderID_);
590  }
591 
592  Side side() const noexcept(true);
593 
594  common::Quantity_t orderQty() const noexcept(true);
595 
596  common::Quantity_t leavesQty() const noexcept(true);
597 
598  common::Quantity_t lastShares() const noexcept(true);
599 
600  Price_t lastPrice() const noexcept(true);
601 
602 private:
603  ClientOrderID_t clientOrderID_;
604 
605 public:
607 
608 private:
609  bitfields_to_type_map bitfields;
610 } __attribute__((packed));
611 
612 /**
613  Section: "4.2.7 Cancel Rejected"
614 */
617  using bitfields_to_type_map=optional::CancelRejected::bitfields_to_type_map;
618  using bitfields_tags_type=bitfields_to_type_map::bitfields_tags_type;
619  enum : std::size_t {
620  header_t_size=sizeof(Header_t)
621  };
622 
623  const DateTime_t transactionTime;
624 
625  CancelRejected() noexcept(true) FORCE_INLINE;
626  CancelRejected(SeqNum_t seqNum, ClientOrderID_t const &clID, OrderRejectReason crr) noexcept(true) FORCE_INLINE;
627 
628  ClientOrderID_t const &clientOrderID() const noexcept(true) {
629  return clientOrderID_;
630  }
631  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
632  libjmmcg::memcpy_opt(clID, clientOrderID_);
633  }
634 
635 private:
636  ClientOrderID_t clientOrderID_;
637 
638 public:
640 
641 private:
642  Text_t text;
643  bitfields_to_type_map bitfields;
644 } __attribute__((packed));
645 
646 /**
647  Section: "4.2.8 Order Execution"
648 */
653  enum : std::size_t {
654  header_t_size=sizeof(Header_t)
655  };
656 
657  const DateTime_t transactionTime;
658 
659  OrderExecution() noexcept(true) FORCE_INLINE;
660  OrderExecution(SeqNum_t seqNum, ClientOrderID_t const &clID, Price_t const price, SecurityID_t const &instID, Side s) noexcept(true) FORCE_INLINE;
661 
662  ClientOrderID_t const &clientOrderID() const noexcept(true) {
663  return clientOrderID_;
664  }
665  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
666  libjmmcg::memcpy_opt(clID, clientOrderID_);
667  }
668 
669  SecurityID_t const &instrumentID() const noexcept(true);
670  void instrumentID(SecurityID_t const &i) noexcept(true);
671 
672  Price_t executedPrice() const noexcept(true) {
673  return lastPx;
674  }
675  void executedPrice(Price_t p) noexcept(true) {
676  lastPx=p;
677  }
678 
679  common::Quantity_t executedQty() const noexcept(true) {
680  return lastShares;
681  }
682  void executedQty(common::Quantity_t eq) noexcept(true) {
683  lastShares=eq;
684  }
685 
686  common::Quantity_t leavesQty() const noexcept(true) {
687  return leavesQty_;
688  }
689  void leavesQty(common::Quantity_t eq) noexcept(true) {
690  leavesQty_=eq;
691  }
692 
693  Side side() const noexcept(true);
694  void side(Side s) noexcept(true);
695 
696 private:
697  ClientOrderID_t clientOrderID_;
698  uint64_t execID;
699  common::Quantity_t lastShares;
700  Price_t lastPx;
701  common::Quantity_t leavesQty_;
702  BaseLiquidityIndicator baseLiquidityIndicator;
703  SubLiquidityIndicator subLiquidityIndicator;
704  SPrice_t accessFee;
705  ContraBroker_t contraBroker;
706  bitfields_to_type_map bitfields;
707 } __attribute__((packed));
708 
709 /**
710  Section: "4.2.9 Trade Cancel or Correct"
711 */
716  enum : std::size_t {
717  header_t_size=sizeof(Header_t)
718  };
719 
720  const DateTime_t transactionTime;
721 
722  explicit TradeCancelOrCorrect(SeqNum_t seqNum, ClientOrderID_t const &clID) noexcept(true) FORCE_INLINE;
723 
724  ClientOrderID_t const &clientOrderID() const noexcept(true) {
725  return clientOrderID_;
726  }
727  void clientOrderID(ClientOrderID_t const &clID) noexcept(true) {
728  libjmmcg::memcpy_opt(clID, clientOrderID_);
729  }
730 
731 private:
732  ClientOrderID_t clientOrderID_;
733  uint64_t orderID;
734  uint64_t execRefID;
735  Side side;
736  BaseLiquidityIndicator baseLiquidityIndicator;
737  ClearingFirm_t clearingFirm;
738  ClearingAccount_t clearingAccount;
739  Quantity_t lastShares;
740  Price_t lastPx;
741  Price_t correctedPrice;
742  DateTime_t origTime;
743  bitfields_to_type_map bitfields;
744 } __attribute__((packed));
745 
746 } } } } }
747 
748 #include "messages_impl.hpp"
749 
750 #endif