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_MIT_JSE_MESSAGES_HPP
2 #define ISIMUD_EXCHANGES_MIT_JSE_MESSAGES_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2016 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 "config.h"
23 #include "reject_codes.hpp"
24 
25 #include "../common/messages.hpp"
26 #include "../common/ref_data.hpp"
27 
28 #include "core/max_min.hpp"
29 
30 #include <boost/mpl/assert.hpp>
31 #include <boost/mpl/deref.hpp>
32 #include <boost/mpl/max_element.hpp>
33 #include <boost/mpl/min_element.hpp>
34 #include <boost/mpl/placeholders.hpp>
35 #include <boost/mpl/sizeof.hpp>
36 #include <boost/mpl/transform_view.hpp>
37 #include <boost/mpl/vector.hpp>
38 #include <boost/variant/variant.hpp>
39 
40 #include <iostream>
41 
42 namespace isimud { namespace ISIMUD_VER_NAMESPACE { namespace exchanges { namespace MIT {
43 
44 /**
45  From <a href="https://www.jse.co.za/content/JSETechnologyDocumentItems/Volume%2001%20-%20Native%20Trading%20Gateway%20v3.03.pdf">"JSE Specification Document Volume 01 - Native Trading Gateway", Version 3.01, 26 April 2016</a>.
46 */
47 namespace JSE {
48 
49 using CompID_t=std::array<char, 6>;
50 using ExecutionID_t=std::array<char, 21>;
51 using ExpireDateTime_t=std::array<char, 17>;
52 using Password_t=std::array<char, 10>;
53 using PasswordExpiry_t=std::int32_t;
54 using TraderMnemonic_t=std::array<char, 17>;
55 using Segment_t=std::array<char, 6>;
56 
57 struct logon_args_t {
58  using UserName_t=JSE::CompID_t;
59  using Password_t=JSE::Password_t;
60 
61  const UserName_t username{{}};
62  const Password_t password{{}};
63  const Password_t new_password{{}};
64 };
65 
66 /**
67  Section: "6.4.8 Transmission Complete"
68 */
70  using Header_t=common::Header;
71  enum : common::MsgType_t {
73  };
74  enum : std::size_t {
75  header_t_size=sizeof(Header_t)
76  };
77 
79 
80  explicit constexpr TransmissionComplete(const common::Status s) noexcept(true) FORCE_INLINE;
81 
82  /// Create a message from the source message.
83  /**
84  If an error is generated, then this function will need to be specialised for the particular Msg-type.
85 
86  \param msg The source message from which the target message should be created.
87  */
88  template<class SrcMsg> explicit __stdcall
89  TransmissionComplete(SrcMsg const &msg) noexcept(true)=delete FORCE_INLINE;
90 } __attribute__((packed));
91 
92 
93 /**
94  Section: "6.4.1 Logon"
95 */
96 struct Logon : public common::Header {
97  using Header_t=common::Header;
98  using logon_args_t=JSE::logon_args_t;
99 
100  enum : common::MsgType_t {
101  static_type=static_cast<common::MsgType_t>(common::AdminMsgType::LogonRequest)
102  };
103  enum : std::size_t {
104  header_t_size=sizeof(Header_t)
105  };
106 
107  const logon_args_t::UserName_t userName;
108  const logon_args_t::Password_t password;
109  const logon_args_t::Password_t newPassword;
110  static inline constexpr const std::uint8_t messageVersion=1;
111 
112  constexpr Logon(const logon_args_t::UserName_t &UN, const logon_args_t::Password_t &P, const logon_args_t::Password_t &NP) noexcept(true) FORCE_INLINE;
113  explicit constexpr Logon(logon_args_t const &a) noexcept(true) FORCE_INLINE;
114 
115  /// Create a message from the source message.
116  /**
117  If an error is generated, then this function will need to be specialised for the particular Msg-type.
118 
119  \param msg The source message from which the target message should be created.
120  */
121  template<class SrcMsg> explicit __stdcall
122  Logon(SrcMsg const &msg) noexcept(true)=delete FORCE_INLINE;
123 } __attribute__((packed));
124 
125 /**
126  Section: "6.4.2 Logon Response"
127 */
128 struct LogonResponse : public common::Header {
129  using Header_t=common::Header;
130  using RejectCode_t=mit_jse::reject_codes_enum;
132  enum : common::MsgType_t {
133  static_type=static_cast<common::MsgType_t>(common::AdminMsgType::LogonReply)
134  };
135  enum : std::size_t {
136  header_t_size=sizeof(Header_t)
137  };
138  /// Allow a client connected to the exchange to process the LogonReponse message.
139  struct respond;
140 
141  static inline constexpr const RejectCode_t logon_success=mit_jse::reject_codes_enum::tag_SUCCESS;
142  static inline constexpr const RejectCode_t invalid_logon_details=mit_jse::reject_codes_enum::Native_Trading_Gateway_Invalid_User_ID_or_password_1;
143  static inline constexpr const RejectCode_t unknown_user=mit_jse::reject_codes_enum::Native_Trading_Gateway_Invalid_User_ID_or_password_1;
144 
145  RejectCode_t rejectCode_;
146  PasswordExpiry_t passwordExpiry;
147 
148  LogonResponse() noexcept(true) FORCE_INLINE;
149 
150  RejectCode_t rejectCode() const noexcept(true) FORCE_INLINE {
151  return rejectCode_;
152  }
153  void rejectCode(RejectCode_t const &rc) noexcept(true) FORCE_INLINE {
154  rejectCode_=rc;
155  }
156 } __attribute__((packed));
157 
158 /**
159  Section: "6.5.1 New Order"
160 */
161 struct NewOrder : public common::Header {
162  using Header_t=common::Header;
163  enum : common::MsgType_t {
164  static_type=static_cast<common::MsgType_t>(common::ClientMsgType::NewOrder)
165  };
166  enum : std::size_t {
167  header_t_size=sizeof(Header_t)
168  };
169  using order_qty_t=std::int32_t;
170  using ref_data=common::ref_data;
171 
172  common::ClientOrderID_t clientOrderID_;
173  common::SecurityID_t instrumentID_;
174  TraderMnemonic_t traderMnemonic{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
175  common::Account_t account{"\0\0\0\0\0\0\0\0\0"};
178  ExpireDateTime_t expireDateTime{};
180  order_qty_t orderQty_;
181  order_qty_t displayQty{};
182  order_qty_t minimumQty{};
183  common::Price_t limitPrice_;
184  common::Price_t stoppedPrice=0;
190 
191  constexpr __stdcall NewOrder(std::int32_t, common::ClientOrderID_t const &clID, common::OrderType const oT, common::TIF const t, common::Side const s, common::SecurityID_t instID, order_qty_t ordQty, common::Price_t p) noexcept(true) FORCE_INLINE;
192 
193  /// Create a message from the source message.
194  /**
195  If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
196 
197  \param msg The source message from which the target message should be created.
198  */
199  template<class SrcMsg> __stdcall
200  NewOrder(SrcMsg const &msg, ref_data const &rd) noexcept(true) FORCE_INLINE;
201 
202  common::SecurityID_t instrumentID() const noexcept(true) {
203  return instrumentID_;
204  }
205  void instrumentID(common::SecurityID_t i) noexcept(true) {
206  instrumentID_=i;
207  }
208 
209  order_qty_t orderQty() const noexcept(true) {
210  return orderQty_;
211  }
212  void orderQty(order_qty_t i) noexcept(true) {
213  orderQty_=i;
214  }
215 
216  common::OrderType orderType() const noexcept(true) {
217  return orderType_;
218  }
219  void orderType(common::OrderType i) noexcept(true) {
220  orderType_=i;
221  }
222 
223  common::Side side() const noexcept(true) {
224  return side_;
225  }
226  void side(common::Side i) noexcept(true) {
227  side_=i;
228  }
229 
230  common::ClientOrderID_t const &clientOrderID() const noexcept(true) {
231  return clientOrderID_;
232  }
233  void clientOrderID(common::ClientOrderID_t const &clID) noexcept(true) {
234  libjmmcg::memcpy_opt(clID, clientOrderID_);
235  }
236 
237  common::Price_t limitPrice() const noexcept(true) {
238  return limitPrice_;
239  }
240  void limitPrice(common::Price_t p) noexcept(true) {
241  limitPrice_=p;
242  }
243 
244  common::TIF tif() const noexcept(true) {
245  return tif_;
246  }
247  void tif(common::TIF t) noexcept(true) {
248  tif_=t;
249  }
250 } __attribute__((packed));
251 
252 /**
253  Section: "6.5.2 Order Cancel Request"
254 */
256  common::SecurityID_t instrumentID_;
257  TraderMnemonic_t traderMnemonic{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
258 
259  explicit constexpr OrderCancelRequestSpecific1(common::SecurityID_t instID) noexcept(true) FORCE_INLINE
260  : instrumentID_(instID) {
261  }
262  common::SecurityID_t instrumentID() const noexcept(true) {
263  return instrumentID_;
264  }
265  void instrumentID(common::SecurityID_t i) noexcept(true) {
266  instrumentID_=i;
267  }
268 } __attribute__((packed));
269 
270 /**
271  Section: "6.5.3 Order Mass Cancel Request"
272 */
274  common::SecurityID_t instrumentID_;
275  Segment_t segment;
276 
277  explicit constexpr OrderMassCancelRequestSpecific1(common::SecurityID_t instID) noexcept(true) FORCE_INLINE
278  : instrumentID_(instID), segment{} {
279  }
280  common::SecurityID_t instrumentID() const noexcept(true) {
281  return instrumentID_;
282  }
283  void instrumentID(common::SecurityID_t i) noexcept(true) {
284  instrumentID_=i;
285  }
286 } __attribute__((packed));
289 } __attribute__((packed));
290 /**
291  Section: "6.5.4 Order Cancel/Replace Request"
292 */
294  using Header_t=common::Header;
295  enum : common::MsgType_t {
297  };
298  enum : std::size_t {
299  header_t_size=sizeof(Header_t)
300  };
301  using order_qty_t=std::int32_t;
302  using ref_data=common::ref_data;
303 
304  common::ClientOrderID_t clientOrderID_;
305  common::ClientOrderID_t originalClientOrderID_;
306  common::OrderID_t orderID{};
307  common::SecurityID_t instrumentID_;
308  TraderMnemonic_t traderMnemonic{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
309  common::Account_t account{"\0\0\0\0\0\0\0\0\0"};
312  ExpireDateTime_t expireDateTime{};
314  order_qty_t orderQty_;
315  order_qty_t displayQty{};
316  order_qty_t minimumQty{};
317  common::Price_t limitPrice_;
318  common::Price_t stoppedPrice=0;
320 
321  OrderCancelReplaceRequest(common::ClientOrderID_t const &clID, common::ClientOrderID_t const &origclID, common::SecurityID_t instID, order_qty_t ordQty, common::Price_t const p, common::TIF t, common::Side s) noexcept(true) FORCE_INLINE;
322 
323  /// Create a message from the source message.
324  /**
325  If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
326 
327  \param msg The source message from which the target message should be created.
328  */
329  template<class SrcMsg> __stdcall
330  OrderCancelReplaceRequest(SrcMsg const &msg, ref_data const &rd) noexcept(true) FORCE_INLINE;
331 
332  common::SecurityID_t instrumentID() const noexcept(true) {
333  return instrumentID_;
334  }
335  void instrumentID(common::SecurityID_t i) noexcept(true) {
336  instrumentID_=i;
337  }
338 
339  common::ClientOrderID_t const &clientOrderID() const noexcept(true) {
340  return clientOrderID_;
341  }
342  void clientOrderID(common::ClientOrderID_t const &clID) noexcept(true) {
343  libjmmcg::memcpy_opt(clID, clientOrderID_);
344  }
345 
346  common::ClientOrderID_t const &originalClientOrderID() const noexcept(true) {
347  return originalClientOrderID_;
348  }
349  void originalClientOrderID(common::ClientOrderID_t const &clID) noexcept(true) {
350  libjmmcg::memcpy_opt(clID, originalClientOrderID_);
351  }
352 
353  common::Price_t limitPrice() const noexcept(true) {
354  return limitPrice_;
355  }
356  void limitPrice(common::Price_t p) noexcept(true) {
357  limitPrice_=p;
358  }
359 
360  order_qty_t orderQty() const noexcept(true) {
361  return orderQty_;
362  }
363  void orderQty(order_qty_t i) noexcept(true) {
364  orderQty_=i;
365  }
366 
367  common::Side side() const noexcept(true) {
368  return side_;
369  }
370  void side(common::Side i) noexcept(true) {
371  side_=i;
372  }
373 
374  common::TIF tif() const noexcept(true) {
375  return tif_;
376  }
377  void tif(common::TIF t) noexcept(true) {
378  tif_=t;
379  }
380 } __attribute__((packed));
381 
382 /**
383  Section: "6.5.5 New Order Cross"
384 */
385 struct NewOrderCross : public common::Header {
386  using Header_t=common::Header;
387  enum : common::MsgType_t {
389  };
390  enum : std::size_t {
391  header_t_size=sizeof(Header_t)
392  };
393  using order_qty_t=std::int32_t;
394 
395  common::CrossID_t crossID{};
397  common::ClientOrderID_t buySideClientOrderID;
399  TraderMnemonic_t buySideTraderMnemonic{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
400  common::Account_t buySideccount{"\0\0\0\0\0\0\0\0\0"};
401  common::ClientOrderID_t sellSideClientOrderID{};
403  TraderMnemonic_t sellSideTraderMnemonic{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
404  common::Account_t sellSideAccount{"\0\0\0\0\0\0\0\0\0"};
405  common::SecurityID_t instrumentID_;
408  common::Price_t limitPrice_;
409  order_qty_t orderQty_;
410 
411  constexpr NewOrderCross(common::ClientOrderID_t const &origclID, common::SecurityID_t instID, order_qty_t ordQty, common::Price_t const p, common::TIF t) noexcept(true) FORCE_INLINE;
412 
413  common::SecurityID_t instrumentID() const noexcept(true) {
414  return instrumentID_;
415  }
416  void instrumentID(common::SecurityID_t i) noexcept(true) {
417  instrumentID_=i;
418  }
419 
420  common::Price_t limitPrice() const noexcept(true) {
421  return limitPrice_;
422  }
423  void limitPrice(common::Price_t p) noexcept(true) {
424  limitPrice_=p;
425  }
426 
427  order_qty_t orderQty() const noexcept(true) {
428  return orderQty_;
429  }
430  void orderQty(order_qty_t i) noexcept(true) {
431  orderQty_=i;
432  }
433 
434  common::TIF tif() const noexcept(true) {
435  return tif_;
436  }
437  void tif(common::TIF t) noexcept(true) {
438  tif_=t;
439  }
440 } __attribute__((packed));
441 
442 /**
443  Section: "6.6.1 Execution Report"
444 */
445 struct ExecutionReport : public common::Header {
446  using Header_t=common::Header;
447  enum : common::MsgType_t {
449  };
450  enum : std::size_t {
451  header_t_size=sizeof(Header_t)
452  };
453  using RejectCode_t=mit_jse::reject_codes_enum;
454  using order_qty_t=std::int32_t;
455 
457  std::int32_t sequenceNumber;
458  ExecutionID_t executionID{};
459  common::ClientOrderID_t clientOrderID_;
460  common::OrderID_t orderID{};
463  RejectCode_t orderRejectCode_{};
465  order_qty_t executedQty_{};
466  order_qty_t leavesQty_{};
468  common::SecurityID_t instrumentID_;
470  TraderMnemonic_t traderMnemonic{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
471  common::Account_t account{"\0\0\0\0\0\0\0\0\0"};
473  common::TransactTime_t transactTime{};
476  common::CrossID_t crossID_{};
478 
479  ExecutionReport() noexcept(true) FORCE_INLINE;
480  constexpr ExecutionReport(std::int32_t seqNum, common::ClientOrderID_t const &clID, common::AppID aID, common::ExecType eT, common::Price_t const price, common::SecurityID_t instID, common::Side s) noexcept(true) FORCE_INLINE;
481 
482  common::ExecType execType() const noexcept(true) {
483  return execType_;
484  }
485  void execType(common::ExecType e) noexcept(true) {
486  execType_=e;
487  }
488 
489  common::ClientOrderID_t const &clientOrderID() const noexcept(true) {
490  return clientOrderID_;
491  }
492  void clientOrderID(common::ClientOrderID_t const &clID) noexcept(true) {
493  libjmmcg::memcpy_opt(clID, clientOrderID_);
494  }
495 
496  common::SecurityID_t instrumentID() const noexcept(true) {
497  return instrumentID_;
498  }
499  void instrumentID(common::SecurityID_t i) noexcept(true) {
500  instrumentID_=i;
501  }
502 
503  common::Price_t executedPrice() const noexcept(true) {
504  return executedPrice_;
505  }
506  void executedPrice(common::Price_t p) noexcept(true) {
507  executedPrice_=p;
508  }
509 
510  common::OrderStatus orderStatus() const noexcept(true) {
511  return orderStatus_;
512  }
513  void orderStatus(common::OrderStatus os) noexcept(true) {
514  orderStatus_=os;
515  }
516 
517  int32_t executedQty() const noexcept(true) {
518  return executedQty_;
519  }
520  void executedQty(std::int32_t eq) noexcept(true) {
521  executedQty_=eq;
522  }
523 
524  int32_t leavesQty() const noexcept(true) {
525  return leavesQty_;
526  }
527  void leavesQty(std::int32_t eq) noexcept(true) {
528  leavesQty_=eq;
529  }
530 
531  common::Side side() const noexcept(true) {
532  return side_;
533  }
534  void side(common::Side s) noexcept(true) {
535  side_=s;
536  }
537 
538  RejectCode_t orderRejectCode() const noexcept(true) {
539  return orderRejectCode_;
540  }
541  void orderRejectCode(RejectCode_t r) noexcept(true) {
543  }
544 } __attribute__((packed));
545 
546 /**
547  Section: "6.6.2 Order Cancel Reject"
548 */
550  using RejectCode_t=mit_jse::reject_codes_enum;
552 
553  common::TransactTime_t transactTime;
554  RejectCode_t cancelRejectReason_;
556 } __attribute__((packed));
557 
558 /**
559  Section: "6.6.3 Order Mass Cancel Report"
560 */
562  using RejectCode_t=mit_jse::reject_codes_enum;
564 
565  common::TransactTime_t transactTime;
567 } __attribute__((packed));
568 
569 /**
570  Section: "6.9.2 Business Reject"
571 */
573  using RejectCode_t=mit_jse::reject_codes_enum;
575  static inline constexpr const RejectCode_t unknown_instrument=mit_jse::reject_codes_enum::MatchingEngine_Unknown_instrument_9000;
576 } __attribute__((packed));
577 
580  using base_t::base_t;
581  using ref_data=common::ref_data;
582 
583  /// Create a message from the source message.
584  /**
585  If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
586 
587  \param msg The source message from which the target message should be created.
588  */
589  template<class SrcMsg> explicit __stdcall
590  OrderCancelRequest(SrcMsg const &msg, ref_data const &rd) noexcept(true);
591 };
592 
593 struct MsgTypes {
594 
595  static inline constexpr const exchanges::common::mic_codes::ISO_10383_MIC_Codes MIC_code=exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_SOUTH_AFRICA_XJSE;
596 
597  using ref_data=common::ref_data;
598 
599  using MsgTypes_t=common::MsgType_t;
600  using UserName_t=JSE::logon_args_t::UserName_t;
601  using Password_t=JSE::logon_args_t::Password_t;
602  using SecurityID_t=common::SecurityID_t;
603  using SeqNum_t=common::SeqNum_t;
604  using Price_t=common::Price_t;
605  using Quantity_t=NewOrder::order_qty_t;
606  using ClientOrderID_t=common::ClientOrderID_t;
607  using OrderType=common::OrderType;
608  using Side=common::Side;
609  using TIF=common::TIF;
610  using ExecType=common::ExecType;
611  using AppID=common::AppID;
612  using OrderStatus=common::OrderStatus;
613  using logon_args_t=JSE::logon_args_t;
614 
615  using Header_t=common::Header;
616  using LogonRequest=JSE::Logon;
617  using LogonReply=JSE::LogonResponse;
618  using LogoutRequest=common::LogoutRequest;
619  using Logout=LogoutRequest;
620  using ClientHeartbeat=common::Heartbeat;
621  using ServerHeartbeat=common::Heartbeat;
623  using MissedMessageRequest=common::MissedMessageRequest;
624  using MissedMessageRequestAck=common::MissedMessageRequestAck;
625  using MissedMessageReport=common::MissedMessageReport;
626  using TransmissionComplete=JSE::TransmissionComplete;
627  using SystemStatus=common::SystemStatus;
628  using NewOrder_t=JSE::NewOrder;
629  using OrderCancelRequest=JSE::OrderCancelRequest;
631  using OrderCancelReplaceRequest=JSE::OrderCancelReplaceRequest;
632  using NewOrderCross=JSE::NewOrderCross;
633  using ExecutionReport=JSE::ExecutionReport;
637 
638  static inline constexpr MsgTypes_t MatchAll=std::numeric_limits<MsgTypes_t>::max()-1; ///< For the meta-state machine to allow a catch-all rule to reject anything unhandled.
639  static inline constexpr MsgTypes_t Exit=std::numeric_limits<MsgTypes_t>::max(); ///< For the meta-state machine: the exit state to exit the msm.
640 
642  NewOrder_t,
647  LogonRequest,
651  >;
652 
659  LogonReply,
660  Logout,
664  Reject,
666  >;
667 
668  enum : std::size_t {
670  boost::mpl::deref<
671  boost::mpl::min_element<
672  boost::mpl::transform_view<client_to_exchange_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
673  >::type::base
674  >::type
675  ),
677  boost::mpl::deref<
678  boost::mpl::max_element<
679  boost::mpl::transform_view<client_to_exchange_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
680  >::type::base
681  >::type
682  ),
684  boost::mpl::deref<
685  boost::mpl::min_element<
686  boost::mpl::transform_view<exchange_to_client_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
687  >::type::base
688  >::type
689  ),
691  boost::mpl::deref<
692  boost::mpl::max_element<
693  boost::mpl::transform_view<exchange_to_client_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
694  >::type::base
695  >::type
696  ),
697  min_msg_size=libjmmcg::min<std::size_t, min_size_client_to_exchange_msg, min_size_exchange_to_client_msg>::value,
698  max_msg_size=libjmmcg::max<std::size_t, max_size_client_to_exchange_msg, max_size_exchange_to_client_msg>::value,
699  header_t_size=LogonRequest::header_t_size
700  };
701  BOOST_MPL_ASSERT_RELATION(max_msg_size, >=, header_t_size);
702 
703  using msg_buffer_t=std::array<std::uint8_t, max_msg_size>;
706 
708 
709  static std::ostream &to_stream(std::ostream &) noexcept(false);
710 };
711 
712 /**
713  \test MIT JSE size tests.
714 */
715 namespace tests {
716 
717 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_size_client_to_exchange_msg);
718 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_size_exchange_to_client_msg);
719 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_msg_size);
720 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogonRequest), ==, 30);
721 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogonReply), ==, 12);
722 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogoutRequest), ==, 24);
723 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ClientHeartbeat), ==, 4);
724 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ServerHeartbeat), ==, 4);
725 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Reject), ==, 59);
726 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageRequest), ==, 9);
727 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageRequestAck), ==, 5);
728 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::TransmissionComplete), ==, 5);
729 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::SystemStatus), ==, 6);
730 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::NewOrder_t), ==, 108);
731 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelRequest), ==, 88);
732 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderMassCancelRequest), ==, 37);
733 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelReplaceRequest), ==, 136);
734 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::NewOrderCross), ==, 139);
735 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ExecutionReport), ==, 149);
736 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelReject), ==, 54);
737 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderMassCancelReport), ==, 43);
738 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::BusinessReject), ==, 54);
739 
740 }
741 
742 } } } } }
743 
744 #include "messages_impl.hpp"
745 
746 #endif