summaryrefslogtreecommitdiff
path: root/services/backtester/src
diff options
context:
space:
mode:
Diffstat (limited to 'services/backtester/src')
-rw-r--r--services/backtester/src/backtester/metrics.py2
-rw-r--r--services/backtester/src/backtester/simulator.py8
-rw-r--r--services/backtester/src/backtester/walk_forward.py17
3 files changed, 14 insertions, 13 deletions
diff --git a/services/backtester/src/backtester/metrics.py b/services/backtester/src/backtester/metrics.py
index 5b43afd..239cb6f 100644
--- a/services/backtester/src/backtester/metrics.py
+++ b/services/backtester/src/backtester/metrics.py
@@ -207,7 +207,7 @@ def compute_detailed_metrics(
# Sortino (downside deviation of excess returns)
downside = [min(r - daily_rf, 0.0) for r in daily_returns]
- downside_var = sum(d ** 2 for d in downside) / len(downside)
+ downside_var = sum(d**2 for d in downside) / len(downside)
downside_std = math.sqrt(downside_var)
sortino = (mean_excess / downside_std * math.sqrt(365)) if downside_std > 0 else 0.0
else:
diff --git a/services/backtester/src/backtester/simulator.py b/services/backtester/src/backtester/simulator.py
index 1e37740..64c88dd 100644
--- a/services/backtester/src/backtester/simulator.py
+++ b/services/backtester/src/backtester/simulator.py
@@ -89,9 +89,7 @@ class OrderSimulator:
if triggered and exit_price is not None:
# Close the position
- close_side = (
- OrderSide.SELL if pos.side == OrderSide.BUY else OrderSide.BUY
- )
+ close_side = OrderSide.SELL if pos.side == OrderSide.BUY else OrderSide.BUY
fee = self._calculate_fee(exit_price, pos.quantity)
if pos.side == OrderSide.BUY:
@@ -198,9 +196,7 @@ class OrderSimulator:
)
return True
- def _close_open_position(
- self, symbol: str, side: OrderSide, quantity: Decimal
- ) -> None:
+ def _close_open_position(self, symbol: str, side: OrderSide, quantity: Decimal) -> None:
"""Remove closed quantity from open positions (FIFO)."""
remaining_qty = quantity
new_positions: list[OpenPosition] = []
diff --git a/services/backtester/src/backtester/walk_forward.py b/services/backtester/src/backtester/walk_forward.py
index fe6d020..c7b7fd8 100644
--- a/services/backtester/src/backtester/walk_forward.py
+++ b/services/backtester/src/backtester/walk_forward.py
@@ -1,4 +1,5 @@
"""Walk-forward analysis for strategy parameter optimization."""
+
from dataclasses import dataclass, field
from decimal import Decimal
from typing import Callable
@@ -10,6 +11,7 @@ from backtester.engine import BacktestEngine, BacktestResult, StrategyProtocol
@dataclass
class WalkForwardWindow:
"""Result for a single in-sample/out-of-sample window."""
+
window_index: int
in_sample_result: BacktestResult
out_of_sample_result: BacktestResult
@@ -19,6 +21,7 @@ class WalkForwardWindow:
@dataclass
class WalkForwardResult:
"""Aggregated walk-forward analysis results."""
+
strategy_name: str
symbol: str
num_windows: int
@@ -130,12 +133,14 @@ class WalkForwardEngine:
engine = BacktestEngine(strategy, self._initial_balance)
oos_result = engine.run(out_of_sample)
- windows.append(WalkForwardWindow(
- window_index=i,
- in_sample_result=best_is_result,
- out_of_sample_result=oos_result,
- best_params=best_params,
- ))
+ windows.append(
+ WalkForwardWindow(
+ window_index=i,
+ in_sample_result=best_is_result,
+ out_of_sample_result=oos_result,
+ best_params=best_params,
+ )
+ )
return WalkForwardResult(
strategy_name=strategy_name,