Phase 4: Add Next.js dashboard for metrics and trade journal#5
Merged
Conversation
Raw generated output of `create-next-app@16.2.11 --ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm --disable-git`, unmodified, in its own commit so the hand-written Phase 4 work stays reviewable on top of it (the same reason the scaffold was deferred out of Phase 0). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8BE1pjFaGWKzeQcY2baYu
parseNs/stringifyNs round-trip the backend's *_ns nanosecond epochs
(~1.76e18 > 2^53) without precision loss, using the ES2025 reviver
context.source on the way in and JSON.rawJSON on the way out — the
pydantic models expect JSON integers, so strings are not an option on
POST. ensureSupported fails loudly on runtimes that would silently
round. This closes the "Phase 4 concern" recorded in backtest.api's
module docstring.
The typed client (api.ts) mirrors every endpoint contract the UI needs
and maps FastAPI error bodies — string details and 422 validation
lists — into ApiError{status, detail}. All calls go through the
same-origin /api/backend prefix, rewritten in next.config.ts to
BACKEND_URL (default localhost:8000): the backend serves no CORS
headers and, behind the proxy, doesn't need any, so Phases 1-3 stay
untouched.
Vitest covers exact BigInt round-trips (2^53+1, digits inside strings,
null timestamps) and the error mapping. tsconfig target moves
ES2017 → ES2022: BigInt literals require ES2020+, tsc is typecheck-only
here, and BigInt cannot be downleveled anyway.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A8BE1pjFaGWKzeQcY2baYu
Metrics page: stat tiles for the latest window plus four charts — OFI as diverging bars (sign-aware 4px rounded data-ends), realized volatility and VWAP as single-series lines, buy/sell volume stacked. VWAP gets its own frame rather than a second axis on the volume chart: a price and a contract count never share one plot. The buy↔sell pair doubles as the diverging palette and was machine-validated against the dark surface (CVD ΔE 19.2, normal-vision 29.0, contrast >= 3:1); single-series charts carry no legend — the title names the series — and text never wears a series color. Window-count selector and manual refresh; refetches hold the previous frame at reduced opacity instead of flashing empty. Journal page: entries joined to their market regime (regime columns dash out when no bucket covers the entry), a log-a-trade form that mirrors the server's exit>=entry rule client-side and surfaces 422 details verbatim, and the behavioral-analysis panel behind an explicit button — one Claude call per click — with distinct 503 (no key) and 502 (no structured analysis) states. useApi derives loading from the not-yet-settled (fetcher, generation) pair instead of setting state synchronously in the effect, which is both what eslint-config-next 16's set-state-in-effect rule demands and race-free under limit switches. System sans everywhere per the dataviz spec — dropping next/font's Google fetch also keeps builds offline. 27 Vitest cases cover the data layer round-trips and the three interactive components against a stubbed fetch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8BE1pjFaGWKzeQcY2baYu
Third CI job (dashboard, Node 22) runs the same gate as locally: npm ci, lint, typecheck, vitest, next build — mirroring the working-directory pattern of the engine and backtest jobs. dashboard/README.md replaces the create-next-app boilerplate with the actual run/verify instructions (backend prerequisite, BACKEND_URL, the *_ns BigInt strategy). Root README ticks Phase 4, adds the dashboard step to "Running locally" and its check line to the CI block, and records the Phase 4 design decisions: Recharts (and the no-dual-axis rule), same-origin proxy over CORS, BigInt end-to-end for *_ns, and the read+create+analyze journal scope. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8BE1pjFaGWKzeQcY2baYu
The rendered pages surfaced two things the unit gate can't see: the volatility y-axis clipped its leading zero (0.000032 → ".000032") at 56px, so the axis gets 72px; and the journal's timestamp cells repeated the UTC suffix the column header already carries, pushing the regime columns behind the horizontal scroll at common widths. Verified against the real pipeline: engine over the sample tape (5000 ticks → 501 buckets), uvicorn serving it, journal seeded and a trade logged through the form (regime join populated on the new row), zero browser console errors on either page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8BE1pjFaGWKzeQcY2baYu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the Phase 4 visualization layer — a Next.js (App Router, TypeScript, Tailwind) dashboard that consumes the
backtest/FastAPI backend API.Summary
Adds a complete frontend dashboard with two main pages:
/): Real-time microstructure charts (order-flow imbalance, realized volatility, volume, VWAP) with configurable window limits and stat tiles for the latest bucket/journal): Trade log with market regime context at entry time, a form to log new trades, and a Claude-powered behavioral analysis panelKey Changes
API Client & Data Handling
src/lib/api.ts: Typed client for the backend withApiErrorexception class, request/response helpers, and type definitions for all data models (metrics, journal entries, behavioral analysis)src/lib/nsjson.ts: BigInt-safe JSON parsing/serialization for nanosecond timestamps using ES2025JSON.parsesource context andJSON.rawJSON— preserves precision beyondNumber.MAX_SAFE_INTEGERsrc/lib/useApi.ts: Minimal fetch-on-mount hook with manual refetch, keeps previous data on error for graceful degradationPages & Components
src/app/page.tsx: Metrics dashboard with limit selector, stat tiles, and four chart componentssrc/app/journal/page.tsx: Journal page with entry form, trade table, and analysis panelsrc/components/EntryForm.tsx: Form to log trades with client-side validation (exit time ≥ entry time)src/components/JournalTable.tsx: Sortable table of trades joined to market regime at entrysrc/components/AnalysisPanel.tsx: Behavioral analysis UI with severity badges and disclaimerCharts
src/components/charts/OfiChart.tsx: Diverging bar chart (buy/sell colored) for order-flow imbalancesrc/components/charts/VolatilityChart.tsx: Line chart for realized volatilitysrc/components/charts/VolumeChart.tsx: Stacked bar chart for buy/sell volumesrc/components/charts/VwapChart.tsx: Line chart for volume-weighted average pricesrc/components/charts/common.tsx: Shared chart chrome (grid, axes, tooltip formatting)Styling & Layout
src/app/globals.css: Dark-only design system with validated color tokens (diverging buy/sell pair, series colors)src/components/Nav.tsx: Navigation between Metrics and Journal pagessrc/components/StatTile.tsx: Reusable stat display componentsrc/components/states.tsx: Error and empty-state UI componentssrc/lib/format.ts: Number formatting utilities (integers, prices, signed values, significant figures)Configuration & Build
next.config.ts: Same-origin proxy rewrite to backend (no CORS needed)tsconfig.json,package.json,postcss.config.mjs: TypeScript, dependencies (Next.js 16, React 19, Recharts), PostCSS setupeslint.config.mjs,vitest.config.ts: Linting and unit test configurationTests
src/lib/api.test.ts: API client tests (BigInt parsing, journal rows with null regime, POST serialization)src/lib/nsjson.test.ts: Nanosecond JSON round-trip tests (precision preservation, null handling, array support)src/components/EntryForm.test.tsx: Form validation and submission testssrc/components/AnalysisPanel.test.tsx: Analysis rendering and error handling testssrc/components/JournalTable.test.tsx: Table rendering with regime columnsCI/CD
.github/workflows/ci.yml: Added Node.js linting, type-checking, and test steps for the dashboardNotable Implementation Details