feat(CORE-002B): roll out hedge quote unit conversion
This commit is contained in:
@@ -7,6 +7,7 @@ from app.domain.instruments import price_per_weight_from_asset_price
|
||||
from app.domain.portfolio_math import (
|
||||
build_alert_context,
|
||||
portfolio_snapshot_from_config,
|
||||
resolve_portfolio_spot_from_quote,
|
||||
strategy_metrics_from_snapshot,
|
||||
)
|
||||
from app.domain.units import BaseCurrency, WeightUnit
|
||||
@@ -89,3 +90,61 @@ def test_strategy_metrics_from_snapshot_preserves_minus_20pct_protective_put_exa
|
||||
("Hedge cost", -6250.0),
|
||||
("Net equity", 58750.0),
|
||||
]
|
||||
|
||||
|
||||
def test_resolve_portfolio_spot_from_quote_converts_gld_share_to_ozt() -> None:
|
||||
"""Hedge/runtime quote resolution should convert GLD share quotes to USD/ozt."""
|
||||
from app.models.portfolio import PortfolioConfig
|
||||
|
||||
config = PortfolioConfig(entry_price=4400.0, gold_ounces=220.0, entry_basis_mode="weight", loan_amount=145000.0)
|
||||
share_quote = {
|
||||
"symbol": "GLD",
|
||||
"price": 404.19,
|
||||
"quote_unit": "share",
|
||||
"source": "yfinance",
|
||||
"updated_at": "2026-03-25T00:00:00+00:00",
|
||||
}
|
||||
|
||||
spot, source, updated_at = resolve_portfolio_spot_from_quote(config, share_quote)
|
||||
|
||||
assert spot == 4041.9 # 404.19 / 0.1 = 4041.9 USD/ozt
|
||||
assert source == "yfinance"
|
||||
assert updated_at == "2026-03-25T00:00:00+00:00"
|
||||
|
||||
|
||||
def test_resolve_portfolio_spot_from_quote_fails_closed_to_configured_price() -> None:
|
||||
"""Missing quote_unit should fail closed to configured entry price."""
|
||||
from app.models.portfolio import PortfolioConfig
|
||||
|
||||
config = PortfolioConfig(entry_price=4400.0, gold_ounces=220.0, entry_basis_mode="weight", loan_amount=145000.0)
|
||||
legacy_quote = {
|
||||
"symbol": "GLD",
|
||||
"price": 404.19,
|
||||
"source": "cache",
|
||||
"updated_at": "",
|
||||
}
|
||||
|
||||
spot, source, updated_at = resolve_portfolio_spot_from_quote(config, legacy_quote)
|
||||
|
||||
assert spot == 4400.0 # Falls back to configured price
|
||||
assert source == "configured_entry_price"
|
||||
assert updated_at == ""
|
||||
|
||||
|
||||
def test_resolve_portfolio_spot_from_quote_fails_closed_for_unsupported_symbol() -> None:
|
||||
"""Unsupported symbols without instrument metadata should fail closed."""
|
||||
from app.models.portfolio import PortfolioConfig
|
||||
|
||||
config = PortfolioConfig(entry_price=4400.0, gold_ounces=220.0, entry_basis_mode="weight", loan_amount=145000.0)
|
||||
btc_quote = {
|
||||
"symbol": "BTC-USD",
|
||||
"price": 70000.0,
|
||||
"quote_unit": "coin",
|
||||
"source": "yfinance",
|
||||
"updated_at": "2026-03-25T00:00:00+00:00",
|
||||
}
|
||||
|
||||
spot, source, updated_at = resolve_portfolio_spot_from_quote(config, btc_quote)
|
||||
|
||||
assert spot == 4400.0 # Falls back to configured price
|
||||
assert source == "configured_entry_price"
|
||||
|
||||
Reference in New Issue
Block a user