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

Expand orderbook structure implementations #39

Merged
merged 2 commits into from
Nov 5, 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
53 changes: 51 additions & 2 deletions atelier/examples/ob_metrics.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use atelier::data::market::{Level, Order, OrderType, Orderbook, Side};
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
// Parameters for synthetic orderbook generation
let bid_price = 50_000.00;
let ask_price = 50_100.00;
let tick_size = 100.0;
let n_levels = 2;
let n_orders = 1;
let n_orders = 2;

// Generate a synthetic orderbook for testing
// this determines the order of the Level objects within
Expand Down Expand Up @@ -148,7 +149,6 @@ fn main() {

println!("\n -- Find Order --");
let i_order = &i_ob.bids[0].orders[0];

let found_order = i_ob.find_order(i_order.side, i_order.price, i_order.order_ts);

println!(
Expand Down Expand Up @@ -184,9 +184,58 @@ fn main() {
// ----------------------------------------------------- Delete Order -- //
// ----------------------------------------------------- ------------ -- //

println!("\n -- Delete Order --");
let to_delete_order = i_ob.bids[0].orders[0].clone();

println!(
"
Order to be deleted,
side: {:?},
price: {:?},
amount: {:?},
order_ts {:?}",
to_delete_order.side,
to_delete_order.price,
to_delete_order.amount,
to_delete_order.order_ts,
);

println!("\nPrevious orderbook.bids has :\n{:?}", i_ob.bids);

let _deleted = i_ob.delete_order(
to_delete_order.side,
to_delete_order.price,
to_delete_order.order_ts,
);

println!("\nNow orderbook.bids has :\n{:?}", i_ob.bids);

// ----------------------------------------------------- Insert Order -- //
// ----------------------------------------------------- ------------ -- //

println!("\n -- Insert Order --");
let inserted_order = i_ob.insert_order(Side::Bids, 50_200.0, 0.1986);
match inserted_order {
Ok(result) => {
println!("This is the result: {:?}", result);
}
Err(result) => {
eprintln!("This was the error: {:?}", result);
}
}

// ----------------------------------------------------- Modify Order -- //
// ----------------------------------------------------- ------------ -- //

println!("\n -- Modify Order --");
let to_modify_order = i_ob.asks[0].orders[0].clone();

let moded = i_ob.modify_order(
to_modify_order.order_ts,
to_modify_order.side,
to_modify_order.price,
999.999,
);

println!("moded_order: {:?}", moded.unwrap());
}
189 changes: 167 additions & 22 deletions atelier/src/data/market.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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)]
Expand All @@ -25,7 +26,7 @@ pub enum OrderType {
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Order {
pub order_id: u32,
pub order_ts: u64,
pub order_ts: u128,
pub order_type: OrderType,
pub side: Side,
pub price: f64,
Expand All @@ -46,7 +47,7 @@ impl Order {
///
pub fn new(
order_id: u32,
order_ts: u64,
order_ts: u128,
order_type: OrderType,
side: Side,
price: f64,
Expand Down Expand Up @@ -99,9 +100,9 @@ impl Order {
let since_epoch_ts = now_ts
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis();
.as_nanos();

let order_ts_gen = since_epoch_ts as u64;
let order_ts_gen = since_epoch_ts as u128;

// Randomize amount
let order_amount_gen = 123.456;
Expand All @@ -123,8 +124,8 @@ impl Order {
}
}

// ---------------------------------------------------------------- LEVEL -- //
// ------------------------------------------------------------------------- //
// -------------------------------------------------------------------------- LEVEL -- //
// ----------------------------------------------------------------------------------- //

/// Represents a price level in an order book.
///
Expand All @@ -141,6 +142,9 @@ pub struct Level {
}

impl Level {
// ------------------------------------------------------------------ New Level -- //
// ------------------------------------------------------------------ ------------ //

/// Creates a new instance of `Level`.
///
/// # Parameters
Expand All @@ -154,6 +158,7 @@ impl Level {
/// # Returns
///
/// Returns a new `Level` instance with the specified parameters.

pub fn new(level_id: u32, side: Side, price: f64, volume: f64, orders: Vec<Order>) -> Self {
match side {
Side::Bids => Level {
Expand Down Expand Up @@ -181,7 +186,6 @@ impl Level {
}
}
}

// ------------------------------------------------------------ ORDERBOOK -- //
// ------------------------------------------------------------------------- //

Expand Down Expand Up @@ -465,10 +469,10 @@ impl Orderbook {
return Err(LevelError::LevelNotFound);
}

// ---------------------------------------------------- Find an Order -- //
// ---------------------------------------------------- ------------- -- //
// -------------------------------------------------------------- Find an Order -- //
// -------------------------------------------------------------- ------------- -- //

/// To find if a given `Order` exists.
/// To find if a given `Order` exists within the current Level.
///
/// ## Parameters
/// side: Side = {Side::Bids, Side::Asks}
Expand All @@ -484,7 +488,7 @@ impl Orderbook {
&self,
side: Side,
price: f64,
order_ts: u64,
order_ts: u128,
) -> Result<(i32, usize), OrderError> {
// see if level exists
let find_level_ob = self.find_level(&price);
Expand Down Expand Up @@ -545,9 +549,15 @@ impl Orderbook {
&self,
side: Side,
price: f64,
order_ts: u64,
order_ts: u128,
) -> Result<(Order), OrderError> {
if let Ok((found_level, found_order)) = self.find_order(side, price, order_ts) {
// Get the curren timestamp
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 {
Expand All @@ -568,15 +578,24 @@ impl Orderbook {
/// ## Results
///

pub fn delete_order(&self, side: Side, price: f64, order_ts: u64) -> Result<(), OrderError> {
// find the order
// delete the order

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].orders[found_order]
self.asks[found_level.abs() as usize - 1]
.orders
.remove(found_order);

Ok(())
} else {
self.bids[found_level.abs() as usize].orders[found_order]
self.bids[found_level.abs() as usize - 1]
.orders
.remove(found_order);
Ok(())
}
} else {
Err(OrderError::OrderNotFound)
Expand All @@ -588,13 +607,70 @@ impl Orderbook {

/// To insert a new `Order`.
///
/// The first process is to find whether the necessary Level in the
/// Orderbook exists. Then, depending on which side is it (or has to be
/// created) all the parameters for Order::new() are created and parsed.
///
/// ## Parameters
///
///
/// ## Results
///

pub fn insert_order() -> Result<(), OrderError> {
Ok(())
pub fn insert_order(&mut self, side: Side, price: f64, amount: f64) -> Result<(), OrderError> {
// see if level exists
let find_level_ob = self.find_level(&price);

match find_level_ob {
Ok(n) if n < 0 => {
// Get the curren timestamp
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 => {
// Get the curren timestamp
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),
}
}

// -------------------------------------------------- Modify an Order -- //
Expand All @@ -607,8 +683,77 @@ impl Orderbook {
/// ## Results
///

pub fn modify_order() -> Result<(), OrderError> {
Ok(())
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),
}
}

// ---------------------------------------------- Synthetic Orderbook -- //
Expand Down
4 changes: 2 additions & 2 deletions atelier/src/generators/randomizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ pub fn randomize_order(side: Side, price: f64, order_type: OrderType) -> Order {
let since_epoch_ts = now_ts
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis();
.as_nanos();
// println!("since_epoch_ts: {:?}", since_epoch_ts);

// Random millis between orders ~Uniform(1,30)
let ms_offset = uni_rand.sample(Uniform::new(1, 30));
// println!("ms_offset: {:?}", ms_offset);

let order_ts = since_epoch_ts as u64 + ms_offset;
let order_ts = since_epoch_ts + ms_offset as u128;
// println!("order_ts: {}", order_ts);

// Randomize amount
Expand Down
Loading
Loading