"use client"; import { useQuery } from "@tanstack/react-query"; import Link from "next/link"; import { useRiskStatus, useSystemStatus } from "@/components/shell"; import { Badge, Card, Dot, Empty, ErrorBox, KV, PageHeader, Spinner, Table, Td, Th, Tile } from "@/components/ui"; import { api } from "@/lib/api"; import { fmtAge, fmtBps, fmtNum, fmtPct, fmtPctPlain, fmtPrice, fmtUsd, signClass } from "@/lib/format"; import type { OverviewSymbol, RunRow } from "@/lib/types"; export default function OverviewPage() { const sys = useSystemStatus(); const risk = useRiskStatus(); const ov = useQuery({ queryKey: ["overview"], queryFn: () => api<{ symbols: OverviewSymbol[] }>("/api/market/overview"), refetchInterval: 5_000 }); const runs = useQuery({ queryKey: ["runs", 5], queryFn: () => api<{ items: RunRow[] }>("/api/backtests?limit=5"), refetchInterval: 10_000 }); const s = sys.data; return ( <>
{s?.mode ?? "…"}} sub={s?.live_trading_enabled ? "live flag ON" : "live flag off"} tone={s?.mode === "live" ? "down" : "muted"} />
{ov.isLoading && } {ov.error && } {ov.data && ( {ov.data.symbols.map((r) => ( ))}
SymbolLast24hBid / AskSpread24h volumeRV 7d (ann.)1h barsData
{r.symbol} {fmtPrice(r.last)} {fmtPct(r.change_pct, 2, true)} {fmtPrice(r.bid)} / {fmtPrice(r.ask)} {fmtBps(r.spread_bps, 2)} {fmtNum(r.volume, 0)} {fmtPctPlain(r.rv_7d_annualized)} {r.hourly_bars} {r.stale ? stale {fmtAge(r.age_s)} : live {fmtAge(r.age_s)}}
)}
{sys.isLoading && } {sys.error && } {s && ( {s.kraken.status}{s.kraken.error ? ` — ${s.kraken.error}` : ""}], ["REST round-trip", s.kraken.rtt_ms != null ? `${s.kraken.rtt_ms} ms` : "—"], ["Clock drift", s.kraken.clock_drift_s != null ? `${s.kraken.clock_drift_s.toFixed(2)} s` : "—"], ["WebSocket", s.stream ? {s.stream.connected ? "connected" : "disconnected"} · {s.stream.messages.toLocaleString()} msgs · {s.stream.reconnects} reconnects · {s.stream.checksum_failures} checksum fails : "worker not reporting"], ["Last message", s.stream?.last_msg_age != null ? `${s.stream.last_msg_age}s ago` : "—"], ["Data key", s.credentials.data_key ? "configured" : "not configured"], ["Trade key", s.credentials.trade_key ? "configured" : "not configured"], ]} /> )} Backtests run on demand from the Strategy Lab; there is no scheduled execution yet. {risk.data && ( )} Open Risk Center →
All runs →}> {runs.data?.items.length ? ( {runs.data.items.map((r) => ( ))}
StatusStrategySymbolIntervalSharpeReturnMax DD
{r.strategy}{r.symbol}{r.interval_min}m {fmtNum(r.sharpe)}{fmtPct(r.total_return)}{fmtPct(r.max_drawdown)}
) : Launch one from the Strategy Lab.}
); } export function StatusBadge({ status }: { status: string }) { const tone = status === "done" ? "up" : status === "failed" ? "down" : status === "running" ? "accent" : "muted"; return {status}; }