Architecture
Layers
Section titled “Layers”| Layer | Stack |
|---|---|
| Backend | Python 3.11+, FastAPI 0.138.2, Uvicorn 0.48.0 |
| Data | SQLite, SQLAlchemy 2.0.51, Pydantic 2.13.4 |
| Market data | yfinance 1.5.1 and Yahoo Finance |
| Public data | SEC EDGAR (filings) and US Treasury (yield curve) — keyless, public domain |
| AI | Anthropic SDK 0.105.2, optional Claude calls (Haiku 4.5 + Sonnet 4.5), local deterministic fallback |
| Frontend | Single HTML shell, Bootstrap 5.3.2, Bootstrap Icons, Chart.js 4.4.0, vanilla JavaScript |
| Desktop | PyInstaller + pywebview native window, in-app auto-update |
| Quality | pytest, Pylint, compileall, pip-audit, Dependency Review, CodeQL |
Request flow
Section titled “Request flow”The browser dashboard talks to the FastAPI app over HTTP/JSON. Routers are thin HTTP adapters: they validate request shapes, call domain modules, and translate domain errors into responses. The modules read/write SQLite, call Yahoo Finance for market data, read public filings and rates from SEC EDGAR and the US Treasury, and optionally call Anthropic Claude when narration is requested and a key is configured.
Each outside source sits behind exactly one module — stock_service for Yahoo,
edgar_service for the SEC, treasury_yield_curve for the curve — so a provider can be
swapped, throttled, or degraded in one place instead of at every call site. edgar_service
owns the SEC’s two hard rules: a declared contact address, and a ceiling of ten requests a
second.
Portfolio integrity modules
Section titled “Portfolio integrity modules”Financial state is concentrated behind four interfaces so callers cannot accidentally use different rules for the same Portfolio:
| Module | Owns | Important invariant |
|---|---|---|
portfolio_lifecycle.py |
Default creation, list/create/rename/delete, owned-record cleanup | Deleting a Portfolio removes its holdings, trades, snapshots, verdict history, DCA ledger, and BOOK:<id> narratives together. |
portfolio_valuation.py |
Live valuation, cost basis, realized + unrealized return, quote quality, daily history | Watchlist rows never enter totals; zero, non-finite, and missing quotes make quality explicit; total-return percentage uses open plus sold cost basis; only complete valuations may update daily snapshots. |
dca_ledger.py |
Plan persistence, catch-up, pending/applied/dismissed transitions, exact apply/undo | Catch-up is idempotent; no simulated buy mutates a holding until the user applies it; a plan with applied buys cannot be deleted until those buys are undone. |
narrative_cache.py |
Portfolio and ticker cache reads/writes, TTL/price freshness, verdict encoding, JSON validation | Portfolio narratives are isolated under BOOK:<portfolio_id>; stale or corrupt rows regenerate safely; incomplete valuations never produce confident Portfolio-level Claude narration. |
Pure DCA scheduling and cost math remains in dca_service.py, while routers and AI/analytics
call these interfaces instead of reaching into each other’s private helpers.
Intelligence Engine
Section titled “Intelligence Engine”The service layer’s core is a modular Intelligence Engine split into two halves:
- Local Intelligence — always on, fully offline. Covers
investment_signal,market_regime,portfolio_exposure, andevent_calendar, producing verdicts, scenarios, regime classification, exposure breakdowns, peer comparisons, and calibration data. - Claude AI — optional. Lives in
ai_service.py, exposinggenerate_action_plan()andgenerate_news_themes(), backed by a 24-hour SQLite cache and live token cost tracking. It uses Claude Haiku 4.5 for fast narration and Claude Sonnet 4.5 for action plans.
The browser view is identical whether you open localhost:8000 yourself or launch the desktop
app — the desktop build (PyInstaller + pywebview) runs the same FastAPI server in-process behind
a native window, and can update itself in place.
Repository layout
Section titled “Repository layout”app/├── main.py FastAPI app, middleware, static assets, startup warmup├── config.py Environment-backed settings├── database.py SQLite engine/session and startup migrations├── models.py SQLAlchemy ORM models├── schemas.py Pydantic request/response contracts├── routers/ Thin HTTP adapters: stocks, portfolio, DCA, AI, news, system└── services/ Lifecycle, valuation, DCA ledger, cache, analytics, signals, data, updates
desktop/ Desktop entry point (uvicorn + native window)packaging/ PyInstaller spec, Inno Setup script, app icons
templates/└── index.html Dashboard shell
static/├── css/style.css Dashboard design system├── js/dashboard.js Main dashboard behavior└── js/analytics-charts.js Chart.js analytics widgets