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()