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:
@@ -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(
|
||||
"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"
|
||||
"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(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-slate-200 bg-slate-50 p-4 shadow-none dark:border-slate-800 dark:bg-slate-950"
|
||||
):
|
||||
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":
|
||||
|
||||
Reference in New Issue
Block a user