root/isimud/exchanges/common/processing_rules.hpp

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. decltype
  2. decltype

   1 #ifndef libjmmcg_isimud_exchanges_common_processing_rules_hpp
   2 #define libjmmcg_isimud_exchanges_common_processing_rules_hpp
   3 
   4 /******************************************************************************
   5 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/isimud/exchanges/common/processing_rules.hpp 2337 2018-10-05 00:51:55Z 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 <boost/mpl/front.hpp>
  25 #include <boost/mpl/pop_front.hpp>
  26 
  27 #include <map>
  28 
  29 namespace isimud { namespace exchanges { namespace common {
  30 
  31 /// A simple, MIT-protocol exchange simulator.
  32 /**
  33         The behaviour of this simulator is a simplification derived from the specification in [1].
  34         [1] "MIT203 - MILLENNIUM EXCHANGE Native Trading Gateway"
  35 */
  36 template<class SrcMsgDetails, class DestMsgDetails, class Derived, class FlowMsgTypes, class SktT>
  37 class message_responses {
  38 public:
  39         /// A type containing the details of the messages that will be received from the client.
  40         using src_msg_details_t=SrcMsgDetails;
  41         /// A type containing the details of the messages that will be sent to the exchange.
  42         using dest_msg_details_t=DestMsgDetails;
  43         using derived_t=Derived;
  44         using flow_msg_types=FlowMsgTypes;
  45         using socket_t=SktT;
  46 
  47 protected:
  48         /// Just default-construct the specified message-type and send it to the exchange socket.
  49         template<class OutMsg>
  50         struct just_send_to_exchg {
  51                 using dest_msg_t=OutMsg;
  52 
  53                 template<class ...Args>
  54                 explicit constexpr just_send_to_exchg(Args &&...) noexcept(true) {}
  55 
  56                 /**
  57                         \param exchg_skt        The socket to which any responses should be written.
  58                         \return The next state from the declaration of the table.
  59                 */
  60                 template<auto state, auto next>
  61                 decltype(next)
  62                 operator()(typename src_msg_details_t::msg_buffer_t const &, socket_t &exchg_skt, socket_t &) const {
  63                         exchg_skt.write(dest_msg_t());
  64                         return next;
  65                 }
  66         };
  67         /// Construct the specified output message-type from the input message and send it to the client socket.
  68         template<class InMsg, class OutMsg>
  69         struct convert_then_send {
  70                 using src_msg_t=InMsg;
  71                 using dest_msg_t=OutMsg;
  72 
  73                 template<class ...Args>
  74                 explicit constexpr convert_then_send(Args &&...) noexcept(true) {}
  75 
  76                 /**
  77                         \param buff     The message that was received, that shall be processed.
  78                         \param client_skt       The socket to which any responses should be written.
  79                         \return The next state from the declaration of the table.
  80                 */
  81                 template<auto state, auto next>
  82                 decltype(next)
  83                 operator()(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const {
  84                         src_msg_t const &msg=reinterpret_cast<src_msg_t const &>(buff);
  85                         assert(msg.type()==state);
  86                         client_skt.write(dest_msg_t(msg));
  87                         return next;
  88                 }
  89         };
  90         /// Construct the specified output message-type from the input message plus reference data and send it to the client socket.
  91         template<class InMsg, class OutMsg>
  92         class convert_then_send_ref_data {
  93         public:
  94                 using src_msg_t=InMsg;
  95                 using dest_msg_t=OutMsg;
  96                 using ref_data_t=typename dest_msg_details_t::ref_data_t;
  97 
  98                 explicit convert_then_send_ref_data(ref_data_t &rd) noexcept(true)
  99                 : ref_data_(rd) {}
 100                 constexpr convert_then_send_ref_data(convert_then_send_ref_data const &v) noexcept(true)
 101                 : ref_data_(v.ref_data_) {}
 102 
 103                 /**
 104                         \param buff     The message that was received, that shall be processed.
 105                         \param client_skt       The socket to which any responses should be written.
 106                         \return The next state from the declaration of the table.
 107                 */
 108                 template<auto state, auto next>
 109                 decltype(next)
 110                 operator()(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const {
 111                         src_msg_t const &msg=reinterpret_cast<src_msg_t const &>(buff);
 112                         assert(msg.type()==state);
 113                         client_skt.write(dest_msg_t(msg, ref_data_));
 114                         return next;
 115                 }
 116 
 117         private:
 118                 ref_data_t &ref_data_;
 119         };
 120         /// Construct the specified output message-type from the input message plus reference data and send it to the client socket.
 121         template<class InMsg, class OutMsg>
 122         class convert_then_send_seq_num {
 123         public:
 124                 using src_msg_t=InMsg;
 125                 using dest_msg_t=OutMsg;
 126                 using ref_data_t=typename dest_msg_details_t::ref_data_t;
 127 
 128                 explicit convert_then_send_seq_num(std::uint32_t &sq) noexcept(true)
 129                 : sequenceNumber(sq) {}
 130                 constexpr convert_then_send_seq_num(convert_then_send_seq_num const &v) noexcept(true)
 131                 : sequenceNumber(v.sequenceNumber) {}
 132 
 133                 /**
 134                         \param buff     The message that was received, that shall be processed.
 135                         \param client_skt       The socket to which any responses should be written.
 136                         \return The next state from the declaration of the table.
 137                 */
 138                 template<auto state, auto next>
 139                 decltype(next)
 140                 operator()(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const {
 141                         src_msg_t const &msg=reinterpret_cast<src_msg_t const &>(buff);
 142                         assert(msg.type()==state);
 143                         client_skt.write(dest_msg_t(msg, sequenceNumber));
 144                         return next;
 145                 }
 146 
 147         private:
 148                 std::uint32_t &sequenceNumber;
 149         };
 150         template<class OutMsg, bool ToClient>
 151         struct send_reject {
 152                 using dest_msg_t=OutMsg;
 153 
 154                 template<class ...Args>
 155                 explicit constexpr send_reject(Args &&...) noexcept(true) {}
 156 
 157                 /**
 158                         \param client_skt       The socket to which any responses should be written.
 159                         \return The next state from the declaration of the table.
 160                 */
 161                 template<auto state, auto next>
 162                 decltype(next)
 163                 operator()(typename src_msg_details_t::msg_buffer_t const &, socket_t &exchg_skt, socket_t &client_skt) const {
 164                         if constexpr (ToClient) {
 165                                 client_skt.write(dest_msg_t(dest_msg_t::unknown_msg));
 166                         } else {
 167                                 exchg_skt.write(dest_msg_t(dest_msg_t::unknown_msg));
 168                         }
 169                         return next;
 170                 }
 171         };
 172 
 173         /**
 174                 \return False to continue processing messages, true otherwise.
 175         */
 176         virtual bool process_msg(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &exchg_skt, socket_t &client_skt)=0;
 177 };
 178 
 179 /// A simple, MIT-protocol exchange simulator.
 180 /**
 181         This server is single-threaded, and permits only one client connection at a time.
 182         The behaviour of this simulator is a simplification derived from the specification in [1].
 183         [1] "MIT203 - MILLENNIUM EXCHANGE Native Trading Gateway"
 184 */
 185 template<class MsgDetails, class Derived, class SktT>
 186 class simulator_responses : public message_responses<MsgDetails, MsgDetails, Derived, typename MsgDetails::client_to_exchange_messages_t, SktT> {
 187 public:
 188         using base_t=message_responses<MsgDetails, MsgDetails, Derived, typename MsgDetails::client_to_exchange_messages_t, SktT>;
 189         using msg_details_t=typename base_t::src_msg_details_t;
 190         using src_msg_details_t=msg_details_t;
 191         using socket_t=typename base_t::socket_t;
 192         using derived_t=typename base_t::derived_t;
 193         using base_t::convert_then_send;
 194         using base_t::convert_then_send_ref_data;
 195         using base_t::send_reject;
 196         using Price_t=typename std::conditional<std::is_integral<typename msg_details_t::Price_t>::value, typename msg_details_t::Price_t, std::uint64_t>::type;
 197 
 198         /// The only valid username.
 199         static inline constexpr typename msg_details_t::UserName_t username{"usr"};
 200         /// The only valid password.
 201         static inline constexpr typename msg_details_t::Password_t password{"fubar"};
 202         /// The only valid new password.
 203         static inline constexpr typename msg_details_t::Password_t new_password{"snafu"};
 204         /// The magic quantity value.
 205         /**
 206                 A value less than this will result in a full-filled ExecutionReport, otherwise a partial fill ExecutionReport will be returned, and the remaining quantity left "on the market".
 207         */
 208         static inline constexpr std::int32_t quantity_limit=100;
 209         /// For limit orders, this is the price at which the order will be traded, otherwise it will be left "on the market".
 210         static inline constexpr Price_t price=42;
 211         /// For limit orders, this is the native, scaled price at which the order will be traded, otherwise it will be left "on the market", which is used within the simulator.
 212         static inline constexpr Price_t scaled_price=42*msg_details_t::implied_decimal_places;
 213 
 214         /**
 215                 \return False to continue processing messages, true otherwise.
 216         */
 217         virtual bool process_msg(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &exchg_skt, socket_t &client_skt)=0;
 218 
 219         std::string to_string() const noexcept(false);
 220 
 221 protected:
 222         using order_book_t=std::map<typename msg_details_t::ClientOrderID_t, typename msg_details_t::NewOrder>;
 223         order_book_t order_book;
 224         std::int32_t sequenceNumber{};
 225 
 226         simulator_responses()=default;
 227         simulator_responses(simulator_responses const &)=default;
 228 };
 229 
 230 template<class MsgDetails, class Derived, class SktT> inline std::ostream &
 231 operator<<(std::ostream &os, simulator_responses<MsgDetails, Derived, SktT> const &ec) noexcept(false);
 232 
 233 } } }
 234 
 235 #include "processing_rules_impl.hpp"
 236 
 237 #endif

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