Judgment, Oversight & Execution
A five-role AI team that independently analyzes pre-market news, manages a core-satellite portfolio on Alpaca, and self-reviews every evening against the SPY benchmark. Runs 24/7 on a Synology NAS.
Share this case study →The hard part: hard risk limits enforced in code the model can't override, and a self-improving loop where a repeated mistake gets promoted from a logged lesson into a permanent, hard-coded gate.
APScheduler-based; wakes each expert on a market-driven schedule
Python, Postgres, Alpaca, Claude, DeepSeek, Qwen
An APScheduler-based orchestrator wakes each agent on a market-driven schedule. The Analyst runs at 08:30 ET on DeepSeek V4 Pro — heavy reasoning, once daily — reading overnight news, the macro calendar, and its own historical lessons before writing a pre-market brief. The Trader runs every 20 minutes from 09:10 to 15:50 ET on DeepSeek V4 Flash — lightweight, about 21 calls a day — deciding which tickers to open or close, at what size, with what stop. Before any consequential open, a Challenger role reviews the same setup on Claude Opus — deliberately the opposite model family from the Trader's DeepSeek, because a same-family second opinion tends to agree with itself for the same reasons it was wrong the first time. The Challenger can veto the trade; if it's unreachable, it fails open rather than freezing the desk. The Evaluator runs at midday on DeepSeek V4 Pro, re-examining every open position against its original thesis. The Reviewer runs at market close and drives the self-improvement loop below. Only the Trader can actually place an order.
Every trading decision function is pure — zero I/O, zero side effects, fully unit-testable. The 52-week-high momentum signal (citing George & Hwang 2004) always returns every diagnostic field, even for candidates that fail, so nothing is ever a black-box rejection. The core-sleeve rebalancer is pure too: no I/O, no LLM, just a list of orders for a thin wrapper to execute. The practical effect: roughly 90% of the trading logic is unit-tested without a live broker connection, without mocking, and without any risk of an accidental real order during a test run.
The Trader has the richest toolset of the five agents, but several deterministic gates constrain it regardless of what the model decides. A cooldown system prevents re-proposing the same ticker on consecutive ticks — 120 minutes after actually opening a position, 40 minutes after evaluating one without acting, and cooldowns only ever extend, never shorten. An exit manager assigns every closed position a standardized reason and flags anything held beyond 48 hours as overdue — a pure implementation of the Triple Barrier Method's vertical barrier. Above both sits a daily circuit breaker: if the portfolio drops 2% or more in a session, new entries halt outright for the rest of the day, no override. And if the Analyst's morning brief is ever missing or stale, the Trader hard-blocks new opens rather than trading blind — a safety default, not a suggestion it can reason its way around.
The portfolio is split into two mechanically separate sleeves. The Core sleeve (SPY/QQQ/VOO, 60% allocation) runs zero-LLM drift-band rebalancing — pure math, an order only when drift exceeds 8%. The Satellite sleeve (Active, 40%) is fully LLM-driven, deciding every 20 minutes via DeepSeek V4 Flash. This guarantees that even if the satellite agent's reasoning goes completely off track, 60% of the portfolio is untouched and still tracking the market. Capital preservation is architected in, not just a policy.
Every trading day ends with the Reviewer computing P&L attribution, looking for patterns across trades, and writing dated, ID-tagged lessons into a journal file — committed and pushed to Gitea, no vector database or RAG pipeline involved; the git history is the memory system. Most lessons just inform the next morning's brief. But when the same mistake shows up on repeat, it graduates: after several logged instances of opening positions below the 20-day moving average and losing, that threshold stopped being a note to remember and became a hard-coded check in the risk module — closing the loop from 'we noticed this went wrong' to 'the code no longer allows it.'
Python, Claude API, DeepSeek API, Alpaca, Finnhub, EDGAR, pgvector, APScheduler, Docker, Gitea Actions CI/CD (self-hosted).