An asynchronous and low-latency trading system designed under service-oriented architecture (SOA).
The project gives an example of a trading system for seven US Treasury securities, with real-time price and orderbook flows, data streaming, user inquiries, algorithm order execution, risk monitor, logging modules, etc.
Data flow into the trading system through Subscribe()
that calls OnMessage()
, transmits among different service components through ProcessAdd()
, and flows out of the system through Publish()
.
Connectors can be subscribe-only or publish-only, or both. An input file connector can both Subscribe
data from outside data sources and Publish
data to a socket with a specified host and port. An inbound connector can then subscribe data from the socket and flow data into the trading system by calling Service.OnMessage()
, or publish data to outside source using Service.Publish()
.
Communication between different components is based on sockets to ensure real-time, low-latency and high throughput. Six servers are running simultaneously, with four (price, market, trade, inquiry server) listening to TCP sockets from localhost:3000
to localhost:3004
and flow data into the system, and two (steaming and execution server) publishing data to TCP sockets localhost:3004
and localhost:3005
.
The instruction to run the system on a Linux machine is as follows (tested on Ubuntu 22.04). Before running the system, make sure you have installed boost
and cmake
tools, and check firewall settings to open local ports 3000-3005
for TCP sockets (important!)
# install boost and cmake tools
sudo apt-get update
sudo apt-get install libboost-all-dev
sudo apt install cmake
The direct way is simply run the bash script run.sh
in the root directory. It starts the system and the servers in the foreground, then start the four client programs in the background.
chmod +x run.sh
./run.sh
Or one can manually build and run the system.
# compile and start servers
mkdir build
cd build
cmake ..
make
./server
# start clients in separate terminals
./price
./market
./trade
./inquiry
-
Main program
InputPriceConnector
: an input connector that subscribes external price data and publishes to TCP socketlocalhost:3000
InputMarketDataConnector
: an input connector that subscribes external orderbook data and publishes to TCP socketlocalhost:3001
InputTradeConnector
: an input connector that subscribes external trade data and publishes to TCP socketlocalhost:3002
InputInquiryConnector
: an input connector that subscribes external user inquiry data and publishes to TCP socketlocalhost:3003
StreamOutputConnector
: an outbound connector that subscribes streaming flow data from TCP socketlocalhost:3000
and publishes tolocalhost:3004
ExecutionOutputConnector
: an outbound connector that subscribes execution data from TCP socketlocalhost:3001
and publishes tolocalhost:3005
main
: connect different services, attach six threads to six servers, and start listening to TCP socketslocalhost:3000-3005
-
Service components
pricingservice
: read in price data from the socket to the system through an inbound connectoralgostreamingservice
: listen to pricing service, flow in data ofPrice<T>
and generate data ofAlgoStream<T>
streamingservice
: listen to algo streaming service, flow in data ofAlgoStream<T>
and record bid/ask prices intopriceStream<T>
, publish streams via socket in a separate processguiservice
: a GUI component that listens to streaming prices that should be throttled with a 300 millisecond throttle., register a service listener on the pricing service and output the updates with a timestamp with millisecond precision to a filegui.txt
.marketdataservice
: read in orderbook data from the socket to the system through an inbound connectoralgoexecutionservice
: listen to market data service, flow in data ofOrderbook<T>
and turn into execution dataAlgoExecution<T>
executionservice
: listen to algo execution service, flow in data ofAlgoExecution<T>
and record order information intoExecutionOrder<T>
, publish order executions via socket in a separate processtradebookingservice
: read in trade data, listen to execution service at the same time, flow inExecutionOrder<T>
and turn in trade data of typeTrade<T>
positionservice
: listen to trade booking service, flow inTrade<T>
data and turn intoPosition<T>
riskservice
: listen to position service, flow inPosition<T>
data and calculate corresponding position risks, such asPV01<T>
.inquiryservice
: read in user inquiry data, interact with connectors and deal with inquiries
-
Other components
products
: define the class for the trading products, which can be treasury bonds, interest rate swaps, future, commodity, or any user-defined product objecthistoricaldataservice
: a last-step service that listens to position service, risk service, execution service, streaming service, and inquiry service; persist objects it receives and saves the data into a database (usually data centers, KDB database, etc)utils
: time displayer, data generator, and risk calculator
-
Data and results
-
data
: data source for price data, orderbook updates, user inquiries, and trade data, can be replaced by other connectivity sources (a database, socket, etc) -
res
: results published by the system, including processed queries, executed orders, positions, risk monitor, data streaming, and GUI output.
-
The trading system is designed to be scalable, extensible, and maintainable. Multi-threading and asynchronous programming ensure low-latency, high throughput, and high-performance. The system is also designed to be modularized, with each service component being independent and loosely coupled with others. New trading products can be added into products.hpp
, new services, listeners, and connectors can all be easily added and integrated into the whole system.