feat: add option contracts to overview, fix default dates, add roadmap items
- Move option contracts from daily results table to overview cards (constant throughout backtest) - Fix default dates to March 2026 (2026-03-02 to 2026-03-25) - Add BT-004 backlog item: candlestick chart with portfolio value line on secondary axis - Add BT-005 backlog item: defer entry spot derivation to backtest run (not on every date change)
This commit is contained in:
@@ -255,9 +255,9 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
default_data_source = "databento"
|
||||
default_dataset = "XNAS.BASIC"
|
||||
default_schema = "ohlcv-1d"
|
||||
# Use a start date that's valid for the default dataset (XNAS.BASIC starts 2024-07-01)
|
||||
default_start_date = date(2024, 7, 1).isoformat()
|
||||
default_end_date = date(2024, 12, 31).isoformat()
|
||||
# Default to March 2026 for testing
|
||||
default_start_date = date(2026, 3, 2).isoformat()
|
||||
default_end_date = date(2026, 3, 25).isoformat()
|
||||
default_symbol = "GLD"
|
||||
default_start_price = 0.0
|
||||
|
||||
@@ -621,12 +621,17 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
ui.label(f"Template: {template_result.template_name}").classes(
|
||||
"text-sm text-slate-500 dark:text-slate-400"
|
||||
)
|
||||
# Get option contracts from first day (constant throughout backtest)
|
||||
option_contracts = (
|
||||
template_result.daily_path[0].option_contracts if template_result.daily_path else 0.0
|
||||
)
|
||||
with ui.grid(columns=4).classes("w-full gap-4 max-lg:grid-cols-2 max-sm:grid-cols-1"):
|
||||
cards = [
|
||||
("Start value", f"${summary.start_value:,.0f}"),
|
||||
("End value hedged", f"${summary.end_value_hedged_net:,.0f}"),
|
||||
("Max LTV hedged", f"{summary.max_ltv_hedged:.1%}"),
|
||||
("Hedge cost", f"${summary.total_hedge_cost:,.0f}"),
|
||||
("Option contracts", f"{option_contracts:,.0f}"),
|
||||
("Margin call days hedged", str(summary.margin_call_days_hedged)),
|
||||
("Margin call days unhedged", str(summary.margin_call_days_unhedged)),
|
||||
(
|
||||
@@ -671,12 +676,6 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
"field": "option_value",
|
||||
"align": "right",
|
||||
},
|
||||
{
|
||||
"name": "contracts",
|
||||
"label": "Contracts",
|
||||
"field": "contracts",
|
||||
"align": "right",
|
||||
},
|
||||
{
|
||||
"name": "ltv_hedged",
|
||||
"label": "LTV hedged",
|
||||
@@ -698,7 +697,6 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
"close": f"${point.spot_close:,.2f}",
|
||||
"portfolio_value": f"${point.net_portfolio_value:,.0f}",
|
||||
"option_value": f"${point.option_market_value:,.0f}",
|
||||
"contracts": f"{point.option_contracts:,.0f}",
|
||||
"ltv_hedged": f"{point.ltv_hedged:.1%}",
|
||||
"margin_call": "Yes" if point.margin_call_hedged else "No",
|
||||
}
|
||||
@@ -982,10 +980,16 @@ 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")
|
||||
|
||||
# Get option contracts from first day (constant throughout backtest)
|
||||
daily_path = first_template.get("daily_path", [])
|
||||
first_day = daily_path[0] if daily_path else {}
|
||||
option_contracts = first_day.get("option_contracts", 0)
|
||||
|
||||
# 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%}"),
|
||||
("Option contracts", f"{option_contracts:,.0f}"),
|
||||
("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"),
|
||||
@@ -998,7 +1002,6 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
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"
|
||||
@@ -1024,12 +1027,6 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
"field": "option_value",
|
||||
"align": "right",
|
||||
},
|
||||
{
|
||||
"name": "contracts",
|
||||
"label": "Contracts",
|
||||
"field": "contracts",
|
||||
"align": "right",
|
||||
},
|
||||
{
|
||||
"name": "ltv_hedged",
|
||||
"label": "LTV hedged",
|
||||
@@ -1051,7 +1048,6 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
"close": f"${dp.get('spot_close', 0):,.2f}",
|
||||
"portfolio_value": f"${dp.get('net_portfolio_value', 0):,.0f}",
|
||||
"option_value": f"${dp.get('option_market_value', 0):,.0f}",
|
||||
"contracts": f"{dp.get('option_contracts', 0):,.0f}",
|
||||
"ltv_hedged": f"{dp.get('ltv_hedged', 0):.1%}",
|
||||
"margin_call": "Yes" if dp.get("margin_call_hedged") else "No",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user