bench: add three-way speed benchmark (backtesting.py vs py-next vs native rust)

Adds a native-Rust SMA strategy path (Engine.run_native_sma) so we can time
the pure-Rust engine against the Python-callback path and backtesting.py.
This commit is contained in:
KhizarImran
2026-07-18 00:08:49 +01:00
parent c31e0088db
commit 494f157c13
2 changed files with 186 additions and 0 deletions
+40
View File
@@ -30,6 +30,35 @@ impl Engine {
}
}
// ponytail: benchmark-only native strategy, mirrors examples/compare_bt.py SmaCrossFx.
// Exists so we can time the pure-Rust engine path (no per-bar Python call) against run_py.
struct SmaCross {
fast: usize,
slow: usize,
lot_size: f64,
closes: Vec<f64>,
}
impl Strategy for SmaCross {
fn next(&mut self, bar: &Bar, broker: &mut Broker) {
self.closes.push(bar.close);
if self.closes.len() <= self.slow {
return;
}
let n = self.closes.len();
let fast_sma: f64 = self.closes[n - self.fast..].iter().sum::<f64>() / self.fast as f64;
let slow_sma: f64 = self.closes[n - self.slow..].iter().sum::<f64>() / self.slow as f64;
if broker.positions.is_empty() {
if fast_sma > slow_sma {
broker.buy(bar.close, self.lot_size, bar.timestamp, None, None);
}
} else if fast_sma < slow_sma {
broker.close_all(bar.close, bar.timestamp);
}
}
}
#[pymethods]
impl Engine {
#[new]
@@ -95,6 +124,17 @@ impl Engine {
let b = broker_py.borrow(py);
Ok(Stats::compute(&b, &self.equity_curve))
}
// ponytail: benchmark hook, runs the SMA strategy entirely in Rust via the native run() path.
pub fn run_native_sma(&mut self, fast: usize, slow: usize, lot_size: f64) -> Stats {
let mut strat = SmaCross {
fast,
slow,
lot_size,
closes: Vec::new(),
};
self.run(&mut strat)
}
}
#[cfg(test)]