bug: backtest.py bug fixes

This commit is contained in:
KhizarImran
2026-06-20 17:43:19 +01:00
parent 6e0b63cb3e
commit 5609249180
2 changed files with 45 additions and 27 deletions
+27 -14
View File
@@ -1,8 +1,15 @@
import backtestingfx as _rust from typing import Any
import backtestingfx as _rust # type: ignore
import pandas as pd import pandas as pd
class Strategy: class Strategy:
def __init__(self):
self._bars: Any = None
self._bar: Any = None
self._broker: Any = None
def init(self): def init(self):
pass pass
@@ -10,10 +17,14 @@ class Strategy:
pass pass
def buy(self, lot_size, stop_loss=None, take_profit=None): def buy(self, lot_size, stop_loss=None, take_profit=None):
self._broker.buy(self._bar.close, lot_size, self._bar.timestamp, stop_loss, take_profit) self._broker.buy(
self._bar.close, lot_size, self._bar.timestamp, stop_loss, take_profit
)
def sell(self, lot_size, stop_loss=None, take_profit=None): def sell(self, lot_size, stop_loss=None, take_profit=None):
self._broker.sell(self._bar.close, lot_size, self._bar.timestamp, stop_loss, take_profit) self._broker.sell(
self._bar.close, lot_size, self._bar.timestamp, stop_loss, take_profit
)
def close_all(self): def close_all(self):
self._broker.close_all(self._bar.close, self._bar.timestamp) self._broker.close_all(self._bar.close, self._bar.timestamp)
@@ -27,7 +38,7 @@ class _Adapter:
self._strategy = strategy self._strategy = strategy
def init(self, bars): def init(self, bars):
self._strategy.bars = bars self._strategy._bars = bars
self._strategy.init() self._strategy.init()
def next(self, bar, broker): def next(self, bar, broker):
@@ -50,20 +61,22 @@ class Backtest:
if isinstance(idx, pd.Timestamp): if isinstance(idx, pd.Timestamp):
ts = int(idx.timestamp()) ts = int(idx.timestamp())
else: else:
ts = int(pd.Timestamp(row["timestamp"]).timestamp()) ts = int(pd.Timestamp(row["timestamp"]).timestamp()) # type: ignore
bars.append(_rust.Bar( bars.append(
timestamp=ts, _rust.Bar( # type: ignore
open=float(row["open"]), timestamp=ts,
high=float(row["high"]), open=float(row["open"]),
low=float(row["low"]), high=float(row["high"]),
close=float(row["close"]), low=float(row["low"]),
volume=float(row.get("volume", 0.0)) close=float(row["close"]),
)) volume=float(row.get("volume", 0.0)),
)
)
return bars return bars
def run(self): def run(self):
bars = self._to_bars() bars = self._to_bars()
engine = _rust.Engine(bars, self._cash, self._commission, self._spread) engine = _rust.Engine(bars, self._cash, self._commission, self._spread) # type: ignore
strategy = self._strategy_class() strategy = self._strategy_class()
return engine.run(_Adapter(strategy)) return engine.run(_Adapter(strategy))
+17 -12
View File
@@ -1,18 +1,18 @@
use pyo3::prelude::*;
use crate::types::Bar;
use crate::broker::Broker; use crate::broker::Broker;
use crate::strategy::Strategy;
use crate::stats::Stats; use crate::stats::Stats;
use crate::strategy::Strategy;
use crate::types::Bar;
use pyo3::prelude::*;
#[pyclass] #[pyclass]
pub struct Engine { pub struct Engine {
pub data: Vec<Bar>, pub data: Vec<Bar>,
pub broker: Broker, pub broker: Broker,
pub equity_curve: Vec<f64> pub equity_curve: Vec<f64>,
} }
impl Engine { impl Engine {
pub fn run (&mut self, strategy: &mut dyn Strategy) -> Stats { pub fn run(&mut self, strategy: &mut dyn Strategy) -> Stats {
strategy.init(&self.data); strategy.init(&self.data);
for bar in &self.data { for bar in &self.data {
self.broker.check_sl_tp(bar); self.broker.check_sl_tp(bar);
@@ -33,7 +33,7 @@ impl Engine {
Engine { Engine {
data, data,
broker: Broker::new(initial_cash, commission, spread), broker: Broker::new(initial_cash, commission, spread),
equity_curve: Vec::new() equity_curve: Vec::new(),
} }
} }
@@ -48,18 +48,23 @@ impl Engine {
} }
} }
let broker_py = Py::new(py, Broker::new( let broker_py = Py::new(
self.broker.initial_cash, py,
self.broker.commission, Broker::new(
self.broker.spread, self.broker.initial_cash,
))?; self.broker.commission,
self.broker.spread,
),
)?;
for bar in &self.data { for bar in &self.data {
{ {
let mut b = broker_py.borrow_mut(py); let mut b = broker_py.borrow_mut(py);
b.check_sl_tp(bar); b.check_sl_tp(bar);
} }
strategy.bind(py).call_method("next", (bar.clone(), broker_py.clone_ref(py)), None)?; strategy
.bind(py)
.call_method("next", (bar.clone(), broker_py.clone_ref(py)), None)?;
let equity = broker_py.borrow(py).equity(bar.close); let equity = broker_py.borrow(py).equity(bar.close);
self.equity_curve.push(equity); self.equity_curve.push(equity);
} }