mirror of
https://github.com/KhizarImran/backtestingfx.git
synced 2026-08-17 05:58:05 +00:00
bug: backtest.py bug fixes
This commit is contained in:
+27
-14
@@ -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))
|
||||||
|
|||||||
+18
-13
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -72,4 +77,4 @@ impl Engine {
|
|||||||
let b = broker_py.borrow(py);
|
let b = broker_py.borrow(py);
|
||||||
Ok(Stats::compute(&b, &self.equity_curve))
|
Ok(Stats::compute(&b, &self.equity_curve))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user