hmbdc
simplify-high-performance-messaging-programming
ipc-market-data-propagate.cpp
//this example is to show how to use hmbdc ipc to write a market data propagating application
//that redistribute market data to trading models that run in a different process locally
//
//to build:
//g++ ipc-market-data-propagate.cpp -g -O3 -std=c++1y -Wall -Werror -pthread -I /opt/hmbdc/include/ /opt/hmbdc/lib/libhmbdc.a /usr/local/lib/libboost_regex.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_iostreams.a -lpthread -lrt -o /tmp/ipcmp
//
//to run - see sceenshot below after executing in two terminals on the same host
//[terminal 1]$ /tmp/ipcmp
// qqqq
// goog
// msft
// gld
// [terminal 2]$ /tmp/ipcmp client #do not expect qqqq below since there is no model interested in it
// recv market data for goog
// recv market data for msft
// recv market data for gld
#include "hmbdc/app/Base.hpp"
#include "hmbdc/os/Signals.hpp"
#include <iostream>
#include <string>
#include <iterator>
using namespace std;
using namespace hmbdc;
using namespace hmbdc::app;
struct MarketData
: hasTag<1005> {
MarketData(string const& s) {
strncpy(symbol, s.c_str(), sizeof(symbol));
}
char symbol[16]; //don't use std::string here, it doesn't work acorss process - duh
//price, qty and other good stuff, omitted for now
};
//! [declare an ipc context]
//! [declare an ipc context]
struct MarketDataPropagator
: Client<MarketDataPropagator> {
MarketDataPropagator()
: ctx_("market-data") {
}
//
//for simplicity of the demo we read 'market data' from the cin
//in the real world, it comes from a socket or another market data lib
//
void readMarketData() {
for (auto iit = istream_iterator<string>(cin)
; iit != istream_iterator<string>()
; iit ++) {
ctx_.sendInPlace<MarketData>(*iit);
}
}
private:
SenderContext ctx_;
};
/**
* @brief run as the source (propagator) of market data
*
*/
void runSource() {
MarketDataPropagator mp;
mp.readMarketData();
}
/**
* @brief a trading model
*/
struct TradingModel
: Client<TradingModel, MarketData> {
TradingModel(char const* symbol)
: symbol_(symbol) {
}
void handleMessageCb(MarketData const& m) {
if (symbol_ == m.symbol) {
cout << "recv market data for " << symbol_ << endl;
//... do something profitable
} //else ignore
}
private:
string symbol_;
};
/**
* @brief run as market data recv (all the trading models)
*/
void runRecv() {
RecvContext ctx("market-data");
TradingModel fastModel("gld");
TradingModel poolModels[] = {"msft", "goog", "amzn", "hpq", "ibm", "csco"};
ctx.start(1, 0x0);
for (auto& m : poolModels) {
ctx.addToPool(m); //slower models run in a pool
}
ctx.start(fastModel, 0x04); //fast model run in direct mode for better latencies
[&ctx] {
ctx.stop();
}
);
ctx.join();
}
int main(int argc, char** argv) {
if (argc == 1) { //run as source
runSource();
} else {//run as recv
runRecv();
}
}