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
@@ -1413,3 +1413,64 @@ test('endedCycleCompletion: a same-day type\'s ended cycle is judged on its day\
|
||||
// Any other type: judged on stage 2's $3,000, as before.
|
||||
assert.equal(endedCycleCompletion({ ...opts, cfg: vestFunded }), null);
|
||||
});
|
||||
|
||||
import { claimedCycle, withinEndedCycleWindow } from '../lib/trading-logic.ts';
|
||||
|
||||
test('claimedCycle: a claim names the complete cycle it ends, where the final day and the catch-up can\'t', () => {
|
||||
const cfg = { ...vestFunded, stagesSameDay: true, dailyLossLimit: 1500 };
|
||||
const activated = { date: '2026-10-20', amount: 50000 };
|
||||
/** A Vest client's numbers for account 7, just before a claim. */
|
||||
const client = (o) => ({
|
||||
accountCashBalances: { 7: o.cash }, dailyPnL: { 7: o.cycle ?? [] }, fundTransactions: { 7: o.rows },
|
||||
lastFundDates: { 7: o.last }, priorProfit: { 7: 0 },
|
||||
tradeDate: () => o.day, sameDayClaims: () => o.today, payoutDays: o.payouts && (() => o.payouts),
|
||||
});
|
||||
|
||||
// Vest day 10-27, 6 PM ET: claim 1 took stage 1's $1,500 at 3 PM, and
|
||||
// stage 2 has made its $3,000 since. The auto-claim at the next tick
|
||||
// beats the 30 s report, and its payout books into 10-27's row: the
|
||||
// latest fund date never moves for the catch-up.
|
||||
const claimedOnce = [activated, { date: '2026-10-27', amount: -1500 }];
|
||||
const second = { cash: { amount: 53000, realizedPnL: 3000 }, rows: claimedOnce, last: '2026-10-27', day: '2026-10-27', today: 1, payouts: ['2026-10-27'] };
|
||||
assert.deepEqual(claimedCycle(client(second), 7, cfg, cdt('2026-10-27T17:00:00')),
|
||||
{ date: '2026-10-27', stage: 2, drain: false, cycle: '2026-10-27', cycleSeq: 0 });
|
||||
// A Claim now short of stage 2's $3,000 names nothing.
|
||||
assert.equal(claimedCycle(client({ ...second, cash: { amount: 51000, realizedPnL: 1000 } }), 7, cfg, cdt('2026-10-27T17:00:00')), null);
|
||||
// The day's third cycle, after that claim, has a key of its own.
|
||||
const twice = [activated, { date: '2026-10-27', amount: -4500 }];
|
||||
assert.deepEqual(claimedCycle(client({ ...second, rows: twice, today: 2, payouts: ['2026-10-27', '2026-10-27'] }), 7, cfg, cdt('2026-10-27T17:00:00')),
|
||||
{ date: '2026-10-27', stage: 3, drain: false, cycle: '2026-10-27', cycleSeq: 1 });
|
||||
|
||||
// Stage 2 made only $1,500 of its $3,000 by the 20:00 ET reset, which
|
||||
// puts the account back on stage 1's $1,500: claimed at the first tick,
|
||||
// 8:00:30 PM ET.
|
||||
const afterReset = { cash: { amount: 51500, realizedPnL: 0 }, rows: claimedOnce, last: '2026-10-27', day: '2026-10-28', today: 0, payouts: ['2026-10-27'] };
|
||||
assert.deepEqual(claimedCycle(client(afterReset), 7, cfg, cdt('2026-10-27T19:00:30')),
|
||||
{ date: '2026-10-28', stage: 2, drain: false, cycle: '2026-10-27', cycleSeq: 0 });
|
||||
// The catch-up after it reads none of that cycle's P&L, all in 10-27's
|
||||
// row, which the cycle before owns.
|
||||
assert.equal(endedCycleCompletion({
|
||||
accountId: 7, rawTradeDate: '2026-10-28', fullDailyPnL: [{ date: '2026-10-27', pnl: 3000 }], cycleDailyPnL: [],
|
||||
fundTransactions: [...claimedOnce, { date: '2026-10-28', amount: -1500 }], lastFundDate: '2026-10-28',
|
||||
endedCycleStart: { fundDate: '2026-10-27', includesDay: false }, rawRealizedPnL: 0, equityProfit: 0, cfg, now: cdt('2026-10-27T19:10:00'),
|
||||
}), null);
|
||||
|
||||
// Where the catch-up does name the cycle — its P&L on a day of its own —
|
||||
// the claim names it by the same key, so the master keeps one.
|
||||
const crossDay = { cash: { amount: 51500, realizedPnL: 1500 }, rows: claimedBefore, last: '2026-10-25', day: '2026-10-26', today: 0, payouts: ['2026-10-25'] };
|
||||
assert.deepEqual(claimedCycle(client(crossDay), 7, cfg, cdt('2026-10-26T12:00:00')),
|
||||
{ date: '2026-10-26', stage: 2, drain: false, cycle: '2026-10-25', cycleSeq: 0 });
|
||||
// Without a payout list, one payout per negative fund row.
|
||||
assert.equal(claimedCycle(client({ ...crossDay, payouts: undefined }), 7, cfg, cdt('2026-10-26T12:00:00')).stage, 2);
|
||||
// Numbers not read yet: nothing.
|
||||
assert.equal(claimedCycle({ ...client(crossDay), accountCashBalances: {} }, 7, cfg, cdt('2026-10-26T12:00:00')), null);
|
||||
assert.equal(claimedCycle({ ...client(crossDay), fundTransactions: {} }, 7, cfg, cdt('2026-10-26T12:00:00')), null);
|
||||
});
|
||||
|
||||
test('withinEndedCycleWindow: a week after the date, and never for one that doesn\'t parse', () => {
|
||||
assert.equal(withinEndedCycleWindow('2026-10-21', '2026-10-28'), true);
|
||||
assert.equal(withinEndedCycleWindow('2026-10-28', '2026-10-28'), true);
|
||||
assert.equal(withinEndedCycleWindow('2026-10-20', '2026-10-28'), false);
|
||||
assert.equal(withinEndedCycleWindow('', '2026-10-28'), false);
|
||||
assert.equal(withinEndedCycleWindow('10/27', '2026-10-28'), false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user