Skip to main content

qs_backtest/
strategy.rs

1//! Strategy trait for strategy-driven backtests.
2//!
3//! Implement [`Strategy`] to define custom trading logic that reacts to
4//! market events and produces [`Action`]s for the engine to process.
5
6use qs_core::types::Action;
7
8use crate::data_feed::MarketEvent;
9
10/// A trading strategy that reacts to market events.
11///
12/// The backtest runner calls [`on_event`](Strategy::on_event) for every
13/// market event (tick or bar) in the data feed.  The strategy inspects the
14/// event and returns zero or more [`Action`]s that the engine will process.
15///
16/// # Example
17///
18/// ```ignore
19/// use qs_backtest::{Strategy, MarketEvent};
20/// use qs_core::types::{Action, OrderType, Side};
21///
22/// struct BuyAndHold { entered: bool }
23///
24/// impl Strategy for BuyAndHold {
25///     fn on_event(&mut self, event: &MarketEvent) -> Vec<Action> {
26///         if self.entered { return vec![]; }
27///         if let MarketEvent::Tick { symbol, ask, .. } = event {
28///             self.entered = true;
29///             return vec![Action::Open {
30///                 symbol: symbol.clone(),
31///                 side: Side::Buy,
32///                 order_type: OrderType::Market,
33///                 price: Some(*ask),
34///                 size: 1.0,
35///                 stoploss: None,
36///                 targets: vec![],
37///                 rules: vec![],
38///                 group: None,
39///             }];
40///         }
41///         vec![]
42///     }
43///
44///     fn on_finished(&mut self) -> Vec<Action> {
45///         vec![Action::CloseAll]
46///     }
47/// }
48/// ```
49pub trait Strategy {
50    /// Called for every market event in the data feed.
51    ///
52    /// Return an empty `Vec` to take no action on this event.
53    fn on_event(&mut self, event: &MarketEvent) -> Vec<Action>;
54
55    /// Called once after the data feed is exhausted.
56    ///
57    /// Use this to emit final actions such as closing all remaining
58    /// positions.  The default implementation does nothing.
59    fn on_finished(&mut self) -> Vec<Action> {
60        vec![]
61    }
62}