MCPcopy Index your code
hub / github.com/MatthewDarnell/redis_orderbook

github.com/MatthewDarnell/redis_orderbook @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
119 symbols 349 edges 31 files 3 documented · 3%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Redis Orderbook

A fast in memory orderbook written in Rust using Redis Data Structures

What is this?

This is an implementation of an orderbook written in Rust and running in Redis. It supports LIMIT and MARKET orders, as well as fill or kill orders. It also supports pairs of any type.

How can I use this?

This is intended to be easy to plug-and-play with any existing service that tracks user accounts and balances. Build the library and integrate with your application, or build the binaries and interact with redis pubsub and a simple http api.

How to build?

First, install rust.

Windows: https://www.rust-lang.org/tools/install

Linux curl https://sh.rustup.rs -sSf | sh

Then build with cargo:

cargo build --bins

Current binaries produced in target output folder:

redis_pubsub_listener
redis_created_orders_listener
redis_trades_completed_listener
http_api

You must also have redis-server running to run the application. https://redis.io/download

Example:

1. Start Redis

redis-server

2. Run the http api

cargo run --bin http_api

This will start the server on 127.0.0.1:3000 You can see the available API if you navigate your web browser there. For now, create a new trading pair:

$ curl -H "Content-type: application/json" "http://127.0.0.1:3000/add_pair?price_ticker=btc&ref_ticker=usd"
{"price_ticker":"btc","ref_ticker":"usd","uuid":"4ef93380-e3eb-40a3-a3d5-2cee1bf9d201"}

This call responds with a uuid, which is the newly createdpair_id. You should store this id in your database.

Now let's take a look at the existing orderbook for this pair and make sure it is empty:

$ curl http://127.0.0.1:3000/orderbook/4ef93380-e3eb-40a3-a3d5-2cee1bf9d201
{"asks": [], "bids": []}

3. Run the pubsub listener

cargo run --bin redis_pubsub_listener

Now let's submit an order to the orderbook for this pair using redis-cli. In your application would just use the redis library to publish orders to the channel.

redis-cli publish incoming_orders "{ \"user_id\": \"user_id_1\", \"order_type\": \"BID\", \"order_execution_type\":\"LIMIT\", \"fill_or_kill\": false, \"price\": 100, \"amount\": 1, \"pair\": \"4ef93380-e3eb-40a3-a3d5-2cee1bf9d201\" }"
(integer) 1

Now let's look at the orderbook:

$ curl http://127.0.0.1:3000/orderbook/4ef93380-e3eb-40a3-a3d5-2cee1bf9d201
{"asks": [], "bids": [{"price": "100", "sum": "1"}]}

We placed an order! Let's fill it with an ASK that will leave some leftover in the orderbook:

redis-cli publish incoming_orders "{ \"user_id\": \"user_id_2\", \"order_type\": \"ASK\", \"order_execution_type\":\"LIMIT\", \"fill_or_kill\": false, \"price\": 99, \"amount\": 2, \"pair\": \"4ef93380-e3eb-40a3-a3d5-2cee1bf9d201\" }"
(integer) 1

And the resulting orderbook:

$ curl http://127.0.0.1:3000/orderbook/4ef93380-e3eb-40a3-a3d5-2cee1bf9d201
{"asks": [{"price": 99, "sum": 1}], "bids": []}

Now let's check this users' open orders and balance.

$ curl http://127.0.0.1:3000/user_order_sums/user_id_2/btc
1

$ curl http://127.0.0.1:3000/user_order_sums/user_id_2/usd
0

This user has an ASK for 1 btc, so his open orderbook balance of btc is 1, you should subtract that from the users' withdrawable balance in your application. Conversely, when a user places a BID, his open balance of the ref_ticker, in this case USD in this case would be the price * amount (A bid of 2 btc at 40000 usd would require 80000 usd)

Some notes: A MARKET order currently does not leave a resulting order in the orderbook, it places an order at any price and does not place a new order for any leftover amount.

Other features

1. To keep track of placed orders, redis subscribe to the channel created_orders

You can run the redis_created_orders_listener as a demo:

cargo run --bin redis_created_orders_listener

"{\"user_id\": \"user_id_1\", \"uuid\": \"b4b09e71-0813-4d8c-a11b-fb33be73d8f0\"}"

2. To keep track of completed trades, redis subscribe to the channel trades_completed

You can run the redis_trades_completed_listener as a demo:

cargo run --bin redis_trades_completed_listener

"{\"pair_id\":\"4ef93380-e3eb-40a3-a3d5-2cee1bf9d201\",\"pair\":\"{\\\"price_ticker\\\":\\\"btc\\\",\\\"ref_ticker\\\":\\\"usd\\\",\\\"uuid\\\":\\\"4ef93380-e3eb-40a3-a3d5-2cee1bf9d201\\\"}\",\"execution_price\":\"100\",\"filled_amount\":\"1\",\"side\":\"ASK\",\"bid_user_id\":\"user_id_1\",\"ask_user_id\":\"user_id_2\",\"bid_order_id\":\"b4b09e71-0813-4d8c-a11b-fb33be73d8f0\",\"ask_order_id\":\"d444bb31-4d90-4b66-a4c4-a8a989886799\",\"timestamp\":\"1613077532\"}"

3. To Retrieve a users' open orders, request the appropriate api from the http server:

$ curl http://127.0.0.1:3000/user_open_orders/user_id_1/4ef93380-e3eb-40a3-a3d5-2cee1bf9d201
[
  {
    "uuid": "6b092b56-67c6-4019-bdd0-2c1d368b838b",
    "user_id": "user_id_1",
    "order_type": "BID",
    "order_execution_type": "LIMIT",
    "fill_or_kill": false,
    "price": 100,
    "amount": 1,
    "pair": {
      "price_ticker": "btc",
      "ref_ticker": "usd",
      "uuid": "4ef93380-e3eb-40a3-a3d5-2cee1bf9d201"
    },
    "timestamp": 1613077682
  }
]

4. To Delete an Order, redis publish a json string containing the order_id and type DELETE

redis-cli publish incoming_orders "{\"order_type\": \"DELETE\", \"uuid\": \"6b092b56-67c6-4019-bdd0-2c1d368b838b\"}"
(integer) 1

How is this orderbook designed?

This orderbook uses provided Redis data structures. Orders themselves are serialized and placed into a hash table, while their uuids are placed into a set. The orderbook itself is a redis sorted set, with each score representing the price and each value the key of a fifo list containing the user id and order uuid.

Operations:

Insertion: O(1)
Deletion: O(n), where n is the number of existing orders at the same price
Lookup: O(1)

Final Notes

This orderbook is limited to 64 bit integers (a constraint of redis' sorted sets). You must multiply any amount by some integer which guarantees the passed amount is a valid int64.

If dealing with cryptocurrencies, you may need to truncate at some number of decimal places. i.e. MAX Bitcoin is 21000000.00000000, and int64 max is 9223372036854775807, so this library should be able to handle the full max of 21000000.00000000 * 100000000 = 2100000000000000

However, Ethereum maintains 18 decimal places

1000000.000000000000000001 * 1000000000000000000 = 1000000000000000000000001 which is greater than MAX int64, so you would have to truncate the maximum number of decimal places handled.

Disclaimer

This orderbook is a work in progress and comes with no real or implied warranty. If you find any bugs, please don't hesitate to submit a fix!

Extension points exported contracts — how you extend this code

Executor (Interface)
(no doc) [1 implementers]
order/src/order/order_executor.rs

Core symbols most depended-on inside this repo

get_connection
called by 23
redis/src/connection.rs
get_input_string
called by 14
src/main.rs
del
called by 14
redis/src/connection.rs
hget
called by 8
redis/src/types/redis_hash.rs
serialize
called by 8
order/src/order/store/order_store.rs
hset
called by 6
redis/src/types/redis_hash.rs
get_pair_by_id
called by 6
order/src/order/store/order_pair_store.rs
increment_user_open_order_balance
called by 6
order/src/order/store/order_store.rs

Shape

Function 92
Method 17
Class 5
Enum 4
Interface 1

Languages

Rust100%

Modules by API surface

order/src/order/store/order_store.rs16 symbols
src/lib.rs10 symbols
redis/src/types/redis_hash.rs10 symbols
redis/src/types/redis_sorted_set.rs9 symbols
redis/src/types/redis_set.rs6 symbols
redis/src/types/redis_list.rs6 symbols
order/src/order.rs6 symbols
trade/src/trade.rs5 symbols
order/src/order/orderbook.rs5 symbols
src/main.rs4 symbols
redis/src/types/redis_pubsub.rs4 symbols
order/src/order/store/order_type_store.rs4 symbols

For agents

$ claude mcp add redis_orderbook \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact