-
Notifications
You must be signed in to change notification settings - Fork 14
/
basic.rs
80 lines (71 loc) · 2.97 KB
/
basic.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! Example usage of Exchange using external trade data.
//! A randomly acting agent places market buy / sell orders every 100 candles
mod load_trades;
use std::{convert::TryInto, time::Instant};
use lfest::{account_tracker::FullAccountTracker, prelude::*};
use load_trades::load_prices_from_csv;
use rand::{thread_rng, Rng};
use tracing::error;
fn main() {
let t0 = Instant::now();
let starting_balance = base!(10);
let acc_tracker = FullAccountTracker::new(starting_balance);
let contract_spec = ContractSpecification::new(
leverage!(1),
Dec!(0.5),
PriceFilter::new(None, None, quote!(0.1), Dec!(2), Dec!(0)).expect("is valid price filter"),
QuantityFilter::default(),
fee!(0.0002),
fee!(0.0006),
)
.expect("is valid");
let config = Config::new(starting_balance, 200, contract_spec, 3600).unwrap();
let mut exchange = Exchange::<
FullAccountTracker<BaseCurrency>,
QuoteCurrency,
(),
InMemoryTransactionAccounting<BaseCurrency>,
>::new(acc_tracker, config);
// load trades from csv file
let prices = load_prices_from_csv("./data/Bitmex_XBTUSD_1M.csv").unwrap();
// use random action every 100 trades to buy or sell
let mut rng = thread_rng();
for (i, p) in prices.iter().enumerate() {
let price_decimal: Decimal = (*p).try_into().expect("Unable to convert f64 into Decimal");
let spread: Decimal = Decimal::ONE / Decimal::from(10);
let exec_orders = exchange
.update_state(
(i as i64).into(),
&bba!(
QuoteCurrency::new(price_decimal),
QuoteCurrency::new(price_decimal + spread)
),
)
.expect("Got REKT. Try again next time :D");
if !exec_orders.is_empty() {
println!("executed orders: {:?}", exec_orders);
}
if i % 100 == 0 {
// Trade a fraction of the available wallet balance
let order_value: BaseCurrency =
exchange.user_balances().available_wallet_balance * Dec!(0.1);
let order_size = order_value.convert(exchange.market_state().bid());
let order = if rng.gen() {
MarketOrder::new(Side::Sell, order_size).unwrap() // Sell using
// market order
} else {
MarketOrder::new(Side::Buy, order_size).unwrap() // Buy using market order
};
// Handle order error here if needed
match exchange.submit_market_order(order) {
Ok(order) => println!("succesfully submitted order: {:?}", order),
Err(order_err) => error!("an error has occurred: {}", order_err),
}
}
}
println!(
"time to simulate 1 million historical trades: {}micros",
t0.elapsed().as_micros()
);
println!("account_tracker: {}", exchange.account_tracker());
}