Skip to content

Commit

Permalink
feat(rust): add functionality to retrieve the depth snapshot.
Browse files Browse the repository at this point in the history
  • Loading branch information
nkaz001 committed Jul 10, 2024
1 parent 568d1a4 commit f6097e1
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 5 deletions.
5 changes: 3 additions & 2 deletions hftbacktest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ keywords = [
"quantitative",
"trading",
"backtesting",
"crypto",
"cryptocurrency",
"hft"
]
categories = ["finance", "mathematics", "science", "algorithms", "simulation"]
Expand All @@ -27,6 +27,7 @@ binancefutures = ["serde", "serde_json", "tokio-tungstenite", "reqwest", "sha2",
bybit = ["serde", "serde_json", "tokio-tungstenite", "reqwest", "sha2", "hmac", "rand"]
unstable_l3 = []
unstable_fuse = []
unstable_marketdeptharrayview = []

[dependencies]
tracing = "0.1.40"
Expand All @@ -37,7 +38,7 @@ chrono = { version = "0.4.33", optional = true }
serde = { version = "1.0.196", features = ["derive"], optional = true }
serde_json = { version = "1.0.113", optional = true }
tokio = { version = "1.35.1", features = ["full"], optional = true }
tokio-tungstenite = { version = "0.23.0", features = ["native-tls"], optional = true }
tokio-tungstenite = { version = "0.23.1", features = ["native-tls"], optional = true }
reqwest = { version = "0.12.3", features = ["json"], optional = true }
zip = { version = "2.1.3", optional = true }
futures-util = { version = "0.3.30", optional = true }
Expand Down
30 changes: 29 additions & 1 deletion hftbacktest/src/depth/btreemarketdepth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
};
use crate::{
backtest::{reader::Data, BacktestError},
prelude::Side,
prelude::{Side, DEPTH_SNAPSHOT_EVENT, EXCH_EVENT, LOCAL_EVENT},
types::{Event, BUY, SELL},
};

Expand Down Expand Up @@ -203,6 +203,34 @@ impl ApplySnapshot<Event> for BTreeMarketDepth {
self.best_bid_tick = *self.bid_depth.keys().last().unwrap_or(&INVALID_MIN);
self.best_ask_tick = *self.ask_depth.keys().next().unwrap_or(&INVALID_MAX);
}

fn snapshot(&self) -> Vec<Event> {
let mut events = Vec::new();

for (&px_tick, &qty) in self.bid_depth.iter().rev() {
events.push(Event {
ev: EXCH_EVENT | LOCAL_EVENT | BUY | DEPTH_SNAPSHOT_EVENT,
// todo: it's not a problem now, but it would be better to have valid timestamps.
exch_ts: 0,
local_ts: 0,
px: px_tick as f32 * self.tick_size,
qty,
});
}

for (&px_tick, &qty) in self.ask_depth.iter() {
events.push(Event {
ev: EXCH_EVENT | LOCAL_EVENT | SELL | DEPTH_SNAPSHOT_EVENT,
// todo: it's not a problem now, but it would be better to have valid timestamps.
exch_ts: 0,
local_ts: 0,
px: px_tick as f32 * self.tick_size,
qty,
});
}

events
}
}

impl L3MarketDepth for BTreeMarketDepth {
Expand Down
42 changes: 41 additions & 1 deletion hftbacktest/src/depth/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::{hash_map::Entry, HashMap};
use super::{ApplySnapshot, L1MarketDepth, L3Order, MarketDepth, INVALID_MAX, INVALID_MIN};
use crate::{
backtest::{reader::Data, BacktestError},
prelude::{L2MarketDepth, Side},
prelude::{L2MarketDepth, Side, DEPTH_SNAPSHOT_EVENT, EXCH_EVENT, LOCAL_EVENT},
types::{Event, BUY, SELL},
};

Expand Down Expand Up @@ -363,6 +363,46 @@ impl ApplySnapshot<Event> for FusedHashMapMarketDepth {
}
}
}

fn snapshot(&self) -> Vec<Event> {
let mut events = Vec::new();

let mut bid_depth = self
.bid_depth
.iter()
.map(|(&px_tick, &qty)| (px_tick, qty))
.collect::<Vec<_>>();
bid_depth.sort_by(|a, b| b.0.cmp(&a.0));
for (px_tick, qty) in bid_depth {
events.push(Event {
ev: EXCH_EVENT | LOCAL_EVENT | BUY | DEPTH_SNAPSHOT_EVENT,
exch_ts: qty.timestamp,
// todo: it's not a problem now, but it would be better to have valid timestamps.
local_ts: 0,
px: px_tick as f32 * self.tick_size,
qty: qty.qty,
});
}

let mut ask_depth = self
.ask_depth
.iter()
.map(|(&px_tick, &qty)| (px_tick, qty))
.collect::<Vec<_>>();
ask_depth.sort_by(|a, b| a.0.cmp(&b.0));
for (px_tick, qty) in ask_depth {
events.push(Event {
ev: EXCH_EVENT | LOCAL_EVENT | SELL | DEPTH_SNAPSHOT_EVENT,
exch_ts: qty.timestamp,
// todo: it's not a problem now, but it would be better to have valid timestamps.
local_ts: 0,
px: px_tick as f32 * self.tick_size,
qty: qty.qty,
});
}

events
}
}

impl L1MarketDepth for FusedHashMapMarketDepth {
Expand Down
42 changes: 41 additions & 1 deletion hftbacktest/src/depth/hashmapmarketdepth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{ApplySnapshot, L3MarketDepth, L3Order, MarketDepth, INVALID_MAX, INV
use crate::{
backtest::{reader::Data, BacktestError},
prelude::{L2MarketDepth, Side},
types::{Event, BUY, SELL},
types::{Event, BUY, DEPTH_SNAPSHOT_EVENT, EXCH_EVENT, LOCAL_EVENT, SELL},
};

/// L2/L3 Market depth implementation based on a hash map.
Expand Down Expand Up @@ -296,6 +296,46 @@ impl ApplySnapshot<Event> for HashMapMarketDepth {
}
}
}

fn snapshot(&self) -> Vec<Event> {
let mut events = Vec::new();

let mut bid_depth = self
.bid_depth
.iter()
.map(|(&px_tick, &qty)| (px_tick, qty))
.collect::<Vec<_>>();
bid_depth.sort_by(|a, b| b.0.cmp(&a.0));
for (px_tick, qty) in bid_depth {
events.push(Event {
ev: EXCH_EVENT | LOCAL_EVENT | BUY | DEPTH_SNAPSHOT_EVENT,
// todo: it's not a problem now, but it would be better to have valid timestamps.
exch_ts: 0,
local_ts: 0,
px: px_tick as f32 * self.tick_size,
qty,
});
}

let mut ask_depth = self
.ask_depth
.iter()
.map(|(&px_tick, &qty)| (px_tick, qty))
.collect::<Vec<_>>();
ask_depth.sort_by(|a, b| a.0.cmp(&b.0));
for (px_tick, qty) in ask_depth {
events.push(Event {
ev: EXCH_EVENT | LOCAL_EVENT | SELL | DEPTH_SNAPSHOT_EVENT,
// todo: it's not a problem now, but it would be better to have valid timestamps.
exch_ts: 0,
local_ts: 0,
px: px_tick as f32 * self.tick_size,
qty,
});
}

events
}
}

impl L3MarketDepth for HashMapMarketDepth {
Expand Down
10 changes: 10 additions & 0 deletions hftbacktest/src/depth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ where
{
/// Applies the snapshot from the given data to this market depth.
fn apply_snapshot(&mut self, data: &Data<EventT>);

/// Returns the current market depth as the depth snapshot events.
fn snapshot(&self) -> Vec<EventT>;
}

/// Level3 order from the market feed.
Expand Down Expand Up @@ -167,3 +170,10 @@ pub trait L1MarketDepth {
timestamp: i64,
) -> (i32, i32, i32, f32, f32, i64);
}

#[cfg(feature = "unstable_marketdeptharrayview")]
pub trait L2MarketDepthArrayView {
fn bid_depth(&self) -> &[f32];

fn ask_depth(&self) -> &[f32];
}

0 comments on commit f6097e1

Please sign in to comment.