21 #define BOOST_TEST_MODULE isimud_tests
22 #include <boost/test/included/unit_test.hpp>
24 #include <boost/mpl/list.hpp>
26 #include "../exchanges/order_book/order_book.hpp"
28 #include "../exchanges/FIX/v5.0sp2/fix.hpp"
29 #include "../exchanges/MIT/BIT/bit.hpp"
41 using namespace libjmmcg;
42 using namespace libisimud;
44 using ob_t_types=boost::mpl::list<
45 order_book<exchanges::FIX::v5_0sp2::MsgTypes>
57 BOOST_AUTO_TEST_SUITE(order_book_basic)
64 BOOST_AUTO_TEST_CASE_TEMPLATE(ctor, ob_t, ob_t_types) {
65 BOOST_CHECK_NO_THROW(ob_t{});
72 BOOST_AUTO_TEST_CASE_TEMPLATE(initially_no_orders, ob_t, ob_t_types) {
73 using symbol_t=
typename ob_t::symbol_t;
76 BOOST_CHECK(ob.empty());
77 BOOST_CHECK(!ob.is_crossed());
78 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 0);
79 BOOST_CHECK(ob.match().empty());
86 BOOST_AUTO_TEST_CASE_TEMPLATE(stream_out_default_ctor, ob_t, ob_t_types) {
90 BOOST_CHECK(!ss.str().empty());
97 BOOST_AUTO_TEST_CASE_TEMPLATE(place_order_not_empty, ob_t, ob_t_types) {
98 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
99 using OrderType=
typename ob_t::msg_details_t::OrderType;
100 using TIF=
typename ob_t::msg_details_t::TIF;
101 using side=
typename ob_t::side_t;
102 using symbol_t=
typename ob_t::symbol_t;
103 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
104 using Price_t=
typename ob_t::msg_details_t::Price_t;
105 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
108 typename ob_t::order_t o(SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON);
109 BOOST_CHECK_NO_THROW(ob.place(o));
110 BOOST_CHECK(!ob.empty());
111 BOOST_CHECK(!ob.is_crossed());
112 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 0);
113 BOOST_CHECK(ob.match().empty());
114 std::stringstream ss;
116 BOOST_CHECK(!ss.str().empty());
117 char const output[]=
"=================\nASK\n110: 5\n------------\nBID\n=================\n";
118 BOOST_CHECK_EQUAL(ss.str(), output);
125 BOOST_AUTO_TEST_CASE_TEMPLATE(place_a_sell_and_a_buy_orders, ob_t, ob_t_types) {
126 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
127 using OrderType=
typename ob_t::msg_details_t::OrderType;
128 using TIF=
typename ob_t::msg_details_t::TIF;
129 using side=
typename ob_t::side_t;
130 using symbol_t=
typename ob_t::symbol_t;
131 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
132 using Price_t=
typename ob_t::msg_details_t::Price_t;
133 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
136 typename ob_t::order_t o_s(SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON);
137 BOOST_CHECK_NO_THROW(ob.place(o_s));
138 typename ob_t::order_t o_b{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
139 BOOST_CHECK_NO_THROW(ob.place(o_b));
140 BOOST_CHECK(!ob.empty());
141 BOOST_CHECK(!ob.is_crossed());
142 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 20);
143 BOOST_CHECK(ob.match().empty());
144 std::stringstream ss;
146 BOOST_CHECK(!ss.str().empty());
147 char const output[]=
"=================\nASK\n110: 5\n------------\n90: 10\nBID\n=================\n";
148 BOOST_CHECK_EQUAL(ss.str(), output);
155 BOOST_AUTO_TEST_CASE_TEMPLATE(place_two_sells_and_a_buy_orders, ob_t, ob_t_types) {
156 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
157 using OrderType=
typename ob_t::msg_details_t::OrderType;
158 using TIF=
typename ob_t::msg_details_t::TIF;
159 using side=
typename ob_t::side_t;
160 using symbol_t=
typename ob_t::symbol_t;
161 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
162 using Price_t=
typename ob_t::msg_details_t::Price_t;
163 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
166 typename ob_t::order_t o_s1(SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON);
167 BOOST_CHECK_NO_THROW(ob.place(o_s1));
168 typename ob_t::order_t o_b{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
169 BOOST_CHECK_NO_THROW(ob.place(o_b));
170 typename ob_t::order_t o_s2{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
171 BOOST_CHECK_NO_THROW(ob.place(o_s2));
172 BOOST_CHECK(!ob.empty());
173 BOOST_CHECK(!ob.is_crossed());
174 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 20);
175 BOOST_CHECK(ob.match().empty());
176 std::stringstream ss;
178 BOOST_CHECK(!ss.str().empty());
179 char const output[]=
"=================\nASK\n110: 5 10\n------------\n90: 10\nBID\n=================\n";
180 BOOST_CHECK_EQUAL(ss.str(), output);
187 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders, ob_t, ob_t_types) {
188 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
189 using OrderType=
typename ob_t::msg_details_t::OrderType;
190 using TIF=
typename ob_t::msg_details_t::TIF;
191 using side=
typename ob_t::side_t;
192 using symbol_t=
typename ob_t::symbol_t;
193 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
194 using Price_t=
typename ob_t::msg_details_t::Price_t;
195 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
198 typename ob_t::order_t o_s[]={
199 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
200 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
201 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
202 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
204 typename ob_t::order_t o_b[]={
205 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
206 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
207 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
208 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
209 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
211 for (
auto const &o : o_s) {
212 BOOST_CHECK_NO_THROW(ob.place(o));
214 for (
auto const &o : o_b) {
215 BOOST_CHECK_NO_THROW(ob.place(o));
217 BOOST_CHECK(!ob.empty());
218 BOOST_CHECK(!ob.is_crossed());
219 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 5);
220 BOOST_CHECK(ob.match().empty());
221 std::stringstream ss;
223 BOOST_CHECK(!ss.str().empty());
224 char const output[]=
"=================\nASK\n110: 5 10\n105: 3 7\n------------\n100: 4 6\n90: 10 2 3\nBID\n=================\n";
225 BOOST_CHECK_EQUAL(ss.str(), output);
232 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_cross, ob_t, ob_t_types) {
233 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
234 using OrderType=
typename ob_t::msg_details_t::OrderType;
235 using TIF=
typename ob_t::msg_details_t::TIF;
236 using side=
typename ob_t::side_t;
237 using symbol_t=
typename ob_t::symbol_t;
238 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
239 using Price_t=
typename ob_t::msg_details_t::Price_t;
240 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
243 typename ob_t::order_t o_s[]={
244 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
245 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
246 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
247 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
249 typename ob_t::order_t o_b[]={
250 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
251 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
252 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
253 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
254 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
255 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
257 for (
auto const &o : o_s) {
258 BOOST_CHECK_NO_THROW(ob.place(o));
260 for (
auto const &o : o_b) {
261 BOOST_CHECK_NO_THROW(ob.place(o));
263 BOOST_CHECK(!ob.empty());
264 BOOST_CHECK(ob.is_crossed());
265 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 0);
266 std::stringstream ss;
268 BOOST_CHECK(!ss.str().empty());
269 char const output[]=
"=================\nASK\n110: 5 10\n105: 3 7\n------------\n105: 4\n100: 4 6\n90: 10 2 3\nBID\n=================\n";
270 BOOST_CHECK_EQUAL(ss.str(), output);
277 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_buy_crosses_then_match, ob_t, ob_t_types) {
278 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
279 using OrderType=
typename ob_t::msg_details_t::OrderType;
280 using TIF=
typename ob_t::msg_details_t::TIF;
281 using side=
typename ob_t::side_t;
282 using symbol_t=
typename ob_t::symbol_t;
283 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
284 using Price_t=
typename ob_t::msg_details_t::Price_t;
285 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
288 typename ob_t::order_t o_s[]={
289 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
290 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
291 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
292 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
294 typename ob_t::order_t o_b[]={
295 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
296 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
297 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
298 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
299 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
300 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
302 for (
auto const &o : o_s) {
303 BOOST_CHECK_NO_THROW(ob.place(o));
305 for (
auto const &o : o_b) {
306 BOOST_CHECK_NO_THROW(ob.place(o));
308 BOOST_CHECK(ob.is_crossed());
309 auto const &executions=ob.match();
310 BOOST_CHECK(!ob.is_crossed());
311 BOOST_CHECK(!executions.empty());
312 BOOST_REQUIRE_EQUAL(executions.size(), 2);
313 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 105);
314 BOOST_CHECK_EQUAL(executions[0].orderQty(), 3);
315 BOOST_CHECK_EQUAL(executions[1].limitPrice(), 105);
316 BOOST_CHECK_EQUAL(executions[1].orderQty(), 1);
317 std::stringstream ss;
319 BOOST_CHECK(!ss.str().empty());
320 char const output[]=
"=================\nASK\n110: 5 10\n105: 6\n------------\n100: 4 6\n90: 10 2 3\nBID\n=================\n";
321 BOOST_CHECK_EQUAL(ss.str(), output);
328 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_sell_crosses_then_match, ob_t, ob_t_types) {
329 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
330 using OrderType=
typename ob_t::msg_details_t::OrderType;
331 using TIF=
typename ob_t::msg_details_t::TIF;
332 using side=
typename ob_t::side_t;
333 using symbol_t=
typename ob_t::symbol_t;
334 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
335 using Price_t=
typename ob_t::msg_details_t::Price_t;
336 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
339 typename ob_t::order_t o_s[]={
340 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
341 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
342 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
343 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
344 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
346 typename ob_t::order_t o_b[]={
347 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
348 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
349 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
350 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
351 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
353 for (
auto const &o : o_s) {
354 BOOST_CHECK_NO_THROW(ob.place(o));
356 for (
auto const &o : o_b) {
357 BOOST_CHECK_NO_THROW(ob.place(o));
359 BOOST_CHECK(ob.is_crossed());
360 auto const &executions=ob.match();
361 BOOST_CHECK(!ob.is_crossed());
362 BOOST_CHECK(!executions.empty());
363 BOOST_REQUIRE_EQUAL(executions.size(), 2);
364 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 100);
365 BOOST_CHECK_EQUAL(executions[0].orderQty(), 4);
366 BOOST_CHECK_EQUAL(executions[1].limitPrice(), 100);
367 BOOST_CHECK_EQUAL(executions[1].orderQty(), 3);
368 std::stringstream ss;
370 BOOST_CHECK(!ss.str().empty());
371 char const output[]=
"=================\nASK\n110: 5 10\n105: 3 7\n------------\n100: 3\n90: 10 2 3\nBID\n=================\n";
372 BOOST_CHECK_EQUAL(ss.str(), output);
379 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_buy_crosses_then_match_exact, ob_t, ob_t_types) {
380 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
381 using OrderType=
typename ob_t::msg_details_t::OrderType;
382 using TIF=
typename ob_t::msg_details_t::TIF;
383 using side=
typename ob_t::side_t;
384 using symbol_t=
typename ob_t::symbol_t;
385 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
386 using Price_t=
typename ob_t::msg_details_t::Price_t;
387 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
390 typename ob_t::order_t o_s[]={
391 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
392 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
393 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
394 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
396 typename ob_t::order_t o_b[]={
397 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
398 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
399 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
400 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
401 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
402 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
404 for (
auto const &o : o_s) {
405 BOOST_CHECK_NO_THROW(ob.place(o));
407 for (
auto const &o : o_b) {
408 BOOST_CHECK_NO_THROW(ob.place(o));
410 BOOST_CHECK(ob.is_crossed());
411 auto const &executions=ob.match();
412 BOOST_CHECK(!ob.is_crossed());
413 BOOST_CHECK(!executions.empty());
414 BOOST_REQUIRE_EQUAL(executions.size(), 2);
415 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 105);
416 BOOST_CHECK_EQUAL(executions[0].orderQty(), 3);
417 BOOST_CHECK_EQUAL(executions[1].limitPrice(), 105);
418 BOOST_CHECK_EQUAL(executions[1].orderQty(), 7);
419 std::stringstream ss;
421 BOOST_CHECK(!ss.str().empty());
422 char const output[]=
"=================\nASK\n110: 5 10\n------------\n100: 4 6\n90: 10 2 3\nBID\n=================\n";
423 BOOST_CHECK_EQUAL(ss.str(), output);
430 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_sell_crosses_then_match_exact, ob_t, ob_t_types) {
431 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
432 using OrderType=
typename ob_t::msg_details_t::OrderType;
433 using TIF=
typename ob_t::msg_details_t::TIF;
434 using side=
typename ob_t::side_t;
435 using symbol_t=
typename ob_t::symbol_t;
436 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
437 using Price_t=
typename ob_t::msg_details_t::Price_t;
438 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
441 typename ob_t::order_t o_s[]={
442 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
443 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
444 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
445 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
446 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
448 typename ob_t::order_t o_b[]={
449 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
450 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
451 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
452 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
453 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
455 for (
auto const &o : o_s) {
456 BOOST_CHECK_NO_THROW(ob.place(o));
458 for (
auto const &o : o_b) {
459 BOOST_CHECK_NO_THROW(ob.place(o));
461 BOOST_CHECK(ob.is_crossed());
462 auto const &executions=ob.match();
463 BOOST_CHECK(!ob.is_crossed());
464 BOOST_CHECK(!executions.empty());
465 BOOST_REQUIRE_EQUAL(executions.size(), 2);
466 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 100);
467 BOOST_CHECK_EQUAL(executions[0].orderQty(), 4);
468 BOOST_CHECK_EQUAL(executions[1].limitPrice(), 100);
469 BOOST_CHECK_EQUAL(executions[1].orderQty(), 6);
470 std::stringstream ss;
472 BOOST_CHECK(!ss.str().empty());
473 char const output[]=
"=================\nASK\n110: 5 10\n105: 3 7\n------------\n90: 10 2 3\nBID\n=================\n";
474 BOOST_CHECK_EQUAL(ss.str(), output);
481 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_buy_and_sell_crosses_then_match, ob_t, ob_t_types) {
482 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
483 using OrderType=
typename ob_t::msg_details_t::OrderType;
484 using TIF=
typename ob_t::msg_details_t::TIF;
485 using side=
typename ob_t::side_t;
486 using symbol_t=
typename ob_t::symbol_t;
487 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
488 using Price_t=
typename ob_t::msg_details_t::Price_t;
489 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
492 typename ob_t::order_t o_s[]={
493 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
494 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
495 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
496 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
498 typename ob_t::order_t o_b[]={
499 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
500 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
501 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
502 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
503 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
504 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
506 for (
auto const &o : o_s) {
507 BOOST_CHECK_NO_THROW(ob.place(o));
509 for (
auto const &o : o_b) {
510 BOOST_CHECK_NO_THROW(ob.place(o));
512 BOOST_CHECK_NO_THROW(ob.match());
513 typename ob_t::order_t aggressive_sell{SeqNum_t{10}, ClientOrderID_t{
"10"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{23}, Price_t{80}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
514 ob.place(aggressive_sell);
515 BOOST_CHECK(ob.is_crossed());
516 auto const &executions=ob.match();
517 BOOST_CHECK(!ob.is_crossed());
518 BOOST_CHECK(!executions.empty());
519 BOOST_REQUIRE_EQUAL(executions.size(), 5);
520 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 100);
521 BOOST_CHECK_EQUAL(executions[0].orderQty(), 4);
522 BOOST_CHECK_EQUAL(executions[1].limitPrice(), 100);
523 BOOST_CHECK_EQUAL(executions[1].orderQty(), 6);
524 BOOST_CHECK_EQUAL(executions[2].limitPrice(), 90);
525 BOOST_CHECK_EQUAL(executions[2].orderQty(), 10);
526 BOOST_CHECK_EQUAL(executions[3].limitPrice(), 90);
527 BOOST_CHECK_EQUAL(executions[3].orderQty(), 2);
528 BOOST_CHECK_EQUAL(executions[4].limitPrice(), 90);
529 BOOST_CHECK_EQUAL(executions[4].orderQty(), 1);
530 std::stringstream ss;
532 BOOST_CHECK(!ss.str().empty());
533 char const output[]=
"=================\nASK\n110: 5 10\n105: 6\n------------\n90: 2\nBID\n=================\n";
534 BOOST_CHECK_EQUAL(ss.str(), output);
541 BOOST_AUTO_TEST_CASE_TEMPLATE(place_more_orders_then_buy_sell_and_buy_crosses_then_match, ob_t, ob_t_types) {
542 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
543 using OrderType=
typename ob_t::msg_details_t::OrderType;
544 using TIF=
typename ob_t::msg_details_t::TIF;
545 using side=
typename ob_t::side_t;
546 using symbol_t=
typename ob_t::symbol_t;
547 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
548 using Price_t=
typename ob_t::msg_details_t::Price_t;
549 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
552 typename ob_t::order_t o_s[]={
553 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
554 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
555 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
556 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{7}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
558 typename ob_t::order_t o_b[]={
559 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
560 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
561 typename ob_t::order_t{SeqNum_t{6}, ClientOrderID_t{
"6"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
562 typename ob_t::order_t{SeqNum_t{7}, ClientOrderID_t{
"7"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
563 typename ob_t::order_t{SeqNum_t{8}, ClientOrderID_t{
"8"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
564 typename ob_t::order_t{SeqNum_t{9}, ClientOrderID_t{
"9"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
566 for (
auto const &o : o_s) {
567 BOOST_CHECK_NO_THROW(ob.place(o));
569 for (
auto const &o : o_b) {
570 BOOST_CHECK_NO_THROW(ob.place(o));
572 BOOST_CHECK_NO_THROW(ob.match());
573 typename ob_t::order_t aggressive_sell{SeqNum_t{10}, ClientOrderID_t{
"10"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{23}, Price_t{80}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
574 ob.place(aggressive_sell);
575 BOOST_CHECK_NO_THROW(ob.match());
576 typename ob_t::order_t aggressive_buy{SeqNum_t{11}, ClientOrderID_t{
"11"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{8}, Price_t{107}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
577 ob.place(aggressive_buy);
578 BOOST_CHECK(ob.is_crossed());
579 auto const &executions=ob.match();
580 BOOST_CHECK(!ob.is_crossed());
581 BOOST_CHECK(!executions.empty());
582 BOOST_REQUIRE_EQUAL(executions.size(), 1);
583 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 105);
584 BOOST_CHECK_EQUAL(executions[0].orderQty(), 6);
585 std::stringstream ss;
587 BOOST_CHECK(!ss.str().empty());
588 char const output[]=
"=================\nASK\n110: 5 10\n------------\n107: 2\n90: 2\nBID\n=================\n";
589 BOOST_CHECK_EQUAL(ss.str(), output);
596 BOOST_AUTO_TEST_CASE_TEMPLATE(place_orders_then_cancel_one, ob_t, ob_t_types) {
597 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
598 using OrderType=
typename ob_t::msg_details_t::OrderType;
599 using TIF=
typename ob_t::msg_details_t::TIF;
600 using side=
typename ob_t::side_t;
601 using symbol_t=
typename ob_t::symbol_t;
602 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
603 using Price_t=
typename ob_t::msg_details_t::Price_t;
604 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
607 typename ob_t::order_t o_s[]={
608 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
609 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
611 typename ob_t::order_t o_b[]={
612 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
613 typename ob_t::order_t{SeqNum_t{5}, ClientOrderID_t{
"5"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
615 for (
auto const &o : o_s) {
616 BOOST_CHECK_NO_THROW(ob.place(o));
618 for (
auto const &o : o_b) {
619 BOOST_CHECK_NO_THROW(ob.place(o));
621 BOOST_CHECK(!ob.empty());
622 BOOST_CHECK(!ob.is_crossed());
623 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 5);
624 BOOST_CHECK(ob.match().empty());
625 BOOST_CHECK_NO_THROW(ob.cancel(o_s[1]));
626 BOOST_CHECK(!ob.empty());
627 BOOST_CHECK(!ob.is_crossed());
628 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 10);
629 BOOST_CHECK(ob.match().empty());
630 std::stringstream ss;
632 BOOST_CHECK(!ss.str().empty());
639 BOOST_AUTO_TEST_CASE_TEMPLATE(place_orders_then_cancel_one_buy_match, ob_t, ob_t_types) {
640 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
641 using OrderType=
typename ob_t::msg_details_t::OrderType;
642 using TIF=
typename ob_t::msg_details_t::TIF;
643 using side=
typename ob_t::side_t;
644 using symbol_t=
typename ob_t::symbol_t;
645 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
646 using Price_t=
typename ob_t::msg_details_t::Price_t;
647 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
650 typename ob_t::order_t o_s[]={
651 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
652 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
654 typename ob_t::order_t o_b[]={
655 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
656 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
658 for (
auto const &o : o_s) {
659 BOOST_CHECK_NO_THROW(ob.place(o));
661 for (
auto const &o : o_b) {
662 BOOST_CHECK_NO_THROW(ob.place(o));
664 BOOST_CHECK_NO_THROW(ob.cancel(o_s[1]));
665 typename ob_t::order_t aggressive_sell{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{23}, Price_t{80}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON};
666 ob.place(aggressive_sell);
667 auto const &executions=ob.match();
668 BOOST_CHECK(!ob.empty());
669 BOOST_CHECK(!ob.is_crossed());
670 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 0);
671 BOOST_CHECK(ob.match().empty());
672 BOOST_REQUIRE_EQUAL(executions.size(), 2);
673 BOOST_CHECK_EQUAL(executions[0].limitPrice(), 100);
674 BOOST_CHECK_EQUAL(executions[0].orderQty(), 4);
675 BOOST_CHECK_EQUAL(executions[1].limitPrice(), 90);
676 BOOST_CHECK_EQUAL(executions[1].orderQty(), 10);
677 std::stringstream ss;
679 BOOST_CHECK(!ss.str().empty());
686 BOOST_AUTO_TEST_CASE_TEMPLATE(cancel_unknown_symbol, ob_t, ob_t_types) {
687 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
688 using OrderType=
typename ob_t::msg_details_t::OrderType;
689 using TIF=
typename ob_t::msg_details_t::TIF;
690 using side=
typename ob_t::side_t;
691 using symbol_t=
typename ob_t::symbol_t;
692 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
693 using Price_t=
typename ob_t::msg_details_t::Price_t;
694 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
697 typename ob_t::order_t o_s[]={
698 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
699 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
701 typename ob_t::order_t o_b[]={
702 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
703 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
705 for (
auto const &o : o_s) {
706 BOOST_CHECK_NO_THROW(ob.place(o));
708 for (
auto const &o : o_b) {
709 BOOST_CHECK_NO_THROW(ob.place(o));
711 BOOST_CHECK_NO_THROW(ob.cancel(
typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"ABC"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}));
712 BOOST_CHECK(!ob.empty());
713 BOOST_CHECK(!ob.is_crossed());
714 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 5);
715 BOOST_CHECK(ob.match().empty());
716 std::stringstream ss;
718 BOOST_CHECK(!ss.str().empty());
725 BOOST_AUTO_TEST_CASE_TEMPLATE(cancel_read_symbol, ob_t, ob_t_types) {
726 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
727 using OrderType=
typename ob_t::msg_details_t::OrderType;
728 using TIF=
typename ob_t::msg_details_t::TIF;
729 using side=
typename ob_t::side_t;
730 using symbol_t=
typename ob_t::symbol_t;
731 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
732 using Price_t=
typename ob_t::msg_details_t::Price_t;
733 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
736 typename ob_t::order_t o_s[]={
737 typename ob_t::order_t{SeqNum_t{0}, ClientOrderID_t{
"0"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{110}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
738 typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
739 typename ob_t::order_t{SeqNum_t{2}, ClientOrderID_t{
"2"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{6}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
741 typename ob_t::order_t o_b[]={
742 typename ob_t::order_t{SeqNum_t{3}, ClientOrderID_t{
"3"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{90}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
743 typename ob_t::order_t{SeqNum_t{4}, ClientOrderID_t{
"4"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{4}, Price_t{100}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
745 for (
auto const &o : o_s) {
746 BOOST_CHECK_NO_THROW(ob.place(o));
748 for (
auto const &o : o_b) {
749 BOOST_CHECK_NO_THROW(ob.place(o));
751 BOOST_CHECK_NO_THROW(ob.cancel(
typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}));
752 BOOST_CHECK_NO_THROW(ob.place(
typename ob_t::order_t{SeqNum_t{1}, ClientOrderID_t{
"1"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{105}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}));
753 BOOST_CHECK(!ob.empty());
754 BOOST_CHECK(!ob.is_crossed());
755 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 5);
756 BOOST_CHECK(ob.match().empty());
757 std::stringstream ss;
759 BOOST_CHECK(!ss.str().empty());
766 BOOST_AUTO_TEST_CASE_TEMPLATE(process_market_data_example, ob_t, ob_t_types) {
767 using SeqNum_t=
typename ob_t::msg_details_t::SeqNum_t;
768 using OrderType=
typename ob_t::msg_details_t::OrderType;
769 using TIF=
typename ob_t::msg_details_t::TIF;
770 using side=
typename ob_t::side_t;
771 using symbol_t=
typename ob_t::symbol_t;
772 using ClientOrderID_t=
typename ob_t::msg_details_t::ClientOrderID_t;
773 using Price_t=
typename ob_t::msg_details_t::Price_t;
774 using Quantity_t=
typename ob_t::msg_details_t::Quantity_t;
777 typename ob_t::order_t o1[]={
778 typename ob_t::order_t{SeqNum_t{100000}, ClientOrderID_t{
"100000"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{1}, Price_t{1075}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
779 typename ob_t::order_t{SeqNum_t{100001}, ClientOrderID_t{
"100001"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{9}, Price_t{1000}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
780 typename ob_t::order_t{SeqNum_t{100002}, ClientOrderID_t{
"100002"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{30}, Price_t{975}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
781 typename ob_t::order_t{SeqNum_t{100003}, ClientOrderID_t{
"100003"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{1050}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
782 typename ob_t::order_t{SeqNum_t{100004}, ClientOrderID_t{
"100004"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{950}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
783 typename ob_t::order_t{SeqNum_t{100005}, ClientOrderID_t{
"100005"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{1025}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
784 typename ob_t::order_t{SeqNum_t{100006}, ClientOrderID_t{
"100006"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{1}, Price_t{1000}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
786 for (
auto const &o : o1) {
787 BOOST_CHECK_NO_THROW(ob.place(o));
789 BOOST_CHECK_NO_THROW(ob.cancel(
typename ob_t::order_t{SeqNum_t{100004}, ClientOrderID_t{
"100004"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{10}, Price_t{950}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}));
790 typename ob_t::order_t o2[]={
791 typename ob_t::order_t{SeqNum_t{100007}, ClientOrderID_t{
"100007"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{5}, Price_t{1025}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON},
792 typename ob_t::order_t{SeqNum_t{100008}, ClientOrderID_t{
"100008"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{1050}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}
794 for (
auto const &o : o2) {
795 BOOST_CHECK_NO_THROW(ob.place(o));
797 BOOST_CHECK_NO_THROW(ob.cancel(
typename ob_t::order_t{SeqNum_t{100008}, ClientOrderID_t{
"100008"}, OrderType::Limit, TIF::Day, side::Buy, symbol_t{
"XYZ"}, Quantity_t{3}, Price_t{1050}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}));
798 BOOST_CHECK_NO_THROW(ob.cancel(
typename ob_t::order_t{SeqNum_t{100005}, ClientOrderID_t{
"100005"}, OrderType::Limit, TIF::Day, side::Sell, symbol_t{
"XYZ"}, Quantity_t{2}, Price_t{102}, exchanges::common::mic_codes::ISO_10383_MIC_Codes::ISO_10383_UNITED_KINGDOM_XLON}));
799 BOOST_CHECK(!ob.empty());
800 BOOST_CHECK(!ob.is_crossed());
801 BOOST_CHECK_EQUAL(ob.agreed_spread(symbol_t{
"XYZ"}), 75);
802 BOOST_CHECK(ob.match().empty());
803 std::stringstream ss;
805 BOOST_CHECK(!ss.str().empty());
808 BOOST_AUTO_TEST_SUITE_END()