Skip to main content

engine/strategies/
random.rs

1use super::Strategy;
2use crate::types::{Observation, Order, OrderRequest, Side};
3use rand::prelude::*;
4use rand::rng;
5use rand::rngs::StdRng;
6
7pub struct RandomStrategy {
8    rng: StdRng,
9    probability: f64,
10    order_counter: u64,
11}
12
13impl RandomStrategy {
14    pub fn new(probability: f64) -> Self {
15        Self {
16            rng: StdRng::from_rng(&mut rng()),
17            probability,
18            order_counter: 0,
19        }
20    }
21}
22
23impl Strategy for RandomStrategy {
24    fn on_tick(&mut self, obs: &Observation, requests: &mut Vec<OrderRequest>) {
25        // Randomly decide whether to place an order
26        if self.rng.random_bool(self.probability) {
27            let side = if self.rng.random_bool(0.5) {
28                Side::Buy
29            } else {
30                Side::Sell
31            };
32
33            // Generate a price relative to the current market
34            // Buy: Randomly below the best bid (passive)
35            // Sell: Randomly above the best ask (passive)
36            let price = match side {
37                Side::Buy => obs.best_bid * (1.0 - self.rng.random_range(0.0..0.001)),
38                Side::Sell => obs.best_ask * (1.0 + self.rng.random_range(0.0..0.001)),
39            };
40
41            let price = (price * 100.0).round() / 100.0;
42            let quantity = self.rng.random_range(1.0..10.0);
43
44            self.order_counter += 1;
45            requests.push(OrderRequest::New(Order::new(
46                self.order_counter,
47                side,
48                price,
49                quantity,
50            )));
51        }
52    }
53
54    fn as_any(&self) -> &dyn std::any::Any {
55        self
56    }
57    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
58        self
59    }
60}