21 template<
class SrcMsgDetails,
class DestMsgDetails>
24 using row_t=libjmmcg::
msm::
unroll::
row_types<
typename src_msg_details_t::MsgType_t,
typename dest_msg_details_t::MsgTypes_t>;
25 using transition_table=
typename msm_base_t::
template rows<
26 typename row_t::
template row<
27 src_msg_details_t::NewOrder_t::static_type,
28 typename base_t::
template convert_then_send_ref_data<
typename src_msg_details_t::NewOrder_t,
typename dest_msg_details_t::NewOrder_t>,
29 dest_msg_details_t::NewOrder_t::static_type
31 typename row_t::
template row<
32 src_msg_details_t::OrderCancelRequest::static_type,
33 typename base_t::
template convert_then_send_ref_data<
typename src_msg_details_t::OrderCancelRequest,
typename dest_msg_details_t::OrderCancelRequest>,
34 dest_msg_details_t::OrderCancelRequest::static_type
36 typename row_t::
template row<
37 src_msg_details_t::OrderCancelReplace::static_type,
38 typename base_t::
template convert_then_send_ref_data<
typename src_msg_details_t::OrderCancelReplace,
typename dest_msg_details_t::OrderCancelReplaceRequest>,
39 dest_msg_details_t::OrderCancelReplaceRequest::static_type
42 typename row_t::
template row<
43 src_msg_details_t::MatchAll,
44 typename base_t::
template send_reject<
typename src_msg_details_t::Reject,
true>,
45 dest_msg_details_t::Reject::static_type
53 client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails>
54 ::
process_msg(
typename src_msg_details_t::msg_buffer_t
const &buff, SktT &exchg_skt, SktT &dest_skt) {
55 typename src_msg_details_t::Header_t
const &hdr=
reinterpret_cast<
typename src_msg_details_t::Header_t
const &>(buff);
56 const auto last_state=msm.process(hdr.type(), buff, exchg_skt, dest_skt);
57 return last_state==dest_msg_details_t::Exit;
60 template<
class SrcMsgDetails,
class DestMsgDetails>
inline std::string
61 client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails>::
to_string()
const noexcept(
false) {
62 std::ostringstream ss;
63 ss<<
"Source message details: ";
64 SrcMsgDetails::to_stream(ss);
65 ss<<
"\n\tDestination message details: ";
66 DestMsgDetails::to_stream(ss);
70 template<
class SrcMsgDetails,
class DestMsgDetails>
inline std::ostream &
71 operator<<(
std::ostream &os, client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails>
const &ec)
noexcept(
false) {
76 template<
class SrcMsgDetails,
class DestMsgDetails>
77 struct exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails>::business_state_machine_t : libjmmcg::
msm::
unroll::
state_transition_table<business_state_machine_t> {
79 using row_t=libjmmcg::
msm::
unroll::
row_types<
typename src_msg_details_t::MsgTypes_t,
typename dest_msg_details_t::MsgType_t>;
90 assert(!ref_data_.lookup_isin().empty());
93 : ref_data_(nor.ref_data_) {
94 assert(!ref_data_.lookup_isin().empty());
97 template<
auto state,
auto next,
class SktT,
class ClientCxn>
99 operator()(
typename src_msg_details_t::msg_buffer_t
const &buff, SktT &, ClientCxn &client_cxn)
const noexcept(
false) {
100 typename src_msg_details_t::ExecutionReport
const &msg=
reinterpret_cast<
typename src_msg_details_t::ExecutionReport
const &>(buff);
101 assert(msg.type()==state);
102 switch (msg.orderStatus()) {
109 assert(!ref_data_.lookup_isin().empty());
110 const typename dest_msg_details_t::ExecutionReport reply(msg, ref_data_);
111 client_cxn->socket().write(reply);
112 return dest_msg_details_t::ExecutionReport::static_type;
116 const typename dest_msg_details_t::OrderRejected reply(msg);
117 client_cxn->socket().write(reply);
118 return dest_msg_details_t::OrderRejected::static_type;
124 ref_data
const &ref_data_;
126 using transition_table=
typename msm_base_t::
template rows<
133 typename row_t::
template row<
134 src_msg_details_t::Reject::static_type,
135 typename base_t::
template convert_then_send<
typename src_msg_details_t::Reject,
typename dest_msg_details_t::OrderRejected>,
136 dest_msg_details_t::OrderRejected::static_type
144 typename row_t::
template row<
145 src_msg_details_t::OrderCancelReject::static_type,
146 typename base_t::
template convert_then_send<
typename src_msg_details_t::OrderCancelReject,
typename dest_msg_details_t::CancelRejected>,
147 dest_msg_details_t::CancelRejected::static_type
149 typename row_t::
template row<
150 src_msg_details_t::ExecutionReport::static_type,
152 dest_msg_details_t::ExecutionReport::static_type|dest_msg_details_t::OrderRejected::static_type
155 typename row_t::
template row<
156 src_msg_details_t::MatchAll,
157 typename base_t::
template send_reject<
typename dest_msg_details_t::Reject,
true>,
158 dest_msg_details_t::Reject::static_type
163 template<
class SrcMsgDetails,
class DestMsgDetails>
164 struct exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails>::admin_state_machine_t : libjmmcg::
msm::
unroll::
state_transition_table<admin_state_machine_t> {
166 using row_t=libjmmcg::
msm::
unroll::
row_types<
typename src_msg_details_t::MsgTypes_t,
typename dest_msg_details_t::MsgType_t>;
176 template<
auto state,
auto next,
class SktT,
class ClientCxn>
177 auto operator()(
typename src_msg_details_t::msg_buffer_t
const &buff, SktT &, ClientCxn &)
const noexcept(
false) {
178 typename src_msg_details_t::LogonReply
const &msg=
reinterpret_cast<
typename src_msg_details_t::LogonReply
const &>(buff);
179 assert(msg.type()==state);
180 switch (msg.rejectCode()) {
181 case src_msg_details_t::LogonReply::RejectCode_t::tag_SUCCESS:
185 std::ostringstream ss;
186 ss<<
"Unrecognised LogonResponse reject-code="<<
static_cast<
typename src_msg_details_t::LogonReply::RejectCodes_t>(msg.rejectCode())<<
", '"<<msg.rejectCode()<<
"'.";
187 throw std::runtime_error(ss.str());
193 using transition_table=
typename msm_base_t::
template rows<
197 typename row_t::
template row<
198 src_msg_details_t::ServerHeartbeat::static_type,
199 typename base_t::
template just_send_to_exchg<
typename src_msg_details_t::ClientHeartbeat>,
200 dest_msg_details_t::ClientHeartbeat::static_type
205 typename row_t::
template row<
206 src_msg_details_t::Logout::static_type,
207 typename msm_base_t::no_op,
208 dest_msg_details_t::Exit
210 typename row_t::
template row<
211 src_msg_details_t::LogonReply::static_type,
213 dest_msg_details_t::LogonRequest::static_type
221 typename row_t::
template row<
222 src_msg_details_t::BusinessReject::static_type,
223 typename base_t::
template convert_then_send<
typename src_msg_details_t::BusinessReject,
typename dest_msg_details_t::BusinessMessageReject>,
224 dest_msg_details_t::BusinessMessageReject::static_type
227 typename row_t::
template row<
228 src_msg_details_t::MatchAll,
229 typename base_t::
template match_all_response<business_machine>,
230 dest_msg_details_t::Reject::static_type
236 template<
class SktT,
class ClientCxn>
238 exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails>
239 ::
process_msg(
typename src_msg_details_t::msg_buffer_t
const &buff, SktT &exchg_skt, ClientCxn &client_skt) {
240 typename src_msg_details_t::Header_t
const &hdr=
reinterpret_cast<
typename src_msg_details_t::Header_t
const &>(buff);
241 const auto last_state=admin_msm.process(hdr.type(), buff, exchg_skt, client_skt);
242 return last_state==dest_msg_details_t::Exit;
245 template<
class SrcMsgDetails,
class DestMsgDetails>
inline std::string
246 exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails>::
to_string()
const noexcept(
false) {
247 std::ostringstream os;
248 os<<
"Source message details: ";
249 SrcMsgDetails::to_stream(os);
250 os<<
"\n\tDestination message details: ";
251 DestMsgDetails::to_stream(os);
255 template<
class SrcMsgDetails,
class DestMsgDetails>
inline std::ostream &
256 operator<<(
std::ostream &os, exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails>
const &ec)
noexcept(
false) {
261 template<
class SrcMsgDetails>
264 using row_t=libjmmcg::
msm::
unroll::
row_types<
typename msg_details_t::MsgTypes_t,
typename msg_details_t::MsgTypes_t>;
274 template<
auto state,
auto next,
class SktT>
275 auto operator()(
typename msg_details_t::msg_buffer_t
const &buff, SktT &, SktT &client_skt)
const noexcept(
false) {
276 typename msg_details_t::LogonRequest
const &msg=
reinterpret_cast<
typename msg_details_t::LogonRequest
const &>(buff);
277 assert(msg.type()==state);
278 typename msg_details_t::LogonReply reply;
279 if (
std::strcmp(msg.userName.begin(), simulator_responses::username.begin())==0) {
280 if (
std::strcmp(msg.password.begin(), simulator_responses::password.begin())==0) {
281 reply.rejectCode(msg_details_t::LogonReply::RejectCode_t::tag_SUCCESS);
282 client_skt.write(reply);
284 reply.rejectCode(msg_details_t::LogonReply::invalid_logon_details);
285 client_skt.write(reply);
288 reply.rejectCode(msg_details_t::LogonReply::unknown_user);
289 client_skt.write(reply);
303 template<
auto state,
auto next,
class SktT>
304 auto operator()(
typename msg_details_t::msg_buffer_t
const &, SktT &, SktT &client_skt)
const noexcept(
false) {
305 client_skt.write(
typename msg_details_t::Logout(simulator_responses::logout_reason));
306 std::this_thread::sleep_for(simulator_responses::logout_timeout);
312 enum :
typename msg_details_t::MsgTypes_t {
313 exec_report=
static_cast<
typename std::underlying_type<
decltype(msg_details_t::ExecutionReport::static_type)>::type>(msg_details_t::ExecutionReport::static_type),
314 cancel_reject=
static_cast<
typename std::underlying_type<
decltype(msg_details_t::OrderCancelReject::static_type)>::type>(msg_details_t::OrderCancelReject::static_type),
320 assert(
dynamic_cast<simulator_responses *>(&sim_resp));
323 : sim_resp(nor.sim_resp) {}
330 template<
auto state,
auto,
class SktT>
332 operator()(
typename msg_details_t::msg_buffer_t
const &buff, SktT &, SktT &client_skt)
const noexcept(
false) {
333 typename msg_details_t::OrderCancelRequest
const &msg=
reinterpret_cast<
typename msg_details_t::OrderCancelRequest
const &>(buff);
334 assert(msg.type()==state);
335 assert(!std::string(msg.originalClientOrderID().data()).empty());
336 assert(
dynamic_cast<simulator_responses *>(&sim_resp));
337 auto const cancelled_order=sim_resp.order_book.find(msg.originalClientOrderID());
338 if (cancelled_order!=sim_resp.order_book.end()) {
339 typename msg_details_t::ExecutionReport reply(
340 sim_resp.sequenceNumber,
341 msg.originalClientOrderID(),
342 msg_details_t::AppID::Partition1,
343 msg_details_t::ExecType::Cancelled,
344 cancelled_order->second.limitPrice(),
345 cancelled_order->second.instrumentID(),
346 cancelled_order->second.side()
348 reply.orderStatus(msg_details_t::OrderStatus::Cancelled);
349 reply.executedQty(0);
350 reply.leavesQty(cancelled_order->second.orderQty());
351 sim_resp.order_book.erase(msg.originalClientOrderID());
352 client_skt.write(reply);
353 return msg_details_t::ExecutionReport::static_type;
355 const typename msg_details_t::OrderCancelReject reply(sim_resp.sequenceNumber, msg.originalClientOrderID());
356 client_skt.write(reply);
357 return msg_details_t::OrderCancelReject::static_type;
362 simulator_responses &sim_resp;
366 enum :
typename msg_details_t::MsgTypes_t {
367 exec_report=
static_cast<
typename std::underlying_type<
decltype(msg_details_t::ExecutionReport::static_type)>::type>(msg_details_t::ExecutionReport::static_type),
368 cancel_reject=
static_cast<
typename std::underlying_type<
decltype(msg_details_t::OrderCancelReject::static_type)>::type>(msg_details_t::OrderCancelReject::static_type),
374 assert(
dynamic_cast<simulator_responses *>(&sim_resp));
377 : sim_resp(nor.sim_resp) {}
384 template<
auto state,
auto,
class SktT>
386 operator()(
typename msg_details_t::msg_buffer_t
const &buff, SktT &, SktT &client_skt)
const noexcept(
false) {
387 typename msg_details_t::OrderCancelReplaceRequest
const &msg=
reinterpret_cast<
typename msg_details_t::OrderCancelReplaceRequest
const &>(buff);
388 assert(msg.type()==state);
389 assert(
dynamic_cast<simulator_responses *>(&sim_resp));
390 auto const modified_order=sim_resp.order_book.find(msg.originalClientOrderID());
391 if (modified_order!=sim_resp.order_book.end()) {
392 modified_order->second.limitPrice(msg.limitPrice());
393 modified_order->second.orderQty(msg.orderQty());
394 modified_order->second.tif(msg.tif());
395 modified_order->second.side(msg.side());
396 typename msg_details_t::ExecutionReport reply(
397 sim_resp.sequenceNumber,
398 msg.originalClientOrderID(),
399 msg_details_t::AppID::Partition1,
400 msg_details_t::ExecType::Replaced,
401 modified_order->second.limitPrice(),
402 modified_order->second.instrumentID(),
403 modified_order->second.side()
405 reply.orderStatus(msg_details_t::OrderStatus::Cancelled);
406 reply.executedQty(0);
407 reply.leavesQty(modified_order->second.orderQty());
408 client_skt.write(reply);
409 return msg_details_t::ExecutionReport::static_type;
411 const typename msg_details_t::OrderCancelReject reply(sim_resp.sequenceNumber, msg.originalClientOrderID());
412 client_skt.write(reply);
413 return msg_details_t::OrderCancelReject::static_type;
418 simulator_responses &sim_resp;
422 enum :
typename msg_details_t::MsgTypes_t {
423 exec_report=
static_cast<
typename std::underlying_type<
decltype(msg_details_t::ExecutionReport::static_type)>::type>(msg_details_t::ExecutionReport::static_type),
424 business_reject=
static_cast<
typename std::underlying_type<
decltype(msg_details_t::BusinessReject::static_type)>::type>(msg_details_t::BusinessReject::static_type),
430 assert(
dynamic_cast<simulator_responses *>(&sim_resp));
433 : sim_resp(nor.sim_resp) {}
440 template<
auto state,
auto next,
class SktT>
442 operator()(
typename msg_details_t::msg_buffer_t
const &buff, SktT &, SktT &client_skt)
const noexcept(
false) {
443 typename msg_details_t::NewOrder_t
const &msg=
reinterpret_cast<
typename msg_details_t::NewOrder_t
const &>(buff);
444 assert(msg.type()==state);
445 assert(
dynamic_cast<simulator_responses *>(&sim_resp));
447 typename msg_details_t::ExecutionReport reply(
448 sim_resp.sequenceNumber,
450 msg_details_t::AppID::Partition1,
451 msg_details_t::ExecType::New,
452 simulator_responses::scaled_price,
456 if (msg.orderQty()<=simulator_responses::quantity_limit) {
457 if (msg.orderType()==msg_details_t::OrderType::Market
458 || (msg.side()==msg_details_t::Side::Buy && msg.limitPrice()<simulator_responses::scaled_price)
459 || (msg.side()==msg_details_t::Side::Sell && msg.limitPrice()>simulator_responses::scaled_price)) {
460 reply.orderStatus(msg_details_t::OrderStatus::Filled);
461 reply.executedQty(msg.orderQty());
463 reply.executedPrice(msg.limitPrice());
464 client_skt.write(reply);
466 sim_resp.order_book.emplace(msg.clientOrderID(), msg);
467 assert(!sim_resp.order_book.empty());
468 assert(sim_resp.order_book.find(msg.clientOrderID())!=sim_resp.order_book.end());
469 reply.orderStatus(msg_details_t::OrderStatus::New);
470 reply.executedQty(0);
471 reply.leavesQty(msg.orderQty());
472 reply.executedPrice(0);
473 client_skt.write(reply);
476 auto new_item=sim_resp.order_book.emplace(msg.clientOrderID(), msg);
477 new_item.first->second.orderQty(msg.orderQty()-simulator_responses::quantity_limit);
478 reply.orderStatus(msg_details_t::OrderStatus::Partiallyfilled);
479 reply.executedQty(simulator_responses::quantity_limit);
480 reply.leavesQty(msg.orderQty()-simulator_responses::quantity_limit);
481 assert(!sim_resp.order_book.empty());
482 assert(sim_resp.order_book.find(msg.clientOrderID())!=sim_resp.order_book.end());
483 client_skt.write(reply);
485 return msg_details_t::ExecutionReport::static_type;
487 typename msg_details_t::BusinessReject reply(
488 sim_resp.sequenceNumber,
491 reply.rejectCode(msg_details_t::BusinessReject::unknown_instrument);
492 client_skt.write(reply);
493 return msg_details_t::BusinessReject::static_type;
498 simulator_responses &sim_resp;
500 using transition_table=
typename msm_base_t::
template rows<
501 typename row_t::
template row<
502 msg_details_t::LogonRequest::static_type,
504 msg_details_t::LogonReply::static_type
509 typename row_t::
template row<
510 msg_details_t::ClientHeartbeat::static_type,
511 typename msm_base_t::no_op,
512 msg_details_t::ServerHeartbeat::static_type
514 typename row_t::
template row<
515 msg_details_t::LogoutRequest::static_type,
519 typename row_t::
template row<
520 msg_details_t::OrderCancelRequest::static_type,
524 typename row_t::
template row<
525 msg_details_t::OrderCancelReplaceRequest::static_type,
529 typename row_t::
template row<
530 msg_details_t::NewOrder_t::static_type,
535 typename row_t::
template row<
536 msg_details_t::MatchAll,
537 typename base_t::
template send_reject<
typename msg_details_t::Reject,
true>,
538 msg_details_t::Reject::static_type
544 template<
class SktT,
class ClientCxn>
546 simulator_responses<SrcMsgDetails>::
process_msg(
typename msg_details_t::msg_buffer_t
const &buff, SktT &exchg_skt, ClientCxn &client_cxn) {
547 ++(
this->sequenceNumber);
548 typename msg_details_t::Header_t
const &hdr=
reinterpret_cast<
typename msg_details_t::Header_t
const &>(buff);
549 const auto last_state=msm.process(hdr.type(), buff, exchg_skt, client_cxn);
550 return last_state==msg_details_t::Exit;
553 template<
class SrcMsgDetails>
inline std::string
554 simulator_responses<SrcMsgDetails>::
to_string()
const noexcept(
false) {
555 std::ostringstream os;
557 <<base_t::to_string()
558 <<
"\n\tValid instrument ID="<<instrumentID
559 <<
"\n\tInvalid instrument ID="<<invalidInstrumentID
560 <<
"\n\tLogout reason: '"<<logout_reason<<
"'"
561 "\n\tLogout timeout="<<logout_timeout.count()<<
" sec";
565 template<
class SrcMsgDetails>
inline std::ostream &
566 operator<<(
std::ostream &os, simulator_responses<SrcMsgDetails>
const &ec)
noexcept(
false) {