21 #define BOOST_TEST_MODULE isimud_tests
22 #include <boost/test/included/unit_test.hpp>
24 #include <boost/mpl/list.hpp>
26 #include "../exchanges/FIX/v5.0sp2/fix_client.hpp"
27 #include "../exchanges/MIT/BIT/bit.hpp"
28 #include "../exchanges/MIT/BIT/bit_sim.hpp"
29 #ifndef JMMCG_PERFORMANCE_TESTS
30 # include "../exchanges/MIT/JSE/jse.hpp"
31 # include "../exchanges/MIT/JSE/jse_sim.hpp"
32 # include "../exchanges/MIT/LSE/lse.hpp"
33 # include "../exchanges/MIT/LSE/lse_sim.hpp"
34 # include "../exchanges/MIT/OSLO/oslo.hpp"
35 # include "../exchanges/MIT/OSLO/oslo_sim.hpp"
36 # include "../exchanges/MIT/TRQ/trq.hpp"
37 # include "../exchanges/MIT/TRQ/trq_sim.hpp"
39 #include "../exchanges/conversions/fix_to_mit_conversions.hpp"
40 #include "../exchanges/conversions/mit_to_fix_conversions.hpp"
42 #include "core/ave_deviation_meter.hpp"
43 #include "core/latency_timestamps.hpp"
44 #include "core/jthread.hpp"
45 #include "core/stats_output.hpp"
49 using namespace libjmmcg;
50 using namespace libisimud;
64 using exchg_t_types=boost::mpl::list<
65 std::pair<exchanges::MIT::BIT::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::MIT::BIT::simulator_t>
66 #ifndef JMMCG_PERFORMANCE_TESTS
68 std::pair<exchanges::MIT::JSE::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::MIT::JSE::simulator_t>,
69 std::pair<exchanges::MIT::LSE::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::MIT::LSE::simulator_t>,
70 std::pair<exchanges::MIT::OSLO::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::MIT::OSLO::simulator_t>,
71 std::pair<exchanges::MIT::TRQ::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::MIT::TRQ::simulator_t>
75 template<
class exchg_t>
77 using link_t=
typename exchg_t::first_type;
78 using simulator_t=
typename exchg_t::second_type;
79 using conn_pol_t=
typename link_t::exchg_link_t::conn_pol_t;
81 typename simulator_t::msg_processor_t::msg_details_t,
84 using ref_data_t=
typename link_t::client_link_t::proc_rules_t::ref_data;
87 const std::string ref_data_file(
88 "133215;FTSE100;SET0;PT_T;TP_1;GB00BH4HKS39;;20060731;0;1;10000;42467000;1;;1;DE;VOD;VODAFONE GRP.;BH4HKS3;15225662730;GBX;1;Y;0023;VOVOD;VODAFONE GROUP PLC;0;;;15000;ORD USD0.20 20/21;;1;1;5;GB;;;FE00;1;;;;1;A;;;;;;\n"
89 "2926;FTSE100;SET1;PT_T;TP_12;GB0000595859;;20000419;0;1;3000;32438040;1;;1;DE;ARM;ARM HLDGS.;0059585;3861344694;GBX;1;Y;0023;ARARM;ARM HOLDINGS PLC;0;;;7500;ORD 0.05P;;1;1;5;GB;;;FS10;4;;;;2;B;;;;;;"
93 return std::move(ref_data_t(ss));
112 no_latency_timestamps
ts{0
};
116 simulator_t::socket_t::socket_priority::low,
117 api_thread_traits::processor_mask_type(exchanges::common::thread_traits::exchange_simulator_thread.core),
118 exchanges::common::thread_traits::exchange_simulator_thread.priority,
119 typename simulator_t::proc_rules_t(),
125 template<
class exchg_t>
128 using link_t=
typename base_t::link_t;
130 #ifdef JMMCG_PERFORMANCE_TESTS
133 no_latency_timestamps
ts;
136 typename link_t::client_link_t::ctor_args{
139 typename link_t::client_link_t::proc_rules_t(
this->ref_data)
142 link_t::socket_t::socket_priority::high,
143 link_t::socket_t::socket_priority::low,
144 typename link_t::exchg_to_client_proc_rules_t(
this->ref_data),
153 template<
class exchg_t>
157 #ifdef JMMCG_PERFORMANCE_TESTS
174 BOOST_AUTO_TEST_SUITE(performance, *stats_to_csv::make_fixture(
"mit_exchanges_performance.csv"))
176 BOOST_AUTO_TEST_SUITE(simulator)
184 BOOST_AUTO_TEST_CASE_TEMPLATE(reject, exchg_t, exchg_t_types) {
185 #ifdef JMMCG_PERFORMANCE_TESTS
186 const unsigned long num_loops=10000;
187 const unsigned short loops_for_conv=1000;
189 const unsigned long num_loops=1;
190 const unsigned short loops_for_conv=1;
192 const double perc_conv_estimate=2.0;
198 typename fixture_t::connection_t link(
204 auto send_and_receive=[&link]() {
205 using msg_details_t=
typename fixture_t::simulator_t::msg_processor_t::msg_details_t;
206 const typename msg_details_t::NewOrder_t msg(
209 msg_details_t::OrderType::Market,
210 exchanges::MIT::common::TIF::Day,
211 msg_details_t::Side::Buy,
212 exchg_t::second_type::proc_rules_t::invalidInstrumentID,
213 exchg_t::second_type::proc_rules_t::quantity_limit-1,
214 exchg_t::second_type::proc_rules_t::price
216 BOOST_CHECK_NO_THROW(link.send(msg));
217 typename msg_details_t::BusinessReject reply;
218 BOOST_CHECK_NO_THROW(link.receive(reply));
221 const std::pair<timed_results_t,
bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
224 [&send_and_receive]() {
225 const auto t1=std::chrono::high_resolution_clock::now();
226 for (
unsigned long i=0; i<num_loops; ++i) {
229 const auto t2=std::chrono::high_resolution_clock::now();
230 return timed_results_t::value_type(
static_cast<
double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count())/num_loops);
233 std::cout<<fixture_t::link_t::thread_traits::demangle_name(
typeid(
typename exchg_t::first_type))<<
"\n\tSimulator round-trip time (microseconds)="<<timed_results.first<<std::endl;
234 #ifdef JMMCG_PERFORMANCE_TESTS
235 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
236 BOOST_CHECK(!timed_results.second);
240 BOOST_AUTO_TEST_SUITE_END()
242 BOOST_AUTO_TEST_SUITE(exchange_gateways)
253 BOOST_AUTO_TEST_CASE_TEMPLATE(order_rejected_at_a_time, exchg_t, exchg_t_types) {
254 #ifdef JMMCG_PERFORMANCE_TESTS
255 const unsigned long num_loops=20000;
256 const unsigned short loops_for_conv=500;
258 const unsigned long num_loops=1;
259 const unsigned short loops_for_conv=1;
261 const double perc_conv_estimate=0.1;
265 fixture_t f(2*3*num_loops*loops_for_conv);
267 auto const &timed_results=f.client.in_order_tx_rx_stats(
272 std::cout<<fixture_t::link_t::thread_traits::demangle_name(
typeid(
typename exchg_t::first_type))<<
"\n\tExchange round-trip in-order time (microseconds)="<<timed_results.first<<
std::endl;
273 #ifdef JMMCG_PERFORMANCE_TESTS
274 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
275 BOOST_CHECK(!timed_results.second);
276 f.ts.write_to_named_csv_file(std::cout,
"mit_exchanges_in_order_performance_latencies");
289 BOOST_AUTO_TEST_CASE_TEMPLATE(order_rejects_parallel, exchg_t, exchg_t_types) {
290 #ifdef JMMCG_PERFORMANCE_TESTS
291 const unsigned long num_loops=20000;
292 const unsigned short loops_for_conv=500;
294 const unsigned long num_loops=1;
295 const unsigned short loops_for_conv=1;
297 const double perc_conv_estimate=0.1;
301 fixture_t f(2*3*num_loops*loops_for_conv);
303 auto send_and_receive=[&f]() {
304 std::chrono::high_resolution_clock::time_point send_time{};
305 std::chrono::high_resolution_clock::time_point receive_time{};
307 auto send_batch_of_orders=[&f, &send_time]() {
308 BOOST_CHECK(f.client.send_fix_msg.is_valid());
310 double accrued_delay_in_msec{};
311 send_time=std::chrono::high_resolution_clock::now();
312 for (
unsigned long i=0; i<num_loops; ++i) {
316 send_time=std::chrono::time_point_cast<std::chrono::high_resolution_clock::duration>(send_time+std::chrono::duration<
double, std::micro>(accrued_delay_in_msec));
319 auto receive_batch_of_rejects=[&f, &receive_time]() {
320 for (
unsigned long i=0; i<num_loops; ++i) {
323 receive_time=std::chrono::high_resolution_clock::now();
324 BOOST_CHECK(f.client.receive_fix_msg.is_valid());
328 ppd::jthread send(
std::move(send_batch_of_orders));
329 ppd::jthread receive(
std::move(receive_batch_of_rejects));
331 return timed_results_t::value_type(
static_cast<
double>(std::chrono::duration_cast<std::chrono::microseconds>(receive_time - send_time).count())/num_loops);
334 const std::pair<timed_results_t,
bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
337 std::move(send_and_receive)
339 std::cout<<fixture_t::link_t::thread_traits::demangle_name(
typeid(
typename exchg_t::first_type))<<
"\n\tExchange round-trip out-of-order time (microseconds)="<<timed_results.first<<std::endl;
340 #ifdef JMMCG_PERFORMANCE_TESTS
341 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
342 BOOST_CHECK(!timed_results.second);
343 f.ts.write_to_named_csv_file(std::cout,
"mit_exchanges_out_of_order_performance_latencies");
347 BOOST_AUTO_TEST_SUITE_END()
349 BOOST_AUTO_TEST_SUITE_END()