A local-only portfolio management system that combines deterministic screening, per-symbol LLM analysis, and a learning loop. It pulls live data from Schwab, screens the Russell 3000 across three risk profiles, produces a CIO-style daily action plan, and mirrors every decision through Alpaca paper trading before any real capital is at risk.
Investment Monitor runs unattended on a single mini PC, reachable over Tailscale. A scheduled task fires the pipeline three times each weekday โ the first run does the heavy LLM work, later runs refresh the deterministic data โ plus a Saturday run that backfills five years of history and forces a full LLM pass. A Flask dashboard surfaces the latest CIO plan, holdings analysis, screener results, and learning-loop metrics.
EXECUTION_ENABLED=false by default), so the paper-trading sandbox is the
testbed for new strategies before any real-money rollout.
The whole run is implemented end-to-end in one orchestrator (src/orchestration/daily_run.py),
read top to bottom. The deterministic screener and action engine always cover the full portfolio; the LLM
stages (amber) operate only on a bounded candidate set capped at 90 symbols.
flowchart TD
A[Schwab snapshot
+ tax-lot sync] --> B[Resolve universe
Russell 3000 + movers + watchlist]
B --> C[Shared data fetch
quotes / fundamentals / prices]
I[SEC EDGAR Form 4
insider-buying signal] --> D
C --> D[Screener x3 profiles
conservative / neutral / aggressive]
C --> E[200-week MA screener]
D --> F[Performance metrics]
E --> F
F --> G[Action engine x3
+ LLM explainer]
G --> H[Candidate set builder
cap 90 symbols]
H --> L{{LLM Analyst
per-symbol BUY/HOLD/SELL}}
L --> M{{CIO Synthesizer
unified action plan}}
M --> O{{Red-team critique}}
O --> P[Decision ledger
+ outcome scoring]
H --> S[Strategy engines
TLH ยท collars ยท rotation
duration ยท dividend ยท quality-mom]
S --> P
P --> R[Email digest]
R --> V[Paper trading
Alpaca]
classDef llm fill:#fef3c7,stroke:#d97706,color:#000
class L,M,O llm
Deterministic stages cover the full portfolio; amber LLM stages run on the bounded candidate set.
Python 3.12, Flask 3.1 dashboard with 90+ routes and 40 templates surfacing the latest run.
SQLAlchemy 2.0 ORM over a 49-table SQLite database. All persistence flows through one DataStore layer.
OAuth client for live quotes, fundamentals, and price history โ the source of truth for holdings and the universe.
Every CIO recommendation is executed in a sandbox and tracked against forward returns to feed the learning loop.
A provider router pins each stage to OpenAI gpt-4.1-mini (high-volume) or Claude via claude-cli (deep analysis).
Research signals feed the agents that screen and contextualise candidates.
A read-only MCP server (MCP 1.14) exposes the system's data as tools for Claude to query directly.
Six pluggable sleeve strategies โ tax-loss harvesting, dividend capture, options collars, sector rotation, duration, quality-momentum โ registered from strategies.yaml behind one Strategy base class.
An insider open-market-purchase counter (transaction code P) over a 90-day window, wired in as an opt-in screening factor and refreshed weekly.
Fires the pipeline three times per weekday plus a Saturday deep-analysis run and a weekly insider-cache backfill.
A single STAGE_ROUTING table is the source of truth for which stage hits which provider.
High-volume per-symbol and aggregate work โ analyst, CIO, explainer, narrator, macro, tax โ is pinned to
OpenAI gpt-4.1-mini for cost and speed. The deeper red-team critique routes to Claude via the
claude-cli at zero marginal cost.
llm_traces table โ model, tokens, latency, stage โ
which the learning loop reads from.
Pull a fresh Schwab snapshot, sync tax lots, then resolve the day's universe: Russell 3000 plus market movers and the personal watchlist.
A shared data fetch feeds three parallel screeners (conservative / neutral / aggressive) using a 15-factor model โ including an opt-in SEC EDGAR insider-buying signal โ alongside a once-daily 200-week moving-average screen.
The action engine turns scores into BUY/HOLD/SELL calls per profile and an LLM explainer attaches a plain-English rationale to each.
Holdings, today's actions, screen hits, 200-week retests, and pinned names are merged into a bounded candidate set (capped at 90 symbols) โ the only thing the expensive LLM stages see.
A per-symbol LLM analyst issues BUY/HOLD/SELL with conviction; a CIO synthesizer ranks them into one unified plan plus a watchlist; a red-team pass critiques the plan before it ships.
Six registered sleeve strategies โ tax-loss harvesting, dividend capture, options collars, sector rotation, duration, and quality-momentum โ evaluate the portfolio and surface their signals into the plan for attribution.
Decisions are written to a ledger with outcome scoring, a digest email goes out, and the approved plan is mirrored as Alpaca paper trades whose forward returns feed the learning loop.