fix: update render_job_result to use correct result field names

The job serialization was fixed to use new field names, but the UI render
function was still using old field names (total_pnl, hedging_cost, etc.)
which don't exist anymore. Now uses:
- start_value, end_value_hedged_net, total_hedge_cost from summary_metrics
- template_results[0].daily_path for daily results table
- Added margin call metrics display
This commit is contained in:
Bu5hm4nn
2026-04-04 22:40:39 +02:00
parent 2de5966a4e
commit 4e9a610452

View File

@@ -944,12 +944,27 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
"text-sm text-slate-500 dark:text-slate-400"
)
# Summary metrics
# Get template results for summary
template_results = result.get("template_results", [])
first_template = template_results[0] if template_results else {}
summary = first_template.get("summary_metrics", {})
# Summary metrics using correct field names
start_value = summary.get("start_value", result.get("start_value", 0))
end_value_hedged = summary.get("end_value_hedged_net", 0)
hedge_cost = summary.get("total_hedge_cost", result.get("total_hedge_cost", 0))
max_ltv_hedged = summary.get("max_ltv_hedged", 0)
margin_days_hedged = summary.get("margin_call_days_hedged", 0)
margin_days_unhedged = summary.get("margin_call_days_unhedged", 0)
# Calculate hedge cost percentage
hedge_cost_pct = (hedge_cost / start_value * 100) if start_value > 0 else 0
summary_data = [
("Start value", f"${result.get('total_pnl', 0):,.0f}"),
("End value hedged", f"${result.get('total_pnl_pct', 0)*100:.1f}%"),
("Hedge cost", f"${result.get('hedging_cost', 0):,.0f}"),
("Hedge cost %", f"{result.get('hedging_cost_pct', 0)*100:.2f}%"),
("Start value", f"${start_value:,.0f}"),
("End value hedged", f"${end_value_hedged:,.0f}"),
("Hedge cost", f"${hedge_cost:,.0f}"),
("Hedge cost %", f"{hedge_cost_pct:.2f}%"),
]
with ui.grid(columns=4).classes("w-full gap-4 max-lg:grid-cols-2 max-sm:grid-cols-1"):
for label, value in summary_data:
@@ -959,14 +974,58 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
ui.label(label).classes("text-sm text-slate-500 dark:text-slate-400")
ui.label(value).classes("text-2xl font-bold text-slate-900 dark:text-slate-100")
# Margin call info
if result.get("margin_call_events"):
# Additional metrics row
with ui.grid(columns=4).classes("w-full gap-4 max-lg:grid-cols-2 max-sm:grid-cols-1"):
extra_data = [
("Max LTV hedged", f"{max_ltv_hedged:.1%}"),
("Margin call days hedged", str(margin_days_hedged)),
("Margin call days unhedged", str(margin_days_unhedged)),
("Breached threshold", "No" if margin_days_hedged == 0 else "Yes"),
]
for label, value in extra_data:
with ui.card().classes(
"rounded-xl border border-slate-200 bg-slate-50 p-4 shadow-none dark:border-slate-800 dark:bg-slate-950"
):
ui.label(label).classes("text-sm text-slate-500 dark:text-slate-400")
ui.label(value).classes("text-2xl font-bold text-slate-900 dark:text-slate-100")
# Daily path table
daily_path = first_template.get("daily_path", [])
if daily_path:
with ui.card().classes(
"w-full mt-4 rounded-xl border border-amber-200 bg-amber-50 p-4 dark:border-amber-900/60 dark:bg-amber-950/30"
"w-full mt-4 rounded-xl border border-slate-200 bg-slate-50 p-4 shadow-none dark:border-slate-800 dark:bg-slate-950"
):
ui.label(f"Margin calls: {len(result['margin_call_events'])}").classes(
"text-amber-800 dark:text-amber-200"
ui.label("Daily Results").classes(
"text-md font-semibold text-slate-900 dark:text-slate-100 mb-2"
)
ui.table(
columns=[
{"name": "date", "label": "Date", "field": "date", "align": "left"},
{"name": "spot", "label": "Spot", "field": "spot", "align": "right"},
{
"name": "ltv_hedged",
"label": "LTV hedged",
"field": "ltv_hedged",
"align": "right",
},
{
"name": "margin_call",
"label": "Margin call",
"field": "margin_call",
"align": "center",
},
],
rows=[
{
"date": dp.get("date", ""),
"spot": f"${dp.get('spot_close', 0):,.2f}",
"ltv_hedged": f"{dp.get('ltv_hedged', 0):.1%}",
"margin_call": "Yes" if dp.get("margin_call_hedged") else "No",
}
for dp in daily_path
],
row_key="date",
).classes("w-full")
# Update cost estimate for Databento
if str(data_source_select.value) == "databento":