Vest: no leg opens past 8 PM ET until a sync has read the new day

The engine's Vest day now turns with the client's numbers, at the first
sync after the reset. A leg opened between 8 PM ET and that sync would be
planned and counted on the day that ended, so both the pick and the open
wait for it. The claim log's "stage N next" counts payouts the way the
engine picks its stage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-10-27 16:10:16 -05:00
co-authored by Claude Opus 5.5
parent e02838409b
commit dc210ffcb7
3 changed files with 23 additions and 3 deletions
+14
View File
@@ -777,6 +777,13 @@ export class VestClient implements PlatformClient {
return vestDayOf(this.numbersAt > 0 ? Math.min(now, this.numbersAt) : now);
}
/** Past 8 PM ET with the numbers still the ended day's: a leg opened now
* would be planned and counted on that day, so none opens until a sync
* has read the new one. */
private newDayUnread(now: number): boolean {
return this.tradeDate(now) !== vestDayOf(now);
}
/**
* See PlatformClient: the gain since the day's base that is still in the
* account — since this client's own claim today, else since the reset,
@@ -1766,6 +1773,10 @@ export class VestClient implements PlatformClient {
console.log(`${this.tag} ${root} → nothing tradable — Vest's 8 PM ET reset in ${Math.ceil(toReset / 60_000)} min`);
return null;
}
if (root !== 'survey' && this.newDayUnread(now)) {
console.log(`${this.tag} ${root} → nothing tradable — Vest's day has turned and no sync has read it yet`);
return null;
}
for (const symbol of symbols) {
const spec = specs.get(symbol);
if (!spec) { board.push({ symbol, score: null, note: 'unknown symbol' }); continue; }
@@ -1963,6 +1974,9 @@ export class VestClient implements PlatformClient {
if (toReset <= RESET_ENTRY_BLOCK_MS) {
throw new OrderNotPlacedError(`Vest's 8 PM ET reset is ${Math.ceil(toReset / 60_000)} min away — no new position until it passes`);
}
if (this.newDayUnread(Date.now())) {
throw new OrderNotPlacedError(`Vest's day has turned and no sync has read it yet — no new position until one has`);
}
const opposite = side === 'long' ? 'short' : 'long';
const hedged = [...this.positionsDetail.values()].flat().some((p) => p.symbol === symbol && p.side === opposite)
|| this.openingSides.get(symbol)?.side === opposite;