Initial commit: Vault Dashboard for options hedging
- FastAPI + NiceGUI web application - QuantLib-based Black-Scholes pricing with Greeks - Protective put, laddered, and LEAPS strategies - Real-time WebSocket updates - TradingView-style charts via Lightweight-Charts - Docker containerization - GitLab CI/CD pipeline for VPS deployment - VPN-only access configuration
This commit is contained in:
66
app/pages/overview.py
Normal file
66
app/pages/overview.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from nicegui import ui
|
||||
|
||||
from app.components import PortfolioOverview
|
||||
from app.pages.common import dashboard_page, portfolio_snapshot, quick_recommendations, recommendation_style, strategy_catalog
|
||||
|
||||
|
||||
@ui.page("/")
|
||||
@ui.page("/overview")
|
||||
def overview_page() -> None:
|
||||
portfolio = portfolio_snapshot()
|
||||
|
||||
with dashboard_page(
|
||||
"Overview",
|
||||
"Portfolio health, LTV risk, and quick strategy guidance for the current GLD-backed loan.",
|
||||
"overview",
|
||||
):
|
||||
with ui.grid(columns=4).classes("w-full gap-4 max-lg:grid-cols-2 max-sm:grid-cols-1"):
|
||||
summary_cards = [
|
||||
("Spot Price", f"${portfolio['spot_price']:,.2f}", "GLD reference price"),
|
||||
("Margin Call Price", f"${portfolio['margin_call_price']:,.2f}", "Implied trigger level"),
|
||||
("Cash Buffer", f"${portfolio['cash_buffer']:,.0f}", "Available liquidity"),
|
||||
("Hedge Budget", f"${portfolio['hedge_budget']:,.0f}", "Approved premium budget"),
|
||||
]
|
||||
for title, value, caption in summary_cards:
|
||||
with ui.card().classes("rounded-2xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900"):
|
||||
ui.label(title).classes("text-sm font-medium text-slate-500 dark:text-slate-400")
|
||||
ui.label(value).classes("text-3xl font-bold text-slate-900 dark:text-slate-50")
|
||||
ui.label(caption).classes("text-sm text-slate-500 dark:text-slate-400")
|
||||
|
||||
portfolio_view = PortfolioOverview(margin_call_ltv=portfolio["margin_call_ltv"])
|
||||
portfolio_view.update(portfolio)
|
||||
|
||||
with ui.row().classes("w-full gap-6 max-lg:flex-col"):
|
||||
with ui.card().classes("w-full rounded-2xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900"):
|
||||
with ui.row().classes("w-full items-center justify-between"):
|
||||
ui.label("Current LTV Status").classes("text-lg font-semibold text-slate-900 dark:text-slate-100")
|
||||
ui.label(f"Threshold {portfolio['margin_call_ltv'] * 100:.0f}%").classes(
|
||||
"rounded-full bg-rose-100 px-3 py-1 text-xs font-semibold text-rose-700 dark:bg-rose-500/15 dark:text-rose-300"
|
||||
)
|
||||
ui.linear_progress(value=portfolio["ltv_ratio"] / portfolio["margin_call_ltv"], show_value=False).props("color=warning track-color=grey-3 rounded")
|
||||
ui.label(
|
||||
f"Current LTV is {portfolio['ltv_ratio'] * 100:.1f}% with a margin buffer of {(portfolio['margin_call_ltv'] - portfolio['ltv_ratio']) * 100:.1f} percentage points."
|
||||
).classes("text-sm text-slate-600 dark:text-slate-300")
|
||||
ui.label(
|
||||
"Warning: if GLD approaches the margin-call price, collateral remediation or hedge monetization will be required."
|
||||
).classes("text-sm font-medium text-amber-700 dark:text-amber-300")
|
||||
|
||||
with ui.card().classes("w-full rounded-2xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900"):
|
||||
ui.label("Strategy Snapshot").classes("text-lg font-semibold text-slate-900 dark:text-slate-100")
|
||||
for strategy in strategy_catalog():
|
||||
with ui.row().classes("w-full items-start justify-between gap-4 border-b border-slate-100 py-3 last:border-b-0 dark:border-slate-800"):
|
||||
with ui.column().classes("gap-1"):
|
||||
ui.label(strategy["label"]).classes("font-semibold text-slate-900 dark:text-slate-100")
|
||||
ui.label(strategy["description"]).classes("text-sm text-slate-500 dark:text-slate-400")
|
||||
ui.label(f"${strategy['estimated_cost']:.2f}/oz").classes(
|
||||
"rounded-full bg-sky-100 px-3 py-1 text-xs font-semibold text-sky-700 dark:bg-sky-500/15 dark:text-sky-300"
|
||||
)
|
||||
|
||||
ui.label("Quick Strategy Recommendations").classes("text-xl font-semibold text-slate-900 dark:text-slate-100")
|
||||
with ui.grid(columns=3).classes("w-full gap-4 max-lg:grid-cols-1"):
|
||||
for rec in quick_recommendations():
|
||||
with ui.card().classes(f"rounded-2xl border shadow-sm {recommendation_style(rec['tone'])}"):
|
||||
ui.label(rec["title"]).classes("text-base font-semibold text-slate-900 dark:text-slate-100")
|
||||
ui.label(rec["summary"]).classes("text-sm text-slate-600 dark:text-slate-300")
|
||||
Reference in New Issue
Block a user