feat(CORE-002): add GLD share quote conversion seam

This commit is contained in:
Bu5hm4nn
2026-03-25 14:52:48 +01:00
parent 1a2dfaff01
commit f0d7ab5748
10 changed files with 425 additions and 34 deletions

View File

@@ -1,8 +1,10 @@
from __future__ import annotations
from decimal import Decimal
from typing import Any
from typing import Any, Mapping
from app.domain.backtesting_math import PricePerAsset
from app.domain.instruments import instrument_metadata
from app.domain.units import BaseCurrency, Money, PricePerWeight, Weight, WeightUnit, decimal_from_float
from app.models.portfolio import PortfolioConfig
@@ -42,6 +44,44 @@ def _gold_weight(gold_ounces: float) -> Weight:
return Weight(amount=decimal_from_float(gold_ounces), unit=WeightUnit.OUNCE_TROY)
def _safe_quote_price(value: object) -> float:
try:
parsed = float(value)
except (TypeError, ValueError):
return 0.0
if parsed <= 0:
return 0.0
return parsed
def resolve_portfolio_spot_from_quote(
config: PortfolioConfig,
quote: Mapping[str, object],
*,
fallback_symbol: str | None = None,
) -> tuple[float, str, str]:
configured_price = float(config.entry_price or 0.0)
quote_price = _safe_quote_price(quote.get("price"))
quote_source = str(quote.get("source", "unknown"))
quote_updated_at = str(quote.get("updated_at", ""))
quote_symbol = str(quote.get("symbol", fallback_symbol or "")).strip().upper()
quote_unit = str(quote.get("quote_unit", "")).strip().lower()
if quote_price <= 0 or not quote_symbol or quote_unit != "share":
return configured_price, "configured_entry_price", ""
try:
metadata = instrument_metadata(quote_symbol)
except ValueError:
return configured_price, "configured_entry_price", ""
converted_spot = metadata.price_per_weight_from_asset_price(
PricePerAsset(amount=decimal_from_float(quote_price), currency=BaseCurrency.USD, symbol=quote_symbol),
per_unit=WeightUnit.OUNCE_TROY,
)
return _decimal_to_float(converted_spot.amount), quote_source, quote_updated_at
def portfolio_snapshot_from_config(config: PortfolioConfig | None = None) -> dict[str, float]:
if config is None:
gold_weight = Weight(amount=Decimal("1000"), unit=WeightUnit.OUNCE_TROY)