Files
vault-dash/tests/test_event_comparison_ui.py
2026-03-26 22:05:31 +01:00

260 lines
9.5 KiB
Python

from __future__ import annotations
from datetime import date
from decimal import Decimal
import pytest
from app.services.event_comparison_ui import EventComparisonFixtureHistoricalPriceSource, EventComparisonPageService
def test_event_comparison_page_service_accepts_string_and_decimal_boundary_values() -> None:
service = EventComparisonPageService()
preview = service.preview_scenario(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m",),
underlying_units="1000.0",
loan_amount=Decimal("68000.0"),
margin_call_ltv="0.75",
)
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m", "protective-put-95pct-12m"),
underlying_units="1000.0",
loan_amount=Decimal("68000.0"),
margin_call_ltv="0.75",
)
assert preview.initial_portfolio.underlying_units == 1000.0
assert preview.initial_portfolio.loan_amount == 68000.0
assert preview.initial_portfolio.margin_call_ltv == 0.75
assert report.scenario.initial_portfolio.underlying_units == 1000.0
assert report.scenario.initial_portfolio.loan_amount == 68000.0
assert report.scenario.initial_portfolio.margin_call_ltv == 0.75
def test_event_comparison_page_service_runs_seeded_gld_preset_deterministically() -> None:
service = EventComparisonPageService()
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m", "protective-put-95pct-12m"),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
assert report.event_preset.slug == "gld-jan-2024-selloff"
assert report.scenario.start_date.isoformat() == "2024-01-02"
assert report.scenario.end_date.isoformat() == "2024-01-08"
assert [item.template_slug for item in report.rankings] == [
"protective-put-atm-12m",
"protective-put-95pct-12m",
]
assert report.rankings[0].rank == 1
assert (
report.rankings[0].result.daily_path[-1].net_portfolio_value
> report.rankings[-1].result.daily_path[-1].net_portfolio_value
)
def test_event_comparison_page_service_rejects_empty_template_selection() -> None:
service = EventComparisonPageService()
with pytest.raises(ValueError, match="Select at least one strategy template"):
service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=(),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
with pytest.raises(ValueError, match="Select at least one strategy template"):
service.preview_scenario(
preset_slug="gld-jan-2024-selloff",
template_slugs=(),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
def test_event_comparison_page_service_exposes_seeded_preset_options() -> None:
service = EventComparisonPageService()
options = service.preset_options("GLD")
assert options[0]["slug"] == "gld-jan-2024-selloff"
assert options[0]["label"] == "GLD January 2024 Selloff"
assert tuple(options[0]["default_template_slugs"]) == (
"protective-put-atm-12m",
"protective-put-95pct-12m",
"protective-put-90pct-12m",
"ladder-50-50-atm-95pct-12m",
)
def test_event_comparison_page_service_keeps_fixture_window_while_using_caller_portfolio_inputs() -> None:
service = EventComparisonPageService()
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m",),
underlying_units=9680.0,
loan_amount=222000.0,
margin_call_ltv=0.80,
)
assert report.scenario.start_date.isoformat() == "2024-01-02"
assert report.scenario.end_date.isoformat() == "2024-01-08"
assert report.scenario.initial_portfolio.entry_spot == 100.0
assert report.scenario.initial_portfolio.underlying_units == 9680.0
assert report.scenario.initial_portfolio.loan_amount == 222000.0
assert report.scenario.initial_portfolio.margin_call_ltv == 0.80
def test_event_comparison_page_service_resets_template_selection_to_preset_defaults() -> None:
service = EventComparisonPageService()
assert service.default_template_selection("gld-jan-2024-selloff") == (
"protective-put-atm-12m",
"protective-put-95pct-12m",
"protective-put-90pct-12m",
"ladder-50-50-atm-95pct-12m",
)
assert service.default_template_selection("gld-jan-2024-drawdown") == (
"protective-put-atm-12m",
"ladder-50-50-atm-95pct-12m",
"ladder-33-33-33-atm-95pct-90pct-12m",
)
def test_event_comparison_page_service_preview_uses_same_materialization_path() -> None:
service = EventComparisonPageService()
scenario = service.preview_scenario(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m",),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
assert scenario.start_date.isoformat() == "2024-01-02"
assert scenario.end_date.isoformat() == "2024-01-08"
assert scenario.initial_portfolio.entry_spot == 100.0
assert [ref.slug for ref in scenario.template_refs] == ["protective-put-atm-12m"]
def test_event_comparison_page_service_rejects_undercollateralized_historical_start() -> None:
service = EventComparisonPageService()
with pytest.raises(ValueError, match="Historical scenario starts undercollateralized"):
service.preview_scenario(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m",),
underlying_units=1000.0,
loan_amount=145000.0,
margin_call_ltv=0.75,
)
with pytest.raises(ValueError, match="Historical scenario starts undercollateralized"):
service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m",),
underlying_units=1000.0,
loan_amount=145000.0,
margin_call_ltv=0.75,
)
def test_event_comparison_fixture_fails_closed_for_unsupported_range() -> None:
source = EventComparisonFixtureHistoricalPriceSource()
with pytest.raises(ValueError, match="seeded 2024-01-02 through 2024-01-08"):
source.load_daily_closes("GLD", date(2024, 1, 1), date(2024, 1, 8))
def test_event_comparison_page_service_builds_chart_model_with_unhedged_reference() -> None:
service = EventComparisonPageService()
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m", "protective-put-95pct-12m"),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
chart_model = service.chart_model(report)
assert chart_model.dates == (
"2024-01-02",
"2024-01-03",
"2024-01-04",
"2024-01-05",
"2024-01-08",
)
assert chart_model.series[0].name == "Unhedged collateral baseline"
assert chart_model.series[1].name == "Protective Put ATM"
assert len(chart_model.series[0].values) == len(chart_model.dates)
def test_event_comparison_page_service_builds_drilldown_for_selected_ranking() -> None:
service = EventComparisonPageService()
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m", "protective-put-95pct-12m"),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
drilldown = service.drilldown_model(report, template_slug="protective-put-95pct-12m")
assert drilldown.rank == 2
assert drilldown.template_name == "Protective Put 95%"
assert drilldown.margin_call_days_hedged == report.rankings[1].margin_call_days_hedged
assert drilldown.hedge_cost == report.rankings[1].hedge_cost
assert drilldown.final_equity == report.rankings[1].final_equity
assert (
drilldown.total_option_payoff_realized == report.rankings[1].result.summary_metrics.total_option_payoff_realized
)
assert drilldown.worst_ltv_date == "2024-01-08"
assert drilldown.rows[0].date == "2024-01-02"
assert drilldown.rows[-1].date == "2024-01-08"
def test_event_comparison_page_service_defaults_drilldown_to_top_ranked_strategy() -> None:
service = EventComparisonPageService()
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m", "protective-put-95pct-12m"),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
drilldown = service.drilldown_model(report)
assert drilldown.rank == 1
assert drilldown.template_slug == report.rankings[0].template_slug
assert drilldown.template_name == report.rankings[0].template_name
def test_event_comparison_page_service_rejects_unknown_drilldown_template_slug() -> None:
service = EventComparisonPageService()
report = service.run_read_only_comparison(
preset_slug="gld-jan-2024-selloff",
template_slugs=("protective-put-atm-12m",),
underlying_units=1000.0,
loan_amount=68000.0,
margin_call_ltv=0.75,
)
with pytest.raises(ValueError, match="Unknown ranked template"):
service.drilldown_model(report, template_slug="missing-template")