From 73eaf704584e5bf3c4499ccdd574af87304e1e5f Mon Sep 17 00:00:00 2001 From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:22:12 +0900 Subject: feat(backtester): integrate detailed metrics and rich reporter - Add timestamp field to SimulatedTrade, pass candle.open_time from engine - Engine now builds TradeRecord list and computes DetailedMetrics - Reporter uses rich tables for summary and monthly returns display - Add export_csv() and export_json() functions - Update reporter tests for rich output and export functions --- services/backtester/tests/test_reporter.py | 74 ++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) (limited to 'services/backtester/tests/test_reporter.py') diff --git a/services/backtester/tests/test_reporter.py b/services/backtester/tests/test_reporter.py index f5c694c..aef3fc6 100644 --- a/services/backtester/tests/test_reporter.py +++ b/services/backtester/tests/test_reporter.py @@ -1,12 +1,35 @@ """Tests for the report formatter.""" +import json +from datetime import timedelta from decimal import Decimal from backtester.engine import BacktestResult -from backtester.reporter import format_report +from backtester.metrics import DetailedMetrics +from backtester.reporter import export_csv, export_json, format_report -def test_format_report_contains_key_metrics(): - result = BacktestResult( +def _make_result(with_detailed: bool = False) -> BacktestResult: + detailed = None + if with_detailed: + detailed = DetailedMetrics( + total_return=0.15, + total_trades=10, + winning_trades=6, + losing_trades=4, + win_rate=60.0, + profit_factor=2.5, + sharpe_ratio=1.5, + sortino_ratio=2.0, + calmar_ratio=3.0, + max_drawdown=0.05, + max_drawdown_duration=timedelta(hours=5), + monthly_returns={"2025-01": 500.0, "2025-02": 1000.0}, + avg_win=250.0, + avg_loss=125.0, + largest_win=600.0, + largest_loss=-300.0, + ) + return BacktestResult( strategy_name="sma_crossover", symbol="BTCUSDT", total_trades=10, @@ -15,7 +38,12 @@ def test_format_report_contains_key_metrics(): profit=Decimal("1500"), profit_pct=Decimal("15"), trades=[], + detailed=detailed, ) + + +def test_format_report_contains_key_metrics(): + result = _make_result(with_detailed=False) report = format_report(result) assert "sma_crossover" in report @@ -24,3 +52,43 @@ def test_format_report_contains_key_metrics(): assert "11500" in report assert "1500" in report assert "15" in report + + +def test_format_report_with_detailed_metrics(): + result = _make_result(with_detailed=True) + report = format_report(result) + + assert "Sharpe Ratio" in report + assert "Sortino Ratio" in report + assert "Max Drawdown" in report + assert "Profit Factor" in report + + +def test_format_report_monthly_returns(): + result = _make_result(with_detailed=True) + report = format_report(result) + + assert "Monthly Returns" in report + assert "2025-01" in report + assert "2025-02" in report + + +def test_export_csv(): + result = _make_result(with_detailed=True) + csv_output = export_csv(result) + + assert "Metric,Value" in csv_output + assert "sma_crossover" in csv_output + assert "Sharpe Ratio" in csv_output + + +def test_export_json(): + result = _make_result(with_detailed=True) + json_output = export_json(result) + + data = json.loads(json_output) + assert data["strategy_name"] == "sma_crossover" + assert data["symbol"] == "BTCUSDT" + assert "detailed" in data + assert data["detailed"]["sharpe_ratio"] == 1.5 + assert data["detailed"]["monthly_returns"]["2025-01"] == 500.0 -- cgit v1.2.3