DEV Community

Chris
Chris

Posted on

I run an AI trading firm on a used Mac Mini. Here is how it is put together.

Three months ago I wanted to know whether a set of AI agents could run a research desk end to end without me sitting over them. So I built one. It has been running since May on a used Mac Mini I paid $343 for, and everything it does gets published.

Paper money only. Up 4.47% since May, worst drawdown along the way was 5.3%. That is not the interesting part. The interesting part is what breaks.

No dependencies

The whole thing is the Python standard library plus sqlite3. No third party packages at all.

That sounds like a constraint I would regret and it has not been. What I gave up: pandas, requests, a dozen convenience libraries. What I got: nothing to pin, nothing to resolve, no virtualenv to activate, and it runs on a fresh machine with nothing but Python on it.

I have never lost an evening to a broken install, and that used to be most of my lost evenings.

If you are building something that has to run unattended for months, the dependency you do not have is the one that cannot break at 9:35 on a Tuesday.

launchd, not cron, not Docker

Every job is a launchd agent. Market open trigger, per-strategy executors, data fetch, sync, publish.

Two things I learned the hard way.

The machine going to sleep will silently kill your schedule. I lost a signal because the Mac dozed through a 15:50 window and nothing anywhere told me. The fix is a caffeinate -i -s job with KeepAlive that never gets unloaded. It looks ridiculous sitting in the agent list. Leave it there.

StartCalendarInterval fires on wall clock, not on completion. If a job runs longer than its interval you now have two of them fighting over the same state file.

One account per strategy

Seven strategies, seven separate broker accounts. This is the single best decision in the system.

Blend them into one account and a losing strategy hides inside a winning month forever. Split them and every month tells you which one actually earned it. Last week I shut one down because its edge turned out to be an artifact of the parameter grid I had searched rather than anything real. I only knew because it had its own equity curve to look at.

The cost is bookkeeping. Worth it.

The failure that taught me the most

A strategy hit its kill threshold and halted. It flattened its positions at the broker correctly. Then it returned before writing that back to its own state file.

For two days the code believed it held three positions that did not exist. Nothing crashed. Nothing logged an error. Every downstream job read a state file that was quietly wrong.

I found it by diffing local state against the broker's positions endpoint, which is now something that runs on a schedule instead of whenever I happen to think of it.

The lesson generalises well past trading. Your stop path has to finish writing state, not just stop. An early return in an error branch is exactly where this hides, because the happy path is the one you tested.

Measure, do not model

I assumed my fills were 5 to 10 basis points optimistic. Then I pulled 125 real filled orders and compared each one against that session's close. The median was -5.9 bps on market entries, and 43% of them filled better than the close. My estimate was worse than reality.

One caveat if you try this: split the audit by order type. Stop and limit exits fill when the market is moving against you, that is the entire point of them, so leaving those in makes your entries look far worse than they are.

Same pattern on my own website. I spent weeks convinced I had a traffic problem. Added a beacon and found people were reaching the final step, hitting an OS security warning, then following instructions on my own page that had stopped working on current macOS.

Both times I had a strong belief and no measurement, and both times the measurement said something else.

Where it is now

It runs unattended. Market opens, agents pull their data, size positions, place orders, log what they did, publish it. I read a summary at night.

Happy to answer anything about the agent setup, keeping scheduled jobs alive on a Mac, going dependency free, or how the isolation is wired.

Top comments (0)