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/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 #ifndef JMMCG_PERFORMANCE_TESTS
32 # include "../exchanges/BATSBOE/US/v1/batsboe.hpp"
33 # include "../exchanges/BATSBOE/US/v1/batsboe_sim.hpp"
35 #include "../exchanges/BATSBOE/US/v2/batsboe.hpp"
36 #include "../exchanges/BATSBOE/US/v2/batsboe_sim.hpp"
37 #include "../exchanges/conversions/fix_to_batsboe_eu_conversions.hpp"
38 #include "../exchanges/conversions/fix_to_batsboe_us_conversions.hpp"
39 #include "../exchanges/conversions/batsboe_eu_to_fix_conversions.hpp"
40 #include "../exchanges/conversions/batsboe_us_to_fix_conversions.hpp"
42 #include "core/ave_deviation_meter.hpp"
43 #include "core/jthread.hpp"
44 #include "core/latency_timestamps.hpp"
45 #include "core/stats_output.hpp"
47 using namespace libjmmcg;
48 using namespace libisimud;
60 using exchg_t_types=boost::mpl::list<
61 std::pair<exchanges::BATSBOE::EU::v1::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::BATSBOE::EU::v1::simulator_t>
62 #ifndef JMMCG_PERFORMANCE_TESTS
65 std::pair<exchanges::BATSBOE::US::v1::link_t<exchanges::FIX::v5_0sp2::MsgTypes>, exchanges::BATSBOE::US::v1::simulator_t>
70 template<
class exchg_t>
72 using link_t=
typename exchg_t::first_type;
73 using simulator_t=
typename exchg_t::second_type;
74 using conn_pol_t=
typename link_t::exchg_link_t::conn_pol_t;
76 typename simulator_t::msg_processor_t::msg_details_t,
96 no_latency_timestamps
ts{0
};
100 simulator_t::socket_t::socket_priority::low,
101 api_thread_traits::processor_mask_type(exchanges::common::thread_traits::exchange_simulator_thread.core),
102 exchanges::common::thread_traits::exchange_simulator_thread.priority,
103 typename simulator_t::proc_rules_t(),
109 template<
class exchg_t>
112 using link_t=
typename base_t::link_t;
114 #ifdef JMMCG_PERFORMANCE_TESTS
117 no_latency_timestamps
ts;
120 typename link_t::client_link_t::ctor_args{
126 link_t::socket_t::socket_priority::high,
127 link_t::socket_t::socket_priority::low,
137 template<
class exchg_t>
140 using base_t::base_t;
142 #ifdef JMMCG_PERFORMANCE_TESTS
159 BOOST_AUTO_TEST_SUITE(performance, *stats_to_csv::make_fixture(
"batsboe_exchanges_performance.csv"))
161 BOOST_AUTO_TEST_SUITE(simulator)
169 BOOST_AUTO_TEST_CASE_TEMPLATE(reject, exchg_t, exchg_t_types) {
170 #ifdef JMMCG_PERFORMANCE_TESTS
171 const unsigned long num_loops=5000;
172 const unsigned short loops_for_conv=500;
174 const unsigned long num_loops=1;
175 const unsigned short loops_for_conv=1;
177 const double perc_conv_estimate=5.0;
183 typename fixture_t::connection_t link(
189 auto send_and_receive=[&link]() {
190 using msg_details_t=
typename fixture_t::simulator_t::msg_processor_t::msg_details_t;
191 const typename msg_details_t::NewOrder_t msg(
194 msg_details_t::OrderType::Market,
195 exchanges::BATSBOE::common::TIF::Day,
196 msg_details_t::Side::Buy,
197 exchg_t::second_type::proc_rules_t::invalidInstrumentID,
198 exchg_t::second_type::proc_rules_t::quantity_limit-1,
199 exchg_t::second_type::proc_rules_t::price
201 BOOST_CHECK_NO_THROW(link.send(msg));
202 typename msg_details_t::OrderRejected reply;
203 BOOST_CHECK_NO_THROW(link.receive(reply));
206 const std::pair<timed_results_t,
bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
209 [&send_and_receive]() {
210 const auto t1=std::chrono::high_resolution_clock::now();
211 for (
unsigned long i=0; i<num_loops; ++i) {
214 const auto t2=std::chrono::high_resolution_clock::now();
215 return timed_results_t::value_type(
static_cast<
double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count())/num_loops);
218 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;
219 #ifdef JMMCG_PERFORMANCE_TESTS
220 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
221 BOOST_CHECK(!timed_results.second);
225 BOOST_AUTO_TEST_SUITE_END()
227 BOOST_AUTO_TEST_SUITE(exchange_gateways)
238 BOOST_AUTO_TEST_CASE_TEMPLATE(order_rejected_at_a_time, exchg_t, exchg_t_types) {
239 #ifdef JMMCG_PERFORMANCE_TESTS
240 const unsigned long num_loops=5000;
241 const unsigned short loops_for_conv=500;
243 const unsigned long num_loops=1;
244 const unsigned short loops_for_conv=1;
246 const double perc_conv_estimate=5.0;
250 fixture_t f(2*3*num_loops*loops_for_conv);
252 auto const &timed_results=f.client.in_order_tx_rx_stats(
257 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;
258 #ifdef JMMCG_PERFORMANCE_TESTS
259 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
260 BOOST_CHECK(!timed_results.second);
261 f.ts.write_to_named_csv_file(std::cout,
"batsboe_exchanges_in_order_performance_latencies");
274 BOOST_AUTO_TEST_CASE_TEMPLATE(order_rejects_parallel, exchg_t, exchg_t_types) {
275 #ifdef JMMCG_PERFORMANCE_TESTS
276 const unsigned long num_loops=20000;
277 const unsigned short loops_for_conv=500;
279 const unsigned long num_loops=1;
280 const unsigned short loops_for_conv=1;
282 const double perc_conv_estimate=0.1;
286 fixture_t f(2*3*num_loops*loops_for_conv);
288 auto send_and_receive=[&f]() {
289 std::chrono::high_resolution_clock::time_point send_time{};
290 std::chrono::high_resolution_clock::time_point receive_time{};
292 auto send_batch_of_orders=[&f, &send_time]() {
293 BOOST_CHECK(f.client.send_fix_msg.is_valid());
295 double accrued_delay_in_msec{};
296 send_time=std::chrono::high_resolution_clock::now();
297 for (
unsigned long i=0; i<num_loops; ++i) {
301 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));
304 auto receive_batch_of_rejects=[&f, &receive_time]() {
305 for (
unsigned long i=0; i<num_loops; ++i) {
308 receive_time=std::chrono::high_resolution_clock::now();
309 BOOST_CHECK(f.client.receive_fix_msg.is_valid());
313 ppd::jthread send(
std::move(send_batch_of_orders));
314 ppd::jthread receive(
std::move(receive_batch_of_rejects));
316 return timed_results_t::value_type(
static_cast<
double>(std::chrono::duration_cast<std::chrono::microseconds>(receive_time - send_time).count())/num_loops);
319 const std::pair<timed_results_t,
bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
322 std::move(send_and_receive)
324 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;
325 #ifdef JMMCG_PERFORMANCE_TESTS
326 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
327 BOOST_CHECK(!timed_results.second);
328 f.ts.write_to_named_csv_file(std::cout,
"batsboe_exchanges_out_of_order_performance_latencies");
332 BOOST_AUTO_TEST_SUITE_END()
334 BOOST_AUTO_TEST_SUITE_END()