fix(CORE-002C): explain undercollateralized historical seeds
This commit is contained in:
@@ -11,6 +11,17 @@ from app.services.strategy_templates import StrategyTemplateService
|
||||
|
||||
SUPPORTED_EVENT_COMPARISON_SYMBOL = "GLD"
|
||||
|
||||
|
||||
def _validate_initial_collateral(underlying_units: float, entry_spot: float, loan_amount: float) -> None:
|
||||
initial_collateral_value = underlying_units * entry_spot
|
||||
if loan_amount >= initial_collateral_value:
|
||||
raise ValueError(
|
||||
"Historical scenario starts undercollateralized: "
|
||||
f"loan ${loan_amount:,.0f} exceeds initial collateral ${initial_collateral_value:,.0f} "
|
||||
f"at entry spot ${entry_spot:,.2f}. Reduce loan amount or increase underlying units."
|
||||
)
|
||||
|
||||
|
||||
DETERMINISTIC_EVENT_COMPARISON_FIXTURE_HISTORY: tuple[DailyClosePoint, ...] = (
|
||||
DailyClosePoint(date=date(2024, 1, 2), close=100.0),
|
||||
DailyClosePoint(date=date(2024, 1, 3), close=96.0),
|
||||
@@ -103,13 +114,27 @@ class EventComparisonPageService:
|
||||
loan_amount: float,
|
||||
margin_call_ltv: float,
|
||||
) -> BacktestScenario:
|
||||
return self.comparison_service.preview_scenario_from_inputs(
|
||||
preset_slug=preset_slug,
|
||||
template_slugs=template_slugs,
|
||||
underlying_units=underlying_units,
|
||||
loan_amount=loan_amount,
|
||||
margin_call_ltv=margin_call_ltv,
|
||||
)
|
||||
try:
|
||||
scenario = self.comparison_service.preview_scenario_from_inputs(
|
||||
preset_slug=preset_slug,
|
||||
template_slugs=template_slugs,
|
||||
underlying_units=underlying_units,
|
||||
loan_amount=loan_amount,
|
||||
margin_call_ltv=margin_call_ltv,
|
||||
)
|
||||
except ValueError as exc:
|
||||
if str(exc) == "loan_amount must be less than initial collateral value":
|
||||
preset = self.event_preset_service.get_preset(preset_slug)
|
||||
preview = self.comparison_service.provider.load_history(
|
||||
preset.symbol.strip().upper(),
|
||||
preset.window_start,
|
||||
preset.window_end,
|
||||
)
|
||||
if preview:
|
||||
_validate_initial_collateral(underlying_units, preview[0].close, loan_amount)
|
||||
raise
|
||||
_validate_initial_collateral(underlying_units, scenario.initial_portfolio.entry_spot, loan_amount)
|
||||
return scenario
|
||||
|
||||
def run_read_only_comparison(
|
||||
self,
|
||||
@@ -134,6 +159,25 @@ class EventComparisonPageService:
|
||||
if normalized_symbol != SUPPORTED_EVENT_COMPARISON_SYMBOL:
|
||||
raise ValueError("BT-003A event comparison is currently limited to GLD on this page")
|
||||
|
||||
try:
|
||||
preview = self.comparison_service.preview_scenario_from_inputs(
|
||||
preset_slug=preset.slug,
|
||||
template_slugs=tuple(template_slugs or preset.scenario_overrides.default_template_slugs),
|
||||
underlying_units=underlying_units,
|
||||
loan_amount=loan_amount,
|
||||
margin_call_ltv=margin_call_ltv,
|
||||
)
|
||||
except ValueError as exc:
|
||||
if str(exc) == "loan_amount must be less than initial collateral value":
|
||||
preview_history = self.comparison_service.provider.load_history(
|
||||
normalized_symbol,
|
||||
preset.window_start,
|
||||
preset.window_end,
|
||||
)
|
||||
if preview_history:
|
||||
_validate_initial_collateral(underlying_units, preview_history[0].close, loan_amount)
|
||||
raise
|
||||
_validate_initial_collateral(underlying_units, preview.initial_portfolio.entry_spot, loan_amount)
|
||||
return self.comparison_service.compare_event_from_inputs(
|
||||
preset_slug=preset.slug,
|
||||
template_slugs=tuple(template_slugs or preset.scenario_overrides.default_template_slugs),
|
||||
|
||||
Reference in New Issue
Block a user