AI trading swarm
A committee of AI analysts that reads point-in-time market data, cites every claim and hands its ideas to Strategy Orchestra to test, with a human approving each idea and every number reproduced before a strategy counts.
- Python
- PostgreSQL
- TradingAgents
- LangGraph
- LM Studio
- FastAPI
- React
- earlier strategies reproduced from stored data, 21 of 21 metrics each
- 10 of 10
- earlier strategies reproduced from stored data, 21 of 21 metrics each
- tests pass on a clean copy, 281 of them against a real PostgreSQL
- 808 of 824
- tests pass on a clean copy, 281 of them against a real PostgreSQL
- design decisions logged, each with its context and consequences
- 71
- design decisions logged, each with its context and consequences
Personal research. Not investment advice. Backtested and paper-traded results are hypothetical.
Problem
I wanted AI agents to do the research before a strategy is built: collect market and text data, argue for an idea from the evidence, and hand that idea to Strategy Orchestra, my strategy-testing system, to build and test. And I wanted to check every step myself before calling any strategy workable.
Two things make that hard with LLM agents:
- Look-ahead. An agent that can see data from after its decision date will find patterns that never existed at the time. The open-source analysts I built on, TradingAgents, have a changelog full of look-ahead bugs fixed one by one.
- Unsupported claims. A model will write a confident paragraph whether or not the data backs it. If I can't see what it read, I can't tell the difference.
So everything has to be checkable after the fact: what each agent read, what it said, what each model was asked and answered, and whether the numbers hold when rerun.
Constraints
- Point-in-time or nothing. Raw data is never edited. A corrected price history or an edited article is stored as a new version beside the old one, and agents can only read through a layer that takes an as-of time.
- Local models first. The analysts run on models in LM Studio on my Mac, for cost and privacy, with cloud models as optional fallbacks. Local models answer one request at a time, and a reasoning model can spend its whole output budget thinking.
- Strategy Orchestra stays unchanged. Its guards against fooling itself only work if nothing else edits its code, configs or shared state. It also needs its own Python interpreter.
- Research only. Nothing in this project places orders. A test scans every module for broker order calls.
- One user, one machine. The API listens on loopback only, and every action that changes something asks for the token again.
Design
Critic
One call reads every assessment with the ids it cites and returns challenges and a verdict for each: accept, weaken or reject. Assessments the answer skips are sent back once, in a second recorded call. A challenge may cite only records the session read, five at most. There's no debate round after it.
for item in answer.critiques:
if item.target_agent not in agents or item.target_agent in out:
continue
backed = [r.strip().strip("[]") for r in item.record_ids]
read = [r for r in dict.fromkeys(backed) if r in allowed][:MAX_CITES]The top row is data. Ten collectors (IBKR bars and news, FRED with its revision history, SEC filings, an economic calendar, Yahoo news and corporate actions, Polymarket, Reddit and StockTwits) write to PostgreSQL, and every collection is logged with what it fetched and what failed. Agents read only through the as-of layer, which logs every read with the ids of the records it returned. A model router records every model call, failed ones too.
The middle row is the committee, and it runs right to left. News and Sentiment are TradingAgents' own analysts, with every data tool answered from my store instead of the web. Macro/Regime, Technical and a Quant Miner compute their findings in code. A Critic then gives every assessment a verdict, and the thesis turns the surviving evidence into a goal for Strategy Orchestra.
The bottom row is the campaign. I approve the thesis, and the bridge starts Strategy Orchestra in its own process with an export of the data as it stood when the thesis was written. Each strategy it judges is then rerun from stored data, compared with buy-and-hold, and comes back to me for review.
| Step | A model decides | Code decides | I decide |
|---|---|---|---|
| Analysts | How to read the findings and the news | Every measured number, the evidence window, which records may be cited | |
| Critic | Each verdict and its challenges | Five citations at most, all records the session read; skipped ones sent back once | |
| Thesis | The argument and the goal | The test periods, orchestra's archetypes only, long only | Approve or reject |
| Campaign | Orchestra's proposals and the Judge's commentary | Orchestra's engine and scores, the data export, launch settings | Settings and checkpoints |
| Review | Whether the replay matches, the edge over buy-and-hold, the workable flag | Confirm, reject or defer |
Key decisions
- Point-in-time by construction. Every record carries the time it became knowable. Bars are served from the version downloaded by the as-of time, and only once the bar has closed. Thirteen leakage tests cover the tables agents read. The alternative was being careful in each agent, which is how TradingAgents ended up fixing look-ahead bugs one at a time.
- Measure in code, let the model judge. Numbers a model computes can't be audited; numbers code computes from cited records can. The Technical analyst scores orchestra's seven strategy archetypes on weekly, daily and 15-minute bars, and its model call has to say why when it disagrees with a baseline computed in code.
- Evidence stops where the test starts. Measured evidence ends the day before Strategy Orchestra's forward-test window, placed exactly where orchestra will place it. Otherwise a campaign would be graded on the data its idea came from.
- One Critic round, no debates. Bull-versus-bear debates and panels of investor personas cost more calls and drift toward agreement, because every participant reads the same inputs. One Critic gives every claim a verdict, and the whole thread stays short enough to read.
- The draft is the thesis. Local models wrote a good thesis as prose but wouldn't copy it into JSON; one answer came back as a placeholder telling itself to copy the text. Code now reads the sections out of the draft, and a second, short call returns only the structure.
- Strategy Orchestra runs unchanged. It runs as a subprocess in its own interpreter, with its model calls recorded through a wrapper. The data export is hashed, and the entry refuses a file that changed. Its bandit and crossover are off for these campaigns, so every slot goes to the thesis's own ideas.
- Built with an AI coding agent under a written contract. Ten hard rules, a plan where each step ends with a checkpoint I review, and a decision log of 71 entries, many recording a failure found in a live run and the fix that followed.
Evidence
The code, checked on a clean copy in October 2026:
- 808 of 824 tests pass. 281 run against a real PostgreSQL and 63 cover the UI. The other 16 need Strategy Orchestra or the network beside the project, or depend on the machine they run on.
- Strict type checking and linting are clean, across 177 Python modules.
In live use, September and October 2026:
- Data. 75 symbols of 15-minute bars, 18 FRED series with their revision history, filings, news and prediction markets. The export Strategy Orchestra reads matched the original data file bar for bar, for all 75 symbols.
- Reproducible numbers. The first real strategy replayed matched all 30 metrics its run had stored. All ten strategies from orchestra's earlier hall of fame matched 21 of 21.
- The Critic at work. In one TQQQ session it accepted one assessment, weakened two and rejected two. One it rejected was the Quant Miner's best rule, which won 75.6% of 78 training bars and 28.7% of 101 later ones.
The research result is still open. By early October, none of the ten strategies that had passed orchestra's Judge beat buying and holding SPY in any test window, so I wrote down what "workable" means: a Sharpe ratio at least as good as buy-and-hold's, a worst loss no more than two thirds of it, and at least half its return, both in the forward test and on data no run has seen. Of 15 candidates from the committee's campaigns by 8 October, 6 were lost when the local model failed to answer and 4 failed orchestra's quick checks. None of the committee's own ideas had been judged yet. The one strategy I've confirmed came from an orchestra run made before this project.
What I'd change
- Get a committee idea to the Judge. Most losses so far were the local model spending its budget thinking. Choosing the model at launch helps, and the funnel now shows where each candidate is lost.
- Lean toward daily bars. Across orchestra's runs, 6 strategies on 15-minute bars reached the Judge and 144 failed the quick checks; on daily bars it was 332 and 301. At about 0.4% a round trip, one 15-minute candidate traded 1,052 times and lost money in every rolling window.
- Make the last tests independent of my machine. One test looks up a real host name, and one compares the order of reads made by parallel tool calls.
- Merge the step branches and keep a copy off the Mac. The work sits on a stack of branches, one per plan step.
- Wire it to the execution engine only after a strategy passes the workable rule. Execution is the last step of the plan, and it stays deferred until then.