Vest: stops reserve 0.02% of the position for slippage, not 0.1%

A platform may now state its own stop slippage share
(PlatformClient.stopSlippageFraction); the daily-loss reserve is the
larger of 10% of the limit and that share of the position. Vest's 9
measured stop-outs filled 0.9 points past the trigger on average and
2.25 at worst, against the ~30 points 0.1% held back. On a $1,400 day
with ~$495k of NDX the stop goes from ~$880 to ~$1,230, and the leg
sizes up for the same hold. Sizing, the placed stop, the dashboard's
next stop and the reset guard all use it; other platforms keep 0.1%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-10-27 11:34:27 -05:00
co-authored by Claude Opus 5.5
parent f0c1569d96
commit beddbdcf6c
11 changed files with 75 additions and 18 deletions
+10 -6
View File
@@ -1327,12 +1327,14 @@ export function obfuscationStopDollars(
* that fills worse than its price (gaps, thin weekend books). */
export const DLL_RESERVE_FRACTION = 0.10;
/** …or this share of the position's notional, when that is more: a stop's
* slippage grows with the position, a flat reserve doesn't. */
* slippage grows with the position, a flat reserve doesn't. A platform whose
* stops are known to fill closer states its own (stopSlippageFraction). */
export const DLL_SLIPPAGE_FRACTION = 0.001;
/** The part of the day's room a stop leaves unspent. */
export function dllReserve(dailyLossLimit: number, notional = 0): number {
return Math.max(DLL_RESERVE_FRACTION * dailyLossLimit, DLL_SLIPPAGE_FRACTION * Math.max(0, notional));
export function dllReserve(dailyLossLimit: number, notional = 0, slippageFraction = DLL_SLIPPAGE_FRACTION): number {
const share = Number.isFinite(slippageFraction) && slippageFraction >= 0 ? slippageFraction : DLL_SLIPPAGE_FRACTION;
return Math.max(DLL_RESERVE_FRACTION * dailyLossLimit, share * Math.max(0, notional));
}
/** Smallest daily-loss stop worth trading. Under a fair walk a leg of L with a
* stop of S wins S/(S + L) of the time — about 9% for $50 against $500 — so
@@ -1454,10 +1456,10 @@ export function dllRoom(o: {
* reset has its entry fee on the old day's books, and the swap takes no more
* than that slot on the new day's.
*/
export function dllStopDollars(o: { room: number; dailyLossLimit: number; entryFee: number; commissionPct: number; notional?: number }): number {
export function dllStopDollars(o: { room: number; dailyLossLimit: number; entryFee: number; commissionPct: number; notional?: number; slippageFraction?: number }): number {
if (!Number.isFinite(o.room)) return Infinity;
const r = Math.max(0, o.commissionPct) / 100;
return (o.room - dllReserve(o.dailyLossLimit, o.notional) - 2 * o.entryFee - 0.01) / (1 + r);
return (o.room - dllReserve(o.dailyLossLimit, o.notional, o.slippageFraction) - 2 * o.entryFee - 0.01) / (1 + r);
}
/**
@@ -1765,6 +1767,8 @@ export function planLegSize(o: {
/** Infinity (or ≤ 0) = no obfuscation stop. */
obfuscationDollars: number;
availableFunds?: number;
/** The platform's stopSlippageFraction; default DLL_SLIPPAGE_FRACTION. */
slippageFraction?: number;
}): {
lastStand: boolean;
cap: number;
@@ -1780,7 +1784,7 @@ export function planLegSize(o: {
obf,
!dllOn ? Infinity
: stand ? breachDistance({ dllRoom: o.dllRoom, maxLossRoom: o.maxLossRoom, entryFee: r * notional })
: dllStopDollars({ room: o.dllRoom, dailyLossLimit: o.dailyLossLimit, entryFee: r * notional, commissionPct: o.commissionPct, notional }),
: dllStopDollars({ room: o.dllRoom, dailyLossLimit: o.dailyLossLimit, entryFee: r * notional, commissionPct: o.commissionPct, notional, slippageFraction: o.slippageFraction }),
);
const cap = notionalCap({ marginRate: o.contract.marginRate, availableFunds: o.availableFunds });
const step = o.contract.stepNotional ?? 0;