Files
QuantDinger/backend_api_python/tests/test_backtest_limits.py
T

129 lines
3.8 KiB
Python

from datetime import datetime
import pytest
from app.services.backtest_limits import (
BacktestRangeLimitError,
backtest_range_policy_metadata,
validate_backtest_range,
)
from app.services.strategy_v2.service import StrategyV2BacktestService
def test_forex_intraday_range_error_includes_actionable_recommendation():
err = validate_backtest_range(
market="Forex",
symbol="EURUSD",
timeframe="15m",
start_date=datetime(2024, 1, 1),
end_date=datetime(2024, 4, 1, 23, 59, 59),
)
assert err is not None
assert err["error_type"] == "BACKTEST_RANGE_LIMIT"
assert err["max_days"] == 60
assert err["recommendation_available"] is True
assert err["recommended_start"] == "2024-02-02"
assert err["recommended_end"] == "2024-02-29"
assert "Suggested fix: use 2024-02-02 to 2024-04-01" in err["msg"]
assert "set end date to 2024-02-29" in err["msg"]
def test_recommendation_accounts_for_indicator_warmup_bars():
err = validate_backtest_range(
market="Forex",
symbol="EURUSD",
timeframe="15m",
start_date=datetime(2024, 1, 1),
end_date=datetime(2024, 4, 1, 23, 59, 59),
warmup_bars=96,
)
assert err is not None
assert err["warmup_bars"] == 96
assert err["warmup_days"] == 1
assert err["fetch_start"] == "2023-12-31"
assert err["recommended_start"] == "2024-02-03"
assert err["recommended_end"] == "2024-02-28"
assert "including 96 warmup bars" in err["msg"]
def test_range_equal_to_limit_is_allowed():
err = validate_backtest_range(
market="Forex",
symbol="EURUSD",
timeframe="15m",
start_date=datetime(2024, 1, 1),
end_date=datetime(2024, 3, 1, 0, 0, 0),
)
assert err is None
def test_warmup_larger_than_policy_has_no_fake_date_recommendation():
err = validate_backtest_range(
market="USStock",
symbol="TSLA",
timeframe="1m",
start_date=datetime(2024, 1, 10),
end_date=datetime(2024, 1, 10, 23, 59, 59),
warmup_bars=60 * 24 * 10,
)
assert err is not None
assert err["max_days"] == 7
assert err["warmup_days"] == 10
assert err["recommendation_available"] is False
assert err["recommended_start"] is None
assert err["recommended_end"] is None
assert "warmup alone exceeds" in err["msg"]
def test_policy_metadata_uses_strictest_market_and_normalizes_timeframe():
policy = backtest_range_policy_metadata(
markets=["Crypto", "USStock"],
timeframe="1h",
warmup_bars=24,
)
assert policy["timeframe"] == "1H"
assert policy["market"] == "USStock"
assert policy["maxDays"] == 700
assert policy["warmupDays"] == 2
assert policy["maxSelectedDays"] == 698
def test_service_rejects_one_year_of_one_minute_data_before_fetching():
code = '''
def initialize(context):
context.set_universe(["Crypto:BTC/USDT"])
context.subscribe(frequency="1m")
def handle_data(context, data):
pass
'''
def unexpected_fetch(*_args, **_kwargs):
raise AssertionError("market data must not be fetched for an oversized request")
service = StrategyV2BacktestService(
repository=object(),
universe_service=object(),
frame_fetcher=unexpected_fetch,
snapshot_store=object(),
)
with pytest.raises(BacktestRangeLimitError) as caught:
service.run(
user_id=1,
code=code,
start_date=datetime(2025, 7, 19),
end_date=datetime(2026, 7, 19, 23, 59, 59),
initial_capital=10_000,
persist=False,
)
assert caught.value.details["error_type"] == "BACKTEST_RANGE_LIMIT"
assert caught.value.details["timeframe"] == "1m"
assert caught.value.details["max_days"] == 30