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_LSE_MESSAGES_HPP
2 #define ISIMUD_EXCHANGES_MIT_LSE_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 "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.londonstockexchange.com/products-and-services/technical-library/millennium-exchange-technical-specifications/mit203160615.pdf">"MIT203 - MILLENNIUM EXCHANGE Native Trading Gateway", Issue 11.6,
46 17 August 2015</a>.
47 */
48 namespace LSE {
49 
50 /**
51  Section: "8.4.1 New Order"
52 */
54  common::SecurityID_t instrumentID_;
56  const std::int8_t reservedField1=0;
57 
58  explicit constexpr NewOrderSpecific1(common::SecurityID_t instID) noexcept(true) FORCE_INLINE
59  : instrumentID_(instID) {
60  }
61  common::SecurityID_t instrumentID() const noexcept(true) {
62  return instrumentID_;
63  }
64  void instrumentID(common::SecurityID_t i) noexcept(true) {
65  instrumentID_=i;
66  }
67  common::MESQualifier mesQualifier() const noexcept(true) {
68  return mesQualifier_;
69  }
70  void mesQualifier(common::MESQualifier m) noexcept(true) {
71  mesQualifier_=m;
72  }
73 } __attribute__((packed));
75  using order_qty_t=std::int32_t;
76 
77  order_qty_t orderQty_;
78  order_qty_t displayQty;
79 
80  explicit constexpr NewOrderSpecific2(order_qty_t ordQty) noexcept(true) FORCE_INLINE
81  : orderQty_(ordQty), displayQty(ordQty) {
82  }
83  order_qty_t orderQty() const noexcept(true) {
84  return orderQty_;
85  }
86  void orderQty(order_qty_t i) noexcept(true) {
87  orderQty_=i;
88  }
89 } __attribute__((packed));
92  common::Price_t stoppedPrice=0;
94  common::ReservedField9_t reservedField;
95  int32_t minimumQuantity=0;
96 
98  return passiveOnlyOrder_;
99  }
101  passiveOnlyOrder_=poo;
102  }
103  static constexpr common::OrderSource FORCE_INLINE orderSource() noexcept(true) {
105  }
106  static void FORCE_INLINE orderSource(common::OrderSource) noexcept(true) {
107  }
108 } __attribute__((packed));
109 
110 /**
111  Section: "8.4.2 New Quote"
112 */
114  common::Price_t bidPrice;
115  int32_t bidSize;
116  common::Price_t askPrice;
117  int32_t askSize;
118 } __attribute__((packed));
120  common::ReservedField10_t reservedField;
121 } __attribute__((packed));
122 
123 /**
124  Section: "8.4.3 Order Cancel Replace Request"
125 */
128  common::ReservedField9_t reservedField;
129  int32_t minimumQuantity=0;
130 
132  return passiveOnlyOrder_;
133  }
135  passiveOnlyOrder_=poo;
136  }
137  static constexpr common::OrderSource FORCE_INLINE orderSource() noexcept(true) {
139  }
140  static void FORCE_INLINE orderSource(common::OrderSource) noexcept(true) {
141  }
142 } __attribute__((packed));
143 
144 /**
145  Section: "8.4.6 Execution Report"
146 */
148  using RejectCode_t=mit_lse::reject_codes_enum;
150  using order_qty_t=std::int32_t;
151 
152  order_qty_t executedQty;
153  order_qty_t leavesQty;
155  order_qty_t displayQty;
156 } __attribute__((packed));
158  const char reservedField1='\0';
162  common::PublicOrderID_t publicOrderID;
163  int32_t minimumQuantity=0;
164 } __attribute__((packed));
165 
167  common::SecurityID_t instrumentID_;
169  const std::int8_t reservedField1=0;
170  common::Segment_t segment{};
171 
172  explicit constexpr OrderMassCancelRequestSpecific1(common::SecurityID_t instID) noexcept(true) FORCE_INLINE
173  : instrumentID_(instID) {
174  }
175  common::SecurityID_t instrumentID() const noexcept(true) {
176  return instrumentID_;
177  }
178  void instrumentID(common::SecurityID_t i) noexcept(true) {
179  instrumentID_=i;
180  }
181  common::MESQualifier mesQualifier() const noexcept(true) {
182  return mesQualifier_;
183  }
184  void mesQualifier(common::MESQualifier m) noexcept(true) {
185  mesQualifier_=m;
186  }
187 } __attribute__((packed));
188 
190  using base_t=common::LogonReply<mit_lse::reject_codes_enum>;
193  using base_t::base_t;
194 
198 };
199 
202  using base_t::base_t;
203  using order_qty_t=NewOrderSpecific2::order_qty_t;
204  using ref_data=common::ref_data;
205 
206  /// Create a message from the source message.
207  /**
208  If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
209 
210  \param msg The source message from which the target message should be created.
211  */
212  template<class SrcMsg> __stdcall
213  NewOrder(SrcMsg const &msg, ref_data const &rd) noexcept(true) FORCE_INLINE;
214 };
215 
218  using base_t::base_t;
219  using order_qty_t=NewOrderSpecific2::order_qty_t;
220  using ref_data=common::ref_data;
221 
222  /// Create a message from the source message.
223  /**
224  If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
225 
226  \param msg The source message from which the target message should be created.
227  */
228  template<class SrcMsg> explicit __stdcall
229  OrderCancelReplaceRequest(SrcMsg const &msg, ref_data const &rd) noexcept(true);
230 };
231 
234  using base_t::base_t;
235  using ref_data=common::ref_data;
236 
237  /// Create a message from the source message.
238  /**
239  If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
240 
241  \param msg The source message from which the target message should be created.
242  */
243  template<class SrcMsg> explicit __stdcall
244  OrderCancelRequest(SrcMsg const &msg, ref_data const &rd) noexcept(true);
245 };
246 
247 struct MsgTypes {
248 
249  static inline constexpr const exchanges::common::mic_codes::ISO_10383_MIC_Codes MIC_code=exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON;
250 
251  using ref_data=common::ref_data;
252 
253  using MsgTypes_t=common::MsgType_t;
254  using UserName_t=common::UserName_t;
255  using Password_t=common::Password_t;
256  using SecurityID_t=common::SecurityID_t;
257  using SeqNum_t=common::SeqNum_t;
258  using Price_t=common::Price_t;
259  using Quantity_t=NewOrderSpecific2::order_qty_t;
260  using ClientOrderID_t=common::ClientOrderID_t;
261  using OrderType=common::OrderType;
262  using Side=common::Side;
263  using TIF=common::TIF;
264  using ExecType=common::ExecType;
265  using AppID=common::AppID;
266  using OrderStatus=common::OrderStatus;
267  using logon_args_t=common::logon_args_t;
268 
269  using Header_t=common::Header;
270  using NewOrder_t=LSE::NewOrder;
271  using OrderCancelRequest=LSE::OrderCancelRequest;
273  using OrderCancelReplaceRequest=LSE::OrderCancelReplaceRequest;
275  typedef common::LogonRequest LogonRequest;
276  typedef common::LogoutRequest LogoutRequest;
277  using ClientHeartbeat=common::Heartbeat;
278  using ServerHeartbeat=common::Heartbeat;
279  typedef common::MissedMessageRequest MissedMessageRequest;
281  using OrderCancelReject=common::OrderCancelReject<common::OrderCancelRejectSpecific<mit_lse::reject_codes_enum>>;
282  using OrderMassCancelReport=common::OrderMassCancelReport<common::OrderMassCancelReportSpecific<mit_lse::reject_codes_enum>>;
284  using LogonReply=LSE::LogonReply;
285  typedef common::MissedMessageRequestAck MissedMessageRequestAck;
286  typedef common::MissedMessageReport MissedMessageReport;
288  typedef common::SystemStatus SystemStatus;
289 
290  using Logout=LogoutRequest;
291 
292  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.
293  static inline constexpr MsgTypes_t Exit=std::numeric_limits<MsgTypes_t>::max(); ///< For the meta-state machine: the exit state to exit the msm.
294 
296  NewOrder_t,
300  NewQuote,
301  LogonRequest,
305  >;
306 
312  LogonReply,
313  Logout,
317  Reject,
319  >;
320 
321  enum : std::size_t {
323  boost::mpl::deref<
324  boost::mpl::min_element<
325  boost::mpl::transform_view<client_to_exchange_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
326  >::type::base
327  >::type
328  ),
330  boost::mpl::deref<
331  boost::mpl::max_element<
332  boost::mpl::transform_view<client_to_exchange_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
333  >::type::base
334  >::type
335  ),
337  boost::mpl::deref<
338  boost::mpl::min_element<
339  boost::mpl::transform_view<exchange_to_client_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
340  >::type::base
341  >::type
342  ),
344  boost::mpl::deref<
345  boost::mpl::max_element<
346  boost::mpl::transform_view<exchange_to_client_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
347  >::type::base
348  >::type
349  ),
350  min_msg_size=libjmmcg::min<std::size_t, min_size_client_to_exchange_msg, min_size_exchange_to_client_msg>::value,
351  max_msg_size=libjmmcg::max<std::size_t, max_size_client_to_exchange_msg, max_size_exchange_to_client_msg>::value,
352  header_t_size=sizeof(typename LogonRequest::Header_t)
353  };
354  BOOST_MPL_ASSERT_RELATION(max_msg_size, >=, header_t_size);
355 
356  using msg_buffer_t=std::array<std::uint8_t, max_msg_size>;
359 
361 
362  static std::ostream &to_stream(std::ostream &) noexcept(false);
363 };
364 
365 /**
366  \test MIT LSE size tests.
367 */
368 namespace tests {
369 
370 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_size_client_to_exchange_msg);
371 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_size_exchange_to_client_msg);
372 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_msg_size);
373 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogonRequest), ==, 80);
374 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogonReply), ==, 38);
375 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogoutRequest), ==, 24);
376 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ClientHeartbeat), ==, 4);
377 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ServerHeartbeat), ==, 4);
378 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageRequest), ==, 9);
379 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageRequestAck), ==, 5);
380 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageReport), ==, 5);
381 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Reject), ==, 59);
382 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::SystemStatus), ==, 6);
383 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::NewOrder_t), ==, 101);
384 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::NewQuote), ==, 76);
385 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelReplaceRequest), ==, 116);
386 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelRequest), ==, 73);
387 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderMassCancelRequest), ==, 46);
388 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ExecutionReport), ==, 155);
389 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelReject), ==, 73);
390 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderMassCancelReport), ==, 56);
391 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::BusinessReject), ==, 63);
392 
393 }
394 
395 } } } } }
396 
397 #include "messages_impl.hpp"
398 
399 #endif