DXtrade: date transactions by the firm's day, not the CT trade date

The firm rolls its day at 22:00 UTC; our trade date at 5 PM CT. In summer
they coincide, in winter the firm's rolls an hour earlier. New entries are
already kept out of that hour, but a take-profit or stop that fills in it
was booked to the day before. firmDayOf labels the firm's day the way
currentTradeDateCT labels ours, and the sync's transfer window now starts
at the firm day behind today's trade date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-09-27 13:59:25 -05:00
co-authored by Claude Opus 5.5
parent 934620e8e9
commit 7f55e49755
3 changed files with 36 additions and 6 deletions
+15 -1
View File
@@ -13,6 +13,7 @@ import {
botStopsActive, sizeNotional, isNoTradeTime, isPastSessionClose, nextTradingDate, effectiveCombine, DEFAULT_TARGET_HOLD_HOURS,
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,
} from '../lib/trading-logic.ts';
// Deterministic PRNG so a failure reproduces.
@@ -502,7 +503,7 @@ test('an every-day firm can finish its cycle on a Saturday', () => {
import {
dxAccountId, accountDisplayName, accountCodeOf, encodeContractName, decodeContractName, roundToStep,
lastUtcReset, ctTradeDayStart, parseDurationMs, ciNum, signedFundValue, inTradingHours,
lastUtcReset, ctTradeDayStart, firmDayOf, parseDurationMs, ciNum, signedFundValue, inTradingHours,
realizedVolPerHour, scoreCandidate, candidateRejection, MIN_VOL_CANDLES, parseTransfers, marginRateOf,
} from '../lib/dxtrade-helpers.ts';
@@ -573,6 +574,19 @@ test('the firm reset and the CT trade-date start', () => {
assert.equal(ctTradeDayStart(cst('2027-01-12T10:00:00')).toISOString(), '2027-01-11T23:00:00.000Z');
});
test('the firm\'s day: the same label as the CT trade date, rolling at its reset', () => {
// Summer: the reset is 5 PM CDT, so the two agree on both sides of it.
assert.equal(firmDayOf(new Date('2026-09-26T21:59:00Z')), '2026-09-26');
assert.equal(firmDayOf(new Date('2026-09-26T22:00:00Z')), '2026-09-27');
assert.equal(firmDayOf(new Date('2026-09-26T22:00:00Z')), currentTradeDateCT(new Date('2026-09-26T22:00:00Z')));
// Winter: a close at 4:30 PM CST is the firm's next day, still ours.
const close = cst('2027-01-12T16:30:00');
assert.equal(firmDayOf(close), '2027-01-13');
assert.equal(currentTradeDateCT(close), '2027-01-12');
assert.equal(firmDayOf(cst('2027-01-12T15:59:00')), '2027-01-12');
assert.equal(firmDayOf(cst('2027-01-12T17:30:00')), currentTradeDateCT(cst('2027-01-12T17:30:00')));
});
test('loose parsing', () => {
assert.equal(parseDurationMs('PT30M'), 30 * 60_000);
assert.equal(parseDurationMs('01:05:08'), (3600 + 300 + 8) * 1000);