#[non_exhaustive]pub struct StrategyReport {
pub name: String,
pub symbol: String,
pub timeframe: Timeframe,
pub initial_capital: f64,
pub currency: Option<String>,
pub risk_free_rate: f64,
pub properties: Vec<(String, String)>,
pub trades: Vec<StrategyTrade>,
pub equity: Vec<(DateTime<Utc>, f64)>,
}Expand description
The result of one strategy run, from any source: a backtest the host runs against the headless
engine, a forward test, or the host’s own analytics. Build it with StrategyReport::new and set
the remaining fields directly; StrategyReport::performance computes the metrics.
§Example
use chrono::{TimeZone, Utc};
use egui_charts::model::{StrategyExit, StrategyReport, OrderSide, StrategyTrade, Timeframe};
let hour = |h| Utc.with_ymd_and_hms(2024, 1, 2, h, 0, 0).unwrap();
let mut report = StrategyReport::new("SMA cross", "AAPL", Timeframe::Hour1, 10_000.0);
report.currency = Some("USD".into());
report.properties.push(("Fast length".into(), "10".into()));
// The host computes each trade's net profit: here (190 - 185) * 10 shares less 2 of fees.
let mut trade = StrategyTrade::new(OrderSide::Buy, 10.0, hour(1), 185.0);
trade.fees = 2.0;
trade.exit = Some(StrategyExit::new(hour(3), 190.0, 48.0));
report.trades.push(trade);
report.equity = vec![(hour(0), 10_000.0), (hour(1), 9_998.0), (hour(2), 10_030.0), (hour(3), 10_048.0)];
let performance = report.performance();
assert_eq!(performance.net_profit, 48.0);
assert_eq!(performance.win_rate, Some(1.0));
assert_eq!(performance.max_drawdown, Some(2.0));
// Three hours of equity are too short to annualise.
assert_eq!(performance.sharpe_ratio, None);
assert!(report.trades_csv().starts_with("number,side,quantity,"));Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.name: StringWhat the run is called, as the host names it.
symbol: StringThe instrument the trades are in.
timeframe: TimeframeThe bar interval the run used.
initial_capital: f64Account value at the start, in currency. Positive and finite, or
StrategyPerformance::net_profit_fraction is unavailable.
currency: Option<String>Currency of capital, profits, fees and equity, such as “USD”. Display only.
risk_free_rate: f64Annual risk-free rate as a fraction (0.02 for 2%), used by the Sharpe and Sortino ratios. Finite and above -1, or the ratios are unavailable.
properties: Vec<(String, String)>Settings of the run as the host wants them shown (parameters, commission, sizing), in order. Display only.
trades: Vec<StrategyTrade>Every trade, closed or open, in any order.
equity: Vec<(DateTime<Utc>, f64)>Account value marked to market at each bar close, oldest first, one point per bar, in strictly increasing time order.
Implementations§
Source§impl StrategyReport
impl StrategyReport
Sourcepub fn signals(&self) -> Vec<Signal>
pub fn signals(&self) -> Vec<Signal>
Labelled entry and exit markers for the host’s signals service. Invalid trades are skipped; open trades have only an entry. Directions describe the fill side, including short exits. Ids remain stable for this report’s original trade indices. When replacing a run, remove its old signals before publishing the replacement, including when it has no trades.
Sourcepub fn new(
name: impl Into<String>,
symbol: impl Into<String>,
timeframe: Timeframe,
initial_capital: f64,
) -> Self
pub fn new( name: impl Into<String>, symbol: impl Into<String>, timeframe: Timeframe, initial_capital: f64, ) -> Self
A report with no trades, no equity, no properties, no currency and a risk-free rate of 0.
Sourcepub fn performance(&self) -> StrategyPerformance
pub fn performance(&self) -> StrategyPerformance
Computes the metrics of the run. Sorts closed trades for streaks; call once per report, not once per frame.
Sourcepub fn equity_curve(&self) -> Vec<(DateTime<Utc>, f64)>
pub fn equity_curve(&self) -> Vec<(DateTime<Utc>, f64)>
Finite equity points in strictly increasing time order, using the same validation as
Self::performance. Empty if the finite points are out of order.
Sourcepub fn comparison(&self, bars: &[Bar]) -> StrategyComparison
pub fn comparison(&self, bars: &[Bar]) -> StrategyComparison
Computes buy-and-hold and excursions from the complete source bars of this run’s symbol and interval, oldest first. The host supplies exactly the run’s bars, including every held bar; this method neither fetches data nor infers missing sessions. Bar times denote opens.
Non-finite or inverted OHLC bars are skipped and counted. Unordered or duplicate timestamps make the whole source unusable. Volume is unused. Buy-and-hold uses the first valid open and last valid close, with fractional units, no fees or reinvested dividends. A non-finite calculation is unavailable. Excursions require at least one held source bar; invalid held bars make that trade’s excursion unavailable rather than understating risk.
Sourcepub fn trades_csv(&self) -> String
pub fn trades_csv(&self) -> String
The valid trades as CSV, sorted by entry time (trades entered at the same time keep their
order), one header line and one line per trade, each ending with \n.
Columns: number (from 1, in this order), side (long or short), quantity,
entry_time, entry_price, exit_time, exit_price, profit, fees, label. Times are
RFC 3339 in UTC (2024-01-02T00:00:00Z), numbers use the shortest form that reads back to the
same value, and an open trade leaves the three exit columns empty.
Text cells starting with =, +, -, @, tab or carriage return gain a leading apostrophe
so spreadsheets treat them as text. Numeric cells, including negative numbers, are unchanged.
Sourcepub fn summary_csv(
&self,
performance: &StrategyPerformance,
comparison: &StrategyComparison,
) -> String
pub fn summary_csv( &self, performance: &StrategyPerformance, comparison: &StrategyComparison, ) -> String
The summary metrics and the properties of the run as CSV, one header line and one line per
metric or property, each ending with \n. performance and comparison are this report’s
Self::performance and Self::comparison, the figures the report panel shows.
Columns: section (summary or properties), name (as the panel labels it), value,
unit and currency. The unit is money (in currency, empty when the report has none),
percent (100 is 100%), ratio, count or text. Percent values round to 15 significant
decimal digits to suppress binary multiplication noise; if rounding would overflow f64,
the unrounded finite value is kept. Numbers use the shortest form that reads back to the
resulting value, with a dot as the decimal separator and no thousands separator. Every
numeric zero is 0, and an unavailable value is an empty cell, so numeric columns stay
numeric in a spreadsheet.
Text cells starting with =, +, -, @, tab or carriage return gain a leading apostrophe
so spreadsheets treat them as text. This also applies to property names and currencies;
numeric cells, including negative numbers, are unchanged by this protection.
Trait Implementations§
Source§impl Clone for StrategyReport
impl Clone for StrategyReport
Source§fn clone(&self) -> StrategyReport
fn clone(&self) -> StrategyReport
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for StrategyReport
impl Debug for StrategyReport
Source§impl<'de> Deserialize<'de> for StrategyReport
impl<'de> Deserialize<'de> for StrategyReport
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for StrategyReport
impl PartialEq for StrategyReport
Source§impl Serialize for StrategyReport
impl Serialize for StrategyReport
impl StructuralPartialEq for StrategyReport
Auto Trait Implementations§
impl Freeze for StrategyReport
impl RefUnwindSafe for StrategyReport
impl Send for StrategyReport
impl Sync for StrategyReport
impl Unpin for StrategyReport
impl UnsafeUnpin for StrategyReport
impl UnwindSafe for StrategyReport
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more