pub trait Strategy {
// Required method
fn on_bar(&mut self, context: &mut StrategyContext<'_>);
// Provided methods
fn inputs(&self) -> Vec<(String, String)> { ... }
fn study_inputs(&self) -> Vec<StudyInput> { ... }
fn set_input(
&mut self,
id: &str,
value: InputValue,
) -> Result<(), &'static str> { ... }
fn prepare(&mut self, bars: &[Bar]) { ... }
fn prepare_update(&mut self, bars: &[Bar]) { ... }
}Expand description
A trading strategy that decides on closed bars and, when enabled, live ticks.
§Example
use egui_charts::model::{Bar, OrderSide, OrderType, Timeframe};
use egui_charts::strategies::{Backtest, Strategy, StrategyContext};
/// Long while the close is above the previous close, flat otherwise.
struct Momentum;
impl Strategy for Momentum {
fn on_bar(&mut self, context: &mut StrategyContext<'_>) {
let [.., previous, bar] = context.bars() else {
return;
};
if bar.close > previous.close && context.position() == 0.0 {
context.entry("Long", OrderSide::Buy, 10.0, OrderType::Market);
} else if bar.close < previous.close && context.position() > 0.0 {
context.exit("Close", None, None, None);
}
}
}
let bar = |minute: i64, price: f64| {
let time = chrono::DateTime::UNIX_EPOCH + chrono::TimeDelta::minutes(minute);
Bar::new(time, price, price, price, price, 0.0)
};
let bars = vec![bar(0, 100.0), bar(1, 101.0), bar(2, 103.0), bar(3, 102.0), bar(4, 101.0)];
let report = Backtest::new("Momentum", "AAPL", Timeframe::Min1, 10_000.0).run(&mut Momentum, &bars, &[]);
// Bought at the next open after the rise to 101, sold at the next open after the fall to 102.
assert_eq!(report.trades.len(), 1);
assert_eq!(report.trades[0].entry_price, 103.0);
assert_eq!(report.trades[0].exit.as_ref().map(|exit| exit.profit), Some(-20.0));
assert_eq!(report.equity.len(), bars.len() + 1);Required Methods§
Sourcefn on_bar(&mut self, context: &mut StrategyContext<'_>)
fn on_bar(&mut self, context: &mut StrategyContext<'_>)
Decides on the bar that just closed, the last of StrategyContext::bars, by placing and
cancelling orders. With fill recalculation enabled this also runs immediately after a fill;
use the context’s price and fill flag rather than reading an unfinished bar. Live updates
also call this on forming-bar changes when enabled; is_forming_bar identifies them. Calls before
the start time warm the strategy’s state, but cannot place orders.
Provided Methods§
Sourcefn inputs(&self) -> Vec<(String, String)>
fn inputs(&self) -> Vec<(String, String)>
Named strategy inputs, copied to the report’s properties before the run.
Sourcefn study_inputs(&self) -> Vec<StudyInput>
fn study_inputs(&self) -> Vec<StudyInput>
Editable calculation inputs, including defaults and accepted bounds.
Sourcefn set_input(&mut self, id: &str, value: InputValue) -> Result<(), &'static str>
fn set_input(&mut self, id: &str, value: InputValue) -> Result<(), &'static str>
Changes a calculation input. Call prepare again before using cached calculations.
Implementations reject unknown ids, wrong types and values outside their schema.
Sourcefn prepare(&mut self, bars: &[Bar])
fn prepare(&mut self, bars: &[Bar])
Computes what the strategy needs from the whole run once, before the first bar, such as its studies. A value at a bar must depend only on that bar and earlier ones, as a study’s does, or the run looks ahead. Reset any decision state here so a corrected history can start a fresh run. Does nothing by default.
Sourcefn prepare_update(&mut self, bars: &[Bar])
fn prepare_update(&mut self, bars: &[Bar])
Refreshes calculations for appended bars or a changed forming bar, preserving decision
state from on_bar. The default calls prepare; override it if prepare resets that
state. Like prepare, calculations must use only the prefix through each bar.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".