From b8dc7344ff99eb23d5f003795f17cdba3b89c40b Mon Sep 17 00:00:00 2001 From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:05:45 +0900 Subject: test: add integration tests for strategy, order, portfolio, and backtest flows --- tests/integration/test_backtest_end_to_end.py | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tests/integration/test_backtest_end_to_end.py (limited to 'tests/integration/test_backtest_end_to_end.py') diff --git a/tests/integration/test_backtest_end_to_end.py b/tests/integration/test_backtest_end_to_end.py new file mode 100644 index 0000000..4bdb5f3 --- /dev/null +++ b/tests/integration/test_backtest_end_to_end.py @@ -0,0 +1,66 @@ +"""Integration test: full backtest with real strategy on generated candles.""" +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "services" / "strategy-engine" / "src")) +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "services" / "strategy-engine")) +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "services" / "backtester" / "src")) + +import pytest +from decimal import Decimal +from datetime import datetime, timedelta, timezone + +from shared.models import Candle +from backtester.engine import BacktestEngine + + +def _generate_candles(prices: list[float], symbol="BTCUSDT") -> list[Candle]: + return [ + Candle( + symbol=symbol, timeframe="1h", + open_time=datetime(2025, 1, 1, tzinfo=timezone.utc) + timedelta(hours=i), + open=Decimal(str(p)), high=Decimal(str(p + 100)), + low=Decimal(str(p - 100)), close=Decimal(str(p)), + volume=Decimal("100"), + ) + for i, p in enumerate(prices) + ] + + +def test_backtest_rsi_strategy_end_to_end(): + """Run RSI strategy through backtester and verify result structure.""" + from strategies.rsi_strategy import RsiStrategy + + strategy = RsiStrategy() + strategy.configure({"period": 5, "oversold": 30, "overbought": 70, "quantity": "0.1"}) + + # Generate price series: decline then rise + prices = [100 - i for i in range(15)] + [85 + i * 2 for i in range(15)] + candles = _generate_candles(prices) + + engine = BacktestEngine(strategy, Decimal("10000")) + result = engine.run(candles) + + assert result.strategy_name == "rsi" + assert result.symbol == "BTCUSDT" + assert result.initial_balance == Decimal("10000") + assert result.detailed is not None + assert result.detailed.total_trades >= 0 + + +def test_backtest_with_no_signals(): + """Strategy that generates no signals should return initial balance.""" + from strategies.rsi_strategy import RsiStrategy + + strategy = RsiStrategy() + strategy.configure({"period": 14, "oversold": 10, "overbought": 90, "quantity": "0.1"}) + + # Flat prices -- no RSI extremes + prices = [100.0] * 30 + candles = _generate_candles(prices) + + engine = BacktestEngine(strategy, Decimal("10000")) + result = engine.run(candles) + + assert result.total_trades == 0 + assert result.final_balance == Decimal("10000") -- cgit v1.2.3