use crate::generators::randomizer::randomize_order;
use crate::messages::errors::{LevelError, OrderError};
use core::f64;
use std::task::Wake;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub enum Side {
Bids,
Asks,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub enum OrderType {
Market,
Limit,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Order {
pub order_id: u32,
pub order_ts: u128,
pub order_type: OrderType,
pub side: Side,
pub price: f64,
pub amount: f64,
}
impl Order {
pub fn new(
order_id: u32,
order_ts: u128,
order_type: OrderType,
side: Side,
price: f64,
amount: f64,
) -> Self {
match side {
Side::Bids => Order {
order_id,
order_ts,
order_type,
side: Side::Bids,
price,
amount,
},
Side::Asks => Order {
order_id,
order_ts,
order_type,
side: Side::Asks,
price,
amount,
},
};
Order {
order_id,
order_ts,
order_type,
side,
price,
amount,
}
}
pub fn randomize(side: Side, price: f64, order_type: OrderType) -> Self {
let now_ts = SystemTime::now();
let since_epoch_ts = now_ts
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_nanos();
let order_ts_gen = since_epoch_ts as u128;
let order_amount_gen = 123.456;
let order_id_gen: u32 = 123;
let order_type_gen = order_type;
Order {
order_id: order_id_gen,
order_ts: order_ts_gen,
order_type: order_type_gen,
side,
price,
amount: order_amount_gen,
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Level {
pub level_id: u32,
pub side: Side,
pub price: f64,
pub volume: f64,
pub orders: Vec<Order>,
}
impl Level {
pub fn new(level_id: u32, side: Side, price: f64, volume: f64, orders: Vec<Order>) -> Self {
match side {
Side::Bids => Level {
level_id,
side: Side::Bids,
price,
volume,
orders: orders.clone(),
},
Side::Asks => Level {
level_id,
side: Side::Asks,
price,
volume,
orders: orders.clone(),
},
};
Level {
level_id,
side,
price,
volume,
orders,
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Orderbook {
pub orderbook_id: u32,
pub orderbook_ts: u64,
pub symbol: String,
pub bids: Vec<Level>,
pub asks: Vec<Level>,
}
impl Orderbook {
pub fn new(
orderbook_id: u32,
orderbook_ts: u64,
symbol: String,
bids: Vec<Level>,
asks: Vec<Level>,
) -> Self {
Orderbook {
orderbook_id,
orderbook_ts,
symbol,
bids,
asks,
}
}
pub fn find_level(&self, level_price: &f64) -> Result<i32, LevelError> {
let mut i_level: i32 = 0;
if level_price <= &self.bids[0].price {
for i_bid in &self.bids {
i_level -= 1;
if level_price == &i_bid.price {
return Ok(i_level);
}
}
}
if level_price >= &self.asks[0].price {
for i_ask in &self.asks {
i_level += 1;
if level_price == &i_ask.price {
return Ok(i_level);
}
}
}
Err(LevelError::LevelNotFound)
}
pub fn retrieve_level(&self, level_price: &f64) -> Result<Level, LevelError> {
if let Ok(i_level) = self.find_level(level_price) {
if i_level < 0 {
let i_level = i_level.abs() + 1;
return Ok(self.bids[i_level as usize].clone());
} else if i_level > 0 {
let i_level = i_level - 1;
return Ok(self.asks[i_level as usize].clone());
} else {
return Err(LevelError::LevelInfoNotAvailable);
}
} else {
return Err(LevelError::LevelNotFound);
}
}
pub fn delete_level(&mut self, level_price: &f64) -> Result<(), LevelError> {
let find_level_ob = self.find_level(level_price);
match find_level_ob {
Ok(n) if n < 0 => {
let bid_found = find_level_ob.unwrap().abs() as usize - 1;
self.bids.remove(bid_found);
Ok(())
}
Ok(n) if n > 0 => {
let ask_found = find_level_ob.unwrap() as usize - 1;
self.asks.remove(ask_found);
Ok(())
}
Err(e) => Err(LevelError::LevelDeletionFailed),
Ok(_) => Err(LevelError::LevelInfoNotAvailable),
}
}
pub fn insert_level(&mut self, level: Level) -> Result<(), LevelError> {
if let Ok(i_level) = self.find_level(&level.price) {
println!("i_level found: {:?}", &i_level);
if i_level < 0 {
let i_level = i_level.abs() - 1;
let same_level_id = &self.bids[i_level as usize].level_id;
self.bids[i_level as usize] = Level::new(
*same_level_id,
Side::Bids,
level.price,
level.volume,
level.orders,
);
return Ok(());
} else if i_level > 0 {
let i_level = i_level - 1;
let same_level_id = &self.asks[i_level as usize].level_id;
self.asks[i_level as usize] = Level::new(
*same_level_id,
level.side,
level.price,
level.volume,
level.orders,
);
return Ok(());
} else {
println!("i_level found: {:?}", &i_level);
return Err(LevelError::LevelNotFound);
}
} else {
match level.side {
Side::Bids => {
let mut v_bids = self.bids.clone().into_iter();
let index_level = v_bids
.position(|existing_level| level.price > existing_level.price)
.unwrap_or(v_bids.len());
self.bids.insert(
index_level,
Level::new(
index_level as u32,
level.side,
level.price,
level.volume,
level.orders,
),
);
return Ok(());
}
Side::Asks => {
let mut v_asks = self.asks.clone().into_iter();
let index_level = v_asks
.position(|existing_level| level.price < existing_level.price)
.unwrap_or(v_asks.len());
self.asks.insert(
index_level,
Level::new(
index_level as u32,
level.side,
level.price,
level.volume,
level.orders,
),
);
return Ok(());
}
}
}
return Err(LevelError::LevelNotFound);
}
pub fn find_order(
&self,
side: Side,
price: f64,
order_ts: u128,
) -> Result<(i32, usize), OrderError> {
let find_level_ob = self.find_level(&price);
match find_level_ob {
Ok(n) if n < 0 => {
let level_found = find_level_ob.unwrap().abs() as usize - 1;
let level_orders = &self.bids[level_found].orders;
if level_orders.len() > 0 {
let r_level = level_orders
.binary_search_by(|order| order.order_ts.cmp(&order_ts))
.unwrap();
Ok((n, r_level))
} else {
Err(OrderError::OrderNotFound)
}
}
Ok(n) if n > 0 => {
let level_found = find_level_ob.unwrap().abs() as usize - 1;
let level_orders = &self.asks[level_found].orders;
if level_orders.len() > 0 {
let r_level = level_orders
.binary_search_by(|order| order.order_ts.cmp(&order_ts))
.unwrap();
Ok((n, r_level))
} else {
Err(OrderError::OrderNotFound)
}
}
Err(e) => Err(OrderError::OrderNotFound),
Ok(_) => Err(OrderError::OrderInfoNotAvailable),
}
}
pub fn retrieve_order(
&self,
side: Side,
price: f64,
order_ts: u128,
) -> Result<(Order), OrderError> {
if let Ok((found_level, found_order)) = self.find_order(side, price, order_ts) {
let bid_ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
if found_level > 0 {
Ok(self.asks[found_level.abs() as usize].orders[found_order])
} else {
Ok(self.bids[found_level.abs() as usize].orders[found_order])
}
} else {
Err(OrderError::OrderNotFound)
}
}
pub fn delete_order(
&mut self,
side: Side,
price: f64,
order_ts: u128,
) -> Result<(), OrderError> {
if let Ok((found_level, found_order)) = self.find_order(side, price, order_ts) {
if found_level > 0 {
self.asks[found_level.abs() as usize - 1]
.orders
.remove(found_order);
Ok(())
} else {
self.bids[found_level.abs() as usize - 1]
.orders
.remove(found_order);
Ok(())
}
} else {
Err(OrderError::OrderNotFound)
}
}
pub fn insert_order(&mut self, side: Side, price: f64, amount: f64) -> Result<(), OrderError> {
let find_level_ob = self.find_level(&price);
match find_level_ob {
Ok(n) if n < 0 => {
let bid_ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let i_order = Order::new(
123,
bid_ts,
OrderType::Limit,
Side::Bids,
self.bids[n as usize].price,
amount,
);
self.bids[find_level_ob.unwrap() as usize]
.orders
.push(i_order);
Ok(())
}
Ok(n) if n > 0 => {
let ask_ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let i_order = Order::new(
123,
ask_ts,
OrderType::Limit,
Side::Asks,
self.asks[n as usize].price,
amount,
);
self.asks[find_level_ob.unwrap() as usize]
.orders
.push(i_order);
Ok(())
}
Err(e) => Err(OrderError::OrderNotFound),
Ok(_) => Err(OrderError::OrderInfoNotAvailable),
}
}
pub fn modify_order(
&mut self,
order_ts: u128,
side: Side,
price: f64,
amount: f64,
) -> Result<Order, OrderError> {
match self.find_order(side, price, order_ts) {
Ok((found_level, found_order)) => {
if found_level < 0 {
println!("\nfounded level: {:?}", found_level.abs() as usize - 1);
let founded_order =
self.bids[found_level.abs() as usize].orders[found_order].clone();
println!("\nfounded order: {:?}", founded_order);
let moded_ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let to_moded_order = Order::new(
founded_order.order_id,
moded_ts,
founded_order.order_type,
founded_order.side,
founded_order.price,
amount,
);
let moded_order = self.bids[found_level.abs() as usize - 1].orders[found_order];
let moded_order = to_moded_order;
Ok(moded_order.clone())
} else if found_level > 0 {
println!("\nfounded_level: {:?}", found_level.abs() as usize - 1);
let founded_order =
self.asks[found_level.abs() as usize].orders[found_order].clone();
println!("founded order: {:?}", founded_order);
let moded_ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let to_moded_order = Order::new(
founded_order.order_id,
moded_ts,
founded_order.order_type,
founded_order.side,
founded_order.price,
amount,
);
let moded_order = self.asks[found_level.abs() as usize - 1].orders[found_order];
let moded_order = to_moded_order;
Ok(moded_order.clone())
} else {
println!("else");
Err(OrderError::OrderNotFound)
}
}
Err(e) => Err(OrderError::OrderNotFound),
}
}
pub fn synthetize(
bid_price: f64,
ask_price: f64,
tick_size: f64,
n_levels: u32,
n_orders: u32,
) -> Self {
let mut i_bids = Vec::new();
let mut i_asks = Vec::new();
for i in 1..=n_levels {
let i_bid_price = bid_price - (&tick_size * i as f64);
let i_bid_side = Side::Bids;
let i_order_type = OrderType::Limit;
let mut v_bid_orders: Vec<Order> = (0..n_orders)
.map(|_| randomize_order(i_bid_side, i_bid_price, i_order_type))
.collect();
v_bid_orders.sort_by_key(|order| order.order_ts);
let i_bid_volume: f64 = v_bid_orders.iter().map(|order| order.amount).sum();
i_bids.push(Level {
level_id: i,
side: i_bid_side,
price: i_bid_price,
volume: i_bid_volume,
orders: v_bid_orders,
});
let i_ask_price = ask_price + (&tick_size * i as f64);
let i_ask_side = Side::Asks;
let mut v_ask_orders: Vec<Order> = (0..n_orders)
.map(|_| randomize_order(i_ask_side, i_ask_price, i_order_type))
.collect();
v_ask_orders.sort_by_key(|order| order.order_ts);
let i_ask_volume: f64 = v_ask_orders.iter().map(|order| order.amount).sum();
i_asks.push(Level {
level_id: i,
side: i_ask_side,
price: i_ask_price,
volume: i_ask_volume,
orders: v_ask_orders,
});
}
Orderbook {
orderbook_id: 123,
orderbook_ts: 321,
symbol: String::from("BTCUSDT"),
bids: i_bids,
asks: i_asks,
}
}
}