feat(CORE-001B): migrate overview and hedge math to unit types
This commit is contained in:
@@ -193,8 +193,12 @@ def test_homepage_and_options_page_render() -> None:
|
||||
assert "$222,000" in hedge_text
|
||||
assert "80.0%" in hedge_text
|
||||
assert "$12,345" in hedge_text
|
||||
assert "Scenario spot" in hedge_text
|
||||
assert "$3,520.00" in hedge_text
|
||||
assert "Unhedged equity" in hedge_text
|
||||
assert "$552,400" in hedge_text
|
||||
assert "Hedged equity" in hedge_text
|
||||
assert "$551,025" in hedge_text
|
||||
page.screenshot(path=str(ARTIFACTS / "hedge.png"), full_page=True)
|
||||
|
||||
browser.close()
|
||||
|
||||
67
tests/test_portfolio_math.py
Normal file
67
tests/test_portfolio_math.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from app.domain.portfolio_math import (
|
||||
build_alert_context,
|
||||
portfolio_snapshot_from_config,
|
||||
strategy_metrics_from_snapshot,
|
||||
)
|
||||
from app.models.portfolio import PortfolioConfig
|
||||
from app.pages.common import strategy_catalog
|
||||
|
||||
|
||||
def test_portfolio_snapshot_from_config_preserves_weight_price_and_margin_values() -> None:
|
||||
config = PortfolioConfig(entry_price=4400.0, gold_ounces=220.0, entry_basis_mode="weight", loan_amount=145000.0)
|
||||
|
||||
snapshot = portfolio_snapshot_from_config(config)
|
||||
|
||||
assert snapshot["spot_price"] == 4400.0
|
||||
assert snapshot["gold_units"] == 220.0
|
||||
assert snapshot["gold_value"] == 968000.0
|
||||
assert snapshot["net_equity"] == 823000.0
|
||||
assert round(snapshot["margin_call_price"], 2) == 878.79
|
||||
|
||||
|
||||
def test_build_alert_context_uses_unit_safe_gold_value_calculation() -> None:
|
||||
config = PortfolioConfig(entry_price=4400.0, gold_ounces=220.0, entry_basis_mode="weight", loan_amount=145000.0)
|
||||
|
||||
context = build_alert_context(
|
||||
config,
|
||||
spot_price=4400.0,
|
||||
source="configured_entry_price",
|
||||
updated_at="",
|
||||
)
|
||||
|
||||
assert context["gold_units"] == 220.0
|
||||
assert context["gold_value"] == 968000.0
|
||||
assert context["net_equity"] == 823000.0
|
||||
assert round(float(context["margin_call_price"]), 2) == 878.79
|
||||
|
||||
|
||||
def test_strategy_metrics_from_snapshot_preserves_minus_20pct_protective_put_example() -> None:
|
||||
strategy = next(item for item in strategy_catalog() if item["name"] == "protective_put_atm")
|
||||
snapshot = {
|
||||
"gold_value": 215000.0,
|
||||
"loan_amount": 145000.0,
|
||||
"net_equity": 70000.0,
|
||||
"spot_price": 215.0,
|
||||
"gold_units": 1000.0,
|
||||
"margin_call_ltv": 0.75,
|
||||
"margin_call_price": 193.33,
|
||||
"cash_buffer": 18500.0,
|
||||
"hedge_budget": 8000.0,
|
||||
"ltv_ratio": 145000.0 / 215000.0,
|
||||
}
|
||||
|
||||
metrics = strategy_metrics_from_snapshot(strategy, -20, snapshot)
|
||||
|
||||
assert metrics["scenario_price"] == 172.0
|
||||
assert metrics["unhedged_equity"] == 27000.0
|
||||
assert metrics["hedged_equity"] == 58750.0
|
||||
assert metrics["waterfall_steps"] == [
|
||||
("Base equity", 70000.0),
|
||||
("Spot move", -43000.0),
|
||||
("Option payoff", 38000.0),
|
||||
("Call cap", 0.0),
|
||||
("Hedge cost", -6250.0),
|
||||
("Net equity", 58750.0),
|
||||
]
|
||||
Reference in New Issue
Block a user