This source file includes following definitions.
- process_msg
- to_string
- process_msg
- to_string
- decltype
- process_msg
- to_string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <functional>
22
23 namespace isimud { namespace exchanges { namespace BATSBOE { namespace common {
24
25 template<class SrcMsgDetails, class DestMsgDetails, class SktT>
26 struct client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails, SktT>::state_machine_t : jmmcg::msm::unroll::state_transition_table<state_machine_t> {
27 using msm_base_t=jmmcg::msm::unroll::state_transition_table<state_machine_t>;
28 using row_t=jmmcg::msm::unroll::row_types<typename src_msg_details_t::ExgchgMsgTypes, typename dest_msg_details_t::MsgTypes_t>;
29 using transition_table=typename msm_base_t::template rows<
30 typename row_t::template row<
31 src_msg_details_t::NewOrder::type_const,
32 typename base_t::template convert_then_send_seq_num<typename src_msg_details_t::NewOrder, typename dest_msg_details_t::NewOrder>,
33 dest_msg_details_t::NewOrder::type_const
34 >,
35 typename row_t::template row<
36 src_msg_details_t::OrderCancelRequest::type_const,
37 typename base_t::template convert_then_send_seq_num<typename src_msg_details_t::OrderCancelRequest, typename dest_msg_details_t::OrderCancelRequest>,
38 dest_msg_details_t::OrderCancelRequest::type_const
39 >,
40 typename row_t::template row<
41 src_msg_details_t::OrderCancelReplace::type_const,
42 typename base_t::template convert_then_send_seq_num<typename src_msg_details_t::OrderCancelReplace, typename dest_msg_details_t::OrderCancelReplaceRequest>,
43 dest_msg_details_t::OrderCancelReplaceRequest::type_const
44 >,
45
46 typename row_t::template row<
47 src_msg_details_t::MatchAll,
48 typename base_t::template send_reject<typename src_msg_details_t::Reject, true>,
49 dest_msg_details_t::OrderRejected::type_const
50 >
51 >;
52 };
53
54 template<class SrcMsgDetails, class DestMsgDetails, class SktT>
55 inline bool
56 client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails, SktT>::process_msg(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &exchg_skt, socket_t &client_skt) {
57 ++sequenceNumber;
58 typename src_msg_details_t::Header_t const &hdr=reinterpret_cast<typename src_msg_details_t::Header_t const &>(buff);
59 const auto last_state=msm.process(hdr.type(), buff, exchg_skt, client_skt);
60 return last_state==dest_msg_details_t::Exit;
61 }
62
63 template<class SrcMsgDetails, class DestMsgDetails, class SktT> inline std::string
64 client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails, SktT>::to_string() const noexcept(false) {
65 std::ostringstream ss;
66 ss
67 <<"\n\tCurrent sequence number="<<sequenceNumber
68 <<"Source message details: ";
69 SrcMsgDetails::to_stream(ss);
70 ss<<"\n\tDestination message details: ";
71 DestMsgDetails::to_stream(ss);
72 return ss.str();
73 }
74
75 template<class SrcMsgDetails, class DestMsgDetails, class SktT> inline std::ostream &
76 operator<<(std::ostream &os, client_to_exchange_transformations<SrcMsgDetails, DestMsgDetails, SktT> const &ec) noexcept(false) {
77 os<<ec.to_string();
78 return os;
79 }
80
81 template<class SrcMsgDetails, class DestMsgDetails, class SktT>
82 struct exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails, SktT>::state_machine_t : jmmcg::msm::unroll::state_transition_table<state_machine_t> {
83 using msm_base_t=jmmcg::msm::unroll::state_transition_table<state_machine_t>;
84 using row_t=jmmcg::msm::unroll::row_types<typename src_msg_details_t::MsgTypes_t, typename dest_msg_details_t::ExgchgMsgTypes>;
85 using transition_table=typename msm_base_t::template rows<
86
87
88
89
90
91
92
93 typename row_t::template row<
94 src_msg_details_t::ServerHeartbeat::type_const,
95 typename base_t::template convert_then_send_seq_num<typename src_msg_details_t::ClientHeartbeat, typename src_msg_details_t::ClientHeartbeat, false>,
96 dest_msg_details_t::ClientHeartbeat::type_const
97 >,
98
99
100
101
102
103
104
105 typename row_t::template row<
106 src_msg_details_t::Logout::type_const,
107 typename msm_base_t::no_op,
108 dest_msg_details_t::Exit
109 >,
110 typename row_t::template row<
111 src_msg_details_t::OrderRejected::type_const,
112 typename base_t::template convert_then_send<typename src_msg_details_t::OrderRejected, typename dest_msg_details_t::OrderRejected>,
113 dest_msg_details_t::OrderRejected::type_const
114 >,
115 typename row_t::template row<
116 src_msg_details_t::OrderCancelReject::type_const,
117 typename base_t::template convert_then_send<typename src_msg_details_t::OrderCancelReject, typename dest_msg_details_t::CancelRejected>,
118 dest_msg_details_t::CancelRejected::type_const
119 >,
120 typename row_t::template row<
121 src_msg_details_t::UserModifyRejected::type_const,
122 typename base_t::template convert_then_send<typename src_msg_details_t::UserModifyRejected, typename dest_msg_details_t::BusinessMessageReject>,
123 dest_msg_details_t::BusinessMessageReject::type_const
124 >,
125 typename row_t::template row<
126 src_msg_details_t::OrderCancelled::type_const,
127 typename base_t::template convert_then_send<typename src_msg_details_t::OrderCancelled, typename dest_msg_details_t::ExecutionReport>,
128 dest_msg_details_t::ExecutionReport::type_const
129 >,
130 typename row_t::template row<
131 src_msg_details_t::ExecutionReport::type_const,
132 typename base_t::template convert_then_send<typename src_msg_details_t::ExecutionReport, typename dest_msg_details_t::ExecutionReport>,
133 dest_msg_details_t::ExecutionReport::type_const
134 >,
135
136 typename row_t::template row<
137 src_msg_details_t::MatchAll,
138 typename base_t::template send_reject<typename dest_msg_details_t::Reject, true>,
139 dest_msg_details_t::Reject::type_const
140 >
141 >;
142 };
143
144 template<class SrcMsgDetails, class DestMsgDetails, class SktT>
145 inline bool
146 exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails, SktT>::process_msg(typename src_msg_details_t::msg_buffer_t const &buff, socket_t &exchg_skt, socket_t &client_skt) {
147 ++sequenceNumber;
148 typename src_msg_details_t::Header_t const &hdr=reinterpret_cast<typename src_msg_details_t::Header_t const &>(buff);
149 const auto last_state=msm.process(static_cast<typename src_msg_details_t::MsgTypes_t>(hdr.type()), buff, exchg_skt, client_skt);
150 return last_state==dest_msg_details_t::Exit;
151 }
152
153 template<class SrcMsgDetails, class DestMsgDetails, class SktT> inline std::string
154 exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails, SktT>::to_string() const noexcept(false) {
155 std::ostringstream os;
156 os<<"Source message details: ";
157 SrcMsgDetails::to_stream(os);
158 os<<"\n\tDestination message details: ";
159 DestMsgDetails::to_stream(os);
160 return os.str();
161 }
162
163 template<class SrcMsgDetails, class DestMsgDetails, class SktT> inline std::ostream &
164 operator<<(std::ostream &os, exchange_to_client_transformations<SrcMsgDetails, DestMsgDetails, SktT> const &ec) noexcept(false) {
165 os<<ec.to_string();
166 return os;
167 }
168
169 template<class SrcMsgDetails, class SktT>
170 struct simulator_responses<SrcMsgDetails, SktT>::state_machine_t : jmmcg::msm::unroll::state_transition_table<state_machine_t> {
171 using msm_base_t=jmmcg::msm::unroll::state_transition_table<state_machine_t>;
172 using row_t=jmmcg::msm::unroll::row_types<typename msg_details_t::MsgTypes_t, typename msg_details_t::MsgTypes_t>;
173 class LogonRequestResponse {
174 public:
175 explicit LogonRequestResponse(simulator_responses &sr) noexcept(true)
176 : sim_resp(sr) {}
177 constexpr LogonRequestResponse(LogonRequestResponse const &v) noexcept(true)
178 : sim_resp(v.sim_resp) {}
179
180
181
182
183
184
185 template<auto state, auto next>
186 auto operator()(typename msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const noexcept(false) {
187 typename msg_details_t::LogonRequest const &msg=reinterpret_cast<typename msg_details_t::LogonRequest const &>(buff);
188 assert(hdr.type()==state);
189 typename msg_details_t::LogonReply reply(sim_resp.sequenceNumber);
190 if (std::strcmp(msg.userName.begin(), sim_resp.username.begin())==0) {
191 if (std::strcmp(msg.password.begin(), sim_resp.password.begin())==0) {
192 reply.rejectCode(msg_details_t::LoginResponseStatus::LoginAccepted);
193 client_skt.write(reply);
194 } else {
195 reply.rejectCode(msg_details_t::LoginResponseStatus::NotAuthorized);
196 client_skt.write(reply);
197 }
198 } else {
199 reply.rejectCode(msg_details_t::LoginResponseStatus::NotAuthorized);
200 client_skt.write(reply);
201 }
202 return next;
203 }
204
205 private:
206 simulator_responses &sim_resp;
207 };
208 class LogoutRequestResponse {
209 public:
210 explicit LogoutRequestResponse(simulator_responses &sr) noexcept(true)
211 : sim_resp(sr) {}
212 constexpr LogoutRequestResponse(LogoutRequestResponse const &v) noexcept(true)
213 : sim_resp(v.sim_resp) {}
214
215
216
217
218
219
220 template<auto state, auto next>
221 auto operator()(typename msg_details_t::msg_buffer_t const &, socket_t &, socket_t &client_skt) const noexcept(false) {
222 const typename msg_details_t::Logout reply(sim_resp.sequenceNumber, LogoutReason::UserRequested);
223 client_skt.write(reply);
224 return next;
225 }
226
227 private:
228 simulator_responses &sim_resp;
229 };
230 class OrderCancelRequestResponse {
231 public:
232 explicit OrderCancelRequestResponse(simulator_responses &sr) noexcept(true)
233 : sim_resp(sr) {}
234 constexpr OrderCancelRequestResponse(OrderCancelRequestResponse const &v) noexcept(true)
235 : sim_resp(v.sim_resp) {}
236
237
238
239
240
241
242 template<auto state, auto>
243 typename msg_details_t::MsgTypes_t
244 operator()(typename msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const noexcept(false) {
245 typename msg_details_t::OrderCancelRequest const &msg=reinterpret_cast<typename msg_details_t::OrderCancelRequest const &>(buff);
246 assert(hdr.type()==state);
247 assert(!std::string(msg.originalClientOrderID().data()).empty());
248 auto cancelled_order=sim_resp.order_book.find(msg.originalClientOrderID());
249 if (cancelled_order!=sim_resp.order_book.end()) {
250 const typename msg_details_t::OrderCancelled reply(
251 sim_resp.sequenceNumber,
252 msg.originalClientOrderID(),
253 msg_details_t::OrderRejectReason::UserRequested,
254 cancelled_order->second.limitPrice(),
255 cancelled_order->second.side(),
256 0,
257 cancelled_order->second.orderQty()
258 );
259 sim_resp.order_book.erase(msg.originalClientOrderID());
260 client_skt.write(reply);
261 return msg_details_t::OrderCancelled::type_const;
262 } else {
263 const typename msg_details_t::OrderCancelReject reply(sim_resp.sequenceNumber, msg.originalClientOrderID(), msg_details_t::OrderRejectReason::ClOrdIDNotMatchKnownOrder);
264 client_skt.write(reply);
265 return msg_details_t::OrderCancelReject::type_const;
266 }
267 }
268
269 private:
270 simulator_responses &sim_resp;
271 };
272 class OrderCancelReplaceRequestResponse {
273 public:
274 explicit OrderCancelReplaceRequestResponse(simulator_responses &sr) noexcept(true)
275 : sim_resp(sr) {}
276 constexpr OrderCancelReplaceRequestResponse(OrderCancelReplaceRequestResponse const &v) noexcept(true)
277 : sim_resp(v.sim_resp) {}
278
279
280
281
282
283
284 template<auto state, auto>
285 typename msg_details_t::MsgTypes_t
286 operator()(typename msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const noexcept(false) {
287 typename msg_details_t::OrderCancelReplaceRequest const &msg=reinterpret_cast<typename msg_details_t::OrderCancelReplaceRequest const &>(buff);
288 assert(hdr.type()==state);
289 auto modified_order=sim_resp.order_book.find(msg.originalClientOrderID());
290 if (modified_order!=sim_resp.order_book.end()) {
291 modified_order->second.limitPrice(msg.limitPrice());
292 modified_order->second.orderQty(msg.orderQty());
293 modified_order->second.side(msg.side());
294 const typename msg_details_t::OrderModified reply(
295 sim_resp.sequenceNumber,
296 msg.originalClientOrderID(),
297 modified_order->second.limitPrice(),
298 modified_order->second.side(),
299 modified_order->second.orderQty()
300 );
301 client_skt.write(reply);
302 return msg_details_t::OrderModified::type_const;
303 } else {
304 const typename msg_details_t::UserModifyRejected reply(sim_resp.sequenceNumber, msg.originalClientOrderID(), OrderRejectReason::ClOrdIDNotMatchKnownOrder);
305 client_skt.write(reply);
306 return msg_details_t::UserModifyRejected::type_const;
307 }
308 }
309
310 private:
311 simulator_responses &sim_resp;
312 };
313 class NewOrderResponse {
314 public:
315 explicit NewOrderResponse(simulator_responses &sr) noexcept(true)
316 : sim_resp(sr) {}
317 constexpr NewOrderResponse(NewOrderResponse const &v) noexcept(true)
318 : sim_resp(v.sim_resp) {}
319
320
321
322
323
324
325 template<auto state, auto>
326 typename msg_details_t::MsgTypes_t
327 operator()(typename msg_details_t::msg_buffer_t const &buff, socket_t &, socket_t &client_skt) const noexcept(false) {
328 typename msg_details_t::NewOrder const &msg=reinterpret_cast<typename msg_details_t::NewOrder const &>(buff);
329 assert(hdr.type()==state);
330
331 if (msg.instrumentID()==sim_resp.instrumentID) {
332 typename msg_details_t::ExecutionReport reply(
333 sim_resp.sequenceNumber,
334 msg.clientOrderID(),
335 sim_resp.scaled_price,
336 msg.instrumentID(),
337 msg.side()
338 );
339 if (msg.orderQty()<=sim_resp.quantity_limit) {
340 if (msg.orderType()==msg_details_t::OrderType::Market
341 || (msg.side()==msg_details_t::Side::Buy && msg.limitPrice()<sim_resp.scaled_price)
342 || (msg.side()==msg_details_t::Side::Sell && msg.limitPrice()>sim_resp.scaled_price)) {
343 reply.executedQty(msg.orderQty());
344 reply.leavesQty(0);
345 reply.executedPrice(msg.limitPrice());
346 client_skt.write(reply);
347 } else {
348 sim_resp.order_book.emplace(msg.clientOrderID(), msg);
349 assert(!sim_resp.order_book.empty());
350 assert(sim_resp.order_book.find(msg.clientOrderID())!=sim_resp.order_book.end());
351 }
352 } else {
353 auto new_item=sim_resp.order_book.emplace(msg.clientOrderID(), msg);
354 new_item.first->second.orderQty(msg.orderQty()-sim_resp.quantity_limit);
355 reply.executedQty(sim_resp.quantity_limit);
356 reply.leavesQty(msg.orderQty()-sim_resp.quantity_limit);
357 assert(!sim_resp.order_book.empty());
358 assert(sim_resp.order_book.find(msg.clientOrderID())!=sim_resp.order_book.end());
359 client_skt.write(reply);
360 }
361 return msg_details_t::ExecutionReport::type_const;
362 } else {
363 const typename msg_details_t::OrderRejected reply(sim_resp.sequenceNumber, msg.clientOrderID(), msg_details_t::OrderRejectReason::SymbolNotSupported);
364 client_skt.write(reply);
365 return msg_details_t::OrderRejected::type_const;
366 }
367 }
368
369 private:
370 simulator_responses &sim_resp;
371 };
372 class RejectUnhandledResponse {
373 public:
374 explicit RejectUnhandledResponse(simulator_responses &sr) noexcept(true)
375 : sim_resp(sr) {}
376 constexpr RejectUnhandledResponse(RejectUnhandledResponse const &v) noexcept(true)
377 : sim_resp(v.sim_resp) {}
378
379
380
381
382
383 template<auto state, auto next>
384 decltype(next)
385 operator()(typename src_msg_details_t::msg_buffer_t const &, socket_t &, socket_t &client_skt) const {
386 const typename msg_details_t::OrderRejected response(sim_resp.sequenceNumber, typename src_msg_details_t::ClientOrderID_t(), src_msg_details_t::OrderRejected::unknown_msg);
387 client_skt.write(response);
388 return next;
389 }
390
391 private:
392 simulator_responses &sim_resp;
393 };
394 using transition_table=typename msm_base_t::template rows<
395 typename row_t::template row<
396 msg_details_t::LogonRequest::type_const,
397 LogonRequestResponse,
398 msg_details_t::LogonReply::type_const
399 >,
400
401
402
403 typename row_t::template row<
404 msg_details_t::ClientHeartbeat::type_const,
405 typename msm_base_t::no_op,
406 msg_details_t::ServerHeartbeat::type_const
407 >,
408 typename row_t::template row<
409 msg_details_t::LogoutRequest::type_const,
410 LogoutRequestResponse,
411 msg_details_t::Exit
412 >,
413 typename row_t::template row<
414 msg_details_t::OrderCancelRequest::type_const,
415 OrderCancelRequestResponse,
416 msg_details_t::OrderCancelled::type_const|msg_details_t::OrderCancelReject::type_const
417 >,
418 typename row_t::template row<
419 msg_details_t::OrderCancelReplaceRequest::type_const,
420 OrderCancelReplaceRequestResponse,
421 msg_details_t::OrderModified::type_const|msg_details_t::UserModifyRejected::type_const
422 >,
423 typename row_t::template row<
424 msg_details_t::NewOrder::type_const,
425 NewOrderResponse,
426 msg_details_t::ExecutionReport::type_const|msg_details_t::OrderRejected::type_const
427 >,
428
429 typename row_t::template row<
430 msg_details_t::MatchAll,
431 RejectUnhandledResponse,
432 msg_details_t::OrderRejected::type_const
433 >
434 >;
435 };
436
437 template<class SrcMsgDetails, class SktT>
438 inline bool
439 simulator_responses<SrcMsgDetails, SktT>::process_msg(typename msg_details_t::msg_buffer_t const &buff, socket_t &exchg_skt, socket_t &client_skt) {
440 ++(this->sequenceNumber);
441 typename msg_details_t::Header_t const &hdr=reinterpret_cast<typename msg_details_t::Header_t const &>(buff);
442 const auto last_state=msm.process(static_cast<typename msg_details_t::MsgTypes_t>(hdr.type()), buff, exchg_skt, client_skt);
443 return last_state==msg_details_t::Exit;
444 }
445
446 template<class SrcMsgDetails, class SktT> inline std::string
447 simulator_responses<SrcMsgDetails, SktT>::to_string() const noexcept(false) {
448 std::ostringstream os;
449 os
450 <<base_t::to_string()
451 <<"\n\tValid instrument ID="<<instrumentID
452 <<"\n\tInvalid instrument ID="<<invalidInstrumentID;
453 return os.str();
454 }
455
456 template<class SrcMsgDetails, class SktT> inline std::ostream &
457 operator<<(std::ostream &os, simulator_responses<SrcMsgDetails, SktT> const &ec) noexcept(false) {
458 os<<ec.to_string();
459 return os;
460 }
461
462 } } } }