libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
mit_to_fix.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/conversions/mit_to_fix_conversions.hpp"
27 
28 #include "core/msm.hpp"
29 
30 using namespace libjmmcg;
31 using namespace libisimud;
32 
33 const int32_t seqNum=1;
34 const exchanges::MIT::common::ClientOrderID_t clientOrderId1{"abcdefghijklm0test1"};
35 const exchanges::MIT::common::AppID aID=exchanges::MIT::common::AppID::Partition1;
36 const exchanges::MIT::common::ExecType eT=exchanges::MIT::common::ExecType::New;
37 const exchanges::MIT::common::Price_t price=42*exchanges::MIT::common::implied_decimal_places;
38 const exchanges::MIT::common::SecurityID_t instID=133215;
39 const exchanges::MIT::common::Side s=exchanges::MIT::common::Side::Buy;
40 
41 typedef boost::mpl::list<
48 
49 BOOST_AUTO_TEST_SUITE(exchange_gateways)
50 
51 BOOST_AUTO_TEST_CASE_TEMPLATE(ExecutionReport, msg, msg_types) {
52  typename msg::first_type::ExecutionReport exchg_msg(seqNum, clientOrderId1, aID, eT, price, instID, s);
53  exchg_msg.orderStatus_=exchanges::MIT::common::OrderStatus::Rejected;
54  exchg_msg.executedQty(0);
55  exchg_msg.leavesQty(0);
56  const std::string ref_data_file("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;;;;;;");
57  std::stringstream ss;
58  ss<<ref_data_file;
59  const typename msg::second_type ref_data(ss);
60  const exchanges::FIX::v5_0sp2::MsgTypes::ExecutionReport fix_msg(exchg_msg, ref_data);
61  BOOST_CHECK(fix_msg.is_valid());
62  auto const client_order_id=fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
63  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second), clientOrderId1.begin());
64  auto const exec_type=fix_msg.find<exchanges::FIX::common::FieldsFast::ExecType>();
65  BOOST_CHECK_EQUAL(static_cast<exchanges::FIX::common::ExecType>(*exec_type.first), exchanges::FIX::common::convert(eT));
66  auto const fix_price=fix_msg.find<exchanges::FIX::common::FieldsFast::Price>();
67  BOOST_CHECK_EQUAL(static_cast<exchanges::MIT::common::Price_t>(fromstring<double>(fix_price.first, fix_price.second-fix_price.first)), price/exchanges::MIT::common::implied_decimal_places);
68  auto const sec_id_type=fix_msg.find<exchanges::FIX::common::FieldsFast::SecurityIDSource>();
69  BOOST_CHECK_EQUAL(std::string(sec_id_type.first, sec_id_type.second), "4");
70  auto const symbol=fix_msg.find<exchanges::FIX::common::FieldsFast::SecurityID>();
71  BOOST_CHECK_EQUAL(std::string(symbol.first, symbol.second), "GB00BH4HKS39");
72  auto const ordStatus=fix_msg.find<exchanges::FIX::common::FieldsFast::OrdStatus>();
73  BOOST_CHECK_EQUAL(static_cast<exchanges::FIX::common::OrdStatus>(*ordStatus.first), exchanges::FIX::common::OrdStatus::Rejected);
74  auto const orderQty=fix_msg.find<exchanges::FIX::common::FieldsFast::OrderQty>();
75  BOOST_CHECK_EQUAL(std::string(orderQty.first, orderQty.second), "0");
76  auto const leavesQty=fix_msg.find<exchanges::FIX::common::FieldsFast::LeavesQty>();
77  BOOST_CHECK_EQUAL(std::string(leavesQty.first, leavesQty.second), "0");
78  auto const side=fix_msg.find<exchanges::FIX::common::FieldsFast::Side>();
79  BOOST_CHECK_EQUAL(std::string(side.first, side.second), "1");
80 }
81 
82 BOOST_AUTO_TEST_CASE_TEMPLATE(reject, msg, msg_types) {
83  typename msg::first_type::Reject exchg_msg(clientOrderId1, static_cast<typename msg::first_type::Reject::RejectCode_t>(2004));
84  const exchanges::FIX::v5_0sp2::MsgTypes::OrderRejected fix_msg(exchg_msg);
85  BOOST_CHECK(fix_msg.is_valid());
86 }
87 
88 BOOST_AUTO_TEST_CASE_TEMPLATE(order_reject, msg, msg_types) {
89  typename msg::first_type::ExecutionReport exchg_msg(seqNum, clientOrderId1, aID, eT, price, instID, s);
90  exchg_msg.orderRejectCode(static_cast<typename msg::first_type::Reject::RejectCode_t>(2004));
91  exchg_msg.orderStatus(exchanges::MIT::common::OrderStatus::Rejected);
92  const exchanges::FIX::v5_0sp2::MsgTypes::OrderRejected fix_msg(exchg_msg);
93  BOOST_CHECK(fix_msg.is_valid());
94  auto const ref_seq_num=fix_msg.find<exchanges::FIX::common::FieldsFast::RefSeqNum>();
95  BOOST_CHECK_EQUAL(std::string(ref_seq_num.first, ref_seq_num.second), "1");
96 }
97 
98 BOOST_AUTO_TEST_CASE_TEMPLATE(BusinessReject, msg, msg_types) {
99  typename msg::first_type::BusinessReject exchg_msg(seqNum, clientOrderId1);
100  exchg_msg.rejectCode(static_cast<typename msg::first_type::BusinessReject::RejectCode_t>(9000));
101  const exchanges::FIX::v5_0sp2::MsgTypes::BusinessMessageReject fix_msg(exchg_msg);
102  BOOST_CHECK(fix_msg.is_valid());
103  auto const ref_seq_num=fix_msg.find<exchanges::FIX::common::FieldsFast::RefSeqNum>();
104  BOOST_CHECK_EQUAL(std::string(ref_seq_num.first, ref_seq_num.second), "1");
105 }
106 
107 BOOST_AUTO_TEST_CASE_TEMPLATE(OrderCancelReject, msg, msg_types) {
108  typename msg::first_type::OrderCancelReject exchg_msg(seqNum, clientOrderId1);
109  exchg_msg.cancelRejectReason(static_cast<typename msg::first_type::Reject::RejectCode_t>(2004));
110  const exchanges::FIX::v5_0sp2::MsgTypes::CancelRejected fix_msg(exchg_msg);
111  BOOST_CHECK(fix_msg.is_valid());
112  auto const client_order_id=fix_msg.find<exchanges::FIX::common::FieldsFast::ClOrdID>();
113  BOOST_CHECK_EQUAL(std::string(client_order_id.first, client_order_id.second), clientOrderId1.begin());
114  auto const order_id=fix_msg.find<exchanges::FIX::common::FieldsFast::OrderID>();
115  // TODO BOOST_CHECK_EQUAL(std::string(order_id.first, order_id.second), clientOrderId1.begin());
116 }
117 
118 using dest_msg_details_t=exchanges::FIX::v5_0sp2::MsgTypes;
119 template<class SrcMsgT>
121  using src_msg_details_t=SrcMsgT;
123  using row_t=msm::unroll::row_types<typename src_msg_details_t::MsgTypes_t, typename dest_msg_details_t::MsgType_t>;
124  /**
125  * From section \todo 5.1: "TODO" of [1]: the response to an ExecutionReport is a various messages.
126  *
127  * \param msg The message that was received, that shall be processed.
128  * \param client_skt The socket to which any responses should be written.
129  */
131  public:
132  explicit constexpr ExecutionReportResponse(typename src_msg_details_t::ref_data const &rd) noexcept(true)
133  : ref_data_(rd) {
134  assert(!ref_data_.lookup_isin().empty());
135  }
136  constexpr ExecutionReportResponse(ExecutionReportResponse const &nor) noexcept(true)
137  : ref_data_(nor.ref_data_) {
138  assert(!ref_data_.lookup_isin().empty());
139  }
140 
141  template<auto state, auto next>
142  typename dest_msg_details_t::MsgType_t
143  operator()(typename src_msg_details_t::ExecutionReport const &buff, typename dest_msg_details_t::ExecutionReport &reply) const noexcept(false) {
144  typename src_msg_details_t::ExecutionReport const &msg=buff;
145  BOOST_CHECK(msg.type()==state);
146  BOOST_CHECK(!ref_data_.lookup_isin().empty());
147  reply=typename dest_msg_details_t::ExecutionReport(msg, ref_data_);
148  return dest_msg_details_t::ExecutionReport::static_type;
149  }
150 
151  private:
152  typename src_msg_details_t::ref_data const &ref_data_;
153  };
154  using transition_table=typename msm_base_t::template rows<
155  typename row_t::template row<
159  >
160  >;
161 };
162 
163 BOOST_AUTO_TEST_CASE_TEMPLATE(ExecutionReportUsingProcRules, msg, msg_types) {
164  using src_msg_details_t=typename msg::first_type;
165  using business_machine=msm::unroll::machine<business_state_machine_t<src_msg_details_t>>;
166 
167  typename src_msg_details_t::ExecutionReport exchg_msg(seqNum, clientOrderId1, aID, eT, price, instID, s);
168  exchg_msg.orderStatus_=exchanges::MIT::common::OrderStatus::Rejected;
169  exchg_msg.executedQty(0);
170  exchg_msg.leavesQty(0);
171  const std::string ref_data_file("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;;;;;;");
172  std::stringstream ss;
173  ss<<ref_data_file;
174  const typename msg::second_type ref_data(ss);
175  BOOST_CHECK(!ref_data.lookup_isin().empty());
176  const business_machine business_msm(ref_data);
177  typename dest_msg_details_t::ExecutionReport reply;
178  BOOST_CHECK_EQUAL(business_msm.process(src_msg_details_t::ExecutionReport::static_type, exchg_msg, reply), dest_msg_details_t::ExecutionReport::static_type);
179 }
180 
181 BOOST_AUTO_TEST_SUITE_END()