Vest: a claim that never reached Vest stops holding the account, and each claim counts once

A claim of unknown outcome now lapses where history is read (bookHistory),
not only in claimPending: its callers wait on historyReady, and the books
check held the account while it counted that claim, so one that never went
in held the account for good. The lapse is the same (no WITHDRAW within 30
min of it, a read an hour on) and is saved; an accepted claim still holds.

An account token that can't be minted means the request never went out:
an order, stop or take-profit reads as not placed, and a claim records no
unknown claim. Only the request's own failure may be "unknown".

A claim Vest dates on the other side of 20:00 ET than it was booked here
no longer leaves a second fund row: the history read takes the local day
back (and the latest fund date with it), and sameDayClaims counts the
claim on Vest's day. A claim Vest doesn't show yet stays on its day.

The report counts payouts one per claim (Vest's WITHDRAWs and the claims
they don't show yet, never fewer than the negative fund rows) for the
account list, payout states and the completion stage, where two claims on
one Vest day were one row. Same-day cycles still share a cycle key; that
needs the master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-10-27 14:14:38 -05:00
co-authored by Claude Opus 5.5
parent beddbdcf6c
commit 9fe7fc0ea3
7 changed files with 334 additions and 72 deletions
+11 -3
View File
@@ -104,11 +104,19 @@ function collectFirmStats() {
// standing, while a wrong zero would clear one early.
const loadedFundTxns = client.fundTransactions?.[acc.id];
const fundTxns = loadedFundTxns ?? [];
// One per payout: a client whose fund rows hold a whole day's
// (Vest: two claims the same day, one row) counts them itself,
// and says nothing until it has read them — falling back to the
// rows there would report fewer and then more again.
const withdrawals = client.withdrawalCount
? client.withdrawalCount(acc.id)
: loadedFundTxns?.filter((f) => f.amount < 0).length;
const withdrawalsTaken = withdrawals ?? fundTxns.filter((f) => f.amount < 0).length;
accounts.push({
name: acc.name,
size: cfg?.accountSize ?? 0,
payoutable: cfg ? loops(cfg) : null,
...(loadedFundTxns ? { withdrawals: loadedFundTxns.filter((f) => f.amount < 0).length } : {}),
...(withdrawals !== undefined ? { withdrawals } : {}),
// For the master's account ledger. Data only: nothing here
// trades on it, and the totals below keep their own test.
...statusFieldsOrUnknown(() => accountStatusFields({
@@ -247,7 +255,7 @@ function collectFirmStats() {
maxDay: qualifying.length > 0 ? Math.max(...qualifying.map((d) => d.pnl)) : 0,
sum,
high: highWater,
withdrawals: fundTxns.filter((f) => f.amount < 0).length,
withdrawals: withdrawalsTaken,
target: effective.profitTarget,
consistency: effective.consistency,
minDays: effective.minTradingDays,
@@ -329,7 +337,7 @@ function collectFirmStats() {
(slice.completedAccounts ??= []).push({
name: acc.name,
date: combined.tradeDate,
stage: 1 + fundTxns.filter((f) => f.amount < 0).length,
stage: 1 + withdrawalsTaken,
kind: completionKind(cfg, effective.drain),
// The fund transaction that started this cycle — the
// catch-up names the same cycle by the same key.