feat(CORE-001C): type historical unit materialization

This commit is contained in:
Bu5hm4nn
2026-03-24 22:30:36 +01:00
parent 7c2729485c
commit c7c8654be7
8 changed files with 309 additions and 19 deletions

View File

@@ -6,6 +6,7 @@ from fastapi import Request
from fastapi.responses import RedirectResponse
from nicegui import ui
from app.domain.backtesting_math import asset_quantity_from_floats
from app.models.workspace import WORKSPACE_COOKIE, get_workspace_repository
from app.pages.common import dashboard_page, render_workspace_recovery
from app.services.backtesting.ui_service import BacktestPageRunResult, BacktestPageService
@@ -67,7 +68,6 @@ def workspace_backtests_page(workspace_id: str) -> None:
_render_backtests_page(workspace_id=workspace_id)
def _render_backtests_page(workspace_id: str | None = None) -> None:
service = BacktestPageService()
template_options = service.template_options("GLD")
@@ -77,7 +77,7 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
config = repo.load_portfolio_config(workspace_id) if workspace_id else None
default_entry_spot = service.derive_entry_spot("GLD", date(2024, 1, 2), date(2024, 1, 8))
default_units = (
float(config.gold_value or 0.0) / default_entry_spot
asset_quantity_from_floats(float(config.gold_value or 0.0), default_entry_spot, "GLD")
if config and config.gold_value is not None and default_entry_spot > 0
else 1000.0
)
@@ -183,10 +183,25 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
columns=[
{"name": "date", "label": "Date", "field": "date", "align": "left"},
{"name": "spot_close", "label": "Spot", "field": "spot_close", "align": "right"},
{"name": "net_portfolio_value", "label": "Net hedged", "field": "net_portfolio_value", "align": "right"},
{"name": "ltv_unhedged", "label": "LTV unhedged", "field": "ltv_unhedged", "align": "right"},
{
"name": "net_portfolio_value",
"label": "Net hedged",
"field": "net_portfolio_value",
"align": "right",
},
{
"name": "ltv_unhedged",
"label": "LTV unhedged",
"field": "ltv_unhedged",
"align": "right",
},
{"name": "ltv_hedged", "label": "LTV hedged", "field": "ltv_hedged", "align": "right"},
{"name": "margin_call_hedged", "label": "Hedged breach", "field": "margin_call_hedged", "align": "center"},
{
"name": "margin_call_hedged",
"label": "Hedged breach",
"field": "margin_call_hedged",
"align": "center",
},
],
rows=[
{
@@ -202,6 +217,20 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
row_key="date",
).classes("w-full")
def refresh_workspace_seeded_units() -> None:
if not workspace_id or config is None or config.gold_value is None:
return
try:
entry_spot = service.derive_entry_spot(
str(symbol_input.value or "GLD"),
parse_iso_date(start_input.value, "Start date"),
parse_iso_date(end_input.value, "End date"),
)
except (ValueError, KeyError):
return
units_input.value = asset_quantity_from_floats(float(config.gold_value), entry_spot, "GLD")
entry_spot_hint.set_text(f"Auto-derived entry spot: ${entry_spot:,.2f}")
def run_backtest() -> None:
validation_label.set_text("")
try:
@@ -224,5 +253,8 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
return
render_result(result)
if workspace_id:
start_input.on_value_change(lambda _event: refresh_workspace_seeded_units())
end_input.on_value_change(lambda _event: refresh_workspace_seeded_units())
run_button.on_click(lambda: run_backtest())
run_backtest()