Vest: a claim names the completed cycle it ends, a day's second and one after the reset too
Two of the cycles a claim ends never got a completion entry. A Vest day's second cycle is one: the auto-claim at the next tick beats the 30 s report, and the payout books into that day's fund row, so the latest fund date never moves for the catch-up. A cycle claimed right after the 20:00 ET reset is the other: the reset puts it back on stage 1, and all of its P&L sits in the previous claim's day row, so endedCycleCompletion reads none of it. Before a claim goes out, claimedCycle (trading-logic) checks whether the cycle stands complete: cycleCompletion 'today' or 'before' on the client's numbers. It keys the cycle the way the final day would (completionPlace on the payout list), so the master dedupes the two. afterClaim keeps the result in account_meta. The reporter names each kept cycle for the catch-up's week. It lists them last in the slice, newest first, under the master's per-slice cap, and adds no counter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4a8e027056
commit
e02838409b
+46
-2
@@ -11,7 +11,7 @@
|
||||
* POST keeps those working unchanged.
|
||||
*/
|
||||
|
||||
import { getSetting, loadEndedCycleStart } from './db';
|
||||
import { getSetting, loadClaimedCycles, loadEndedCycleStart } from './db';
|
||||
import { pushReport } from './master-link';
|
||||
import { getBuildVersion } from './version';
|
||||
import { tradeMixFor } from './trade-mix';
|
||||
@@ -20,7 +20,10 @@ import { getClients } from './clients';
|
||||
import { getAccountTypeById, getKeptRuleIdsForFirm, getTradableFirms } from './firm-catalog';
|
||||
import { getAccountConfig } from './account-type-resolver';
|
||||
import { getSchedulerStatus } from './auto-trade';
|
||||
import { botStopsActive, combineCmeSessions, computeDayPlan, completionPlace, cycleCompletion, endedCycleCompletion, LEG_COMPLETION_EPSILON, projectPerfectPath, resolveEffectiveConfig, stageInputsFor, tradeDateFor } from './trading-logic';
|
||||
import {
|
||||
botStopsActive, combineCmeSessions, computeDayPlan, completionPlace, cycleCompletion, endedCycleCompletion, LEG_COMPLETION_EPSILON,
|
||||
projectPerfectPath, resolveEffectiveConfig, stageInputsFor, tradeDateFor, withinEndedCycleWindow,
|
||||
} from './trading-logic';
|
||||
import type { AccountTypeStats, FirmStats, InstrumentStats, SymbolStats } from './master-protocol';
|
||||
import { accountNextLeg, accountLegShape } from './leg-estimate';
|
||||
import { sizingHoldHours } from './person-size';
|
||||
@@ -92,6 +95,9 @@ function collectFirmStats() {
|
||||
}
|
||||
return entry;
|
||||
};
|
||||
// The completed cycles this instance's own claims ended, by slice
|
||||
// (listed after the accounts — see below).
|
||||
const claimedBySlice = new Map<AccountTypeStats, NonNullable<AccountTypeStats['completedAccounts']>>();
|
||||
|
||||
for (const acc of client.accountList) {
|
||||
const reportedCash = client.accountCashBalances[acc.id];
|
||||
@@ -314,6 +320,28 @@ function collectFirmStats() {
|
||||
}
|
||||
}
|
||||
|
||||
// The completed cycles this instance's own claims ended
|
||||
// (afterClaim), named for the catch-up's week: a claim can end
|
||||
// one before any report saw it complete, where the catch-up
|
||||
// can't find it again (a Vest day's second claim, or one right
|
||||
// after the reset — trading-logic claimedCycle). Named only, as
|
||||
// the catch-up's: no counter moves.
|
||||
if (cfg) {
|
||||
for (const c of loadClaimedCycles(acc.id).reverse()) {
|
||||
if (!withinEndedCycleWindow(c.date, rawToday)) continue;
|
||||
let list = claimedBySlice.get(slice);
|
||||
if (!list) claimedBySlice.set(slice, list = []);
|
||||
list.push({
|
||||
name: acc.name,
|
||||
date: c.date,
|
||||
stage: c.stage,
|
||||
kind: completionKind(cfg, c.drain),
|
||||
cycle: c.cycle,
|
||||
...(c.cycleSeq > 0 ? { cycleSeq: c.cycleSeq } : {}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (client.positions[acc.id]) {
|
||||
inTrade++;
|
||||
accountsTraded++;
|
||||
@@ -423,6 +451,22 @@ function collectFirmStats() {
|
||||
}
|
||||
}
|
||||
|
||||
// Claimed cycles go last in each slice's list, newest first: the
|
||||
// master reads only so many entries a slice (twice its accounts), so
|
||||
// what it has long had drops off before a final day, a catch-up or a
|
||||
// fresh claim. One those already name goes once.
|
||||
for (const [slice, claimed] of claimedBySlice) {
|
||||
const list = slice.completedAccounts ?? [];
|
||||
const key = (e: (typeof list)[number]) => `${e.name}\n${e.cycle}\n${e.cycleSeq ?? 0}`;
|
||||
const named = new Set(list.map(key));
|
||||
for (const e of claimed.sort((a, b) => b.date.localeCompare(a.date))) {
|
||||
if (named.has(key(e))) continue;
|
||||
named.add(key(e));
|
||||
list.push(e);
|
||||
}
|
||||
if (list.length > 0) slice.completedAccounts = list;
|
||||
}
|
||||
|
||||
// Biggest shortfall first — the account types with the most left to do
|
||||
// are the ones worth reading, and Unassigned sinks to the bottom only
|
||||
// when it is genuinely small.
|
||||
|
||||
Reference in New Issue
Block a user