OnixS C++ CME iLink 3 Binary Order Entry Handler  1.12.0
API Documentation
Gateway Emulator

To simplify development and testing, the Handler's SDK includes the Gateway Emulator. The Emulator simulates the CME Gateway. It can accept a connection, establish a FIXP session, and send/receive session-level/application-level messages. To receive notifications about incoming message, there are corresponding callbacks declared in OnixS::CME::iLink3::Testing::ClientMessageListener and OnixS::CME::iLink3::Testing::ClientSessionMessageListener classes. One can inherit from the corresponding class, override corresponding virtual methods, and implement the necessary logic.

To simplify running and testing, most of the samples from the distribution package use the Gateway Emulator by default. Therefore, one can see in detail how to use the Gateway Emulator.

Note
The Gateway Emulator is supported in C++11 or higher codebase only.

Example

using namespace OnixS::CME::iLink3;
// The listener class for the session.
class MyListener : public SessionListener
{
public:
void onExecutionReportNew(const ExecutionReportNew522& msg, Session* /*sn*/) ONIXS_ILINK3_OVERRIDE
{
std::clog << msg << std::endl;
}
};
// The listener class for the gateway emulator.
class GatewayListener : public Testing::ClientMessageListener
{
public:
// Receive and process NewOrderSingle messages from the session.
void onNewOrderSingle(const NewOrderSingle514& order, Testing::Gateway* gateway) ONIXS_ILINK3_OVERRIDE
{
updateReport(order);
report_->setUuId(gateway->uuid());
// Send the ExecutionReportNew message to the session.
gateway->send(report_, ++reportsCounter_);
// Maintain the sequence numbers.
gateway->outSeqNum(reportsCounter_ + 1);
}
private:
void updateReport(const NewOrderSingle514& order)
{
const auto sinchEpoch = UtcWatch::now().sinceEpoch();
report_->setClOrdId(order.clOrdId())
.setExecId(std::to_string(reportsCounter_))
.setSenderId(order.senderId())
.setClOrdId(order.clOrdId())
.setPartyDetailsListReqId(order.partyDetailsListReqId())
.setOrderId(reportsCounter_)
.setTransactTime(sinchEpoch)
.setSendingTimeEpoch(sinchEpoch)
.setOrderRequestId(order.orderRequestId())
.setLocation(order.location())
.setSecurityId(order.securityId())
.setOrderQty(order.orderQty())
.setOrdType(OrderType::Limit)
.setSide(order.side())
.setManualOrderIndicator(order.manualOrderIndicator())
.setPossRetransFlag(BooleanFlag::False)
.setExecInst(ExecInst(0));
TimeInForce::Enum timeInForce;
if(order.timeInForce(timeInForce))
report_->setTimeInForce(timeInForce);
PRICE9 price;
if(order.price(price))
report_->setPrice(price);
else
report_->setPrice(PRICE9(10));
}
UInt32 reportsCounter_{ 0 };
};
const std::string CounterpartyHost = "Localhost";
const int CounterpartyPort = 64124;
// Create the gateway emulator using the same host and port to which the session will connect.
Testing::Gateway gateway(CounterpartyPort, CounterpartyHost.c_str());
std::promise<void> emulatorTaskPromise;
std::future<void> emulatorTaskDone = emulatorTaskPromise.get_future();
// Create and run a separate thread to accept the connection and handle the emulator's events
// since the emulator works in a synchronous way.
// This is not necessary in case you use a separate application for the emulator.
std::thread(
std::bind(
[&](std::promise<void>& p)
{
try
{
// Create the emulator listener object.
GatewayListener clientMessageListener;
// Run the event loop of the gateway emulator and provide the listener object.
// The method will work until the Terminate message is received from the session.
gateway.run(clientMessageListener);
p.set_value();
}
catch (...)
{
std::cerr << "Exception in Emulator's thread." << std::endl;
p.set_exception(
std::current_exception());
}
},
std::move(emulatorTaskPromise)))
.detach();
SessionSettings settings;
settings.licenseStore("../../license")
.sessionId("SessionId")
.secretKey("secretKey")
.accessKey("accessKey")
.firmId("firmId");
MyListener listener;
const int MarketSegmentId = 54;
Session session(settings, MarketSegmentId, &listener);
// Connect the session to the gateway emulator.
session.connect(CounterpartyHost, CounterpartyPort);
typedef MessageHolder<NewOrderSingle514> NewOrderSingle;
NewOrderSingle order;
.setSenderId("SomeSenderId")
.setClOrdId("SomeOrderID")
.setOrderQty(1000)
// Send an order to the gateway emulator and disconnect the session.
session.send(order).disconnect();
// Wait for the completion of the thread of the gateway emulator.
emulatorTaskDone.get();