Over eight weeks I built a safety-first, AI-assisted crypto trading system, drilled it until it held, and tested every strategy honestly. None beat simply holding Bitcoin after real fees, so it never traded real money. That result is the point, and the whole thing is now open source as Guarded Trader.
Why I built it
I wanted a self-improving AI trader, and I wanted it to be impossible for it to hurt me. So before writing any code, I wrote four rules and made the system enforce them:
- One deposit of $100, never topped up. The worst case is bounded from day one.
- It trades only that $100 plus its own profit. No other money in the account counts.
- Profit above a daily cap is fenced off for me to withdraw by hand. The system can never move money.
- Hard loss limits halt trading, and only a human can resume it.
One principle sat above all of them: the AI may propose strategies, but it never places an order. Every idea from the language model is treated as an untrusted proposal until deterministic tests say otherwise.
This came out of early research. Public experiments that let large language models trade real money directly mostly lost, largely to over-trading and fees. I did not want to repeat that.
What I built
Guarded Trader splits the system into two trust domains: a boring, deterministic execution side, and a research side where AI ideas live until they earn their way across.
| Layer | What it does | Why it matters |
|---|---|---|
| Freqtrade | Executes orders, runs built-in protections | Mature, open-source execution; dry-run and live share one code path |
| Conductor (my service) | Ledger, capital rules, risk checks, kill switch, Telegram control, dashboard | A second, independent safety layer that derives risk from its own ledger |
| Research harness | Walk-forward backtests, trial registry, random-entry baseline | Stops lucky backtests from looking like skill |
| Code admission gate | Static checks and a no-network sandbox for AI-written strategies | AI output is untrusted code until proven otherwise |
| Hosting | Hetzner VPS, zero public ports, Tailscale-only access | Nothing to attack from the internet |
A few design choices did most of the work:
- Fail closed. Freqtrade boots paused. Conductor starts it only if no halt is active.
- Halts survive everything. They live in the ledger, so restarts, crashes and even a full server rebuild cannot clear them.
-
Every destructive command needs a code.
/kill,/flattenand/resumein Telegram each ask for a one-time confirmation code within 60 seconds. - Keys can never withdraw. The exchange key is created without withdrawal rights and checked by a script before every go-live.
How I tried to break it
Safety features you never test are just hopes. Before any real money, I ran six drills against the live server, and all six passed.
| Drill | What I did | What it proved |
|---|---|---|
| Kill switch |
/kill from my phone |
New entries paused in about 10 seconds |
| Nuclear |
/flatten with a position open |
Orders cancelled, position closed, bot stopped, halt saved |
| Restart under a halt | Restarted every container mid-halt | The bot never resumed by itself |
| Heartbeat silence | Stopped the control service | An independent watchdog alerted me within about 11 minutes |
| Backup and restore | Restored the ledger from off-site backups | Data intact, integrity checks clean |
| Full rebuild | Destroyed and recreated the server from code | Same IP, same data, still halted, in about 85 minutes |
The drills also found real bugs before money was at stake. A firewall rule that Terraform reported as removed was still open. An environment variable silently re-enabled the exchange bot's own Telegram commands. A mistyped key ID made the server's private-network join fail without a clear error. Each became a fix and a test.
What the evidence said
No strategy survived real costs. At my exchange's real fee tier (0.80% per trade for small accounts, plus slippage), every candidate lost money, none beat random entries, and holding Bitcoin beat them all.
| Strategy (Jan 2022 to Oct 2026, $100 start) | Net result | Max drawdown | Beat random entries? |
|---|---|---|---|
| BTC buy-and-hold (benchmark) | +$75 | 67% | — |
| EMA cross, no stop (C05) | −$61 | 83% | No |
| Baseline EMA cross with ATR stop | −$65 | 84% | No |
| Weekly momentum + volatility sizing (C04) | −$30 | 38% | No |
| Weekly momentum (C01) | −$89 | 92% | No |
Three findings mattered more than any single number:
- Fees were the whole story. An early four-month backtest showed +18%. Over two years it was −2.8% at old fee assumptions, and −46% once the real fee tier was verified.
- Sample size lies. That +18% came almost entirely from three trades the backtest force-closed at the end of the data.
- Many tries manufacture luck. If an AI proposes hundreds of strategies, the best one will look good by chance. The harness now registers every trial and compares each candidate against a random-entry baseline.
A lower-fee Canadian exchange improved one strategy enough to beat random entries for the first time, but it still failed at the exchange's true cost including spreads. That exchange also could not prove an API key was unable to withdraw, so it was rejected for live use.
What I learned
The most valuable thing the system did was stop me from losing money on strategies that did not work. Five lessons carry well beyond trading:
- Let AI propose, and let code decide. The language model was most useful as a researcher and code reviewer, never as the decision-maker.
- Write the rules before the code. Fixing the four capital rules first made every later design decision easy.
- Drill your safety features. Every drill I ran found something that tests alone had missed.
- Model real costs from day one. A fee assumption off by 3× turned a "promising" strategy into a steady loss.
- Publish negative results. Most trading projects show only winners. An honest "it didn't work, and here is why" is rarer and more useful.
Try it
Guarded Trader is open source under Apache-2.0 at github.com/aplicy-com/guarded-trader. It runs in dry-run (paper trading) by default, and every runbook, drill result and failed backtest is in the repo.
- Run it: clone the repo and follow the dry-run quick start in the README. No exchange key or money needed.
- Contribute: issues labelled "good first issue" are a good start. Strategy proposals must be pre-registered before they are tested.
- Support it: if the project saved you time or money, a star on GitHub helps others find it. You can also buy me a coffee.
This is not financial advice, and nothing here shows a way to make money trading. It shows how to find out safely whether you can.
Top comments (0)