36void checkSettingSanity(
const Settings& settings)
38 const auto traderId = settings.get(
"TraderId");
39 const auto traderPwd = settings.get(
"TraderPwd");
40 const auto clientId = settings.get<
Int32>(
"ClientId");
41 const auto userId = settings.get(
"UserId");
42 const auto userPwd = settings.get(
"Password");
43 const auto host = settings.get(
"Host");
44 const auto port = settings.get<
Port>(
"Port");
45 const auto onBehalfOfSubId = settings.get(
"OnBehalfOfSubId");
46 const auto onBehalfOfLocationId = settings.get(
"OnBehalfOfLocationId");
47 const auto onBehalfOfCompId = settings.get(
"OnBehalfOfCompId");
48 const auto clearingFirm = settings.get<
Int32>(
"ClearingFirm");
49 const auto clearingAccount = settings.get(
"ClearingAccount");
50 const auto mifidId = settings.get<
Int64>(
"MifidId");
51 const auto keepAliveInterval = settings.get<
UInt16>(
"KeepAliveInterval");
52 const auto investmentDecision = settings.get<
Int64>(
"InvestmentDecision");
53 const auto executionDecision = settings.get<
Int64>(
"ExecutionDecision");
77 checkSettingSanity(settings);
83 .
userId(settings.get(
"UserId"))
84 .clientId(settings.get<
Int32>(
"ClientId"))
85 .rawData(settings.get(
"Password"))
86 .reconnectAttempts(100)
88 .keepAliveInterval(settings.get<
UInt16>(
"KeepAliveInterval"))
92 return sessionSettings;
95auto initSecurityDefinitionRequest(
const Settings&)
101auto initNewOrder(
const Settings& settings)
106 originatorUserId(settings.get(
"TraderId"))
107 .onBehalfOfSubId(settings.get(
"OnBehalfOfSubId"))
108 .onBehalfOfLocationId(settings.get(
"OnBehalfOfLocationId"))
109 .onBehalfOfCompId(settings.get(
"OnBehalfOfCompId"))
110 .clearingFirm(settings.get<
Int32>(
"ClearingFirm"))
111 .clearingAccount(settings.get(
"ClearingAccount"))
112 .mifidId(settings.get<
Int64NULL>(
"MifidId"))
113 .manualOrderIndicator(BooleanEnum::True)
114 .custOrderHandlingInst(CustOrderHandlingInstEnum::Y)
115 .memo(
"NewOrderRequest")
116 .selfMatchPreventionInstruction(SelfMatchPreventionInstructionEnum::CancelTakingOrder);
118 if(settings.isSet(
"SelfMatchPreventionId"))
119 request->selfMatchPreventionId(settings.get<
Int64>(
"SelfMatchPreventionId"));
124auto initOrderCancelRequest(
const Settings& settings)
128 request->originatorUserId(settings.get(
"TraderId"));
133auto initOrderReplaceRequest(
const Settings& settings)
138 originatorUserId(settings.get(
"TraderId"))
139 .onBehalfOfSubId(settings.get(
"OnBehalfOfSubId"))
140 .onBehalfOfLocationId(settings.get(
"OnBehalfOfLocationId"))
141 .onBehalfOfCompId(settings.get(
"OnBehalfOfCompId"))
142 .clearingFirm(settings.get<
Int32>(
"ClearingFirm"))
143 .clearingAccount(settings.get(
"ClearingAccount"))
144 .mifidId(settings.get<
Int64NULL>(
"MifidId"))
145 .manualOrderIndicator(BooleanEnum::True)
146 .memo(
"CancelReplaceRequest")
147 .selfMatchPreventionInstruction(SelfMatchPreventionInstructionEnum::CancelTakingOrder);
149 if(settings.isSet(
"SelfMatchPreventionId"))
150 request->selfMatchPreventionId(settings.get<
Int64>(
"SelfMatchPreventionId"));
155auto initNewOrderCrossRequest(
const Settings& settings)
159 const auto onBehalfOfSubId = settings.get(
"OnBehalfOfSubId");
160 const auto onBehalfOfLocationId = settings.get(
"OnBehalfOfLocationId");
161 const auto onBehalfOfCompId = settings.get(
"OnBehalfOfCompId");
162 const auto clearingFirm = settings.get<
Int32>(
"ClearingFirm");
163 const auto clearingAccount = settings.get(
"ClearingAccount");
164 const auto mifidId = settings.get<
Int64NULL>(
"MifidId");
166 request->originatorUserId(settings.get(
"TraderId"));
167 request->crossType(CrossTypeEnum::IOC);
169 auto sides = request->sides(2);
172 .onBehalfOfSubId(onBehalfOfSubId)
173 .onBehalfOfLocationId(onBehalfOfLocationId)
174 .onBehalfOfCompId(onBehalfOfCompId)
175 .clearingFirm(clearingFirm)
176 .clearingAccount(clearingAccount)
178 .manualOrderIndicator(BooleanEnum::True)
179 .memo(
"NewOrderCrossRequest[0]")
180 .custOrderHandlingInst(CustOrderHandlingInstEnum::Y)
181 .selfMatchPreventionInstruction(SelfMatchPreventionInstructionEnum::CancelTakingOrder);
184 .onBehalfOfSubId(onBehalfOfSubId)
185 .onBehalfOfLocationId(onBehalfOfLocationId)
186 .onBehalfOfCompId(onBehalfOfCompId)
187 .clearingFirm(clearingFirm)
188 .clearingAccount(clearingAccount)
190 .manualOrderIndicator(BooleanEnum::True)
191 .memo(
"NewOrderCrossRequest[1]")
192 .custOrderHandlingInst(CustOrderHandlingInstEnum::Y)
193 .selfMatchPreventionInstruction(SelfMatchPreventionInstructionEnum::CancelTakingOrder);
195 if(settings.isSet(
"SelfMatchPreventionId"))
197 const auto id = settings.get<
Int64>(
"SelfMatchPreventionId");
198 sides[0].selfMatchPreventionId(
id);
199 sides[1].selfMatchPreventionId(
id);
205auto initOrderMassCancelRequest(
const Settings& settings)
209 request->originatorUserId(settings.get(
"TraderId"));
210 request->massCancelRequestType(MassCancelRequestTypeEnum::CancelAllForTrader);
215auto initQuoteRequest(
const Settings& settings)
220 originatorUserId(settings.get(
"TraderId"))
221 .onBehalfOfSubId(settings.get(
"OnBehalfOfSubId"))
222 .onBehalfOfLocationId(settings.get(
"OnBehalfOfLocationId"))
223 .onBehalfOfCompId(settings.get(
"OnBehalfOfCompId"))
224 .clearingFirm(settings.get<
Int32>(
"ClearingFirm"))
225 .clearingAccount(settings.get(
"ClearingAccount"));
230auto initQuoteCancelRequest(
const Settings& settings)
234 request->originatorUserId(settings.get(
"TraderId"));
235 request->quoteCancelType(QuoteCancelTypeEnum::CancelByUnderlyingMarket);
236 request->quoteEntries(1);
241auto initMassQuoteRequest(
const Settings& settings)
246 mifidId(settings.get<
Int64NULL>(
"MifidId"))
247 .selfMatchPreventionInstruction(SelfMatchPreventionInstructionEnum::CancelTakingOrder)
248 .riskProtectionReset(BooleanEnum::True)
249 .directElectronicAccess(BooleanEnum::True)
250 .originatorUserId(settings.get(
"TraderId"))
253 if(settings.isSet(
"SelfMatchPreventionId"))
254 request->selfMatchPreventionId(settings.get<
Int64>(
"SelfMatchPreventionId"));
261auto queryString(
const char* name,
const std::string& defaultValue)
263 Screen::out(
"Enter ", name,
" (default=", defaultValue,
"): ");
267auto queryTimestamp(
const char* name,
Timestamp defaultValue)
272 if(userInput.empty())
278template <
typename OptionalType>
279auto queryOptionalTimestamp(
const char* name, OptionalType defaultValue = {})
284 if(userInput.empty())
288 return OptionalType{};
294auto queryNumeric(
const char* name, T defaultValue,
typename std::enable_if<std::is_integral<T>::value,
void*>::type =
nullptr)
300template <
typename OptionalType>
301auto queryOptionalNumeric(
const char* name,
typename std::enable_if<
isOptional<OptionalType>::value && std::is_integral<typename OptionalType::HeldType>::value,
void*>::type =
nullptr)
308 return OptionalType{};
313auto queryDecimal(
const char* name,
Decimal9 defaultValue)
318 if(userInput.empty())
324template <
typename OptionalType>
325auto queryOptionalDecimal(
const char* name, OptionalType defaultValue = {},
typename std::enable_if<isOptional<OptionalType>::value,
void*>::type=
nullptr)
327 Screen::out(
"Enter ", name,
", optional, (default=",
toStr(defaultValue),
"): ");
331 if(userInput.empty())
335 return OptionalType{};
340template<
typename Type,
size_t Size>
341auto queryEnum(
const char* name,
const Type (&allowedValues)[Size], Type defaultValue,
typename std::enable_if<isScopedEnum<Type>::value,
void*>::type=
nullptr)
343 const std::set<Type> val{std::begin(allowedValues), std::end(allowedValues)};
344 Screen::out(
"Enter ", name,
" [",
join(val.begin(), val.end(),
','),
"] (default=",
toStr(defaultValue),
"):");
348 if(userInput.empty())
353 if(val.find(value) == val.end())
354 throw std::invalid_argument(
"Invalid user input: '" +
toStr(value) +
"'");
359template<
typename OptionalType,
size_t Size>
360auto queryOptionalEnum(
const char* name,
const typename OptionalType::HeldType (&allowedValues)[Size], OptionalType defaultValue = {},
typename std::enable_if<isOptional<OptionalType>::value && isScopedEnum<typename OptionalType::HeldType>::value,
void*>::type=
nullptr)
362 const std::set<typename OptionalType::HeldType> val{std::begin(allowedValues), std::end(allowedValues)};
363 Screen::out(
"Enter ", name,
" [",
join(val.begin(), val.end(),
','),
"], optional, (default=",
toStr(
nullOpt),
"):");
367 if(userInput.empty())
371 return OptionalType{};
375 return OptionalType{value};
381 return queryEnum(
"Side", allowedValues, defaultValue);
384template<
typename OptionalType,
size_t Size>
385auto querySideOptional(
const SideEnum (&allowedValues)[Size])
387 return queryOptionalEnum<OptionalType>(
"Side", allowedValues);
393 return queryEnum(
"OrderType", allowedValues, defaultValue);
396template<
typename OptionalType,
size_t Size>
397auto queryOrderTypeOptional(
const typename OptionalType::HeldType (&allowedValues)[Size])
399 return queryOptionalEnum<OptionalType, Size>(
"OrderType", allowedValues);
405 return queryEnum(
"TimeInForce", allowedValues, defaultValue);
408template<
typename OptionalType,
size_t Size>
409auto queryTimeInForceOptional(
const TimeInForceEnum (&allowedValues)[Size])
411 return queryOptionalEnum<OptionalType, Size>(
"TimeInForce", allowedValues);
417 return queryEnum(
"SecurityRequestType", allowedValues, defaultValue);
420template<
typename OptionalType,
size_t Size>
421auto queryPriceTypeOptional(
const typename OptionalType::HeldType (&allowedValues)[Size])
423 return queryOptionalEnum<OptionalType, Size>(
"PriceType", allowedValues);
426template<
typename OptionalType,
size_t Size>
427auto queryBenchmarkPriceTypeOptional(
const typename OptionalType::HeldType (&allowedValues)[Size])
429 return queryOptionalEnum<OptionalType, Size>(
"BenchmarkPriceType", allowedValues);
432template<
typename OptionalType,
size_t Size>
433auto queryExecInstOptional(
const typename OptionalType::HeldType (&allowedValues)[Size], OptionalType defaultValue)
435 return queryOptionalEnum<OptionalType, Size>(
"ExecInst", allowedValues, defaultValue);
438template<
typename OptionalType,
size_t Size>
439auto queryBooleanOptional(
const char* name,
const BooleanEnum (&allowedValues)[Size])
441 return queryOptionalEnum<OptionalType>(name, allowedValues);
447 return queryEnum(
"CustOrderHandlingInst", allowedValues, defaultValue);
450struct QuoteIdGenerator
460void TradingClient::checkConnected(
const SessionPtr& sn,
const char* kind)
465 throw std::runtime_error(
"A " + std::string(kind) +
" session must be in the [Established] state");
469 : settings_(settings)
470 , sessionSettings_(fillSessionSettings(settings_))
471 , newOrderRequest_(initNewOrder(settings))
472 , securityDefinitionRequest_(initSecurityDefinitionRequest(settings))
473 , cancelRequest_(initOrderCancelRequest(settings))
474 , replaceRequest_(initOrderReplaceRequest(settings))
475 , newOrderCrossRequest_(initNewOrderCrossRequest(settings))
476 , orderMassCancelRequest_(initOrderMassCancelRequest(settings))
477 , quoteRequest_(initQuoteRequest(settings))
478 , quoteCancelRequest_(initQuoteCancelRequest(settings))
479 , massQuoteRequest_(initMassQuoteRequest(settings))
485 auto ord = orderBook_.
find(orderId);
495 auto settings = sessionSettings_;
500 busSession_->connect(settings_.get(
"Host"), settings_.get<
Port>(
"Port"));
505 checkConnected(busSession_,
"BUS");
507 const auto userId = settings_.get(
"UserId");
510 request->clientId(sessionSettings_.clientId());
511 request->users(1)[0].userId(userId);
513 bgwCredentials_ = {};
514 TradingClient::send(busSession_, request);
519 checkConnected(busSession_,
"BUS");
522 const auto requestType = querySecurityRequestType(
523 {SecurityRequestTypeEnum::RequestListofOptions,
524 SecurityRequestTypeEnum::RequestListofStrategies,
525 SecurityRequestTypeEnum::RequestListofFutures,
526 SecurityRequestTypeEnum::RequestListOfProducts
530 request->marketTypeId(marketTypeId);
532 request->securityRequestType(requestType);
534 instruments_.clear();
535 send(busSession_, request);
540 std::vector<Messaging::SbeMessage> messages;
542 for (
auto element : instruments_)
545 std::reverse(messages.begin(), messages.end());
551 if(!ONIXS_ICEBOE_MESSAGING_NAMESPACE::processTypified(msg, [&](
const auto msg) {
toStr(res, msg); }))
562 std::vector<Messaging::SecurityDefinitionReport> messages;
564 for (
auto element : instruments_)
568 if(msg.
symbol() == symbol)
569 messages.push_back(msg);
578 throw std::runtime_error(
"BGW credentials must be obtained first");
580 auto settings = sessionSettings_;
585 bgwSession_->connect(bgwCredentials_.host(), bgwCredentials_.port(), bgwCredentials_.ipSessionToken());
590 checkConnected(bgwSession_,
"BGW");
593 request->originatorUserId(settings_.get(
"TraderId"));
594 request->rawData(settings_.get(
"TraderPwd"));
595 request->directElectronicAccess(BooleanEnum::True);
596 request->tradingCapacity(TradingCapacityEnum::DEAL);
597 request->liquidityProvision(BooleanEnum::True);
598 request->commodityDerivIndicator(BooleanEnum::False);
599 request->investmentDecision(settings_.get<
Int64>(
"InvestmentDecision"));
600 request->executionDecision(settings_.get<
Int64>(
"ExecutionDecision"));
602 TradingClient::send(bgwSession_, request);
607 checkConnected(bgwSession_,
"BGW");
610 request->originatorUserId(settings_.get(
"TraderId"));
612 TradingClient::send(bgwSession_, request);
617 checkConnected(bgwSession_,
"BGW");
619 const auto order = orderBook_.store(newOrder());
622 newOrderRequest_->price(order.price_.raw())
623 .orderQty(order.orderQty_)
624 .symbol(order.securityId_)
625 .clOrdId(order.cIOrdId_)
626 .stopPx(order.stopPx_.raw())
627 .ordType(order.ordType_)
628 .timeInForce(order.timeInForce_)
630 .maxShow(order.maxShow_.raw())
631 .execInst(order.execInst_.raw())
634 if (order.timeInForce_ == TimeInForceEnum::GTD && order.expireDate_)
635 newOrderRequest_->expireDate(*order.expireDate_);
637 newOrderRequest_->expireDate(
nullOpt);
639 const auto custOrderHandlingInst =
640 queryCustOrderHandlingInst({
641 CustOrderHandlingInstEnum::C
642 ,CustOrderHandlingInstEnum::D
643 ,CustOrderHandlingInstEnum::G
644 ,CustOrderHandlingInstEnum::H
645 ,CustOrderHandlingInstEnum::W
646 ,CustOrderHandlingInstEnum::Y
649 newOrderRequest_->custOrderHandlingInst(custOrderHandlingInst);
651 const auto selfMatchPreventionInstruction =
652 queryOptionalEnum<decltype(std::declval<const NewOrderRequest&>().selfMatchPreventionInstruction())>(
653 "SelfMatchPreventionInstruction",
655 SelfMatchPreventionInstructionEnum::CancelRestingOrder
656 ,SelfMatchPreventionInstructionEnum::CancelTakingOrder
657 ,SelfMatchPreventionInstructionEnum::CancelBothOrders
660 newOrderRequest_->selfMatchPreventionInstruction(selfMatchPreventionInstruction.raw());
662 TradingClient::send(bgwSession_, newOrderRequest_);
667 checkConnected(bgwSession_,
"BGW");
669 const auto transactDetails = queryString(
"TransactDetails",
"***");
671 const auto priceType =
672 queryPriceTypeOptional<decltype(std::declval<const NewOrderCrossRequest&>().priceType())>({
673 PriceTypeEnum::PerContract,
674 PriceTypeEnum::FixedCabinetTradePrice,
675 PriceTypeEnum::FixedRate,
677 PriceTypeEnum::RateDifferential,
678 PriceTypeEnum::NPVDifferential});
680 const auto benchmarkPriceType =
681 queryBenchmarkPriceTypeOptional<decltype(std::declval<const NewOrderCrossRequest&>().benchMarkPriceType())>({
682 BenchmarkPriceTypeEnum::FixedAmount});
685 queryOptionalDecimal<decltype(std::declval<const NewOrderCrossRequest&>().benchmarkPrice())>(
"BenchmarkPrice");
687 const auto crossType = queryEnum(
"CrossType", {CrossTypeEnum::AON, CrossTypeEnum::IOC}, CrossTypeEnum::AON);
689 const auto custOrderHandlingInst =
690 queryCustOrderHandlingInst({
691 CustOrderHandlingInstEnum::C
692 ,CustOrderHandlingInstEnum::D
693 ,CustOrderHandlingInstEnum::G
694 ,CustOrderHandlingInstEnum::H
695 ,CustOrderHandlingInstEnum::W
696 ,CustOrderHandlingInstEnum::Y
699 newOrderCrossRequest_->priceType(priceType.raw());
700 newOrderCrossRequest_->benchMarkPriceType(benchmarkPriceType.raw());
701 newOrderCrossRequest_->benchmarkPrice(bmPrice.raw());
702 newOrderCrossRequest_->transactDetails(
toStrRef(transactDetails));
703 newOrderCrossRequest_->crossType(crossType);
705 auto crossOrder = orderBook_.store(newOrderCross());
709 const auto& buySideOrder = *crossOrder.buySideOrder_;
710 const auto& sellSideOrder = *crossOrder.sellSideOrder_;
712 auto sides = newOrderCrossRequest_->sides();
713 assert(sides.size() == 2);
715 newOrderCrossRequest_->crossId(crossOrder.id());
717 newOrderCrossRequest_->price(buySideOrder.price_.raw())
718 .orderQty(buySideOrder.orderQty_)
719 .symbol(buySideOrder.securityId_)
720 .ordType(buySideOrder.ordType_)
721 .timeInForce(buySideOrder.timeInForce_);
723 sides[0].side(buySideOrder.side_);
724 sides[0].clOrdId(buySideOrder.cIOrdId_);
725 sides[0].custOrderHandlingInst(custOrderHandlingInst);
727 sides[1].side(sellSideOrder.side_);
728 sides[1].clOrdId(sellSideOrder.cIOrdId_);
729 sides[1].custOrderHandlingInst(custOrderHandlingInst);
733 TradingClient::send(bgwSession_, newOrderCrossRequest_);
738 checkConnected(bgwSession_,
"BGW");
742 const auto requestType = queryEnum(
743 "RequestType", {MassCancelRequestTypeEnum::CancelAllForTrader, MassCancelRequestTypeEnum::CancelForTradingSession}, MassCancelRequestTypeEnum::CancelAllForTrader);
745 const auto ordType = queryOrderTypeOptional<decltype(std::declval<const OrderMassCancelRequest&>().ordType())>(
746 {OrderTypeEnum::Limit});
748 const auto side = querySideOptional<decltype(std::declval<const OrderMassCancelRequest&>().side())>(
749 {SideEnum::Buy, SideEnum::Sell});
751 const auto symbol = queryOptionalNumeric<decltype(std::declval<const OrderMassCancelRequest&>().symbol())>(
"Symbol");
753 const auto marketTypeId = queryOptionalNumeric<decltype(std::declval<const OrderMassCancelRequest&>().marketTypeId())>(
"MarketTypeId");
755 const auto price = queryOptionalDecimal<decltype(std::declval<const OrderMassCancelRequest&>().price())>(
"Price");
757 const auto timeInForce = queryTimeInForceOptional<decltype(std::declval<const OrderMassCancelRequest&>().timeInForce())>({TimeInForceEnum::Day});
759 const auto onBehalfOfSubId = queryString(
"OnBehalfOfSubId",
"");
761 orderMassCancelRequest_->massCancelRequestType(requestType);
762 orderMassCancelRequest_->ordType(ordType.raw());
763 orderMassCancelRequest_->side(side.raw());
764 orderMassCancelRequest_->symbol(symbol.raw());
765 orderMassCancelRequest_->marketTypeId(marketTypeId.raw());
766 orderMassCancelRequest_->price(price.raw());
767 orderMassCancelRequest_->timeInForce(timeInForce.raw());
768 orderMassCancelRequest_->onBehalfOfSubId(
toStrRef(onBehalfOfSubId));
770 TradingClient::send(bgwSession_, orderMassCancelRequest_);
775 checkConnected(bgwSession_,
"BGW");
778 const auto side = querySide({SideEnum::Buy, SideEnum::Sell});
787 TradingClient::send(bgwSession_, quoteRequest_);
790Int32 TradingClient::getQuoteSetId(
Int32 underlyingSymbol)
792 for(
auto&& pair : quoteSetId_)
794 if(pair.second == underlyingSymbol)
798 quoteSetId_.emplace_back(
static_cast<Int32>(quoteSetId_.size() + 1), underlyingSymbol);
799 return quoteSetId_.back().first;
804 checkConnected(bgwSession_,
"BGW");
806 massQuoteRequest_->quoteId(QuoteIdGenerator::id());
808 const auto riskProtectionReset =
809 queryBooleanOptional<decltype(std::declval<const MassQuoteRequest&>().riskProtectionReset())>(
810 "RiskProtectionReset", {BooleanEnum::False, BooleanEnum::True});
812 massQuoteRequest_->riskProtectionReset(riskProtectionReset.raw());
814 const auto quotes = massQuoteRequest_->quoteSets();
816 for(
auto&& quote : quotes)
822 .underlyingSymbol(underlyingSymbol)
823 .quoteSetId(getQuoteSetId(underlyingSymbol))
832 TradingClient::send(bgwSession_, massQuoteRequest_);
837 checkConnected(bgwSession_,
"BGW");
839 quoteCancelRequest_->quoteId(QuoteIdGenerator::id());
840 assert(quoteCancelRequest_->quoteEntries().size() == 1);
842 const auto quoteCancelType = queryEnum(
"QuoteCancelType",
843 { QuoteCancelTypeEnum::CancelAll, QuoteCancelTypeEnum::CancelByProductID, QuoteCancelTypeEnum::CancelByUnderlyingMarket},
844 QuoteCancelTypeEnum::CancelByUnderlyingMarket);
846 quoteCancelRequest_->quoteCancelType(quoteCancelType);
848 auto entry = quoteCancelRequest_->quoteEntries()[0];
850 using OptSymbol =
decltype(std::declval<const QuoteCancelRequest::QuoteEntry&>().underlyingSymbol());
851 const auto underlyingSymbol = queryOptionalNumeric<OptSymbol>(
"UnderlyingSymbol");
853 using OptSecId =
decltype(std::declval<const QuoteCancelRequest::QuoteEntry&>().underlyingSecurityId());
854 const auto secId = queryOptionalNumeric<OptSecId>(
"SecurityId");
856 using OptProduct =
decltype(std::declval<const QuoteCancelRequest::QuoteEntry&>().underlyingProduct());
857 const auto product = queryOptionalNumeric<OptProduct>(
"Product");
859 entry.underlyingSymbol(underlyingSymbol.raw());
860 entry.underlyingSecurityId(secId.raw());
861 entry.underlyingProduct(product.raw());
863 TradingClient::send(bgwSession_, quoteCancelRequest_);
868 checkConnected(bgwSession_,
"BGW");
870 constexpr size_t CreateStrategyMaxLegsCount = 5;
878 msg->securityRequestType(SecurityRequestTypeEnum::CreateStrategy);
879 msg->securityType(SecurityTypeEnum::MLEG);
881 using OptionalDate =
decltype(std::declval<const SecurityDefinitionRequest_CreateStrategy&>().startDate());
882 const auto startDate = queryOptionalTimestamp<OptionalDate>(
"StartDate");
883 const auto endDate = queryOptionalTimestamp<OptionalDate>(
"EndDate");
886 msg->startDate(*startDate);
891 msg->endDate(*endDate);
895 const auto legsCount = queryNumeric(
"Number of Legs",
UInt32{2});
897 assert(legsCount <= CreateStrategyMaxLegsCount);
902 auto legs = msg->legs(legsCount);
904 for(
auto&& leg : legs)
906 leg.legSecurityType(SecurityTypeEnum::OPT);
908 leg.legSymbol(queryNumeric(
"Symbol", *defaultSymbol));
910 const auto side = querySide({SideEnum::Buy, SideEnum::Sell});
913 using OptDenominator =
decltype(std::declval<
const std::decay<
decltype(leg)>::type>().legRatioQtyDenominator());
914 const auto denominator = queryOptionalNumeric<OptDenominator>(
"LegRatioQtyDenominator");
916 using OptNuminator =
decltype(std::declval<
const std::decay<
decltype(leg)>::type>().legRatioQtyNumerator());
917 const auto numerator = queryOptionalNumeric<OptNuminator>(
"LegRatioQtyNumerator");
919 leg.legRatioQtyDenominator(denominator.raw());
920 leg.legRatioQtyNumerator(numerator.raw());
925 TradingClient::send(bgwSession_, msg);
930 checkConnected(bgwSession_,
"BGW");
933 msg->securityRequestType(SecurityRequestTypeEnum::CreateFlexOption);
937 const auto type = queryEnum(
"SecurityType", {SecurityTypeEnum::OPT, SecurityTypeEnum::FUT, SecurityTypeEnum::MLEG}, SecurityTypeEnum::OPT);
939 using OptionalDate =
decltype(std::declval<const SecurityDefinitionRequest_CreateFlex&>().maturityDate());
940 const auto maturityDate = queryOptionalTimestamp<OptionalDate>(
"MaturityDate");
942 using OptionalProductId =
decltype(std::declval<const SecurityDefinitionRequest_CreateFlex&>().productId());
943 const auto productId = queryOptionalNumeric<OptionalProductId>(
"ProductId");
945 using OptionalSymbol =
decltype(std::declval<const SecurityDefinitionRequest_CreateFlex&>().symbol());
946 const auto symbol = queryOptionalNumeric<OptionalSymbol>(
"Symbol");
948 using OptionalPrice =
decltype(std::declval<const SecurityDefinitionRequest_CreateFlex&>().strikePrice());
949 const auto price = queryOptionalDecimal<OptionalPrice>(
"StrikePrice");
951 msg->securityType(type);
952 msg->marketTypeId(marketTypeId);
953 msg->productId(productId.raw());
954 msg->symbol(symbol.raw());
955 msg->strikePrice(price.raw());
958 msg->maturityDate(*maturityDate);
962 TradingClient::send(bgwSession_, msg);
967 auto crossOrder = std::make_shared<CrossOrder>();
969 Order& buySideOrder = *crossOrder->buySideOrder_;
970 Order& sellSideOrder = *crossOrder->sellSideOrder_;
976 const auto ordType = queryOrderType({OrderTypeEnum::Market, OrderTypeEnum::Limit}, OrderTypeEnum::Limit);
981 if (ordType == OrderTypeEnum::Limit)
983 const auto price = queryDecimal(
"Price", 64570000);
984 buySideOrder.
price_ = price;
985 sellSideOrder.
price_ = price;
997 buySideOrder.
side_ = SideEnum::Buy;
998 sellSideOrder.
side_ = SideEnum::Sell;
1005 OrderPtr result = std::make_shared<Order>();
1006 auto& order = *result;
1008 order.securityId_ = queryNumeric(
"Symbol", base ? base->securityId_ :
Default::Symbol);
1010 order.ordType_ = queryOrderType(
1011 {OrderTypeEnum::Market, OrderTypeEnum::Limit, OrderTypeEnum::Stop, OrderTypeEnum::StopLimit},
1012 base ? base->ordType_ : OrderTypeEnum::Limit);
1014 if (order.ordType_ == OrderTypeEnum::Limit || order.ordType_ == OrderTypeEnum::StopLimit)
1017 if (order.ordType_ == OrderTypeEnum::StopLimit || order.ordType_ == OrderTypeEnum::Stop)
1021 order.leavesQty_ = order.orderQty_;
1023 order.timeInForce_ = queryTimeInForce(
1024 {TimeInForceEnum::Day, TimeInForceEnum::GTC, TimeInForceEnum::FAK, TimeInForceEnum::FOK, TimeInForceEnum::GTD},
1025 base ? base->timeInForce_ : TimeInForceEnum::Day );
1027 if (order.timeInForce_ == TimeInForceEnum::GTD)
1028 order.expireDate_ = queryTimestamp(
"ExpireDate", (base && base->expireDate_) ? *base->expireDate_ :
Default::Timestamp);
1030 order.side_ = querySide({SideEnum::Buy, SideEnum::Sell}, base ? base->side_ : SideEnum::Buy);
1034 const auto maxShow =
1035 queryOptionalDecimal(
"MaxShow", base ? base->maxShow_ :
Order::QtiOptional{nullOpt});
1039 if(*maxShow > order.orderQty_)
1040 throw std::logic_error(
"Invalid `MaxShow` for order");
1042 order.maxShow_ = *maxShow;
1055 return order.orderStatus_ == ExecTypeEnum::New || order.orderStatus_ == ExecTypeEnum::PartialFill || order.orderStatus_ == ExecTypeEnum::Replaced;
1065 checkConnected(bgwSession_,
"BGW");
1067 const auto ordersInBook = orderBook_.getEntries(
activeOrder);
1069 if (ordersInBook.empty())
1077 Screen::out(
"Enter the index of the order to be canceled");
1080 const Order& order = *ordersInBook.at(orderIndex - 1);
1089 TradingClient::send(bgwSession_, cancelRequest_);
1094 checkConnected(bgwSession_,
"BGW");
1096 const auto ordersInBook = orderBook_.getEntries(
activeOrder);
1098 if (ordersInBook.empty())
1106 Screen::out(
"Enter the index of the order to be replaced");
1109 const auto order = ordersInBook.at(orderIndex - 1);
1111 auto replaceOrder = orderBook_.store(newOrder(order.get()));
1128 replaceRequest_->expireDate(*
replaceOrder.expireDate_);
1130 replaceRequest_->expireDate(
nullOpt);
1132 TradingClient::send(bgwSession_, replaceRequest_);
1143 if(status == RFCStatusEnum::None || status == RFCStatusEnum::Success)
1146 const auto crossId = msg.
crossId();
1147 auto crossOrder = orderBook_.
findCross(crossId);
1155 auto& buySideOrder = *(crossOrder->get()->buySideOrder_);
1156 auto& sellSideOrder = *(crossOrder->get()->sellSideOrder_);
1158 if(status == RFCStatusEnum::PartialSuccessBidFailure || status == RFCStatusEnum::Failure)
1164 if(status == RFCStatusEnum::PartialSuccessOfferFailure || status == RFCStatusEnum::Failure)
1171void TradingClient::onExecutionReport_New(
const Messaging::ExecutionReport_New msg,
Session* sn)
1178 if(
auto order = findByOrderId(msg.
clOrdId()))
1181 setCommonMessageFields(**order, msg);
1183 Screen::info(
"Order changed: " + order->get()->toString());
1187void TradingClient::onExecutionReport_Reject(
const Messaging::ExecutionReport_Reject msg,
Session* sn)
1196 if(
auto order = findByOrderId(msg.
clOrdId()))
1199 setCommonMessageFields(**order, msg);
1201 Screen::info(
"Order changed: " + order->get()->toString());
1206void TradingClient::onExecutionReport_Cancel(
const Messaging::ExecutionReport_Cancel msg,
Session* sn)
1217 if(
auto order = findByOrderId(*origClOrdId))
1220 setCommonMessageFields(**order, msg);
1222 Screen::info(
"Order changed: " + order->get()->toString());
1227void TradingClient::onExecutionReport_Modify(
const Messaging::ExecutionReport_Modify msg,
Session* sn)
1234 auto newOrder = findByOrderId(msg.
clOrdId());
1237 auto oldOrder = origClOrdId ? findByOrderId(*origClOrdId) : decltype(findByOrderId(*origClOrdId)){};
1242 setCommonMessageFields(**newOrder, msg);
1245 newOrder->get()->origCIOrdId_ = oldOrder->get()->cIOrdId_;
1247 Screen::info(
"Order changed: " + newOrder->get()->toString());
1251 oldOrder->get()->orderStatus_ = ExecTypeEnum::Replaced;
1254void TradingClient::onExecutionReport_Trade(
const Messaging::ExecutionReport_Trade msg,
Session* sn)
1261 if(
auto order = findByOrderId(msg.
clOrdId()))
1265 setCommonMessageFields(**order, msg);
1266 order->get()->lastPx_ = msg.
lastPx();
1268 Screen::info(
"Order changed: " + order->get()->toString());
1272void TradingClient::onExecutionReport_Snapshot(
const Messaging::ExecutionReport_Snapshot msg,
Session* sn)
1276 std::shared_ptr<Order> order;
1277 auto found = findByOrderId(msg.
clOrdId());
1282 order = std::make_shared<Order>();
1286 if(status !=
nullOpt && (*status == OrderStatusEnum::New || *status == OrderStatusEnum::PartialFill))
1288 if(*status == OrderStatusEnum::New)
1289 order->orderStatus_ = ExecTypeEnum::New;
1290 else if(*status == OrderStatusEnum::PartialFill)
1291 order->orderStatus_ = ExecTypeEnum::PartialFill;
1293 order->cIOrdId_ = msg.
clOrdId();
1294 order->price_ = msg.
price();
1297 order->securityId_ = msg.
symbol();
1298 order->side_ = msg.
side();
1299 order->ordType_ = msg.
ordType();
1300 order->stopPx_ = msg.
stopPx();
1303 order->transactTime_ = msg.
execId().transactTime();
1304 order->maxShow_ = msg.
maxShow();
1306 order->origCIOrdId_ = msg.
clOrdId();
1309 orderBook_.store(order);
1313void TradingClient::onIPReport(
const Messaging::IPReport msg,
Session* sn)
1319 const auto users = msg.
users();
1322 throw std::runtime_error(
"'IPReport' message does not contain connectivity information.");
1324 Messaging::IPReport::UsersEntry entry = users[0];
1326 if (!(entry.
success() && *entry.
success() == Messaging::BooleanEnum::True))
1327 throw std::runtime_error(
"IPReport::UsersEntry is invalid: success flag is missing or not set to True.");
1330 throw std::runtime_error(
"Invalid 'IPReport::UsersEntry'");
1334 bgwCredentials_ = credentials;
1336 catch(std::exception& e)
1342void TradingClient::onSecurityDefinitionReport(
const Messaging::SecurityDefinitionReport msg,
Session* sn)
1344 if(sn == bgwSession_.get())
1349 std::shared_ptr<std::vector<uint8_t>> p(
new std::vector<uint8_t>(msg.
calculateBinarySize()));
1351 std::memcpy(p->data(), msg.
binary(), p->size());
1353 instruments_.push_back(p);
1356void TradingClient::onSecurityDefinitionReport_Strategy(
const Messaging::SecurityDefinitionReport_Strategy msg,
Session* sn)
1358 if(sn == bgwSession_.get())
1363 std::shared_ptr<std::vector<uint8_t>> p(
new std::vector<uint8_t>(msg.
calculateBinarySize()));
1365 std::memcpy(p->data(), msg.
binary(), p->size());
1367 instruments_.push_back(p);
1385void TradingClient::onMessageSending(
char* bytes,
size_t size,
Session* sn)
#define ONIXS_ICEBOE_NAMESPACE
#define ONIXS_ICEBOE_MESSAGING_NAMESPACE
Contains the SimpleOpenFramingHeader, the SBE message, and the data buffer.
const void * binary() const noexcept
MessageTemplateId templateId() const noexcept
MessageSize EncodedLength
Length of the message binary data.
HeaderFlags headerFlags() const noexcept
The time point without the time-zone information.
static Timestamp fromStr(const std::string &, TimestampFormat::Enum=TimestampFormat::YYYYMMDDHHMMSSnsec)
De-serializes a timestamp from the given string.
Ticks sinceEpoch() const noexcept
const std::string & userId() const noexcept
SessionSettings & licenseStore(const std::string &value)
Sets the path to the folder that contains license file(s).
OptionalRef< CrossOrder > findCross(BookEntryId id)
Finds a cross order.
OptionalRef< Order > find(BookEntryId id)
Finds an instance of the entry by its identifier.
void createStrategy()
Creates a strategy.
void traderLogout()
Logs the trader out from the BGW session.
TradingClient(const Settings &settings)
Initializes the client with the given settings.
void listInstruments()
Prints the list of instruments currently known to the client.
void requestBgwCredentials()
Requests BGW credentials (IpRequest) over the active BUS session.
void connectBus()
Commands.
void connectBgw()
Establishes a BGW session using previously obtained credentials.
void createFlex()
Creates a flexible instrument (flex).
void sendOrderCross()
Sends a cross order.
void sendMassCancel()
Submits a mass cancel request.
void replaceOrder()
Issues a replace for an existing live order.
void lookupInstruments()
Prints the list of instruments currently known to the client by the provided Symbol value.
void sendQuoteCancelRequest()
Cancels a previously submitted quote.
void cancelOrder()
Sends a cancel request for a specific order.
void sendOrder()
Sends a new order via BGW.
void sendMassQuote()
Sends a multiple quote request.
void showActiveOrders()
Displays active orders sent by this client session and their last-known statuses.
void showOrders()
Displays orders sent by this client session and their last-known statuses.
void sendQuote()
Sends a quote message.
void traderLogon()
Logs a trader into the connected BGW session.
void requestInstruments()
Submits a SecurityDefinitionRequest to fetch/refresh known instruments.
OrderTypeEnum
OrderTypeEnum type.
FloatingPointDecimal< Int64, Int32 > Decimal
Universal decimal type.
BooleanEnum
BooleanEnum type.
constexpr std::enable_if<!details::HasMemberTraits< Value >::value, size_t >::type size() noexcept
constexpr std::enable_if< MaxMessageSizeTraits< Message >::UseCustomValue, MessageSize >::type getMaxMessageSize(UInt8)
Calculates the buffer size for a message with the given number of repeating group items.
Int64 Decimal9
Quantity, Price with constant exponent -9.
constexpr bool hasFlag(T value, T flag, typename std::enable_if< isBitset< T >::value, void * >::type=nullptr) noexcept
std::string toStr(const FixedPointDecimal< Mantissa, Exponent > &)
Serializes a fixed-point decimal into a string.
SecurityRequestTypeEnum
SecurityRequestTypeEnum type.
CustOrderHandlingInstEnum
CustOrderHandlingInstEnumNULL type.
UInt16 MessageSize
Message length type.
TimeInForceEnum
TimeInForceEnum type.
StrRef toStrRef(const std::string &str)
Constructs a StrRef instance over th std::string content.
Int64 Int64NULL
int64NULL.
constexpr Int32 MarketTypeId
constexpr Int32 QuantityMantissa
constexpr Int32 Symbols[]
constexpr Int32 UnderlyingSymbol
const Timestamp Timestamp
constexpr Decimal9 PriceMantissa
MessageHolder< CancelReplaceRequest > CancelReplaceRequestMsg
auto print(OrderPtr order)
constexpr size_t MassQuoteRequestMaxEntriesCount
void setOrdStatus(Order &order, MsgType &&msg, ExecTypeEnum defaultValue)
MessageHolder< OrderMassCancelRequest > OrderMassCancelRequestMsg
MessageHolder< SecurityDefinitionRequest > SecurityDefinitionRequestMsg
T parseUserInput(const std::string &userInput, typename std::enable_if< std::is_integral< T >::value, void * >::type=nullptr)
void ignoreUnusedVariableWarning(T &&...) noexcept
std::shared_ptr< CrossOrder > CrossOrderPtr
MessageHolder< NewOrderRequest > NewOrderRequestMsg
auto join(It first, It last, char delim, typename std::enable_if< isScopedEnum< typename It::value_type >::value, void * >::type=nullptr)
MessageHolder< QuoteRequest > QuoteRequestMsg
std::optional< std::shared_ptr< T > > OptionalRef
Manages an optional contained reference.
MessageHolder< MassQuoteRequest, getMaxMessageSize< MassQuoteRequest >(MassQuoteRequestMaxEntriesCount)> MassQuoteRequestMsg
MessageHolder< QuoteCancelRequest, getMaxMessageSize< QuoteCancelRequest >(QuoteCancelRequestMaxEntriesCount)> QuoteCancelRequestMsg
std::string toStr(Order::PriceOptional value)
std::shared_ptr< Order > OrderPtr
MessageHolder< NewOrderCrossRequest, getMaxMessageSize< NewOrderCrossRequest >(NewOrderCrossRequestMaxEntriesCount)> NewOrderCrossRequestMsg
bool activeOrder(const Order &order) noexcept
MessageHolder< CancelRequest > CancelRequestMsg
Decimal9 toPriceMantissa(Decimal value)
static void outputItems(const EntryList &items, Print print=[](auto item){ return toStr(item);}, size_t itemsPerPage=100)
Outputs list items.
static void traceMsg(const std::string &sessionId, SbeMessage message, Direction direction)
static void error(const Args &... args)
static void trace(const Args &... args)
static void printProgress(size_t cur, size_t total)
static std::ostream & out()
static void warning(const Args &... args)
static void info(const Args &... args)
static T getInput(const T &defaultValue={})
auto origClOrdId() const noexcept
int64NULL.
auto clOrdId() const noexcept
Provides access to clOrdID field.
auto origClOrdId() const noexcept
int64NULL.
auto clOrdId() const noexcept
Provides access to clOrdID field.
auto rejectResponseTo() const noexcept
Provides access to rejectResponseTo field.
auto clOrdId() const noexcept
Provides access to clOrdID field.
auto maxShow() const noexcept
Quantity, Price with constant exponent -9.
auto execId() const noexcept
Provides access to execID field.
auto clOrdId() const noexcept
Provides access to clOrdID field.
auto leavesQty() const noexcept
Quantity, Price with constant exponent -9.
auto orderStatus() const noexcept
uint8NULL.
auto timeInForce() const noexcept
Provides access to timeInForce field.
auto expireDate() const noexcept(dateToTimestamp::Nothrow)
UTC days since Unix epoch (January 1st, 1970).
auto side() const noexcept
Provides access to side field.
auto symbol() const noexcept
Provides access to symbol field.
auto ordType() const noexcept
Provides access to ordType field.
auto stopPx() const noexcept
Quantity, Price with constant exponent -9.
auto price() const noexcept
Quantity, Price with constant exponent -9.
auto execInst() const noexcept
Provides access to execInst field.
auto clOrdId() const noexcept
Provides access to clOrdID field.
auto leavesQty() const noexcept
Quantity, Price with constant exponent -9.
auto lastPx() const noexcept
Quantity, Price with constant exponent -9.
auto success() const noexcept
uint8NULL.
auto port() const noexcept
int16NULL.
auto ipSessionToken() const noexcept
ipSessionToken for the Gateway ID for assigned ipAddress and port for use in Binary Order Gateway Log...
auto ipAddress() const noexcept
Provides access to ipAddress field.
Users users() const noexcept
auto crossId() const noexcept
Provides access to crossID field.
auto rfcStatus() const noexcept
Provides access to rfcStatus field.
auto rpts() const noexcept
Provides access to noRpts field.
EncodedLength calculateBinarySize() const noexcept
auto listSeqNo() const noexcept
Provides access to listSeqNo field.
Security Definition for futures, options, and FLEX creations. Each report will contain a single marke...
auto symbol() const noexcept
Market ID. Unique identifier of the market.
auto rpts() const noexcept
Provides access to noRpts field.
EncodedLength calculateBinarySize() const noexcept
auto listSeqNo() const noexcept
Provides access to listSeqNo field.
Security Definition Request to create a strategy.
static constexpr Int32 nanosecondsPerSecond() noexcept
static const std::string & toString(Enum state) noexcept
@ Established
Session is fully established.
@ BUS
Binary Utility Service Gateway.
@ BGW
Binary Order Gateway.
TimeInForceEnum timeInForce_
std::string toString() const
Human-readable presentation of the most interesting fields stored in the order.
decltype(std::declval< const NewOrderRequest & >().maxShow()) QtiOptional
decltype(std::declval< const NewOrderRequest & >().execInst()) ExecInstOptional
ExecTypeEnum orderStatus_