perf: reduce Python callback overhead and verify matched benchmarks

Reuse the Python callback method-name string and expose constant-time position count and presence. Preserve dynamic callbacks, Bar identity, and snapshot behavior with regression tests.

Add isolated callback measurements and replace approximate cross-library comparisons with matched trades and equity assertions, separate setup/run timings, and reproducible reports. Track the remaining ingestion bottleneck in #53.

Refs #48, #38, #39, #53

Codex 🤖, On behalf of Khizar
This commit is contained in:
Khizar Imran
2026-10-31 22:45:13 +00:00
parent d9687e7943
commit 872c8a30c8
13 changed files with 1101 additions and 208 deletions
+10
View File
@@ -286,6 +286,16 @@ impl Broker {
self.positions()
}
#[getter]
fn position_count(&self) -> usize {
self.positions.len()
}
#[getter]
fn has_positions(&self) -> bool {
!self.positions.is_empty()
}
#[pyo3(name = "buy")]
fn py_buy(
&mut self,
+13 -1
View File
@@ -70,6 +70,12 @@ impl Strategy for SmaCross {
}
}
struct Noop;
impl Strategy for Noop {
fn next(&mut self, _bar: &Bar, _broker: &mut Broker) {}
}
impl Engine {
pub fn new(
data: Vec<Bar>,
@@ -128,6 +134,7 @@ impl Engine {
),
)?;
let next_name = pyo3::intern!(py, "next");
for bar in &self.data {
{
let mut b = broker_py.borrow_mut(py);
@@ -135,7 +142,7 @@ impl Engine {
}
strategy
.bind(py)
.call_method("next", (bar.clone(), broker_py.clone_ref(py)), None)?;
.call_method1(next_name, (bar.clone(), broker_py.clone_ref(py)))?;
let equity = broker_py.borrow(py).equity(bar.close);
self.equity_curve.push(equity);
}
@@ -164,6 +171,11 @@ impl Engine {
};
Ok(self.run(&mut strat))
}
// Benchmark baseline with the same broker, equity, statistics, and finalization paths.
fn _run_native_noop(&mut self) -> Stats {
self.run(&mut Noop)
}
}
#[cfg(test)]