In developmentPython · SQLite · Interactive Brokers

Four applications,
pointed the same way.

An automated trading operation is not one program. It is a chain: something decides an idea is worth taking, something places and defends the order, something reconstructs what actually happened, and something reads the accumulation. We built all four, for ourselves, and gave every surface that can move money a way to fail closed.

The trading desk interface: a dark screen with open positions, pending orders, an order entry panel and a live activity log
The pipeline

Each app owns one job and hands over cleanly.

The boundaries are the design. The app that scores an idea cannot size it; the app that places an order does not decide whether the idea was any good; the app that reports on the result cannot write to the record it reads. When something goes wrong, the boundary tells you which program to open.

  1. Idea Feeder

    Reads and scores

    Watches a high-noise chat channel and a pre-market volume scan, extracts one candidate at a time, and scores it against a strategy's parameters using live broker data. It sizes nothing and manages nothing. Its only output is a flag: this one qualifies.

    Chat + scanner → scored idea
  2. Trading App

    Places and defends

    Takes a flagged idea and owns everything after it: the entry, the stop, the size, the partial exits, and the interlocks that cancel or flatten when the tape stops behaving. It is the only application here that can send an order.

    Idea → order → position
  3. Trade Importer

    Reconstructs what happened

    Reads the trading app's journal, snapshots it, and rebuilds each round trip from the broker's own historical bars — profit, R multiple, commission, session extremes and every exit leg. It never opens the live journal for writing.

    Journal → enriched record
  4. Trade Analyzer

    Reviews the accumulation

    Runs unattended after the importer and appends to a cumulative file per strategy. One session cannot answer whether an approach works; a hundred of them, recorded the same way each time, can begin to.

    Record → cumulative review
The handover

One direction, and no way back up the chain.

An idea travels forward and never returns. The feeder dispatches an intent and stops caring; the trading app is free to move its own trigger as the shape changes, and does. That means the two disagree about the entry price by design — so the record keeps both, and the difference between them is a column rather than a thing nobody noticed.

The same rule governs the review half. The trading app declares what a strategy is, once. The importer reads that declaration rather than inventing a taxonomy of its own, so the two cannot drift apart quietly. A value the declaration does not name is filed as uncategorised and shows up in the reports, which is the point.

  1. Hearchat line or volume scan
  2. Qualifygates, then a score
  3. Placeentry, stop, size
  4. Defendinterlocks and partial exits
  5. Reconstructbroker bars, real fills
  6. Reviewappended, never overwritten
Failing closed

The dangerous direction is the one that looks like it worked.

Software that can spend money has a failure mode ordinary software does not: carrying on confidently with a wrong premise. Most of the design effort here goes into making that impossible rather than unlikely.

  • The control surfaces are not on the internet

    The desk front end and the phone panel refuse to bind to anything but a private-network address. That check runs when settings load, not when the socket opens, so a configuration that would expose them never starts at all.

  • The lock matches what the surface can do

    The phone panel guards a profit figure, a switch and a flatten — the safe direction — behind four digits. The desk front end can open positions, so it takes a passphrase, holds its own secret rather than sharing the panel's, and has a read-only mode for a screen you only watch.

  • A missing broker is a refusal, not a guess

    The app is bound to a specific account and will not trade without it. When the connection is not there, it says so in the banner and stages nothing. Nothing here degrades quietly into a state that looks like it is working.

  • The review tools are read-only by construction

    The importer and the analyzer read a live real-money database. They copy it with its write-ahead sidecars and read the copy. Neither of them holds a write handle to the original at any point.

A dark screen showing only a small panel that reads Trading Desk, This page can stage trades, and a passphrase field
The desk front end shows nothing at all until it is unlocked — and refuses to listen in the first place if no passphrase has been set.
The record

The reporting is only worth what the reconstruction is worth.

A trade is not one row anywhere. It is an intent in one application, a sequence of state changes in another, and a set of fills at the broker. Putting those back together correctly is most of the work, and getting it subtly wrong is how a review tool starts lying quietly.

The event log is not the event log

Some events never reach the table.

Adding an event to a trade in memory does not by itself write a row; only certain transitions do. Everything raised while a trade is being built — the derived stop and the rule behind it, the risk decision, the liquidity probe, the size cap — lives in the snapshot instead. Over three sessions the snapshot held every row the table did and a hundred and twenty-six more.

A measurement and a bound are not the same

An absent number can be correct.

The adverse extreme is deliberately suppressed on a trade that was stopped, because its adverse extreme is the stop and restates a column already on the row. Where a lower bound is derived instead, the record says which of the two you are reading — so nothing can average a bound in with a measurement and call the result a figure.

Capture on the day or not at all

Some inputs expire.

Part of the trading app's own notification history is pruned after about a week, and some defensive notes live there and nowhere else. The daily archive exists because of that: a session not captured on the day is gone, which is the argument for running the review from the first day rather than intending to backfill later.

Audits

Read the code as though it is already wrong.

Several times now the whole tree has been read end to end looking for behaviour that raises nothing, logs nothing unusual, and is wrong anyway. The findings are dated, kept, and answered in writing.

What an audit is for here

The expensive failures were the silent ones.

The defects worth the audits were never crashes. A stale quote was preferred over a fresher one, so a promoted idea was watched against a price frozen at the moment it was promoted. A failed alert marked itself as delivered and started its own re-alert timer, silencing the next hour. Neither raised anything.

Written down, then answered

Each audit has a remediation plan beside it.

The plans record what was actually built against what was planned, including the places the plan itself was wrong and the tests said so. An audit nobody acted on is labelled as such rather than left to look like work.

Re-run from scratch

The second pass deliberately did not read the first.

A later audit re-ran every check without looking at the earlier findings, so anything it reported was reached independently. It found two defects that would have cost money and that the test suite could not see, because the test doubles could not express the failure.

A dark panel headed Data Integrity, listing twelve named consistency checks each answered none, ending with the line: All 12 checks ran and found nothing
The habit ends up in the software. Every session is run past the same twelve consistency checks between the four applications, and the report says how many ran rather than only what they found — so a check that quietly stopped running cannot look like a clean session. Demonstration data.
The screens

Dense on purpose.

These are working tools for one operator who already knows what every column means. They are not trying to be approachable; they are trying to put the whole state of a session on one screen without a scroll. Every image below uses fabricated data and invented names.