Welcome to UnlimitedOrderBook, a C++ project created based on my findings and personal vision for the implementation of a stock exchange, with a primary focus on OrderBook functionality. This project serves as a platform for my exploration into various concepts, learning C++, and gaining insights into the workings of financial exchanges.
- Market Order: Execute an order as fast as possible, crossing the spread.
- Limit Order: Execute an order with a limit on bid/ask price (e.g., $x or less for a bid, or $y or more for an ask).
- STOP: Stop order, set a stop price which will activate the order once the market price crosses it.
- AON (All or Nothing): Don't allow partial fills.
- IOC (Immediate or Cancel): Immediately fill what's possible, cancel the rest.
- FOK (Fill or Kill): AON+IOC, immediately match an order in full (without partial fills) or cancel it.
- Basic orderbook functionalities
- Add Trade repository and order repository
- Add server functionalities
- GFD, GTC, GTD orders
- Implement a proper way of doing orderbook snapshots
- Perform comprehensive benchmarking
- Add Python bindings
- Implement risk assessment and limits
In the UnlimitedOrderBook, market orders always take precedence over other orders and are sorted based on the time of arrival.
- Orders are processed on a first-in-first-out (FIFO) basis.
- For Bids:
- Sorted by price (descending) and then by time of arrival (ascending).
- For Asks:
- Sorted by price (ascending) and then by time of arrival (ascending).
- Quantity does not influence the sorting process.
- For Bids:
- The market price is set at the last trade price.
- Stop Bids are activated when the market price is above or equal to the stop price.
- Stop Asks are activated when the market price is below or equal to the stop price.
- When a match occurs between two limit orders, the price is set based on the bid price.
- Example: A Bid of $25 and an Ask of $24 will be matched at $25.
The exchange contains information about existing instruments, and each instrument has its own orderbook. Each object communicates with others using a lock-free ring buffer.
- exchange: Exchange functionalities
- orderbook: Orderbook functionalities
- data_structures: All data structures used in the project (order, limit, trade...)
- storage: RBTree implementation used as in-memory storage
- server: Seastar server
- order repository: Persistent storage of orders in RocksDB
- trade repository: Persistent storage of trades in ScyllaDB
- utils: Lock-free ring buffer implementation, thread pool implementation, UUID generator...
-
Start the project by running the following command in the project root:
docker-compose up -d
This will build the UnlimitedOrderBook image, and it may take some time.
-
In the
postman/
directory, you can find a collection of API requests to play around with. -
For local development (developed and tested on linux OS), follow these steps:
-
If needed, install dependencies (check them out before running command):
sudo ./install-dependencies.sh
-
Start ScyllaDB locally:
docker run --name trade-repository -d -v $(pwd)/scylla/:/etc/scylla/ scylladb/scylla --smp 1 --memory 750M --overprovisioned 1 --api-address 0.0.0.0 sudo docker exec -it trade-repository cqlsh -f etc/scylla/trade-repository.txt
Note: wait for a least 30 sec for scylladb to boot up before running second command.
-
Compile and start the project:
mkdir -p build sudo cmake -DCMAKE_BUILD_TYPE=Release .. sudo make -j4 ./UnlimitedOrderBook
Supported flags are:
--server_name
: Specifies the server name. Default value is "UnlimitedExchange".--server_address
: Sets the IP address on which the server will listen. Default is "0.0.0.0".--server_port
: Configures the port on which the server will listen. Default is 8000.--trade_repository_address
: Defines the IP address of the Scylla database used as the trade repository. Default is "172.17.0.2".--trade_repository_batch_size
: Sets the batch size for inserting into the trade repository. Currently, only a batch size of 1 is supported, so the value should be set to 1.--rocksdb_dir
: Specifies the directory for the order RocksDB. Default is "./order_rocksdb".--ringbuffer_size
: Configures the ringbuffer size. Default is 1024 (same for all instances).--instrument_init_file
: Sets the path for the initial instrument information file. Default is "../init/instruments.txt".
-