refactor(BT-001C): share historical fixture provider
This commit is contained in:
@@ -282,3 +282,39 @@ def test_backtest_page_service_uses_injected_provider_identity_in_provider_ref()
|
||||
|
||||
assert result.scenario.provider_ref.provider_id == "custom_v1"
|
||||
assert result.scenario.provider_ref.pricing_mode == "custom_mode"
|
||||
|
||||
|
||||
def test_backtest_page_service_preserves_injected_provider_behavior_beyond_history_loading() -> None:
|
||||
class CustomProvider(SyntheticHistoricalProvider):
|
||||
provider_id = "custom_v2"
|
||||
pricing_mode = "custom_mode"
|
||||
|
||||
def price_option_by_type(self, **kwargs: object):
|
||||
quote = super().price_option_by_type(**kwargs)
|
||||
return quote.__class__(
|
||||
position_id=quote.position_id,
|
||||
leg_id=quote.leg_id,
|
||||
spot=quote.spot,
|
||||
strike=quote.strike,
|
||||
expiry=quote.expiry,
|
||||
quantity=quote.quantity,
|
||||
mark=42.0,
|
||||
)
|
||||
|
||||
provider = CustomProvider(source=StaticBacktestSource(), implied_volatility=0.2, risk_free_rate=0.01)
|
||||
injected_service = BacktestService(provider=provider)
|
||||
page_service = BacktestPageService(backtest_service=injected_service)
|
||||
|
||||
result = page_service.run_read_only_scenario(
|
||||
symbol="GLD",
|
||||
start_date=date(2024, 1, 2),
|
||||
end_date=date(2024, 1, 8),
|
||||
template_slug="protective-put-atm-12m",
|
||||
underlying_units=1000.0,
|
||||
loan_amount=68000.0,
|
||||
margin_call_ltv=0.75,
|
||||
)
|
||||
|
||||
template_result = result.run_result.template_results[0]
|
||||
assert template_result.daily_path[0].option_market_value == 42000.0
|
||||
assert template_result.summary_metrics.total_hedge_cost == 42000.0
|
||||
|
||||
74
tests/test_backtesting_fixture_source.py
Normal file
74
tests/test_backtesting_fixture_source.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
|
||||
from app.services.backtesting.fixture_source import (
|
||||
SEEDED_GLD_2024_FIXTURE_HISTORY,
|
||||
SharedHistoricalFixtureSource,
|
||||
WindowPolicy,
|
||||
)
|
||||
from app.services.backtesting.ui_service import BacktestPageService
|
||||
from app.services.event_comparison_ui import EventComparisonPageService
|
||||
|
||||
|
||||
def test_shared_fixture_source_exact_window_requires_seeded_bounds() -> None:
|
||||
source = SharedHistoricalFixtureSource(
|
||||
feature_label="BT-001A",
|
||||
supported_symbol="GLD",
|
||||
history=SEEDED_GLD_2024_FIXTURE_HISTORY,
|
||||
window_policy=WindowPolicy.EXACT,
|
||||
)
|
||||
|
||||
rows = source.load_daily_closes("GLD", date(2024, 1, 2), date(2024, 1, 8))
|
||||
|
||||
assert [row.date.isoformat() for row in rows] == [
|
||||
"2024-01-02",
|
||||
"2024-01-03",
|
||||
"2024-01-04",
|
||||
"2024-01-05",
|
||||
"2024-01-08",
|
||||
]
|
||||
|
||||
with pytest.raises(ValueError, match="seeded 2024-01-02 through 2024-01-08 window"):
|
||||
source.load_daily_closes("GLD", date(2024, 1, 3), date(2024, 1, 8))
|
||||
|
||||
|
||||
def test_shared_fixture_source_bounded_window_allows_subranges_but_fails_closed_outside_seeded_bounds() -> None:
|
||||
source = SharedHistoricalFixtureSource(
|
||||
feature_label="BT-003A",
|
||||
supported_symbol="GLD",
|
||||
history=SEEDED_GLD_2024_FIXTURE_HISTORY,
|
||||
window_policy=WindowPolicy.BOUNDED,
|
||||
)
|
||||
|
||||
rows = source.load_daily_closes("GLD", date(2024, 1, 3), date(2024, 1, 5))
|
||||
|
||||
assert [row.date.isoformat() for row in rows] == ["2024-01-03", "2024-01-04", "2024-01-05"]
|
||||
|
||||
with pytest.raises(ValueError, match="seeded 2024-01-02 through 2024-01-08 window"):
|
||||
source.load_daily_closes("GLD", date(2024, 1, 1), date(2024, 1, 8))
|
||||
|
||||
with pytest.raises(ValueError, match="start_date must be on or before end_date"):
|
||||
source.load_daily_closes("GLD", date(2024, 1, 5), date(2024, 1, 3))
|
||||
|
||||
|
||||
def test_backtest_page_service_uses_shared_exact_fixture_source() -> None:
|
||||
service = BacktestPageService()
|
||||
|
||||
source = service.backtest_service.provider.source
|
||||
|
||||
assert isinstance(source, SharedHistoricalFixtureSource)
|
||||
assert source.feature_label == "BT-001A"
|
||||
assert source.window_policy is WindowPolicy.EXACT
|
||||
|
||||
|
||||
def test_event_comparison_page_service_uses_shared_bounded_fixture_source() -> None:
|
||||
service = EventComparisonPageService()
|
||||
|
||||
source = service.comparison_service.provider.source
|
||||
|
||||
assert isinstance(source, SharedHistoricalFixtureSource)
|
||||
assert source.feature_label == "BT-003A"
|
||||
assert source.window_policy is WindowPolicy.BOUNDED
|
||||
Reference in New Issue
Block a user