feat(CORE-001C): type historical unit materialization
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user