#![allow(
unused_crate_dependencies,
missing_docs,
reason = "Benchmarks don't use all dev-dependencies"
)]
use std::{
hint::black_box,
num::NonZeroU16,
};
use const_decimal::Decimal;
use criterion::{
BenchmarkId,
Criterion,
criterion_group,
criterion_main,
};
use lfest::{
load_trades_from_csv,
prelude::*,
};
const DECIMALS: u8 = 5;
fn generate_quotes_from_trades(
trades: &[Trade<i64, DECIMALS, QuoteCurrency<i64, DECIMALS>>],
) -> Vec<Bba<i64, DECIMALS>> {
Vec::from_iter(trades.iter().map(|trade| Bba {
bid: trade.price - QuoteCurrency::one(),
ask: trade.price + QuoteCurrency::one(),
timestamp_exchange_ns: trade.timestamp_exchange_ns,
}))
}
fn update_state<I, const D: u8, BaseOrQuote, U>(
exchange: &mut Exchange<I, D, BaseOrQuote, NoUserOrderId>,
trades: &[U],
) where
I: Mon<D>,
BaseOrQuote: Currency<I, D>,
BaseOrQuote::PairedCurrency: MarginCurrency<I, D>,
U: MarketUpdate<I, D, BaseOrQuote> + Clone,
{
for trade in trades.iter() {
exchange.update_state(trade).expect("is a valid update");
}
}
fn criterion_benchmark(c: &mut Criterion) {
let starting_balance = BaseCurrency::new(1, 0);
let contract_spec = ContractSpecification::new(
leverage!(1),
Decimal::try_from_scaled(5, 1).unwrap(),
PriceFilter::new(
None,
None,
QuoteCurrency::new(5, 1),
Decimal::TWO,
Decimal::try_from_scaled(5, 1).unwrap(),
)
.expect("is valid filter"),
QuantityFilter::new(None, None, QuoteCurrency::one()).expect("is valid filter"),
Fee::from(Decimal::try_from_scaled(2, 0).unwrap()),
Fee::from(Decimal::try_from_scaled(6, 0).unwrap()),
)
.expect("works");
let config = Config::new(
starting_balance,
NonZeroU16::new(200).unwrap(),
contract_spec,
OrderRateLimits::default(),
)
.unwrap();
let mut exchange = Exchange::new(config);
let trades = load_trades_from_csv("./data/Bitmex_XBTUSD_1M.csv");
const COUNT: usize = 1_000_000;
assert_eq!(trades.len(), COUNT);
let mut group = c.benchmark_group("Exchange");
group.throughput(criterion::Throughput::Elements(COUNT as u64));
group.bench_with_input(
BenchmarkId::new("update_state_trade", COUNT),
&COUNT,
|b, _| {
b.iter(|| {
update_state::<
_,
DECIMALS,
QuoteCurrency<_, DECIMALS>,
Trade<_, DECIMALS, QuoteCurrency<_, DECIMALS>>,
>(black_box(&mut exchange), black_box(&trades))
})
},
);
let bbas = generate_quotes_from_trades(&trades);
group.bench_with_input(
BenchmarkId::new("update_state_quotes", COUNT),
&COUNT,
|b, _n| {
b.iter(|| {
update_state::<_, DECIMALS, QuoteCurrency<_, DECIMALS>, Bba<_, DECIMALS>>(
black_box(&mut exchange),
black_box(&bbas),
)
})
},
);
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);