Vest: no leg opens into a market close, and accounts plan on Vest's day

Market close: a Vest entry now needs its symbol's market to stay open
for RESET_CLEAR_HOLDS holds of the leg (clearsClose), the clearance the
8 PM ET reset already gets: at the target hold, and at the leg's sized
hold when a leverage cap stretches it. That covers the weekly close and
the daily maintenance hour as Vest's market-hours periods list them.
Before a closure that runs past an 8 PM ET reset (the weekend, a
holiday: longClosure), the bot's own legs still open in the last 5
minutes are closed at market, loudly; a position the bot didn't open is
named in the log and left alone.

Vest's day: Vest accounts are planned, and their legs and entries
counted, on Vest's day (20:00 ET) instead of the Central date
(tradeDateFor, PlatformClient.tradeDate). Between 5 PM CT and the reset
the Central date counted the open Vest day as a prior day and as today's
realized P&L both ($3,000 to go, $800 made: $2,050 left, not $1,900) and
started the leg count over. Other platforms keep the Central date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-10-27 14:12:27 -05:00
co-authored by Claude Opus 5.5
parent beddbdcf6c
commit ec3e6ea388
8 changed files with 290 additions and 32 deletions
+20 -1
View File
@@ -14,7 +14,7 @@ import {
projectPerfectPath, cycleCompletion, DLL_RESERVE_FRACTION, DLL_MIN_STOP, notionalCap, expectedSwapToWin, MARGIN_HEADROOM,
dllReserve, DLL_SLIPPAGE_FRACTION, maxLossRoom, lastStand, breachDistance, LAST_STAND_FRACTION, planLegSize, rankForTarget,
currentTradeDateCT, foldReason, withinFirmCaps, personSizeFactor, personHoldHours, PERSON_SIZE_SPREAD, machineSide,
resolveEffectiveConfig, stageInputsFor, floorRoom, resetClearStop, shortestNextLeg, computeDayPlan,
resolveEffectiveConfig, stageInputsFor, floorRoom, resetClearStop, shortestNextLeg, computeDayPlan, clearsClose, RESET_CLEAR_HOLDS,
} from '../lib/trading-logic.ts';
// Deterministic PRNG so a failure reproduces.
@@ -527,6 +527,25 @@ test('resetClearStop: the widest stop a leg may carry and still close before the
assert.ok(resetClearStop({ leg: 500, resetInMs: 16 * h, holdHours: 1.5 }) - 1400 > 2604.24);
});
test('clearsClose: no leg starts under four holds of its market\'s close', () => {
const h = 3_600_000;
assert.equal(RESET_CLEAR_HOLDS, 4);
// The weekly close 7.5 h off, legs sized for 2 h: no entry.
assert.equal(clearsClose({ closeInMs: 7.5 * h, holdHours: 2 }), false);
// Exactly four holds off, or more: the clearance the daily reset gets.
assert.equal(clearsClose({ closeInMs: 8 * h, holdHours: 2 }), true);
assert.equal(clearsClose({ closeInMs: 8 * h - 1, holdHours: 2 }), false);
assert.equal(clearsClose({ closeInMs: 20 * h, holdHours: 2 }), true);
// A leg its leverage cap holds to 3.5 h needs 14 h, where a 2 h one is clear.
assert.equal(clearsClose({ closeInMs: 10 * h, holdHours: 3.5 }), false);
// It agrees with resetClearStop, which gives no stop at all under four holds.
for (const off of [5.9, 6, 6.1, 12]) {
assert.equal(clearsClose({ closeInMs: off * h, holdHours: 1.5 }), resetClearStop({ leg: 500, resetInMs: off * h, holdHours: 1.5 }) > 0);
}
// An unknown hold never clears.
assert.equal(clearsClose({ closeInMs: 20 * h, holdHours: NaN }), false);
});
test('planLegSize: a split day\'s next leg, with the day\'s gain on its stop, sizes up for the same hold', () => {
// Dingo's 2026-10-27 evals: up $2,604.24 on a $1,400 day, $2,395.76 to
// pass, NDX at ~$29.5k on Vest (1.31%/day), sized for 1.5 h.