Sizing: the broker's largest and smallest order bind the leg's size
fireLeg clamped the order to the instrument's max and min size, but the size the pick ranked by (and the Firms page shows) didn't: an instrument whose largest order falls short of the ideal notional ranked on a hold it can't reach. planLegSize now holds the notional to the margin cap and the broker's largest order, then its smallest, so the ranking, the stats and the trade agree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7f55e49755
commit
1782c16145
@@ -425,6 +425,34 @@ test('planLegSize: the stop, a last stand, the margin cap and the cost, as fireL
|
||||
assert.equal(planLegSize({ ...base, maxLossRoom: null, contract: {} }).sizing, null);
|
||||
});
|
||||
|
||||
test('planLegSize: the broker\'s order size limits bind the sizing, so the pick sees the real hold', () => {
|
||||
const eth = { stepNotional: 26.86, volatilityPerHour: 0.022 / Math.sqrt(24), spreadFraction: 0.00004, marginRate: 0.2 };
|
||||
const base = {
|
||||
leg: 12239, contract: eth, commissionPct: 0.04, targetHoldHours: 12, financingPctPerDay: 0.033,
|
||||
dailyLossLimit: 3000, dllRoom: 2757.39, maxLossRoom: 5757.39, obfuscationDollars: Infinity, availableFunds: 99757.39,
|
||||
};
|
||||
const free = planLegSize(base);
|
||||
// A largest order well under the ideal size: the notional stops there and
|
||||
// the hold grows past the target (the margin cap stays what it was).
|
||||
const capped = planLegSize({ ...base, contract: { ...eth, maxContracts: 5000 } });
|
||||
assert.ok(Math.abs(capped.sizing.notional - 5000 * 26.86) < 1e-6, `notional ${capped.sizing.notional}`);
|
||||
assert.ok(capped.sizing.notional < free.sizing.notional);
|
||||
assert.ok(capped.sizing.predictedHoldHours > 12, `hold ${capped.sizing.predictedHoldHours}`);
|
||||
assert.equal(capped.cap, free.cap);
|
||||
// One that doesn't bind changes nothing.
|
||||
assert.equal(planLegSize({ ...base, contract: { ...eth, maxContracts: 1e9 } }).sizing.notional, free.sizing.notional);
|
||||
// A smallest order above the ideal size: the order is that big.
|
||||
const floored = planLegSize({ ...base, contract: { ...eth, minContracts: 20000 } });
|
||||
assert.ok(Math.abs(floored.sizing.notional - 20000 * 26.86) < 1e-6);
|
||||
assert.ok(floored.sizing.predictedHoldHours < 12);
|
||||
// Ranked on the capped hold, a capped instrument no longer wins on cost.
|
||||
const order = rankForTarget([
|
||||
{ holdHours: capped.sizing.predictedHoldHours, cost: capped.cost },
|
||||
{ holdHours: free.sizing.predictedHoldHours, cost: free.cost + 50 },
|
||||
], 12);
|
||||
assert.deepEqual(order, [1, 0]);
|
||||
});
|
||||
|
||||
test('rankForTarget: reach the target hold first, cheapest; else quickest', () => {
|
||||
const order = rankForTarget([
|
||||
{ holdHours: 12, cost: 330 }, // ETH
|
||||
|
||||
Reference in New Issue
Block a user