Each instrument's volatility is measured at the first good sync (or pick) of
a trade date and held for the day, so a day's sizing and hold estimate stay
put. The dashboard shows each DXtrade account's next-leg hold ("hold ~Nh")
with its symbol, notional, volatility and win odds. Accounts the firm has
closed (TERMINATED, EXPIRED, NO_TRADING) read as dead instead of inactive,
and skip the books check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tradeify247's API user may not read DXtrade market data (code 34), which
skipped every batch at the instrument pick. Quotes and hourly candles then
come from Hyperliquid's public API (BTC, ETH on the main dex; XYZ100, SP500
and tokenized stocks on trade[XYZ]) — for the pick and sizing only; orders,
fills and exit prices stay DXtrade's.
Closing STOP/LIMIT orders close the whole position by positionCode and must
not carry a quantity (code 33) — the exit bracket was refused, and the
daily-loss guard flattened both accounts. A close's fill price also falls
back to its executions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The symbol map's fixed notional per contract is gone: every DXtrade leg is
sized from the instrument's recent volatility for the firm's target hold
(blank = 12 h), and a candidate without a volatility isn't picked. Percent
commission and every-day trading are ignored on non-DXtrade firms, which keep
measured per-contract fees and the CME calendar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- DXtrade client (lib/dxtrade-class.ts): REST session login with lockout-safe
backoff, 60s sync of accounts/metrics/positions/orders/transfers, history and
fund transactions from cash transactions, day-start balance at the 22:00 UTC
reset, CLOSE-by-positionCode exits (native OCO group, else a stop-first
emulated pair), a cross-account hedge guard, stray-order reaper.
- Instrument selector: the firm's symbol map lists candidate symbols per CME
root; the cheapest tradable one per unit of recent hourly volatility wins
(spread + 2x commission [+ financing] / sigma).
- Fees: a firm's commission % of notional prices every fee off the fill; the
take-profit is solved in closed form so the leg nets its target.
- Hard daily loss limit per account type: every leg carries a stop keeping the
firm's day inside the limit less a 10% reserve and both fees (rounded in);
a green day never widens it; no room or a refused bracket flattens.
- Notional sizing where the platform prices positions: target-hold volatility
sizing or the symbol map's fixed notional, under a per-type notional cap.
- Every-day firms trade weekends/holidays; the scheduler runs lanes (futures,
one per DXtrade firm) with their own hours, flat gate, mutex and batches.
- The catalog sync skips platforms this build doesn't know instead of treating
them as Tradovate. One shared fireLeg replaces the duplicated batch/copy code.
- npm run check: fee/stop/sizing/hours/selector checks; scripts/dxtrade-smoke.mjs
confirms the API against a real login before trading.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The master clears a completed cycle once the payout it was waiting for has
left the account, and the balance going down is only visible from here.
Omitted rather than zeroed while an account's fund history hasn't loaded:
undercounting leaves an entry standing, a wrong zero would clear one early.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seventh review round (57835c0):
- An entry of unknown outcome is judged — filled after all, or never
filled — only on a good sync that started after its settle window and
with no order still working. A partial pass (position read failed or
predated the fill, trades read after it) can no longer release it as
"filled and flat" into a second entry.
- Tradovate counts every order not Filled/Canceled/Rejected/Expired/
Completed as working (PendingCancel, Unknown included).
- TopstepX: an account whose order ended with its outcome unknown gets its
open orders checked (Order/searchOpen) on each sync until none show, and
counts as holding a working order until then.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sixth review round (8e66631):
- An entry of unknown outcome is judged against a good sync that STARTED
at least 90s after it was declared unknown (lastSyncStartedAt: TopstepX's
pass start, Tradovate's request time), not one that merely ended then —
a sequential pass can read the account before a late fill.
- Once the broker shows its fill (a position, or realized P&L moved), the
entry becomes an ordinary filled one instead of holding the account for
the rest of the day.
- It never settles while the broker still shows a working order on the
account: Tradovate now reads working orders from the sync snapshot, and
its fill-timeout cancel checks Tradovate's answer instead of assuming it.
- A second wipe (after a restart) keeps the pending wipe's pre-wipe fund
signature instead of overwriting it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fifth review round (1eb0736):
- An entry now has three outcomes. Filled (confirmed): one-and-done is done
for the day. Never placed: leg taken back, free to retry. Unknown (an ack
or fill that never came back): the account — any mode — is held until a
good sync at least 90s later shows it flat with realized P&L unchanged,
then the leg is taken back and it may retry. Stop-after-all counts it in
play meanwhile. This closes both the day-long bench of 52ed9c7 and the
stacked re-entries of 1eb0736.
- Tradovate cancels an acked order whose fill didn't come within 30s (as
TopstepX already does), so a retry can't sit beside a still-working one.
- A wipe keeps the rebuild's guards: wipeAccountData leaves the Cash History
baseline, roll base, wipe hold, pre-wipe fund signature and the
resolver's inferred size in account_meta; the routes forget history
before wiping (so the stored rows are still there to read), and a wipe
hold restored after a restart keeps its pre-wipe yardstick.
- Wipe routes take the set of typed accounts before wiping, so an account
the resolver un-assigns mid-rebuild still counts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fourth review round (52ed9c7):
- The one-and-done guard counts only entries the broker confirmed filled,
so an entry that timed out or was rejected unfilled no longer benches the
account for the day.
- TopstepX: an account is promoted only by a sync that actually checked its
funds; one with no account type stays out (not traded) without costing a
sync per pass, and once typed waits for that check. Wipe routes don't
count untyped accounts as failures.
- Tradovate: an unchecked balance-hold release needs Cash History refused
for a full hour straight (a 4xx other than 401/403/408/429, or an answer
without data); any other outcome resets it, so one stray reply during a
5xx outage can't release a payout.
- A wipe keeps the pre-wipe baseline and fund rows as its yardstick: the
rebuild must explain today's balance against them, so a payout the
rebuilt report hasn't booked yet stays held.
- The roll base of an unrolled record is kept per trade date in
account_meta, so a restart later the same trade date counts from the same
point instead of from a value that already includes the day's fills.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Third review round (088886e):
- Tradovate: a record still on the ended trade date waits only inside
17:00-17:45 CT (every account rolled 17:17-17:21 on 2026-09-24); nothing
trades on it there, so no pre-roll fill can be lost or double-counted by
the broker's roll. Past the window an unrolled record (an idle account)
counts from its value when first read, so nothing waits indefinitely —
across restarts, stale bases or accounts the broker rolls only on a fill.
- One-and-done accounts also stop once this process fired a leg today.
- A balance hold is released unchecked only when Cash History is refused
outright (4xx / errorText, e.g. a passed account's 404s); a 5xx, timeout
or queue outage keeps the payout held until it recovers.
- A Cash History is judged against the baseline as it stood when requested,
so a fold observed while it was in flight is not taken for a payout.
- TopstepX: a cache fallback for an account not loaded before waits for a
funds check; accounts with no account type (not ours) aren't left
pending; a fetch awaits a sync already running and syncs again if its
accounts still wait, so wipe routes report the real outcome.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Second review round (e496404, 9b2d677):
- Tradovate: past the 5 PM roll an old-dated cash record counts only what
it gained since the roll (its realizedPnL as last seen while current is
kept as the roll base), so tonight's fills booked onto it before
Tradovate rolls the account stay visible — no re-trading a one-and-done
account. A record this process never saw before the roll leaves the
account waiting for the broker's roll (ROLL_PENDING, counted in play for
stop-after-all). The 60s snapshot carries the roll base and can't undo a
newer record the socket delivered.
- A wipe's hold is kept in account_meta, so a restart onto a failing Cash
History still holds the account.
- A Cash History whose pre-request balance the last vouched-for baseline
can't explain, and which booked nothing, holds the account instead of
rebasing onto an unbooked payout.
- Holds compare fund transactions by date and amount (a second payout on a
date that already has one), and an in-flight hold is judged against the
rows from before its report.
- The saved baseline tracks the day's realized P&L and folds, so a restart
judges against current figures; held refetches back off to an hour, and
a balance hold no Cash History can check is released after an hour.
- TopstepX: a fetched account is promoted only by a sync whose
reconcileFunds actually checked the books (not one skipped for an open
position), and a direct fetch awaits that sync, so wipe routes report
the real outcome.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up to 77d8c2e from its adversarial review:
- Stop-after-all no longer shuts down before an open while histories are
still loading (a regression in 77d8c2e): a pending account counts as in
play everywhere but the weekday 2:55-5:00 PM CT stretch after the close.
- Tradovate balance holds lift only when a Cash History books a fund
transaction the account didn't have when the hold began; one that never
does is released after 3 clean reports over 15 minutes, with a warning.
The baseline comes from the balance when the report was requested, so a
payout landing mid-report is held for the next one. Held accounts
refetch every 5 minutes, not every sync.
- The Cash History baseline is kept in account_meta, so a restart onto a
failing report server still catches a payout from the DB cache.
- A wipe holds the account until a Cash History rebuilds its fund
transactions (the Fills report and the cache can't).
- A report still queued after its polls, or answered without data, is a
failure, not an empty history.
- TopstepX: a newly fetched account (new, wiped, failed) waits for a sync
that reconciles its funds, and the fetch starts that sync right away.
- Accounts a fetch is already working through aren't fetched again by the
targeted pass; the TopstepX REST fill search spans ±15 minutes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tradovate rolls each account's cash record to the new trade date on its own
schedule (18 minutes after the 17:00 CT open on 2026-09-24, or not until the
account trades), and until then the latest record still carries the ended
day's realizedPnL. Plans sized legs off it, one-and-done accounts read as
already traded, the reporter scored every account partial/loss, and an entry
across the record roll took a whole day's P&L as its "commission", parking
the take-profit out of reach.
- Cash records keep their trade date; realized P&L from an earlier trade
date reads as 0 (judged when read, so a record stored before the roll
counts as ended after it). Archived or older records never overwrite a
newer one, whichever order the roll pair arrives in.
- The entry-commission delta falls back to $2.50/contract when it exceeds
any real fee ($10/contract).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Both clients track which accounts this process has loaded history for
(historyReady). An account restarted, rebuilt, wiped or newly listed is
ineligible until its fetch lands, instead of trading as a fresh stage-1
first day; a failed fetch with no cache no longer reads as empty history.
Waiting accounts get a targeted fetch on the next sync.
- Tradovate holds an account whose start-of-day balance moves without a fill
(a payout between hourly Cash History runs) until a Cash History books it,
so a payout-pending account isn't re-traded on its ended cycle.
- Wipe routes forget history through the client and count accounts whose
history didn't come back as failures.
- TopstepX sendOrder picks up a fill that arrived before the place response,
and its REST backstop uses the documented Trade/search and Order/search.
- POINT_VALUES: SI 5000 (was 50), M2K 5 (was 10).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the drain cycle's first day draws from the $4-$15 grid. Under a
consistency rule, later days follow the standard consistency math and
the day that can close the cycle aims at the midpoint of the amounts
that close it, so accounts drained together finish together whatever
their first draw.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why the autotrader sometimes broke after a weekend until `pm2 restart`:
`next start` only logs uncaught errors, so nothing ever crashed, and a few
paths could leave a client dead for the life of the process.
Tradovate: a closed socket scheduled exactly one re-login, with no catch —
one failure during weekend maintenance (or a rate-limit penalty returned as
a 200 without a token) and the client never came back. connectAndAuth is now
a single-flight loop that never throws: jittered backoff capped at 5 min,
penalty tickets waited out, captcha demands backed off. A 15s watchdog
abandons silent, never-authorized or stuck-closing sockets and stale syncs;
renewal falls back to a fresh login; orders fail fast (OrderNotPlacedError)
on a dead socket and time out instead of hanging; a bad sync answer no
longer wipes accounts and positions.
TopstepX: hub start/stop/invoke and every REST call are bounded; a wedged
hub is discarded and rebuilt; a stuck sync is superseded after 3 min;
re-login no longer tears down the sync loop; a watchdog re-logs when syncs
go stale; a no-fill timeout cancels the order.
Scheduler: one unready client used to hold every firm forever. It now holds
the tick for a 10-minute grace, then trades the other firms without it.
Per-firm try/catch in batch collection, one batch at a time, accounts marked
in flight, legs un-counted only when the entry never reached the broker, and
the scheduler starts before the first batch fires.
Boot and supervision: instrumentation.ts boots the process at server start
(it used to wait for the first dashboard request); a supervisor rebuilds a
client that has been unhealthy for 20 min (not a TopstepX one holding a
position); broker HTTP calls default to a 60s timeout; GET /api/health shows
each client's liveness and the scheduler's last decision. Shared state the
eager boot would otherwise split across bundles lives on globalThis. Logs no
longer carry access tokens or whole AxiosErrors (which include the encoded
Tradovate password).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PM2 runs update-check.mjs as a cron *restart*, and PM2 7 stops a process
that is still running at the next minute boundary. Any update that needed
npm install or next build (more than ~55s) was killed half-way: the lock
was left behind, HEAD had already moved at the pull so the next run saw
nothing to do, and next build had already wiped .next under the live
server — a box that broke after a weekend push and stayed broken.
- The cron run is now a quick CHECK: fetch, decide, and hand the work to a
detached worker (--apply) that PM2's next tick can't reach.
- "Up to date" is judged against scripts/.built-commit (what .next was built
from), not HEAD, so a pull that was never built finishes on the next check.
First run on a machine adopts a complete build that is newer than HEAD's
last move and rebuilds anything else — that rescues boxes the old updater
already stranded.
- The previous build is set aside as .next-prev and restored if the build
fails, so a broken push never leaves a box without a build; failures retry
after 15 min, then hourly (scripts/.update-failed).
- The lock holds a pid and is atomic; build dirs are deleted without ever
following the links in .next/node_modules into the real node_modules.
- Every instance in scripts/instances.json is restarted, and python/pip
children stay hidden on Windows now that the worker has no console.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`node -` puts '-' in argv[1], so the registry snippets in add-instance.sh
and remove-instance.sh were one slot off: they wrote the registry to a file
named "-" in the working directory, with the instances.json path as the
instance name, a null port and the port as the db. scripts/instances.json
was never created, so the updater and start-all only ever knew instance 1 —
after an update, instance 2 and up kept running old code against the new
build until someone ran `pm2 restart all`.
Devices that already ran add-instance.sh need their scripts/instances.json
written by hand (and the stray "-" file deleted).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a fund transaction starts a new cycle (the days revert to 0), the
cycle it ended is checked against the completion rule for a week after and
named if it stood complete — its final day may never have been reported.
Only for a cycle this instance saw begin: the clients now note where the
ended cycle started as they move last_fund_date forward. Completions carry
the cycle they belong to, and each firm reports its whole account list so
the master can tell erased accounts and spot new funded ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cycleCompletion() says whether today's P&L finished the current cycle
(profit target, consistency and minimum days all met) — projectPerfectPath's
completion probe run without and with today. The reporter counts those as
`completed` (a subset of targetHit) and sends their names, so the master
can keep an account a firm erases after it passes. Checked ahead of the
lockout branch: a firm locking a passed account is no DLL loss. The local
dashboard shows them with a purple Completed pill.
Because the master keeps a completion for good, doubtful reads stay
'none': weekends, a Monday with a weekend-dated row, the first minutes
after the 5 PM roll, and history that hasn't freshly loaded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lib/db.ts switched to WAL at module load before setting busy_timeout.
next build imports it from several workers while the live server holds
the same file, and a journal-mode change needs the file to itself — so
the pragma failed instantly with SQLITE_BUSY and took the whole build
down ("Failed to collect page data"), blocking updates on any box whose
database was still in rollback mode. The timeout is now set first and
the WAL switch is wrapped: a held file keeps its current mode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fleet tooling is npm-only (setup-linux.sh installs with npm,
update-check.mjs triggers installs off package-lock.json), so the
committed yarn.lock did nothing for any VPS — but yarn regenerating it
locally dirtied working trees and blocked git pull on machines where
yarn had ever been run. Now gitignored: yarn dev still works wherever
someone wants it, with a local lockfile git never sees.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Matches the master's tokenless-push change: pushBackup no longer waits
for master_backup_token — every instance with a uuid backs up on its
own, and the 5-minute tick force-pushes so a poisoned master copy
self-heals. The token now only gates pulling a backup back (restore),
so setup-linux.sh asks for it only when restoring and the Settings
help text says so.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four features:
- Backup: lib/backup-sync.ts pushes the full settings table and firm
credentials (the deliberate exception to "credentials never leave the
machine") to the master's bearer-gated /api/instances/backup — every
5 minutes when the content hash changed, within seconds of a settings
or credential edit, and on the new backup-now command. Enabled by the
master_backup_token setting.
- Restore: a dead VPS's replacement pulls the backup and adopts its
uuid/name, so roster, payouts and card links carry on. Pre-boot via
seed-settings.js --restore-from (setup-linux.sh prompts for it) or
the Settings page's restore picker (lib/backup-restore.ts). Stop the
old machine first; the master 409s a live-name rename.
- Proxy: the proxy_url setting routes BROKER traffic only — TopstepX
REST + SignalR hub, Tradovate REST + websocket, Yahoo quotes — via
lib/outbound-proxy.ts (axios agents, undici dispatcher, ws agent).
The master link, reporter, catalog and backup push stay direct, so a
dead proxy cannot take down the control channel. Restart to apply.
- Multi-instance: AUTOFIRMER_DB moves the SQLite file so one checkout
runs N instances; scripts/instances.json (per-device, gitignored)
drives start-all/update-check, and add-instance.sh / remove-instance.sh
manage the extra PM2 processes. Absent registry = single-instance
behavior, unchanged. Instance 1 keeps port 3000 for the clicker and
extension.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A drain stage zeroed consistency, so the payout was planned (and the
account stopped trading) as soon as the min days were booked — even when
the cycle's biggest day still exceeded the firm's ratio (Topstep holds
its 40% through the drain). Carry stage.consistency into the effective
config and keep booking drain days until the cycle total covers
maxDay / consistency.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a popup button that scans the Topstep dashboard's GraphQL API
(crystal.topstep.com) for passed evaluations that can still be
activated into an Express Funded account.
An eval is activatable when its status is "Passed" and its subscription
id is not shared by ANY funded account it ever spawned — regardless of
that funded account's current status, since activation is one-way. The
result and its progress are mirrored to chrome.storage so the popup
renders them independent of the message port (avoids the "message port
closed" error on this ~20s scan). Activatable accounts link to their
Topstep detail page.
Adds https://*.topstep.com/* host permission; bumps to 0.15.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the single hardcoded signed-out check with a guards list on each
firm: any guard can trip mid-run via a URL substring (checked on every
step) or a selector probe (checked when a step fails). Each guard defines
recovery steps or a human-wait fallback, a per-run trigger cap, and a
resume policy — 'continue' retries the tripped step, 'restart' rewinds
the run to step 1.
Runner bumped to 0.20.0; the server still ships the legacy
signedOut/authSteps shape for stale runners, and a new runner synthesizes
a guard from a legacy payload.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both the MLL floor and the books-invariant fund detector assumed a $0
starting balance (correct for Express, wrong for funded/eval sizes). A
150K account (accountSize 150000) built its balance curve from $0, so
the floor came out near -$4,500 and a $145k balance never crossed it —
the account never marked dead — while reconcileFunds saw the whole
$150k as an unexplained deposit. Seed both with accountSize so the floor
is an absolute balance (150K/$4,500 drawdown → 145,500, locked at the
funded size once the EOD high climbs a drawdown above it) and the books
invariant nets out the starting balance. Skip reconcile until the
account type is known, since the start balance is unknowable before then.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
projectPerfectPath worked on the raw daily P&L, so for a combining firm a
holiday-session trade (e.g. the Labor Day session) counted as its own
trading day — an account one real day short of its min days looked
complete and anchored its payout to the last traded day. The projection
now folds sessions through combineCmeSessions like the live path, and
projected days skip dates that clear into the next full day.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A completed cycle's payout now lands on its last traded day (requestable
after that session's close) instead of whatever day the projection ran —
a Friday finish viewed over the weekend stayed pinned to Sunday. Also
stop inserting the platform's stale weekend realizedPnL as a Sat/Sun
P&L row, which fabricated an extra qualifying day and made accounts one
day short look already complete.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The MLL floor no longer recomputes while a position is open or while
the balance disagrees with the books beyond fee noise — the last
settled floor stands, so balance ≤ floor can only come true when a
booked fill crosses a settled floor (Topstep's own liquidation fill
included). The floor also survives canTrade flipping off, so a blown
account stays ☠ instead of demoting to inactive.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
23 deterministic values per (account, date) instead of $5/$10/$15; the
qualifying floor moves to the grid minimum so every draw counts toward
the cycle. The per-stage min-day field no longer drives the amount.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
TopstepX never reports the Maximum Loss Limit, but it's deterministic:
floor = min(0, eodBalanceHigh − trailingDrawdown), locking at the $0
starting balance. The EOD curve rebuilds from daily P&L + fund events,
with off-book fee drift spread across days proportionally to reported
fees (validated against a platform-reported MLL to ~$0.10). Stored in
autoLiqThresholds — negative, or +$0.01 once locked — so dead detection,
dashboards, and the ruin model's startThreshold all use the real room.
Guards move from '> 0' to '!== 0'; 0 still means no floor. canTrade=false
accounts are skipped. daily_pnl gains a fees column for the weighting.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@microsoft/signalr does an unconditional require('ws')/require('eventsource')
when constructing a connection; bundled (turbopack) builds throw 'dynamic
usage of require is not supported', which the login chain mislabelled as a
login failure and retried every 60s. Externalize the package and never let
hub setup fail the login — REST polling covers everything the hub does.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
setup-linux.sh accepted being run as root and simply set SUDO="". That quietly
broke everything user-scoped: PM2 keeps its process list in $HOME/.pm2 and the
login entry goes in $HOME/.config/autostart, so under sudo both landed in /root.
The install reported success, then `pm2 list` as the real user showed nothing -
it was talking to a different daemon - and the autostart entry sat in a home
directory that never logs in.
Both scripts now refuse, and name the account to use when SUDO_USER says how
they were invoked. setup-linux.sh still uses sudo for apt, which is the only
part that needs it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A payoutable account with no withdrawal stages (e.g. MFFU same-equity)
now withdraws its share and re-targets the same equity each cycle instead
of stopping after the first payout. Non-payoutable evals still stop at
one completion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When target and min trading days are already satisfied, the payout fires
on the current trade date instead of being pushed to the next session —
so an account that has already hit its target with its days in shows the
payout as requestable now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An eval that completes its target passes to the next account rather than
paying out — the projected completion marker reads 'Passed ✓' unless the
type is marked payoutable on the master.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The version is the checkout's HEAD commit (short hash + commit time),
read once at startup — updates arrive as `git pull`, so there is no
release number to bump. It rides on the socket hello, socket reports,
and the HTTP report fallback; the field is optional in the protocol so
older masters ignore it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- projectPerfectPath books each cycle's payout ON its final trading day
and anchors ruin probabilities to the platform's real liquidation floor
(Tradovate auto-liq) when reported, else the configured trailing
drawdown with the maxLoss/$2,000 fallback
- Account calendar shows the cumulative reach % on every projected day,
caps the projection at two payouts ahead, and renders potential days
as dashed outlines instead of shaded cells
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>