Skip to main content

engine/strategies/
zi.rs

1use super::Strategy;
2use crate::types::{Observation, Order, OrderRequest, Side};
3use rand::prelude::*;
4use rand::rng;
5use rand::rngs::StdRng;
6
7/// Zero Intelligence market maker.
8///
9/// On every tick, places both a bid and an ask with half-spreads drawn
10/// independently from U(0, max_spread).  No memory, no inventory skew.
11pub struct ZeroIntelligenceStrategy {
12    rng: StdRng,
13    max_spread: f64,
14    order_counter: u64,
15}
16
17impl ZeroIntelligenceStrategy {
18    pub fn new(max_spread: f64) -> Self {
19        Self {
20            rng: StdRng::from_rng(&mut rng()),
21            max_spread,
22            order_counter: 0,
23        }
24    }
25}
26
27impl Strategy for ZeroIntelligenceStrategy {
28    fn on_tick(&mut self, obs: &Observation, requests: &mut Vec<OrderRequest>) {
29        let mid = (obs.best_bid + obs.best_ask) / 2.0;
30
31        let delta_bid: f64 = self.rng.random_range(0.0..self.max_spread);
32        let delta_ask: f64 = self.rng.random_range(0.0..self.max_spread);
33
34        requests.push(OrderRequest::CancelAll);
35
36        self.order_counter += 1;
37        requests.push(OrderRequest::New(Order::new(
38            self.order_counter,
39            Side::Buy,
40            mid - delta_bid,
41            1.0,
42        )));
43
44        self.order_counter += 1;
45        requests.push(OrderRequest::New(Order::new(
46            self.order_counter,
47            Side::Sell,
48            mid + delta_ask,
49            1.0,
50        )));
51    }
52
53    fn as_any(&self) -> &dyn std::any::Any {
54        self
55    }
56    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
57        self
58    }
59}