wickra_backtest_core/
lib.rs1#![cfg_attr(docsrs, feature(doc_cfg))]
24#![forbid(unsafe_code)]
25
26pub mod data;
27pub mod engine;
28pub mod error;
29pub mod metrics;
30pub mod portfolio;
31pub mod registry;
32pub mod report;
33pub mod request;
34pub mod rules;
35pub mod spec;
36
37pub use data::{
38 Candle, CrossSection, CrossSectionMember, DerivativesTick, Level, OrderBook, TradePrint,
39 TradeSide,
40};
41pub use engine::{
42 run, run_stream, run_with_capital, run_with_cross_section, run_with_deriv, run_with_orderbook,
43 run_with_ref, run_with_trades, Feeds, StreamingBacktest, DEFAULT_CAPITAL,
44};
45pub use error::{BacktestError, Result};
46pub use metrics::Metrics;
47pub use portfolio::Trade;
48pub use registry::EvalIndicator;
49pub use report::{BacktestReport, EquityPoint, REPORT_SCHEMA_VERSION};
50pub use request::{run_json, RunRequest, StepFeeds, StepRequest};
51pub use spec::{
52 Condition, Costs, Execution, Feed, FillTiming, IndicatorSpec, IntPredicate, Operand,
53 OperandExpr, OrderType, PriceField, Risk, Sizing, Slippage, StrategySpec, SPEC_VERSION,
54};
55
56#[must_use]
58pub fn version() -> &'static str {
59 env!("CARGO_PKG_VERSION")
60}
61
62#[must_use]
66pub fn strategy_spec_schema() -> String {
67 let schema = schemars::schema_for!(StrategySpec);
68 serde_json::to_string_pretty(&schema).unwrap_or_default()
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn version_is_reported() {
77 assert!(!version().is_empty());
78 }
79
80 #[test]
81 fn strategy_spec_schema_is_committed() {
82 let schema = strategy_spec_schema();
85 assert!(schema.contains("StrategySpec"));
86 let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
87 .join("../../schema/strategy_spec.schema.json");
88 if std::env::var("WICKRA_BLESS").is_ok() {
89 std::fs::create_dir_all(path.parent().unwrap()).unwrap();
90 std::fs::write(&path, format!("{schema}\n")).unwrap();
91 return;
92 }
93 let committed =
94 std::fs::read_to_string(&path).expect("schema file missing (run WICKRA_BLESS=1)");
95 assert_eq!(schema, committed.trim_end(), "schema drift");
96 }
97
98 #[test]
99 fn errors_render() {
100 let e = BacktestError::UnknownIndicator("Foo".into());
101 assert!(e.to_string().contains("Foo"));
102 }
103}