Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: adds add order fn #39

Merged
merged 8 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions crates/common/src/types/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub struct OrderResponse {
pub transact_time: u64,
pub price: f64,
pub orig_qty: f64,
pub executed_ty: f64,
pub executed_qty: f64,
pub status: OrderStatus,
pub time_in_force: TimeInForce,
#[serde(rename = "type")]
Expand All @@ -81,10 +81,11 @@ pub struct Order {
pub symbol: String,
pub order_id: u64,
pub client_order_id: String,
pub client_id: String,
pub transact_time: u64,
pub price: f64,
pub orig_qty: f64,
pub executed_ty: f64,
pub executed_qty: f64,
pub status: OrderStatus,
pub time_in_force: TimeInForce,
#[serde(rename = "type")]
Expand Down
177 changes: 177 additions & 0 deletions crates/engine/snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
"orderbook": [
{
"base_asset": "BTC",
"quote_asset": "USDC",
"bids": [
{
"price": 30000.5,
"quantity": 0.1,
"order_id": 1,
"client_order_id": "a1b2c3d4-e5f6-7g8h-9i0j-k1l2m3n4o5p6",
"transact_time": 1696446000000,
"orig_qty": 0.1,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "BUY",
"fills": []
},
{
"price": 29950.2,
"quantity": 0.2,
"order_id": 2,
"client_order_id": "b2c3d4e5-f6g7-8h9i-0j1k-2l3m4n5o6p7",
"transact_time": 1696446001000,
"orig_qty": 0.2,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "BUY",
"fills": []
},
{
"price": 29975.3,
"quantity": 0.15,
"order_id": 3,
"client_order_id": "c3d4e5f6-g7h8-9i0j-k1l2-m3n4o5p6q7r",
"transact_time": 1696446002000,
"orig_qty": 0.15,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "BUY",
"fills": []
},
{
"price": 29990.1,
"quantity": 0.25,
"order_id": 4,
"client_order_id": "d4e5f6g7-h8i9-j0k1-l2m3-n4o5p6q7r8s",
"transact_time": 1696446003000,
"orig_qty": 0.25,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "BUY",
"fills": []
},
{
"price": 29960.8,
"quantity": 0.3,
"order_id": 5,
"client_order_id": "e5f6g7h8-i9j0-k1l2-m3n4-o5p6q7r8s9t",
"transact_time": 1696446004000,
"orig_qty": 0.3,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "BUY",
"fills": []
}
],
"asks": [
{
"price": 31000.5,
"quantity": 0.1,
"order_id": 1,
"client_order_id": "f6g7h8i9-j0k1-l2m3-n4o5-p6q7r8s9t0u",
"transact_time": 1696446005000,
"orig_qty": 0.1,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "SELL",
"fills": []
},
{
"price": 31200.3,
"quantity": 0.2,
"order_id": 2,
"client_order_id": "g7h8i9j0-k1l2-m3n4-o5p6-q7r8s9t0u1v",
"transact_time": 1696446006000,
"orig_qty": 0.2,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "SELL",
"fills": []
},
{
"price": 31150.7,
"quantity": 0.15,
"order_id": 3,
"client_order_id": "h8i9j0k1-l2m3-n4o5-p6q7-r8s9t0u1v2w",
"transact_time": 1696446007000,
"orig_qty": 0.15,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "SELL",
"fills": []
},
{
"price": 31300.1,
"quantity": 0.25,
"order_id": 4,
"client_order_id": "i9j0k1l2-m3n4-o5p6-q7r8-s9t0u1v2w3x",
"transact_time": 1696446008000,
"orig_qty": 0.25,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "SELL",
"fills": []
},
{
"price": 31400.0,
"quantity": 0.3,
"order_id": 5,
"client_order_id": "j0k1l2m3-n4o5-p6q7-r8s9-t0u1v2w3x4y",
"transact_time": 1696446009000,
"orig_qty": 0.3,
"executed_qty": 0.0,
"status": "NEW",
"time_in_force": "GTC",
"type": "LIMIT",
"side": "SELL",
"fills": []
}
],
"lastTradeId": 128,
"currentPrice": 0
}
],
"balances": [
[
"e0c2b9a7-2f4d-4c9b-b72b-d0c5de93b248",
{
"USDC": { "available": 99996278.15, "locked": 268377.9999999999 },
"BTC": { "available": 1000000.67, "locked": 0 }
}
],
[
"f5b6e2c4-4a9e-4d8e-8c4a-6d87b7b1a0d1",
{
"USDC": { "available": 1000000.0, "locked": 0 },
"BTC": { "available": 1000000.0, "locked": 0 }
}
],
[
"a1c9d3b4-1f2e-4b5c-8d9e-6a7b1c2d3e4f",
{
"USDC": { "available": 102218.3, "locked": 101588.7 },
"BTC": { "available": 85884.0, "locked": 14049.0 }
}
]
]
}
1 change: 1 addition & 0 deletions crates/engine/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use tokio::signal;

mod process;
mod trade;
mod types;

use common::redis::initialize_redis_pool;
use process::handle_process;
Expand Down
134 changes: 133 additions & 1 deletion crates/engine/src/trade/orderbook.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use common::types::order::Order;
use std::collections::HashMap;

use common::types::order::{Fill, Order, OrderSide};

pub struct Orderbook {
pub bids: Vec<Order>,
Expand Down Expand Up @@ -42,4 +44,134 @@ impl Orderbook {
last_trade_id: self.last_trade_id.clone(),
}
}

pub fn add_order(&mut self, order: &mut Order) {
match order.side {
OrderSide::BUY => {
self.match_bid(order);

if order.executed_qty == order.orig_qty {
return;
}
self.bids.push(order.clone());
return;
}
OrderSide::SELL => {
self.match_asks(order);

if order.executed_qty == order.orig_qty {
return;
}
self.asks.push(order.clone());
return;
}
}
}

fn match_bid(&mut self, order: &mut Order) {
order.executed_qty = 0.0;
let mut filled_ask_order_id: Vec<u64> = vec![];
for ask in self.asks.iter_mut() {
if ask.price <= order.price && order.executed_qty < order.orig_qty {
let fill_qty = ask.orig_qty.min(order.orig_qty - order.executed_qty);
let fill = Fill {
price: ask.price,
qty: fill_qty,
commission: 0.0,
client_order_id: order.client_order_id.clone(),
side: order.side.clone(),
filled: fill_qty,
};
ask.executed_qty += fill_qty;
order.fills.push(fill);
order.executed_qty += fill_qty;

if ask.executed_qty == ask.orig_qty {
filled_ask_order_id.push(ask.order_id.clone());
}
}
}
self.asks
.retain(|ask| !filled_ask_order_id.contains(&ask.order_id.clone()));
}

fn match_asks(&mut self, order: &mut Order) {
order.executed_qty = 0.0;
let mut filled_bid_order_id: Vec<u64> = vec![];
for bids in self.bids.iter_mut() {
if bids.price >= order.price && order.executed_qty < order.orig_qty {
let fill_qty = bids.orig_qty.min(order.orig_qty - order.executed_qty);
let fill = Fill {
price: bids.price,
qty: fill_qty,
commission: 0.0,
client_order_id: order.client_order_id.clone(),
side: order.side.clone(),
filled: fill_qty,
};
bids.executed_qty += fill_qty;
order.fills.push(fill);
order.executed_qty += fill_qty;
if bids.executed_qty == bids.orig_qty {
filled_bid_order_id.push(bids.order_id.clone());
}
}
}

self.bids
.retain(|bid| !filled_bid_order_id.contains(&bid.order_id.clone()));
}

pub fn get_depth(&self) -> (Vec<(String, String)>, Vec<(String, String)>) {
let mut bids_obj: HashMap<String, f64> = HashMap::new();
let mut asks_obj: HashMap<String, f64> = HashMap::new();
for order in &self.bids {
let price_str = order.price.to_string();
let entry = bids_obj.entry(price_str.clone()).or_insert(0.0);
*entry += order.orig_qty;
}

for order in &self.asks {
let price_str = order.price.to_string();
let entry = asks_obj.entry(price_str.clone()).or_insert(0.0);
*entry += order.orig_qty;
}

let bids: Vec<(String, String)> = bids_obj
.into_iter()
.map(|(price, quantity)| (price, quantity.to_string()))
.collect();

let asks: Vec<(String, String)> = asks_obj
.into_iter()
.map(|(price, quantity)| (price, quantity.to_string()))
.collect();

(bids, asks)
}

pub fn get_open_orders(&self, client_id: String) -> Vec<Order> {
let mut open_orders: Vec<Order> = vec![];
for order in self.bids.iter() {
if order.client_id == client_id {
open_orders.push(order.clone());
}
}

for order in self.asks.iter() {
if order.client_id == client_id {
open_orders.push(order.clone());
}
}

open_orders
}

pub fn cancel_bid(&mut self, order_id: u64) {
self.bids.retain(|order| order.order_id != order_id);
}

pub fn cancel_ask(&mut self, order_id: u64) {
self.asks.retain(|order| order.order_id != order_id);
}
}
5 changes: 5 additions & 0 deletions crates/engine/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
use common::types::order::Fill;

pub struct AddOrderResponse {
pub executed_qty: f64,
pub fills: Vec<Fill>,
}
Loading