This sample shows how to connect to the B3 BOE Gateway or the local Gateway emulator.
#include "../Common/Helpers.h"
#include "../Common/Listener.h"
#include "../Settings/Defaults.h"
using namespace Samples;
Session* createSession(const SessionSettings& settings, SessionListener* listener)
{
return new Session(settings, listener);
}
int main(int argc, char * argv[])
{
clog << "B3 BOE Getting Started Sample." << endl << endl;
string host = "127.0.0.1";
bool useEmulator = false;
if (argc < 4)
{
#if defined(ONIXS_B3_BOE_HAS_GATEWAY_EMULATOR)
useEmulator = true;
#else
std::cerr << "usage: [MarketSegmentId] [Host] [Port] (SecurityId) (PriceMantissa)" << std::endl;
return 1;
#endif
}
else
{
marketSegmentId = atoi(argv[1]);
host = argv[2];
port = atoi(argv[3]);
}
const SecurityID securityId = argc > 4 ? fromStr<SecurityID>(argv[4]) : DefaultSecurityId;
const Int64 priceMantissa = argc > 5 ? fromStr<Int64>(argv[5]) : DefaultPriceMantissa;
try
{
SignalHelper::manageLinuxSignals();
const SessionSettings settings = fillSettings(useEmulator);
#if defined(ONIXS_B3_BOE_HAS_GATEWAY_EMULATOR)
std::unique_ptr<GatewayEmulatorThread> gateway;
if (useEmulator)
gateway.reset(new GatewayEmulatorThread(settings.licenseStores(), host, port));
#endif
Listener listener;
ScopedPtr<Session> session(createSession(settings, &listener));
NewOrderSingle order;
Helper::setOrderFields(order, marketSegmentId, securityId, DefaultAccount, priceMantissa);
session
->connect(host, port)
.send(order);
clog << "\nThe order was sent." << endl;
Helper::waitUntilEnterKey("disconnect the session and terminate the application");
session->disconnect();
}
catch(const std::exception & ex)
{
cerr << "\nEXCEPTION: " << ex.what() << endl;
return 1;
}
return 0;
}
#include "../Settings/Defaults.h"
#include <string>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <fstream>
#ifdef _WIN32
#include <conio.h>
#else
#include <pthread.h>
#include <csignal>
#include <cstdlib>
#include <vector>
#include <sys/poll.h>
#endif
#if defined(ONIXS_B3_BOE_HAS_GATEWAY_EMULATOR)
#include <thread>
#include <future>
#include <functional>
#include <chrono>
#endif
namespace Samples
{
class Helper
{
public:
{
order->setOrdTagId(100)
.setMmProtectionReset(Boolean::FalseValue)
.setClOrdId(1)
.setAccount(account)
.setSenderLocation("DMA")
.setEnteringTrader("TADA")
.setSelfTradePreventionInstruction(SelfTradePreventionInstruction::None)
.setSecurityId(securityId)
.setSide(Side::Buy)
.setOrdType(OrdType::Limit)
.setTimeInForce(TimeInForce::Day)
.setRoutingInstructionToNull()
.setOrderQty(100)
.setInvestorIdToNull()
.setMemo("VALE3 1714479423613")
.setDeskId("1");
order->setInvestorId(iid);
}
static void waitUntilEnterKey(const std::string& message)
{
std::clog << "\nPress the ENTER key to " << message << ".." << std::endl;
#ifdef _WIN32
_getch();
#else
getchar();
#endif
}
static bool keyPressed()
{
#ifdef __linux__
pollfd pfd = { 0, POLLIN, 0 };
return poll(&pfd, 1, 0) != 0;
#else
return _kbhit() != 0;
#endif
}
};
template <typename T>
{
std::istringstream ss(s);
T result = T();
ss >> result;
return result;
}
class IdGenerator
{
public:
static std::string newStrId()
{
static UInt64 idCounter = 0;
const size_t startOfTime = 9;
std::string timestamp =
toStr(UtcWatch::now(), TimestampFormat::YYYYMMDDHHMMSSmsec).substr(startOfTime);
std::string id;
id += timestamp[0];
id += timestamp[1];
id += timestamp[3];
id += timestamp[4];
id += timestamp[6];
id += timestamp[7];
id += timestamp[9];
id += timestamp[10];
id +=
toStr(++idCounter);
return id;
}
static UInt64 newId()
{
return UtcWatch::now().time().nanoseconds();
}
};
#ifndef _WIN32
class SignalHelper
{
public:
typedef std::vector<int> SuppressedSignals;
static void manageLinuxSignals()
{
SuppressedSignals suppressedSignals;
suppressedSignals.push_back(SIGPIPE);
pthread_t signalThreadId;
int status;
sigemptyset(&signalSet());
for (SuppressedSignals::const_iterator i = suppressedSignals.begin(),
e = suppressedSignals.end();
i != e; ++i)
sigaddset(&signalSet(), *i);
if (status != 0)
errorAbort(status, "Set signal mask");
if (status != 0)
errorAbort(status, "Create signalWaiter");
}
private:
static void errorAbort(int status, const char* reason)
{
printf("Aborted due to status %d: %s\n", status, reason ? reason : "no error message");
exit(1);
}
static void* signalWaiter(void* )
{
int signalNumber;
while (true)
{
sigwait(&signalSet(), &signalNumber);
printf("Signal %d received and suppressed.\n", signalNumber);
}
}
static sigset_t& signalSet()
{
static sigset_t set;
return set;
}
};
#else
struct SignalHelper
{
static void manageLinuxSignals(){}
};
#endif
#if defined(ONIXS_B3_BOE_HAS_GATEWAY_EMULATOR)
class GatewayListener : public Testing::ClientMessageListener
{
public:
void onNewOrderSingle(
const NewOrderSingle102& order, Testing::Gateway* gateway)
override {
updateReport(order);
gateway->send(report_, ++reportsCounter_);
gateway->outSeqNum(reportsCounter_ + 1);
}
protected:
{
sendingTime.
setTime(UtcWatch::now().sinceEpoch());
report_->setOrdTagId(1)
.setMmProtectionResetToNull()
.setClOrdId(1714479417808)
.setAccount(1529)
.setSecurityId(200000163669)
.setSide(Side::Buy)
.setOrdType(OrdType::Limit)
.setOrderQty(100)
.setInvestorIdToNull()
.setMemo("VALE3 1714479416336")
.setExecId(800422000000001091)
.setOrdStatus(OrdStatus::New)
.setSecondaryOrderId(804604488)
.setOrderId(8047407153)
.setTradeDate(
Timestamp::fromStr(
"20240430-00:00:00.000000000", TimestampFormat::YYYYMMDDHHMMSSnsec))
.setWorkingIndicator(Boolean::FalseValue);
report_->setPrice(price);
else
}
UInt32 reportsCounter_{ 0 };
};
class GatewayEmulatorThread
{
public:
GatewayEmulatorThread(
const SessionSettings::LicenseStores& licenseStores,
const std::string & host,
Port port, Testing::ClientMessageListener * clientMessageListener =
nullptr,
const std::chrono::seconds& acceptTimeout = std::chrono::seconds(10), const std::chrono::seconds& sendReceiveTimeout = std::chrono::seconds(10))
: gateway_(licenseStores, port, host.c_str(), acceptTimeout, sendReceiveTimeout)
, clientMessageListener_(clientMessageListener)
{
std::promise<void> emulatorTaskPromise;
emulatorTaskDone_ = emulatorTaskPromise.get_future();
std::thread(
std::bind(
[&](std::promise<void>& p)
{
try
{
if(clientMessageListener_)
{
gateway_.run(*clientMessageListener_);
}
else
{
GatewayListener clientMessageListener;
gateway_.run(clientMessageListener);
}
p.set_value();
}
catch (const std::exception& ex)
{
std::cerr << "Exception in Emulator's thread: " << ex.what() << '.' << std::endl;
p.set_exception(
std::current_exception());
}
catch (...)
{
std::cerr << "UNKNOWN Exception in Emulator's thread." << std::endl;
p.set_exception(
std::current_exception());
}
},
std::move(emulatorTaskPromise)))
.detach();
}
~GatewayEmulatorThread()
{
if(emulatorTaskDone_.valid())
emulatorTaskDone_.wait_for(std::chrono::seconds(10));
}
void wait(std::chrono::seconds timeout = std::chrono::seconds(10)) {
if(emulatorTaskDone_.valid()) {
std::future<void> f = std::move(emulatorTaskDone_);
f.wait_for(timeout);
f.get();
}
}
private:
Testing::Gateway gateway_;
Testing::ClientMessageListener * clientMessageListener_;
std::future<void> emulatorTaskDone_;
};
#endif
template <typename Object>
class ScopedPtr
{
public:
: obj_(obj)
{
}
~ScopedPtr()
{
delete obj_;
}
{
return obj_;
}
{
return *obj_;
}
private:
Object * const obj_;
ScopedPtr(const ScopedPtr&);
ScopedPtr& operator =(const ScopedPtr&);
};
inline
{
const std::string settingsFilename("settings.ini");
std::ifstream settingsFile(settingsFilename.c_str());
if (settingsFile)
{
settingsFile.close();
settings.
load(settingsFilename);
}
else
{
settings
if(useEmulator)
settings
.enteringFirm(900)
.accessKey("AccessKey")
.tradingSystemName("OnixS 1");
else
settings
.accessKey("Value Received From B3")
.enteringFirm(900 )
.tradingSystemName("OnixS 1");
}
if(useEmulator)
return settings;
}
{
#ifdef _WIN32
if(session)
session->receivingThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
#else
const int policy = SCHED_RR;
try
{
if(session)
session->receivingThreadPolicy(policy);
}
catch (const std::exception&)
{
std::cerr << "\nWARNING: Cannot change the scheduling policy to " << policy <<
", it requires root permissions, so you either have to be root or run it with sudo." << std::endl;
}
#endif
}
}