Futures legs respect a firm's per-instrument contract limit
A firm can cap how many contracts of an instrument its accounts may hold (the catalog's instrumentLimits, set on the master's Firms page). A leg trades one contract per $1,000, capped by the account type's max contracts and that limit. The Auto draw sizes each instrument's hold with the capped count, so a limit that slows a leg past 12 hours takes it out of the draw. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b125257d4e
commit
58e7414849
@@ -10,7 +10,7 @@ import assert from 'node:assert/strict';
|
||||
import {
|
||||
CME_SPECS, CME_ROOTS, POINT_VALUES, MICRO_OF, tickValue, spreadDollars, dailyMoveDollars, futuresContracts,
|
||||
expectedHoldHours, sessionProgress, drawChances, pickByChance, housekeepingRoot, sanitizeInstruments,
|
||||
resolveAllowlist, MAX_HOLD_HOURS, DRAW_FLOOR, DEFAULT_MAX_ENTRY_SPREAD, spreadTooWide,
|
||||
resolveAllowlist, MAX_HOLD_HOURS, DRAW_FLOOR, DEFAULT_MAX_ENTRY_SPREAD, spreadTooWide, sanitizeInstrumentLimits,
|
||||
} from '../lib/instrument-specs.ts';
|
||||
import { mergeTopstepxQuote, parseTradovateFrame, bookSpread } from '../lib/quote-helpers.ts';
|
||||
|
||||
@@ -234,3 +234,25 @@ test('the draw leaves out what is over the spread limit', () => {
|
||||
// All of them wide: nothing to draw.
|
||||
assert.deepEqual(drawChances(cands.map((c) => ({ ...c, wide: true })), 0.5).chances, []);
|
||||
});
|
||||
|
||||
test('a firm\'s per-instrument limit caps the contracts, with the account type\'s max', () => {
|
||||
// One per $1,000 of leg ...
|
||||
assert.equal(futuresContracts(4200, 0), 5);
|
||||
// ... capped by the account type's max, the firm's limit, whichever is lower.
|
||||
assert.equal(futuresContracts(4200, 0, 3), 3);
|
||||
assert.equal(futuresContracts(4200, 4, 2), 2);
|
||||
assert.equal(futuresContracts(4200, 2, 4), 2);
|
||||
assert.equal(futuresContracts(4200, 0, 0), 5);
|
||||
// Never under one contract.
|
||||
assert.equal(futuresContracts(300, 0, 5), 1);
|
||||
// A capped leg holds longer: 5 contracts on NQ vs a cap of 2.
|
||||
const free = expectedHoldHours({ leg: 5000, stopDollars: Infinity, contracts: futuresContracts(5000, 0), dailyMove: 5227 });
|
||||
const capped = expectedHoldHours({ leg: 5000, stopDollars: Infinity, contracts: futuresContracts(5000, 0, 2), dailyMove: 5227 });
|
||||
assert.ok(Math.abs(capped / free - 6.25) < 1e-9, `${capped} vs ${free}`);
|
||||
});
|
||||
|
||||
test('instrument limits off the catalog: CME roots, whole numbers 1-1000', () => {
|
||||
assert.deepEqual(sanitizeInstrumentLimits({ NQ: 15, CL: 5, GC: 0, ES: 2.5, ZZ: 3, SI: 2000, YM: '4' }), { NQ: 15, CL: 5 });
|
||||
assert.deepEqual(sanitizeInstrumentLimits(null), {});
|
||||
assert.deepEqual(sanitizeInstrumentLimits(['NQ']), {});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user