Aryan Singh e1ac514f30 Add dynamic agent registry and options mandate
Introduces a dashboard-managed agent registry (`state/agents.json`) used by nightly research and market-open execution, including support for custom/disabled agents and per-agent time budgets. Expands personas to four agents (adds Maverick), shifts pick targets to include mandatory options, and updates prompts/finalization nudges to enforce option research without hard-failing runs.

Strengthens execution safety by adding option-specific guardrails (conviction floor, premium cap, reserved option slot through trade/day/buying-power caps), validates OCC option symbols in schemas, and normalizes invalid option direction cases. The dashboard was refactored into modular views, adds an Agents admin tab, and improves live portfolio visibility with Alpaca-first data and snapshot fallback.
e1ac514f30 · 2026-07-07 22:00:20 -05:00
16 Commits
2026-07-01 16:29:40 -05:00
2026-07-02 00:46:34 -05:00
2026-07-02 00:46:34 -05:00

Overnight Local-LLM Paper-Trading Agent

Every night the Mac wakes itself, runs 4 trader personas one at a time against one local LLM (gpt-oss-20b via oMLX, an Apple-MLX inference server). Each persona researches the web + live market data, forms up to 4 trade theses — at least one of them an options trade — and writes JSON. In the morning at market open a separate job reads that JSON and places Alpaca paper trades with programmatic risk guardrails. Everything is visible in a local Streamlit dashboard, including an Agents tab that manages the roster (add/edit/disable agents, per-agent research budgets) via state/agents.json — no code edits needed.

Paper trading only. Fake money, real prices. "The build works" ≠ "it's profitable" — the quality of a local model's theses is the open question you tune over time.

Requirements

  • Apple Silicon Mac (built/tested on M4 Pro, 24 GB), plugged in, lid open, logged in overnight.
  • oMLX (Apple-MLX server) auto-running on :8090 with a model downloaded (default gpt-oss-20b; toggle qwen35_27b). Enforces an API key, auto-read from ~/.omlx/settings.json.
  • uv for Python env management.
  • Alpaca paper account + Finnhub free key.

Setup

# 1. Python env + deps
uv sync

# 2. Secrets
cp .env.example .env      # then paste your Alpaca paper + Finnhub keys

# 3. Model host — oMLX auto-starts on login; if not, bring it up + verify tool-calling
omlx start                                  # OpenAI-compatible API on http://127.0.0.1:8090
uv run python scripts/smoke_toolcalling.py  # GATE: multi-turn tool calls must PASS

# 4. Phase-0 gate
uv run pytest

Switch models any time with one line in .env: MODEL_PROFILE=gpt_oss or qwen35_27b.

Entry points

Command What it does
uv run python -m orchestration.run_nightly Nightly research run (all enabled agents → JSON). --compressed for a fast test
uv run python -m execution.run_market_open Morning: JSON → guardrails → Alpaca paper orders. --force to test while closed
uv run streamlit run web/dashboard.py Dashboard: positions, PnL, theses, orders, logs
uv run python -m reporting.report CLI summary

How it works

run_nightly starts oMLX, then runs Nova → Warren-lite → Atlas → Maverick sequentially (one model, time-sliced with rollover budgets; per-agent budgets are dashboard-editable). The roster comes from config/agent_registry.py (built-ins merged with state/agents.json). Each agent researches with tools (run_python for math, run_analysis for data/charts, web search/fetch, Alpaca/Finnhub/yfinance market data, options chains, get_portfolio for continuity) and its output is checkpointed incrementally to state/output/<date>/. Nudges keep agents researching broadly, steer them to the options mandate (each night's picks must include a researched single-leg option), and converge them near the end of their budget.

Each persona trades its own Alpaca paper account (Nova→agent1, Warren-lite→agent2, Atlas→agent3, Maverick→agent4 — Maverick is the deliberately aggressive options/shorts book), so the books — and their PnL — stay separate and comparable. run_market_open gates on Alpaca's clock, then per account applies execution/guardrails.py (position/day caps, sizing, buying-power, an options conviction floor + premium cap, and a reserved slot so the mandated option trade isn't trimmed) and places GTC bracket orders (marketable-limit entry so stop/take legs survive multi-day holds).

Adding an agent: use the dashboard's 🤖 Agents tab (clone a template, tweak knobs), create a fresh Alpaca paper account for it, enable options trading (level 2) on that account, and add ALPACA_<ID>_KEY / ALPACA_<ID>_SECRET to .env. Maverick ships built-in but still needs its own account keys the same way.

The differentiating layer

  • Market regime snapshot — SPY trend / VIX / sector momentum computed in code each night and injected into every agent's kickoff (shared ground truth).
  • Self-learning journal — each agent sees its own past picks marked-to-market before researching; losses and wins become explicit lessons.
  • AI Investment Committee — a Chief-Risk-Officer LLM pass reviews the whole book after research and issues per-pick verdicts (APPROVE / REDUCE / VETO with reasons). The memo lands in the Reports tab and the morning executor enforces the verdicts.

Automate it (America/Chicago)

  • 00:00–07:00 research (fair-share time-slicing: ~105 min/agent with 4 agents; tune per-agent budgets from the dashboard), machine woken at 23:55.
  • 08:30 execution (= 09:30 ET open; gated on Alpaca's clock, never local time).
scripts/install_launchd.sh                      # loads the 3 launchd jobs
sudo pmset repeat wakeorpoweron MTWRFSU 23:55:00 # one-time: wake the Mac nightly (needs sudo)

Overnight requirements: plugged in, lid open, logged in (lock screen OK), oMLX running, .env filled. Remove with scripts/uninstall_launchd.sh + sudo pmset repeat cancel.

Instruments & safety

  • Trades stocks (long or short) and single-leg long options (buy calls/puts). Per-trade
    • per-day caps; stops/takes enforced in code, not trusted from the LLM. Shorts use inverted brackets; options are sized by premium×100 (max loss = premium; see docs/options-phase.md).
  • run_python executes model-generated code locally — kept math-only, sandboxed, no network.
S
Description
Recovered from Google Drive GitHub backup
Readme
6.3 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 98.7%
Shell 1.3%