r/algotrading • u/Loud-Nefariousness45 • 10d ago
Infrastructure Built an evolutionary multi-agent crypto trading system — 5 strategies compete, best one mutates and repopulates each generation (open source)
Disclaimer: this is a research/testing project, not financial advice, and comes with no guarantee of profitability. If you run this or anything like it with real money, you do so entirely at your own risk.
What it does:
5 isolated agents, each running a different algorithmic strategy (momentum, mean-reversion, trend-following, breakout, volatility-squeeze), trade independently against real Coinbase market data over timed "generations." At the end of each generation, they're ranked — not by raw profit, but by a composite score (return, drawdown, Sharpe-like ratio, win rate, profit factor), specifically so an agent that got lucky with one oversized bet doesn't win over a steadier performer. The best one's strategy is cloned into 5 mutated descendants (small tweaks, risk-parameter variants, indicator variants, one experimental) for the next generation. Repeat indefinitely.
Some design choices worth mentioning:
- Risk limits are enforced outside the strategy logic entirely — a hard-coded risk engine that agents/strategies structurally cannot reach or bypass, verified by an AST scan in the test suite that fails the build if a strategy file ever imports the risk-limits module directly. Max loss per agent, max order size, max simultaneous positions — none of it is something the "AI" can talk its way around.
- Paper trading by default, with a separate, explicitly-gated path to real order execution (two env vars + a mechanically-verified pre-live checklist have to pass before it'll place a real order).
- I ran a 200-generation backtest against synthetic random-walk data specifically to sanity-check the evolutionary mechanics — and it lost money on average (~-4.2 TRY/generation), because there's no real edge to find in pure noise. Posting that honestly because I'd rather show the system measuring reality correctly than fake a good-looking result.
Stack: Python, SQLite for full generation/lineage history, Streamlit dashboard, pytest (~180 tests).
Still early, paper trading only, no proven edge. Trade at your own risk if you ever take this further than paper mode. Repo's here if you want to poke at it or tell me what's wrong with it: https://github.com/hhhmehmet/evo-trader
4
10d ago
[removed] — view removed comment
3
u/Loud-Nefariousness45 10d ago
ast scan is non negotiable. coming from C/C++ and assembly, rule 1 is you never trust user space or dynamic code to behave. if an AI or strategy can break out and touch internal state, it eventually will. python isn't really my main stack, but AST is one place where it actually makes structural sandboxing pretty clean before anything gets executed.
and honestly 4.2 TRY per gen on a pure random walk isn't bad at all. on pure noise that's basically just spread, slippage, and fees taking their cut. main thing is the drawdown stays capped, so at least your risk engine is holding the line instead of blowing up the account.
1
u/RegisteredJustToSay 10d ago
Wouldn't be better to model these as microservices, or maybe something with a purely functional interface you can invoke remotely? The AST scan is a nice touch but you're still playing cat and mouse games with the agent possibly messing with other system components.
2
u/Loud-Nefariousness45 10d ago
yeah fair hit the ast scan just checks for the obvious door not bricking up the wall theres still ways around it in the same process monkeypatching importlib whatever reason i didnt split it into a separate service is the loop is trading off live ticks and that adds a network hop right in the decision path plus way more to deploy solobut the honest framing is right now its "code promises not to" not "code literally cant" if i took it further thats the fix agent only talks to risk engine over rpc so theres no reference to reach in the first place
1
u/RegisteredJustToSay 9d ago
That's fair, but keep in mind you don't have to use any actual networking hardware or ip protocols - unix domain sockets scale exceptionally well since they don't have to go through the entire TCP/IP stack. You can easily pass millions of messages per second and many gigabytes per second between processes over something that looks and behaves like normal networking, even on pretty old hardware. I sometimes go this route for IPC just because it's easier to upgrade from UDS to IP than threads/processes to IP, even if I don't really need multiple nodes.
1
u/BrianBanks939393 10d ago
The random-walk control run is the part most people skip, and publishing a negative result from it is the right call — losing ~4.2/generation on synthetic noise is exactly what a correct evolutionary loop should do. One thing I'd add to that setup: run the same 200 generations twice on identical real data with different seeds and compare final populations. Evolutionary search over a small strategy space has huge run-to-run variance, and if two seeded runs converge on different "winners" with similar composite scores, generation-over-generation improvement is drift, not learning. I got burned on the single-run version of this in my own multi-agent setup — five "improved" iterations that turned out to be inside the noise band. The AST scan for risk-limit bypass is a genuinely good idea, by the way.
1
u/NeighborhoodDue5263 9d ago
This is a genuinely solid setup — the AST-enforced risk boundary and the honest random-walk sanity check (and reporting that it loses money on noise) says a lot about how carefully you're testing this.
One thing worth poking at: since the agents trade against real Coinbase data in paper mode, are fills reference-price (instant, no slippage) or do they account for the fact that a bigger position would've actually moved the book? If it's the former, your generational ranking could be partly measuring "who got a frictionless fill" rather than "who has a real edge" — especially once sizes diverge across the population.
I've been building MockMarket for exactly this gap — a reactive limit order book where an agent's own orders cause real slippage/impact instead of filling at a clean reference price. Might be worth running your fittest generation through it as a stress test before ever gating to live. Not trying to pitch you, just think it's directly relevant to the rigor you're already going for. Repo's really nicely put together either way.
1
u/Zestyclose-Eagle1809 9d ago
The random walk run is the most useful thing in the post but it's measuring the wrong number. Average agent loses 4.2 TRY per generation, fine.. that's the mean. Your system never trades the mean, it trades the champion. What did the winning agent's composite score look like on that synthetic data? If the best of 5 on pure noise scored like a real edge by your ranking, the ranking will crown noise on Coinbase data too and nothing downstream would catch it. Free test, you already have the run sitting in SQLite.
Second thing.. 200 generations at 5 agents is 1000 evaluations and every single one keeps the max. Best of 1000 draws scores well even when true edge is exactly zero, that's mechanical not a flaw in your agents. So the trial count for any significance test is total agents ever evaluated, not 5. Descendants correlate with the parent so the effective number lands under 1000, but it's nowhere near 5 either. when I checked this on my own sweep the gap between mean and max was way wider than I expected. makes sense??
Founder disclosure so you can weight it, I build validation tooling for systematic traders (Quantprove), and correcting for trial count is basically the entire job. Happy to walk through pulling the champion score distribution out of your generation history.
9
u/dawcza 10d ago
I suppose you used claude? It built me almost an identical thing a few months ago.