root/isimud/exchanges/MIT/LSE/messages.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   1 #ifndef libjmmcg_isimud_exchanges_MIT_LSE_messages_hpp
   2 #define libjmmcg_isimud_exchanges_MIT_LSE_messages_hpp
   3 
   4 /******************************************************************************
   5 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/isimud/exchanges/MIT/LSE/messages.hpp 2330 2018-09-26 03:49:30Z jmmcg $
   6 **
   7 ** Copyright (c) 2015 by J.M.McGuiness, isimud@hussar.me.uk
   8 **
   9 ** This library is free software; you can redistribute it and/or
  10 ** modify it under the terms of the GNU Lesser General Public
  11 ** License as published by the Free Software Foundation; either
  12 ** version 2.1 of the License, or (at your option) any later version.
  13 **
  14 ** This library is distributed in the hope that it will be useful,
  15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17 ** Lesser General Public License for more details.
  18 **
  19 ** You should have received a copy of the GNU Lesser General Public
  20 ** License along with this library; if not, write to the Free Software
  21 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23 
  24 #include "config.h"
  25 #include "reject_codes.hpp"
  26 
  27 #include "../common/messages.hpp"
  28 #include "../common/ref_data.hpp"
  29 
  30 #include "core/max_min.hpp"
  31 
  32 #include <boost/mpl/assert.hpp>
  33 #include <boost/mpl/deref.hpp>
  34 #include <boost/mpl/max_element.hpp>
  35 #include <boost/mpl/min_element.hpp>
  36 #include <boost/mpl/placeholders.hpp>
  37 #include <boost/mpl/sizeof.hpp>
  38 #include <boost/mpl/transform_view.hpp>
  39 #include <boost/mpl/vector.hpp>
  40 #include <boost/variant/variant.hpp>
  41 
  42 #include <iostream>
  43 
  44 namespace isimud { namespace exchanges { namespace MIT {
  45 
  46 /**
  47         From <a href="http://www.londonstockexchange.com/products-and-services/technical-library/millennium-exchange-technical-specifications/mit203160615.pdf">"MIT203 - MILLENNIUM EXCHANGE Native Trading Gateway", Issue 11.6,
  48 17 August 2015</a>.
  49 */
  50 namespace LSE {
  51 
  52 /**
  53         Section: "8.4.1 New Order"
  54 */
  55 struct NewOrderSpecific1 {
  56         common::SecurityID_t instrumentID_;
  57         common::MESQualifier mesQualifier_=common::MESQualifier::NonMES;
  58         const std::int8_t reservedField1=0;
  59 
  60         explicit constexpr NewOrderSpecific1(common::SecurityID_t instID) noexcept(true) FORCE_INLINE
  61         : instrumentID_(instID) {
  62         }
  63         common::SecurityID_t instrumentID() const noexcept(true) {
  64                 return instrumentID_;
  65         }
  66         void instrumentID(common::SecurityID_t i) noexcept(true) {
  67                 instrumentID_=i;
  68         }
  69         common::MESQualifier mesQualifier() const noexcept(true) {
  70                 return mesQualifier_;
  71         }
  72         void mesQualifier(common::MESQualifier m) noexcept(true) {
  73                 mesQualifier_=m;
  74         }
  75 } __attribute__((packed));
  76 struct NewOrderSpecific2 {
  77         using order_qty_t=std::int32_t;
  78 
  79         order_qty_t orderQty_;
  80         order_qty_t displayQty;
  81 
  82         explicit constexpr NewOrderSpecific2(order_qty_t ordQty) noexcept(true) FORCE_INLINE
  83         : orderQty_(ordQty), displayQty(ordQty) {
  84         }
  85         order_qty_t orderQty() const noexcept(true) {
  86                 return orderQty_;
  87         }
  88         void orderQty(order_qty_t i) noexcept(true) {
  89                 orderQty_=i;
  90         }
  91 } __attribute__((packed));
  92 struct NewOrderSpecific3 {
  93         common::Anonymity anonymity=common::Anonymity::Anonymous;
  94         common::Price_t stoppedPrice=0;
  95         common::PassiveOnlyOrder passiveOnlyOrder_=common::PassiveOnlyOrder::NoConstraint;
  96         common::ReservedField9_t reservedField;
  97         int32_t minimumQuantity=0;
  98 
  99         common::PassiveOnlyOrder FORCE_INLINE passiveOnlyOrder() const noexcept(true) {
 100                 return passiveOnlyOrder_;
 101         }
 102         void FORCE_INLINE passiveOnlyOrder(common::PassiveOnlyOrder poo) noexcept(true) {
 103                 passiveOnlyOrder_=poo;
 104         }
 105         static constexpr common::OrderSource FORCE_INLINE orderSource() noexcept(true) {
 106                 return common::OrderSource::MarketParticipantDealsOnOwnAccount;
 107         }
 108         static void FORCE_INLINE orderSource(common::OrderSource) noexcept(true) {
 109         }
 110 } __attribute__((packed));
 111 
 112 /**
 113         Section: "8.4.2 New Quote"
 114 */
 115 struct NewQuoteSpecific1 {
 116         common::Price_t bidPrice;
 117         int32_t bidSize;
 118         common::Price_t askPrice;
 119         int32_t askSize;
 120 } __attribute__((packed));
 121 struct NewQuoteSpecific2 {
 122         common::ReservedField10_t reservedField;
 123 } __attribute__((packed));
 124 
 125 /**
 126         Section: "8.4.3 Order Cancel Replace Request"
 127 */
 128 struct OrderCancelReplaceRequestSpecific {
 129         common::PassiveOnlyOrder passiveOnlyOrder_;
 130         common::ReservedField9_t reservedField;
 131         int32_t minimumQuantity=0;
 132 
 133         common::PassiveOnlyOrder FORCE_INLINE passiveOnlyOrder() const noexcept(true) {
 134                 return passiveOnlyOrder_;
 135         }
 136         void FORCE_INLINE passiveOnlyOrder(common::PassiveOnlyOrder poo) noexcept(true) {
 137                 passiveOnlyOrder_=poo;
 138         }
 139         static constexpr common::OrderSource FORCE_INLINE orderSource() noexcept(true) {
 140                 return common::OrderSource::MarketParticipantDealsOnOwnAccount;
 141         }
 142         static void FORCE_INLINE orderSource(common::OrderSource) noexcept(true) {
 143         }
 144 } __attribute__((packed));
 145 
 146 /**
 147         Section: "8.4.6 Execution Report"
 148 */
 149 struct ExecutionReportSpecific1 {
 150         using RejectCode_t=mit_lse::reject_codes_enum;
 151         using RejectCodes_t=std::underlying_type<RejectCode_t>::type;
 152 
 153         int32_t executedQty;
 154         int32_t leavesQty;
 155         common::Container container;
 156         int32_t displayQty;
 157 } __attribute__((packed));
 158 struct ExecutionReportSpecific2 {
 159         const char reservedField1='\0';
 160         common::TypeOfTrade typeOfTrade;
 161         common::Capacity capacity;
 162         common::PriceDifferential priceDifferential;
 163         common::PublicOrderID_t publicOrderID;
 164         int32_t minimumQuantity=0;
 165 } __attribute__((packed));
 166 
 167 struct OrderMassCancelRequestSpecific1 {
 168         common::SecurityID_t instrumentID_;
 169         common::MESQualifier mesQualifier_=common::MESQualifier::NonMES;
 170         const std::int8_t reservedField1=0;
 171         common::Segment_t segment{};
 172 
 173         explicit constexpr OrderMassCancelRequestSpecific1(common::SecurityID_t instID) noexcept(true) FORCE_INLINE
 174         : instrumentID_(instID) {
 175         }
 176         common::SecurityID_t instrumentID() const noexcept(true) {
 177                 return instrumentID_;
 178         }
 179         void instrumentID(common::SecurityID_t i) noexcept(true) {
 180                 instrumentID_=i;
 181         }
 182         common::MESQualifier mesQualifier() const noexcept(true) {
 183                 return mesQualifier_;
 184         }
 185         void mesQualifier(common::MESQualifier m) noexcept(true) {
 186                 mesQualifier_=m;
 187         }
 188 } __attribute__((packed));
 189 
 190 struct LogonReply : public common::LogonReply<mit_lse::reject_codes_enum> {
 191         using base_t=common::LogonReply<mit_lse::reject_codes_enum>;
 192         using RejectCode_t=base_t::RejectCode_t;
 193         using RejectCodes_t=std::underlying_type<RejectCode_t>::type;
 194         using base_t::base_t;
 195 
 196         static constexpr const RejectCode_t logon_success=mit_lse::reject_codes_enum::tag_SUCCESS;
 197         static constexpr const RejectCode_t invalid_logon_details=mit_lse::reject_codes_enum::AuthServer_INVALID_USERID_PWD______1;
 198         static constexpr const RejectCode_t unknown_user=mit_lse::reject_codes_enum::AuthServer_USER_NOT_FOUND_4;
 199 };
 200 
 201 struct NewOrder : public common::NewOrder<NewOrderSpecific1, NewOrderSpecific2, NewOrderSpecific3> {
 202         using base_t=common::NewOrder<NewOrderSpecific1, NewOrderSpecific2, NewOrderSpecific3>;
 203         using base_t::base_t;
 204         using order_qty_t=NewOrderSpecific2::order_qty_t;
 205         using ref_data_t=common::ref_data_t;
 206 
 207         /// Create a message from the source message.
 208         /**
 209                 If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
 210 
 211                 \param  msg     The source message from which the target message should be created.
 212         */
 213         template<class SrcMsg> __stdcall
 214         NewOrder(SrcMsg const &msg, ref_data_t rd) noexcept(true) FORCE_INLINE;
 215 };
 216 
 217 struct OrderCancelReplaceRequest : public common::OrderCancelReplaceRequest<NewOrderSpecific1, NewOrderSpecific2, OrderCancelReplaceRequestSpecific> {
 218         using base_t=common::OrderCancelReplaceRequest<NewOrderSpecific1, NewOrderSpecific2, OrderCancelReplaceRequestSpecific>;
 219         using base_t::base_t;
 220         using order_qty_t=NewOrderSpecific2::order_qty_t;
 221         using ref_data_t=common::ref_data_t;
 222 
 223         /// Create a message from the source message.
 224         /**
 225                 If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
 226 
 227                 \param  msg     The source message from which the target message should be created.
 228         */
 229         template<class SrcMsg> explicit __stdcall
 230         OrderCancelReplaceRequest(SrcMsg const &msg, ref_data_t rd) noexcept(true);
 231 };
 232 
 233 struct OrderCancelRequest : public common::OrderCancelRequest<NewOrderSpecific1> {
 234         using base_t=common::OrderCancelRequest<NewOrderSpecific1>;
 235         using base_t::base_t;
 236         using ref_data_t=common::ref_data_t;
 237 
 238         /// Create a message from the source message.
 239         /**
 240                 If a linker error is generated, then this function will need to be specialised for the particular Msg-type.
 241 
 242                 \param  msg     The source message from which the target message should be created.
 243         */
 244         template<class SrcMsg> explicit __stdcall
 245         OrderCancelRequest(SrcMsg const &msg, ref_data_t rd) noexcept(true);
 246 };
 247 
 248 struct MsgTypes {
 249 
 250         static inline constexpr const isimud::exchanges::common::mic_codes::ISO_10383_MIC_Codes MIC_code=isimud::exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON;
 251 
 252         using ref_data=common::ref_data;
 253         using ref_data_t=common::ref_data_t;
 254 
 255         using MsgTypes_t=common::MsgType_t;
 256         using UserName_t=common::UserName_t;
 257         using Password_t=common::Password_t;
 258         using SecurityID_t=common::SecurityID_t;
 259         using Price_t=common::Price_t;
 260         using ClientOrderID_t=common::ClientOrderID_t;
 261         using OrderType=common::OrderType;
 262         using Side=common::Side;
 263         using ExecType=common::ExecType;
 264         using AppID=common::AppID;
 265         using OrderStatus=common::OrderStatus;
 266         using logon_args_t=common::logon_args_t;
 267 
 268         using Header_t=common::Header;
 269         using NewOrder=LSE::NewOrder;
 270         using OrderCancelRequest=LSE::OrderCancelRequest;
 271         typedef common::OrderMassCancelRequest<OrderMassCancelRequestSpecific1> OrderMassCancelRequest;
 272         using OrderCancelReplaceRequest=LSE::OrderCancelReplaceRequest;
 273         typedef common::NewQuote<NewQuoteSpecific1, NewQuoteSpecific2> NewQuote;
 274         typedef common::LogonRequest LogonRequest;
 275         typedef common::LogoutRequest LogoutRequest;
 276         using ClientHeartbeat=common::Heartbeat;
 277         using ServerHeartbeat=common::Heartbeat;
 278         typedef common::MissedMessageRequest MissedMessageRequest;
 279         typedef common::ExecutionReport<ExecutionReportSpecific1, ExecutionReportSpecific2> ExecutionReport;
 280         using OrderCancelReject=common::OrderCancelReject<common::OrderCancelRejectSpecific<mit_lse::reject_codes_enum>>;
 281         using OrderMassCancelReport=common::OrderMassCancelReport<common::OrderMassCancelReportSpecific<mit_lse::reject_codes_enum>>;
 282         using BusinessReject=common::BusinessReject<common::BusinessRejectSpecific<mit_lse::reject_codes_enum, mit_lse::reject_codes_enum::MatchingEngine_Unknown_instrument_9000>>;
 283         using LogonReply=LSE::LogonReply;
 284         typedef common::MissedMessageRequestAck MissedMessageRequestAck;
 285         typedef common::MissedMessageReport MissedMessageReport;
 286         using Reject=common::Reject<mit_lse::reject_codes_enum, mit_lse::reject_codes_enum::NativeGateway_Message_not_supported_102>;
 287         typedef common::SystemStatus SystemStatus;
 288 
 289         using Logout=LogoutRequest;
 290 
 291         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.
 292         static inline constexpr MsgTypes_t Exit=std::numeric_limits<MsgTypes_t>::max(); ///< For the meta-state machine: the exit state to exit the msm.
 293 
 294         using client_to_exchange_messages_t=boost::mpl::vector<
 295                 NewOrder,
 296                 OrderCancelRequest,
 297                 OrderMassCancelRequest,
 298                 OrderCancelReplaceRequest,
 299                 NewQuote,
 300                 LogonRequest,
 301                 LogoutRequest,
 302                 ClientHeartbeat,
 303                 MissedMessageRequest
 304         >;
 305 
 306         using exchange_to_client_messages_t=boost::mpl::vector<
 307                 ExecutionReport,
 308                 OrderCancelReject,
 309                 OrderMassCancelReport,
 310                 BusinessReject,
 311                 LogonReply,
 312                 Logout,
 313                 ServerHeartbeat,
 314                 MissedMessageRequestAck,
 315                 MissedMessageReport,
 316                 Reject,
 317                 SystemStatus
 318         >;
 319 
 320         enum : std::size_t {
 321                 min_size_client_to_exchange_msg=sizeof(
 322                         boost::mpl::deref<
 323                                 boost::mpl::min_element<
 324                                         boost::mpl::transform_view<client_to_exchange_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
 325                                 >::type::base
 326                         >::type
 327                 ),
 328                 max_size_client_to_exchange_msg=sizeof(
 329                         boost::mpl::deref<
 330                                 boost::mpl::max_element<
 331                                         boost::mpl::transform_view<client_to_exchange_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
 332                                 >::type::base
 333                         >::type
 334                 ),
 335                 min_size_exchange_to_client_msg=sizeof(
 336                         boost::mpl::deref<
 337                                 boost::mpl::min_element<
 338                                         boost::mpl::transform_view<exchange_to_client_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
 339                                 >::type::base
 340                         >::type
 341                 ),
 342                 max_size_exchange_to_client_msg=sizeof(
 343                         boost::mpl::deref<
 344                                 boost::mpl::max_element<
 345                                         boost::mpl::transform_view<exchange_to_client_messages_t, boost::mpl::sizeof_<boost::mpl::_1> >
 346                                 >::type::base
 347                         >::type
 348                 ),
 349                 min_msg_size=jmmcg::min<std::size_t, min_size_client_to_exchange_msg, min_size_exchange_to_client_msg>::value,
 350                 max_msg_size=jmmcg::max<std::size_t, max_size_client_to_exchange_msg, max_size_exchange_to_client_msg>::value,
 351                 header_t_size=sizeof(typename LogonRequest::Header_t)
 352         };
 353         BOOST_MPL_ASSERT_RELATION(max_msg_size, >=, header_t_size);
 354 
 355         using msg_buffer_t=std::array<std::uint8_t, max_msg_size>;
 356         using client_to_exchange_messages_container=boost::make_variant_over<client_to_exchange_messages_t>::type;
 357         using exchange_to_client_messages_container=boost::make_variant_over<exchange_to_client_messages_t>::type;
 358 
 359         static inline constexpr Price_t implied_decimal_places=common::implied_decimal_places;
 360 
 361         static std::ostream &to_stream(std::ostream &) noexcept(false);
 362 };
 363 
 364 /**
 365         \test MIT LSE size tests.
 366 */
 367 namespace tests {
 368 
 369 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_size_client_to_exchange_msg);
 370 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_size_exchange_to_client_msg);
 371 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Header_t), <=, MsgTypes::max_msg_size);
 372 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogonRequest), ==, 80);
 373 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogonReply), ==, 38);
 374 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::LogoutRequest), ==, 24);
 375 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ClientHeartbeat), ==, 4);
 376 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ServerHeartbeat), ==, 4);
 377 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageRequest), ==, 9);
 378 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageRequestAck), ==, 5);
 379 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::MissedMessageReport), ==, 5);
 380 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::Reject), ==, 59);
 381 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::SystemStatus), ==, 6);
 382 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::NewOrder), ==, 101);
 383 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::NewQuote), ==, 76);
 384 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelReplaceRequest), ==, 116);
 385 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelRequest), ==, 73);
 386 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderMassCancelRequest), ==, 46);
 387 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::ExecutionReport), ==, 155);
 388 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderCancelReject), ==, 73);
 389 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::OrderMassCancelReport), ==, 56);
 390 BOOST_MPL_ASSERT_RELATION(sizeof(MsgTypes::BusinessReject), ==, 63);
 391 
 392 }
 393 
 394 } } } }
 395 
 396 #include "messages_impl.hpp"
 397 
 398 #endif

/* [<][>][^][v][top][bottom][index][help] */