Ten months of solo build and operation of an automated intraday equities platform, plus the research rig that decides what is allowed anywhere near live capital. This page is about the engineering and the process. The strategy is not here, on purpose.
The platform watches a rotating pool of US equities through the pre-market and opening session, evaluates entry and exit conditions once per second against live and reconstructed bars, and routes the resulting orders to a broker. It runs unattended from before 04:00 ET, supervises itself, records everything it saw, and reconciles against the broker's own record at the end of the day.
Several strategy variants run side by side. Some trade real capital. Others run in shadow mode on the same live feed, taking no positions, so a candidate can be measured against production conditions for weeks before anyone argues for promoting it.
One screen decides whether the day proceeds. Per-engine attribution across each session window sits at the top, the ranked candidate universe on the left, and one card per active slot showing what every engine currently thinks about that symbol. A single entry and exit is running through it below; the trade lands in the blotter underneath as it closes.
| WINDOW 1 | WINDOW 2 | SESSION | |
|---|---|---|---|
| Engine 1 | 5 | 19 | 24 |
| Engine B | 2 | 7 | 9 |
| Engine 2 | 4 | 13 | 17 |
| Engine C | 1 | 5 | 6 |
1SUNE$3.82121.06M
2FTFT$2.6178.03M
3YMAT$2.3036.03M
4ODD$16.5711.91M
5TNON$2.6911.48M
6BIAF$10.6810.41M
7TENX$2.139.15M
8FJET$2.057.30M
9BNC$4.565.98M
10LABT$2.285.08M
| IN | SYM | ENTRY | QTY | P/L |
|---|---|---|---|---|
| 10:44:50 | BIAF | $11.28 | 443 | |
| 10:29:36 | SUNE | $3.39 | 1474 | |
| 10:26:06 | BIAF | $11.32 | 441 | |
| 10:10:36 | SUNE | $3.18 | 1572 | |
| 10:03:46 | SUNE | $3.13 | 1594 | |
| 10:01:21 | BIAF | $11.37 | 439 | |
| 09:57:56 | SUNE | $3.13 | 1597 | |
| 09:47:41 | BIAF | $11.25 | 444 | |
| 09:41:41 | BIAF | $11.59 | 431 | |
| ALL | 17 trades |
The single design decision I would defend hardest is the split below. Orders leave on a send-only webhook. Everything that reads account state — the watchdog's ground truth, the operator panel, the end-of-day reconciliation — comes back over a separate, credential-scoped read-only API that has no order endpoint at all.
The result is that the component most likely to have a bug under stress, the supervisor deciding whether to intervene, is reading from a path that cannot itself cause a trade.
None of these were designed up front. Each is the permanent residue of something that went wrong once, in production, with money on it.
| Control | The failure it prevents | Origin |
|---|---|---|
| Reduce-only exits | An entry that never filled left the exit free to open a fresh short instead of closing nothing.Exits are now structurally incapable of increasing exposure. | Incident |
| Confirm-before-arm | A variant could be armed for live routing without anyone stating the account and mode out loud. | Incident |
| Boot-order preflight | A convenience launcher changed how the process was invoked, which silently disabled a bridge that keyed off the launch path.Preflight now asserts the launch contract before the market opens and fails loudly. | Incident |
| Recorder boot check | The evidence recorder only started from certain launchers. Three sessions of bar data were lost with no error anywhere.Absence of data is now itself an alarm. | Incident |
| Credential validity check | A mistyped path pointed at a token file that did not exist, so the check on token age passed while the credential was dead.Freshness is not validity — the check now proves the token works. | Incident |
| Supervised stop path | A network-level kill switch blocked the exit path along with the entry path, leaving open positions with no way out.Replaced with a stop that flattens first, then stops. | Incident |
| Watchlist freshness gate | A frozen upstream terminal served yesterday's candidates as if they were today's. | Incident |
| Duplicate-process detection | Two copies of the same engine means two orders per signal; two copies of the feed means a rate-limit storm. | Pre-emptive |
A production incident is not closed by a runbook note. It is closed by an automated check that would have caught it, running before the next session. A runbook entry depends on a human remembering at 4am. A check does not.
The live code tree is immutable while running. Every change ships as a dated package that states exactly which files it touches, installs itself, and can revert itself. Thirty-five such packages exist, each one a permanent record of what changed and why.
Before a package is accepted, the entire tree is hashed and compared file by file against the running baseline. The deploy note has to show the expected modification count and nothing else. Then the revert is run and the tree is hashed again, and it has to come back byte-identical. A change that cannot prove it undoes itself does not ship.
A new entry filter. Scope: one 14-line insertion into the launcher, one operator-panel card, two new files. Install proof: 2 modified, 4 added, 0 missing against the running baseline. Revert proof: 0 modified, 0 added, 0 missing — byte-identical. Shipped in observe mode, blocking nothing, on an audit of 26 of 26 cases.
Nothing reaches the live system on the strength of a backtest alone. The research platform reconstructs each candidate trade from one-second bars and then asks two independent questions about it, from two sources that do not share a failure mode:
Recorder files are named for the session they were opened in, not the session they contain, and several open the evening before. Indexing by filename produced a fake 62% "the system never saw it" rate that was entirely an artefact. Files are now indexed by the real time span of their contents.
Separately, the reconstruction's exits resolve against bar wicks, which is the optimistic end of the range. That is stated on every result the rig produces rather than discovered later by whoever reads it.
The research backlog ran to roughly twenty candidate changes. The majority were killed. Two examples are worth stating plainly, because they are the reason I trust the remaining ones at all.
| Candidate | What the first result said | What the audit found | Call |
|---|---|---|---|
| Variant with the strongest backtest | A large positive return across the sample. | The entire result traced to a single overnight data gap the walk-forward treated as a continuous session. Corrected, the same variant lost heavily.The bug was systemic and invalidated a whole class of earlier results, which were re-run. | Killed |
| A gate-window filter | A clean improvement across the book. | The windows were counting bars rather than seconds, admitting roughly 8% phantom trades that could not have existed live. | Killed |
| Shadow variants on the live feed | Promising on paper. | Run in shadow against production conditions instead of promoted on the backtest. | Observing |
The live sample is roughly 46 to 47 trading days. A power analysis on that sample says it is far short of what would be needed to separate a real effect from noise for changes of the size being tested. Every in-sample filter result the rig produces is therefore reported as suggestive, never as a win. Reporting an underpowered result as a win is the single most expensive mistake available in this domain, and the discipline not to do it is the deliverable.
Effectively all of the implementation was produced with an AI coding agent. I did not write most of these 381 modules by hand, and I would not claim otherwise. What I did own is the part that makes the output usable: the specification, the acceptance criteria, the verification, and the decision to ship or not.
That division is the whole reason the change-control machinery above exists. An agent that can produce a working feature in an hour can also produce a plausible-looking one that quietly breaks a dependency three files away. Hash-proofed additive packages, observe-mode rollout, install-order audits and a pre-session QC harness are not bureaucracy — they are the control surface that makes fast AI-generated change safe to put in front of real capital.
Ambiguous strategy intent turned into testable specifications with per-variant acceptance criteria, so "is this better?" became a question with a defined answer.
An additive-only process with verifiable rollback, adopted because the system could not be taken offline to fix a bad deploy.
Failure modes enumerated at the channel level, not the feature level. Read and write paths separated so the supervisor cannot cause the event it supervises.
Root-cause analysis on live incidents, each closed by permanent automated coverage rather than documentation.
A ~20-item backlog ranked against statistical power, with candidates cancelled on evidence including the one with the best headline result.
Self-contained analytics dashboards built so a decision-maker can reach the go/no-go call themselves, including when the honest answer is "inconclusive".
Three market-data providers and a broker routing layer, each with its own liveness contract, credential lifecycle and documented failure behaviour.
A system that starts before 04:00 ET unattended, supervises itself, and reconciles against the broker's record daily.