Take firms from the master instead of defining them per machine

This box no longer decides what firms exist. It caches the master's catalog
and stores one thing of its own: the Tradovate login for each firm. Creating
firms locally is gone — app/add, POST /api/firms, the account-config routes
and the banned-symbol route with it.

The cache is the point, not an optimisation. The scheduler needs every
account's target and size on each 60s tick, so fetching them per tick would
stop trading with positions open the first time the master rebooted. It is
one JSON blob in settings, replaced only by a complete valid response, and a
response with zero firms is refused outright: a misconfigured FIRMS_DB serves
{"firms":[]} as a healthy 200, and mirroring that would idle the whole fleet
at once.

Accounts bind to an account type by prefix AND size, the size taken from the
opening funding transaction. That does not arrive with the first sync, so an
account sits Unassigned and the resolver tries again next sync rather than
guessing. A type picked by hand is never overwritten by an auto pass. This
replaces the longest-prefix helper that had been copy-pasted into five files,
which could not tell two types with the same prefix apart at all.

firm_credentials and account_assignments deliberately have no foreign key to
the cached catalog. foreign_keys is ON, so a cascade would erase the Tradovate
passwords the moment a firm was removed on the master — routine, not
exceptional. They survive it, and are re-keyed by name if the master's database
is ever rebuilt with fresh ids.

The legacy firms/account_configs/firm_banned_symbols tables are left on disk,
unreferenced. firms is the only table that ever held plaintext credentials and
dropping it would make a rollback unrecoverable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-08-31 22:17:23 -05:00
co-authored by Claude Opus 5
parent 8b2e78d766
commit 8bdc85080c
27 changed files with 1489 additions and 1311 deletions
+15 -5
View File
@@ -70,12 +70,22 @@ The dashboard runs on port **3000**: `http://localhost:3000`.
On first run, the SQLite database (`autotrader.sqlite`) is created automatically in the project root. No migrations need to be run manually.
Open the app in your browser and add your firms through the UI:
Firms and their account types live on the master dashboard, not here — every
machine pulls the same catalog so they cannot drift apart. This machine only
stores the Tradovate login for each firm.
1. Click **+ Add Firm** on the main page
2. Enter the firm name, Tradovate username, and password
3. Go to the firm's **Settings** page to configure account types (prefix, profit target, consistency %, etc.)
4. Return to the main page — accounts will populate once the firm connects to Tradovate
1. On the **master dashboard**, open **Firms**, add the firm, and give it one
account type per prefix + account size combination (profit target,
consistency %, min trading days, and so on)
2. Set **Dashboard URL** on this machine's **Settings** page so it can reach the
master. The catalog is pulled at startup and then every 60 seconds
3. On the main page, each firm from the catalog appears. Firms without stored
credentials are greyed out — enter the Tradovate username and password in the
fields beside the firm name and click **Save**
4. Accounts populate once the firm connects. Each is matched to an account type
by its name prefix *and* its size, so a new account shows as **Unassigned**
until its opening funding transaction has been fetched. Use the **Account
Type** dropdown to pin one by hand; a manual pick is never overwritten
---