libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
batsboe_exchanges.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2015 by J.M.McGuiness, isimud@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "stdafx.h"
20 
21 #define BOOST_TEST_MODULE isimud_tests
22 #include <boost/test/included/unit_test.hpp>
23 
24 #include <boost/mpl/list.hpp>
25 
26 #include "../exchanges/FIX/v5.0sp2/fix.hpp"
27 #include "../exchanges/BATSBOE/EU/v1/batsboe.hpp"
28 #include "../exchanges/BATSBOE/EU/v1/batsboe_sim.hpp"
29 #include "../exchanges/BATSBOE/EU/v2/batsboe.hpp"
30 #include "../exchanges/BATSBOE/EU/v2/batsboe_sim.hpp"
31 #include "../exchanges/BATSBOE/US/v1/batsboe.hpp"
32 #include "../exchanges/BATSBOE/US/v1/batsboe_sim.hpp"
33 #include "../exchanges/BATSBOE/US/v2/batsboe.hpp"
34 #include "../exchanges/BATSBOE/US/v2/batsboe_sim.hpp"
35 #include "../exchanges/conversions/fix_to_batsboe_eu_conversions.hpp"
36 #include "../exchanges/conversions/fix_to_batsboe_us_conversions.hpp"
37 #include "../exchanges/conversions/batsboe_eu_to_fix_conversions.hpp"
38 #include "../exchanges/conversions/batsboe_us_to_fix_conversions.hpp"
39 
40 using namespace libjmmcg;
41 using namespace libisimud;
42 
43 using api_thread_traits=ppd::thread_params<ppd::platform_api>;
44 
45 const boost::asio::ip::address localhost(boost::asio::ip::address_v4::loopback());
46 const unsigned short client_port=12377u;
47 const boost::asio::ip::address primary_gw(boost::asio::ip::address_v4::loopback());
48 const unsigned short unused_primary_port=client_port+1;
49 const exchanges::BATSBOE::common::SeqNum_t sequenceNumber(1);
50 
51 typedef boost::mpl::list<
52  std::pair<exchanges::BATSBOE::EU::v1::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::BATSBOE::EU::v1::simulator_t>,
53 // TODO std::pair<exchanges::BATSBOE::EU::v2::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::BATSBOE::EU::v2::simulator_t>,
54  std::pair<exchanges::BATSBOE::US::v1::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::BATSBOE::US::v1::simulator_t>//,
55 // TODO std::pair<exchanges::BATSBOE::US::v2::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::BATSBOE::US::v2::simulator_t>
56 > exchg_t_types;
57 
58 template<class exchg_t>
59 struct only_sim {
60  using link_t=typename exchg_t::first_type;
61  using simulator_t=typename exchg_t::second_type;
62  using conn_pol_t=typename link_t::exchg_link_t::conn_pol_t;
63  using connection_t=exchanges::common::connection<
64  typename simulator_t::msg_processor_t::msg_details_t,
65  conn_pol_t
66  >;
67 
68  const typename conn_pol_t::gateways_t gateways{
70  };
71  const conn_pol_t conn_pol{
72  gateways,
74  0,
75  {"000"},
78  false
79  },
82  }
83  };
84  no_latency_timestamps ts{0};
85  simulator_t svr{
86  primary_gw,
88  simulator_t::socket_t::socket_priority::low,
89  api_thread_traits::processor_mask_type(exchanges::common::thread_traits::exchange_simulator_thread.core),
90  exchanges::common::thread_traits::exchange_simulator_thread.priority,
91  typename simulator_t::proc_rules_t(),
92  ts,
93  "sim" LIBJMMCG_ENQUOTE(__LINE__)
94  };
95 };
96 
97 template<class exchg_t>
98 struct simulator_and_link : public only_sim<exchg_t> {
99  using base_t=only_sim<exchg_t>;
100  using link_t=typename base_t::link_t;
101 
102  no_latency_timestamps ts{0};
103  link_t link{
104  typename link_t::client_link_t::ctor_args{
105  localhost,
106  client_port,
107  typename link_t::client_link_t::proc_rules_t(sequenceNumber)
108  },
109  this->conn_pol,
110  link_t::socket_t::socket_priority::high,
111  link_t::socket_t::socket_priority::low,
112  typename link_t::exchg_to_client_proc_rules_t(sequenceNumber),
113  ts,
114  "link" LIBJMMCG_ENQUOTE(__LINE__)
115  };
116 };
117 
118 template<class exchg_t>
119 struct simulator_and_link_client_too : public simulator_and_link<exchg_t> {
120  exchanges::FIX::v5_0sp2::connection_t client{
124  )
125  ),
128  };
129 };
130 
131 BOOST_AUTO_TEST_SUITE(exchange_gateways)
132 
133 BOOST_AUTO_TEST_SUITE(client_initiated)
134 
135 /**
136  \test Verify Logon - no clients.
137  ==========================
138  Verify that the link can log on to the exchange, with no clients.
139 */
140 BOOST_AUTO_TEST_CASE_TEMPLATE(logon_no_clients, exchg_t, exchg_t_types) {
141  using fixture_t=simulator_and_link<exchg_t>;
142 
143  const fixture_t f{};
144 
145  BOOST_CHECK(f.link.is_logged_on());
146 }
147 
148 /**
149  \test Verify that gateway can re-Logon.
150  =================================
151  Verify that the gateway can re-log on to the exchange, without any clients.
152 */
153 BOOST_AUTO_TEST_CASE_TEMPLATE(re_logon_no_clients, exchg_t, exchg_t_types) {
154  using fixture_t=only_sim<exchg_t>;
155 
156  const fixture_t f;
157  no_latency_timestamps ts{0};
158 
159  {
160  const typename fixture_t::link_t link{
161  typename fixture_t::link_t::client_link_t::ctor_args{
162  localhost,
163  client_port,
164  typename fixture_t::link_t::client_link_t::proc_rules_t(sequenceNumber)
165  },
166  f.conn_pol,
169  typename fixture_t::link_t::exchg_to_client_proc_rules_t(sequenceNumber),
170  ts,
171  "link" LIBJMMCG_ENQUOTE(__LINE__)
172  };
173  BOOST_CHECK(link.is_logged_on());
174  }
175  {
176  const typename fixture_t::link_t link{
177  typename fixture_t::link_t::client_link_t::ctor_args{
178  localhost,
179  client_port,
180  typename fixture_t::link_t::client_link_t::proc_rules_t(sequenceNumber)
181  },
182  f.conn_pol,
183  fixture_t::link_t::socket_t::socket_priority::high,
184  fixture_t::link_t::socket_t::socket_priority::low,
185  typename fixture_t::link_t::exchg_to_client_proc_rules_t(sequenceNumber),
186  ts,
187  "link" LIBJMMCG_ENQUOTE(__LINE__)
188  };
189  BOOST_CHECK(link.is_logged_on());
190  }
191 }
192 
193 /**
194  \test Verify Logon - with a client.
195  =============================
196  Verify that the link can log on to the exchange and remains logged on, with a client connected.
197 */
198 BOOST_AUTO_TEST_CASE_TEMPLATE(logon_with_a_client, exchg_t, exchg_t_types) {
199  using fixture_t=simulator_and_link<exchg_t>;
200 
201  const fixture_t f;
202 
203  BOOST_CHECK(f.link.is_logged_on());
204  {
205  const exchanges::FIX::v5_0sp2::connection_t client(
206  exchanges::FIX::v5_0sp2::connection_t::conn_pol_t(
207  typename exchanges::FIX::v5_0sp2::connection_t::conn_pol_t::gateways_t(
208  std::make_pair(localhost, client_port)
209  )
210  ),
211  socket::socket_priority::high,
212  exchanges::common::thread_traits::client_to_exchange_thread.core
213  );
214  BOOST_CHECK(f.link.is_logged_on());
215  }
216  BOOST_CHECK(f.link.is_logged_on());
217 }
218 
219 /**
220  \test Verify that clients can re-connect to logged-on gateway.
221  ========================================================
222  Verify that the gateway can re-log on to the exchange, with a connected client.
223 */
224 BOOST_AUTO_TEST_CASE_TEMPLATE(re_connect_client_with_logon, exchg_t, exchg_t_types) {
225  using fixture_t=simulator_and_link<exchg_t>;
226 
227  const fixture_t f;
228 
229  BOOST_CHECK(f.link.is_logged_on());
230  {
231  const exchanges::FIX::v5_0sp2::connection_t client(
232  exchanges::FIX::v5_0sp2::connection_t::conn_pol_t(
233  typename exchanges::FIX::v5_0sp2::connection_t::conn_pol_t::gateways_t(
234  std::make_pair(localhost, client_port)
235  )
236  ),
237  socket::socket_priority::high,
238  exchanges::common::thread_traits::client_to_exchange_thread.core
239  );
240  BOOST_CHECK(f.link.is_logged_on());
241  }
242  BOOST_CHECK(f.link.is_logged_on());
243  {
244  const exchanges::FIX::v5_0sp2::connection_t client(
245  exchanges::FIX::v5_0sp2::connection_t::conn_pol_t(
246  typename exchanges::FIX::v5_0sp2::connection_t::conn_pol_t::gateways_t(
247  std::make_pair(localhost, client_port)
248  )
249  ),
250  socket::socket_priority::high,
251  exchanges::common::thread_traits::client_to_exchange_thread.core
252  );
253  BOOST_CHECK(f.link.is_logged_on());
254  }
255  BOOST_CHECK(f.link.is_logged_on());
256 }
257 
258 /**
259  \test Verify Heartbeats - no clients.
260  ===============================
261  Verify that Heartbeats occur, without any clients.
262 */
263 BOOST_AUTO_TEST_CASE_TEMPLATE(heartbeats_no_clients, exchg_t, exchg_t_types) {
264  using fixture_t=simulator_and_link<exchg_t>;
265 
266  const fixture_t f;
267 
268  std::this_thread::sleep_for(std::chrono::seconds(fixture_t::simulator_t::svr_mgr_t::heartbeats_t::heartbeat_interval*(fixture_t::simulator_t::svr_mgr_t::heartbeats_t::max_missed_heartbeats+1)));
269  BOOST_CHECK(f.link.is_logged_on());
270 }
271 
272 /**
273  \test Verify Heartbeats - with client.
274  ================================
275  Verify that Heartbeats occur, with a connected client.
276 */
277 BOOST_AUTO_TEST_CASE_TEMPLATE(heartbeats_with_client, exchg_t, exchg_t_types) {
278  using fixture_t=simulator_and_link<exchg_t>;
279 
280  const fixture_t f;
281 
282  std::this_thread::sleep_for(std::chrono::seconds(fixture_t::simulator_t::svr_mgr_t::heartbeats_t::heartbeat_interval*(fixture_t::simulator_t::svr_mgr_t::heartbeats_t::max_missed_heartbeats+1)));
283  BOOST_CHECK(f.link.is_logged_on());
284 }
285 
286 /**
287  \test Response to an invalid NewOrder.
288  ================================
289  Verify that the response to an invalid NewOrder is a BusinessReject.
290 */
291 BOOST_AUTO_TEST_CASE_TEMPLATE(reject, exchg_t, exchg_t_types) {
292  using fixture_t=simulator_and_link_client_too<exchg_t>;
293 
294  fixture_t f;
295 
296  BOOST_CHECK(f.link.is_logged_on());
297 
298  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer fix_buffer={
299  "8=FIX.5.0\0019=154\00135=D\00134=10\00143=N\00149=VENDOR\00150=CUSTOME\00156=BROKER\00160=19980930-09:25:58\0011=XQCCFUND\00111=10\00121=1\00155=EK\00148=GB0000595859\00122=4\00154=1\00138=10000\00140=2\00144=76.750000\00159=0\00110=092\001"
300  };
301  exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &>(*fix_buffer.begin());
302  BOOST_CHECK_EQUAL(fix_msg.type(), exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle::static_type);
303  BOOST_REQUIRE_NO_THROW(f.client.send(fix_msg));
304  BOOST_CHECK(f.link.is_logged_on());
305  exchanges::FIX::v5_0sp2::MsgTypes::OrderRejected receive_fix_msg;
306  BOOST_REQUIRE_NO_THROW(f.client.receive(receive_fix_msg));
307  BOOST_CHECK(receive_fix_msg.is_valid());
308  auto const ref_seq_num=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::RefSeqNum>();
309  BOOST_CHECK_EQUAL(std::string(ref_seq_num.first, ref_seq_num.second), "2");
310  BOOST_CHECK(f.link.is_logged_on());
311 }
312 
313 /**
314  \test Response to an invalid OrderCancelRequest.
315  ==========================================
316  Verify that the response to an invalid OrderCancelRequest is a CancelRejected.
317 */
318 BOOST_AUTO_TEST_CASE_TEMPLATE(cancel_reject, exchg_t, exchg_t_types) {
319  using fixture_t=simulator_and_link_client_too<exchg_t>;
320 
321  fixture_t f;
322 
323  BOOST_CHECK(f.link.is_logged_on());
324 
325  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer fix_buffer={
326  "8=FIX.5.0\0019=141\00135=F\00111=10\00141=10\00148=GB00BH4HKS39\00149=VENDOR\00156=BROKER\00134=10\00152=20000426-12:05:06\00155=EK\00154=1\00160=19980930-09:25:58\00138=99\00140=1\00144=43.000000\00159=0\00110=101\001"
327  };
328  exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelRequest const &fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelRequest const &>(*fix_buffer.begin());
329  BOOST_CHECK_EQUAL(fix_msg.type(), exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelRequest::static_type);
330  BOOST_REQUIRE_NO_THROW(f.client.send(fix_msg));
331  BOOST_CHECK(f.link.is_logged_on());
332  exchanges::FIX::v5_0sp2::MsgTypes::BusinessMessageReject receive_fix_msg;
333  BOOST_REQUIRE_NO_THROW(f.client.receive(receive_fix_msg));
334  BOOST_CHECK(receive_fix_msg.is_valid());
335  auto const client_order_id=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
336  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second).c_str(), "10");
337  auto const seqNum=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::MsgSeqNum>();
338  BOOST_CHECK_EQUAL(std::string(seqNum.first, seqNum.second), "2");
339  BOOST_CHECK(f.link.is_logged_on());
340 }
341 
342 /**
343  \test Response to a valid OrderCancelRequest.
344  =======================================
345  Verify that the response to a valid OrderCancelRequest is a cancelled order ExecutionReport.
346 */
347 BOOST_AUTO_TEST_CASE_TEMPLATE(cancel_accept, exchg_t, exchg_t_types) {
348  using fixture_t=simulator_and_link_client_too<exchg_t>;
349 
350  fixture_t f;
351 
352  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer order_fix_buffer={
353  "8=FIX.5.0\0019=151\00135=D\00134=10\00143=N\00149=VENDOR\00150=CUSTOME\00156=BROKER\00160=19980930-09:25:58\0011=XQCCFUND\00111=10\00121=1\00155=EK\00148=GB00BH4HKS39\00122=4\00154=1\00138=99\00140=2\00144=43.000000\00159=0\00110=136\001"
354  };
355  exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &order_fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &>(*order_fix_buffer.begin());
356  BOOST_CHECK_EQUAL(order_fix_msg.type(), exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle::static_type);
357  BOOST_CHECK(order_fix_msg.is_valid());
358  BOOST_REQUIRE_NO_THROW(f.client.send(order_fix_msg));
359  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer cancel_fix_buffer={
360  "8=FIX.5.0\0019=141\00135=F\00111=10\00141=10\00148=GB00BH4HKS39\00149=VENDOR\00156=BROKER\00134=10\00152=20000426-12:05:06\00155=EK\00154=1\00160=19980930-09:25:58\00138=99\00140=2\00144=43.000000\00159=0\00110=102\001"
361  };
362  exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelRequest const &cancel_fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelRequest const &>(*cancel_fix_buffer.begin());
363  BOOST_REQUIRE_NO_THROW(f.client.send(cancel_fix_msg));
364  exchanges::FIX::v5_0sp2::MsgTypes::ExecutionReport receive_fix_msg;
365  BOOST_REQUIRE_NO_THROW(f.client.receive(receive_fix_msg));
366  BOOST_CHECK(receive_fix_msg.is_valid());
367  auto const client_order_id=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
368  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second).c_str(), "10");
369  auto const seqNum=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::MsgSeqNum>();
370  BOOST_CHECK_EQUAL(std::string(seqNum.first, seqNum.second), "3");
371  auto const price=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::Price>();
372  BOOST_CHECK_EQUAL(std::string(price.first, price.second), "43.000000");
373  auto const side=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::Side>();
374  BOOST_CHECK_EQUAL(std::string(side.first, side.second), "1");
375  auto const orderQty=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::OrderQty>();
376  BOOST_CHECK_EQUAL(std::string(orderQty.first, orderQty.second), "99");
377  auto const leavesQty=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::LeavesQty>();
378  BOOST_CHECK_EQUAL(std::string(leavesQty.first, leavesQty.second), "99");
379  BOOST_CHECK(f.link.is_logged_on());
380 }
381 
382 /**
383  \test Response to an invalid OrderCancelReplaceRequest.
384  =================================================
385  Verify that the response to an invalid OrderCancelReplaceRequest is a cancelled order CancelRejected.
386 */
387 BOOST_AUTO_TEST_CASE_TEMPLATE(modify_reject, exchg_t, exchg_t_types) {
388  using fixture_t=simulator_and_link_client_too<exchg_t>;
389 
390  fixture_t f;
391 
392  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer fix_buffer={
393  "8=FIX.5.0\0019=141\00135=G\00111=10\00141=10\00148=GB00BH4HKS39\00149=VENDOR\00156=BROKER\00134=10\00152=20000426-12:05:06\00155=EK\00154=1\00160=19980930-09:25:58\00138=99\00140=1\00144=43.000000\00159=0\00110=102\001"
394  };
395  exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelReplace const &fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelReplace const &>(*fix_buffer.begin());
396  BOOST_CHECK_EQUAL(fix_msg.type(), exchanges::FIX::v5_0sp2::MsgTypes::OrderCancelReplace::static_type);
397  BOOST_CHECK(fix_msg.is_valid());
398  BOOST_REQUIRE_NO_THROW(f.client.send(fix_msg));
399  exchanges::FIX::v5_0sp2::MsgTypes::BusinessMessageReject receive_fix_msg;
400  BOOST_REQUIRE_NO_THROW(f.client.receive(receive_fix_msg));
401  BOOST_CHECK(receive_fix_msg.is_valid());
402  auto const client_order_id=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
403  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second).c_str(), "10");
404  auto const seqNum=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::MsgSeqNum>();
405  BOOST_CHECK_EQUAL(std::string(seqNum.first, seqNum.second), "2");
406  BOOST_CHECK(f.link.is_logged_on());
407 }
408 
409 BOOST_AUTO_TEST_SUITE_END()
410 
411 BOOST_AUTO_TEST_SUITE(new_order)
412 
413 BOOST_AUTO_TEST_SUITE(buy)
414 
415 BOOST_AUTO_TEST_SUITE(day)
416 
417 /**
418  \test "Order handling" Test: Response to a BUY, DAY, MARKET NewOrder is a filled FIX message.
419  =======================================================================================
420  Verify that the response to a buy, day, market NewOrder is a filled FIX message.
421 */
422 BOOST_AUTO_TEST_CASE_TEMPLATE(market_fill, exchg_t, exchg_t_types) {
423  using fixture_t=simulator_and_link_client_too<exchg_t>;
424 
425  fixture_t f;
426 
427  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer fix_buffer={
428  "8=FIX.5.0\0019=151\00135=D\00134=10\00143=N\00149=VENDOR\00150=CUSTOME\00156=BROKER\00160=19980930-09:25:58\0011=XQCCFUND\00111=10\00121=1\00155=EK\00148=GB00BH4HKS39\00122=4\00154=1\00138=99\00140=1\00144=41.000000\00159=0\00110=133\001"
429  };
430  exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &>(*fix_buffer.begin());
431  BOOST_CHECK_EQUAL(fix_msg.type(), exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle::static_type);
432  BOOST_CHECK(fix_msg.is_valid());
433  BOOST_REQUIRE_NO_THROW(f.client.send(fix_msg));
434  exchanges::FIX::v5_0sp2::MsgTypes::ExecutionReport receive_fix_msg;
435  BOOST_REQUIRE_NO_THROW(f.client.receive(receive_fix_msg));
436  BOOST_CHECK(receive_fix_msg.is_valid());
437  auto const client_order_id=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
438  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second).c_str(), "10");
439  auto const seqNum=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::MsgSeqNum>();
440  BOOST_CHECK_EQUAL(std::string(seqNum.first, seqNum.second), "2");
441  auto const securityIDSource=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::SecurityIDSource>();
442  BOOST_CHECK_EQUAL(std::string(securityIDSource.first, securityIDSource.second), "4");
443  auto const securityID=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::SecurityID>();
444  BOOST_CHECK_EQUAL(std::string(securityID.first), "GB00BH4HKS39");
445  auto const price=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::Price>();
446  BOOST_CHECK_EQUAL(std::string(price.first, price.second), "41.000000");
447  auto const side=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::Side>();
448  BOOST_CHECK_EQUAL(std::string(side.first, side.second), "1");
449  auto const orderQty=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::OrderQty>();
450  BOOST_CHECK_EQUAL(std::string(orderQty.first, orderQty.second), "99");
451  auto const leavesQty=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::LeavesQty>();
452  BOOST_CHECK_EQUAL(std::string(leavesQty.first, leavesQty.second), "0");
453 }
454 
455 /**
456  \test "Order handling" Test: Response to a BUY, DAY, MARKET NewOrder is a filled FIX message.
457  =======================================================================================
458  Verify that the response to a buy, day, market NewOrder is a filled FIX message.
459 */
460 BOOST_AUTO_TEST_CASE_TEMPLATE(market_partial_fill, exchg_t, exchg_t_types) {
461  using fixture_t=simulator_and_link_client_too<exchg_t>;
462 
463  fixture_t f;
464 
465  ALIGN_TO_L1_CACHE const exchanges::FIX::common::underlying_fix_data_buffer fix_buffer={
466  "8=FIX.5.0\0019=152\00135=D\00134=10\00143=N\00149=VENDOR\00150=CUSTOME\00156=BROKER\00160=19980930-09:25:58\0011=XQCCFUND\00111=10\00121=1\00155=EK\00148=GB00BH4HKS39\00122=4\00154=1\00138=101\00140=1\00144=41.000000\00159=0\00110=166\001"
467  };
468  exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &fix_msg=reinterpret_cast<exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle const &>(*fix_buffer.begin());
469  BOOST_CHECK_EQUAL(fix_msg.type(), exchanges::FIX::v5_0sp2::MsgTypes::NewOrderSingle::static_type);
470  BOOST_CHECK(fix_msg.is_valid());
471  BOOST_REQUIRE_NO_THROW(f.client.send(fix_msg));
472  exchanges::FIX::v5_0sp2::MsgTypes::ExecutionReport receive_fix_msg;
473  BOOST_REQUIRE_NO_THROW(f.client.receive(receive_fix_msg));
474  BOOST_CHECK(receive_fix_msg.is_valid());
475  auto const client_order_id=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
476  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second).c_str(), "10");
477  auto const seqNum=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::MsgSeqNum>();
478  BOOST_CHECK_EQUAL(std::string(seqNum.first, seqNum.second), "2");
479  auto const securityIDSource=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::SecurityIDSource>();
480  BOOST_CHECK_EQUAL(std::string(securityIDSource.first, securityIDSource.second), "4");
481  auto const securityID=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::SecurityID>();
482  BOOST_CHECK_EQUAL(std::string(securityID.first), "GB00BH4HKS39");
483  auto const price=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::Price>();
484  BOOST_CHECK_EQUAL(std::string(price.first, price.second), "42.000000");
485  auto const side=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::Side>();
486  BOOST_CHECK_EQUAL(std::string(side.first, side.second), "1");
487  auto const orderQty=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::OrderQty>();
488  BOOST_CHECK_EQUAL(std::string(orderQty.first, orderQty.second), "100");
489  auto const leavesQty=receive_fix_msg.find<exchanges::FIX::common::FieldsFast::LeavesQty>();
490  BOOST_CHECK_EQUAL(std::string(leavesQty.first, leavesQty.second), "1");
491 }
492 
493 BOOST_AUTO_TEST_SUITE_END()
494 
495 BOOST_AUTO_TEST_SUITE_END()
496 
497 BOOST_AUTO_TEST_SUITE_END()
498 
499 BOOST_AUTO_TEST_SUITE_END()