Last stand: measured against the full daily loss, not the stop after its reserve

The rule is: when hitting the day's loss limit would leave the account 15%
of that loss or less above its max-drawdown floor, ride without a
daily-loss stop. It had compared against the stop-out after the 10%
reserve, which made it stricter — $3,294.70 to the floor with $3,000 of
daily room (9.8% left) wasn't a last stand, and now is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-09-27 13:43:07 -05:00
co-authored by Claude Opus 5.5
parent ff9b107452
commit 5a4e85cc18
4 changed files with 25 additions and 21 deletions
+4 -3
View File
@@ -169,9 +169,10 @@ Per account type, in the **Hard Daily Loss** column: the **daily loss limit**
(Tradeify: 3% of size — every leg then carries a stop that keeps the firm's (Tradeify: 3% of size — every leg then carries a stop that keeps the firm's
day inside it, less fees and a reserve of 10% of the limit or 0.1% of the day inside it, less fees and a reserve of 10% of the limit or 0.1% of the
position, whichever is more) and the **static max drawdown** (Tradeify position, whichever is more) and the **static max drawdown** (Tradeify
1-Step: $6,000 on 100K). When a daily-loss stop-out would leave the account 1-Step: $6,000 on 100K). When hitting the day's loss limit would leave the
within 15% of that loss above its max-drawdown floor, the leg is a *last account within 15% of that loss above its max-drawdown floor, the leg is a
stand*: no daily-loss stop, running to its take-profit or the firm's breach. *last stand*: no daily-loss stop, running to its take-profit or the firm's
breach.
Before the scheduler trades a DXtrade firm, run the smoke test against a real Before the scheduler trades a DXtrade firm, run the smoke test against a real
login (with this instance's client for the firm disconnected): login (with this instance's client for the firm disconnected):
+1 -1
View File
@@ -388,7 +388,7 @@ function AccountRow({ account, firm, hideDead, privacy, onAssigned }: {
<span className="text-amber-600" title="The next trade's stop — dollars of price movement it may lose before booking the day (fees come on top; the daily-loss stop already reserves for them)"> · stop ${fmt(account.nextStop)}</span> <span className="text-amber-600" title="The next trade's stop — dollars of price movement it may lose before booking the day (fees come on top; the daily-loss stop already reserves for them)"> · stop ${fmt(account.nextStop)}</span>
)} )}
{account.lastStand && ( {account.lastStand && (
<span className="text-red-600" title="Last stand: a daily-loss stop-out would leave this account within 15% of that loss of its max-drawdown floor — nothing left to trade on — so the next leg carries no daily-loss stop and runs to its take-profit or the firm's breach"> · no stop (last stand)</span> <span className="text-red-600" title="Last stand: hitting the day's loss limit would leave this account within 15% of that loss above its max-drawdown floor — nothing left to trade on — so the next leg carries no daily-loss stop and runs to its take-profit or the firm's breach"> · no stop (last stand)</span>
)} )}
{typeof account.dllRoom === 'number' && ( {typeof account.dllRoom === 'number' && (
<span className="text-slate-500" title="Hard daily loss limit: what the firm's day may still lose before a breach. A reserve — 10% of the limit, or 0.1% of the position if larger — is never spent."> · DLL room ${fmt(account.dllRoom)}</span> <span className="text-slate-500" title="Hard daily loss limit: what the firm's day may still lose before a breach. A reserve — 10% of the limit, or 0.1% of the position if larger — is never spent."> · DLL room ${fmt(account.dllRoom)}</span>
+11 -11
View File
@@ -1242,23 +1242,23 @@ export function maxLossRoom(o: { balance: number; accountSize: number; maxLoss:
return floors.length > 0 ? round2(o.balance - Math.max(...floors)) : null; return floors.length > 0 ? round2(o.balance - Math.max(...floors)) : null;
} }
/** A daily-loss stop is kept only while a stop-out would leave at least this /** A daily-loss stop is kept only while the max-drawdown floor lies more than
* share of its loss above the max-drawdown floor. */ * this share of a full daily loss beyond it. */
export const LAST_STAND_FRACTION = 0.15; export const LAST_STAND_FRACTION = 0.15;
/** /**
* Whether a leg should ride without its daily-loss stop. The stop is there to * Whether a leg should ride without its daily-loss stop. The stop is there to
* keep the account alive for another day; when a stop-out would leave it * keep the account alive for another day; when hitting the day's loss limit
* within 15% of that loss of its max-drawdown floor — or the floor is nearer * would leave it within 15% of that loss of its max-drawdown floor — or the
* than the stop — there is no useful day after, and the stop only gives up * floor is nearer than the limit — there is no useful day after, and the stop
* room (the reserve, and whatever the floor allows past it) for nothing. The * only gives up room (the reserve, and whatever the floor allows past it)
* leg then runs until its take-profit or the firm's own breach. * for nothing. The leg then runs until its take-profit or the firm's own
* breach. E.g. $3,000 of daily room with $3,294.70 to the floor: $294.70
* left, 9.8% — a last stand.
*/ */
export function lastStand(o: { dllRoom: number; dailyLossLimit: number; maxLossRoom: number | null }): boolean { export function lastStand(o: { dllRoom: number; dailyLossLimit: number; maxLossRoom: number | null }): boolean {
if (o.maxLossRoom === null || !(o.dailyLossLimit > 0) || !Number.isFinite(o.dllRoom)) return false; if (o.maxLossRoom === null || !(o.dailyLossLimit > 0) || !Number.isFinite(o.dllRoom) || !(o.dllRoom > 0)) return false;
const stopOut = o.dllRoom - DLL_RESERVE_FRACTION * o.dailyLossLimit; return o.maxLossRoom - o.dllRoom <= LAST_STAND_FRACTION * o.dllRoom;
if (!(stopOut > 0)) return false;
return o.maxLossRoom - stopOut <= LAST_STAND_FRACTION * stopOut;
} }
/** On a last stand: how far price can move against the leg before the firm's /** On a last stand: how far price can move against the leg before the firm's
+9 -6
View File
@@ -375,16 +375,19 @@ test('max-drawdown room: the static floor, the broker floor, the higher', () =>
assert.equal(maxLossRoom({ balance: 99000, accountSize: 100000, maxLoss: 0 }), null); assert.equal(maxLossRoom({ balance: 99000, accountSize: 100000, maxLoss: 0 }), null);
}); });
test('last stand: no daily-loss stop once a stop-out would leave under 15% of it', () => { test('last stand: no daily-loss stop once hitting the daily limit would leave 15% of it or less', () => {
// Full day: a stop-out spends $2,700 (room less the $300 reserve). // A full day's $3,000 of room.
const at = (maxRoom) => lastStand({ dllRoom: 3000, dailyLossLimit: 3000, maxLossRoom: maxRoom }); const at = (maxRoom) => lastStand({ dllRoom: 3000, dailyLossLimit: 3000, maxLossRoom: maxRoom });
assert.equal(LAST_STAND_FRACTION, 0.15); assert.equal(LAST_STAND_FRACTION, 0.15);
assert.equal(at(5757.39), false, 'a fresh 1-Step keeps its stop'); assert.equal(at(5757.39), false, 'a fresh 1-Step keeps its stop');
assert.equal(at(2700 * 1.15 + 1), false, 'just over 15% left: keep the stop'); assert.equal(at(3000 * 1.15 + 1), false, 'just over 15% left: keep the stop');
assert.equal(at(2700 * 1.15), true, '15% left: last stand'); assert.equal(at(3000 * 1.15), true, '15% left: last stand');
assert.equal(at(3000), true, 'two stopped days in: last stand'); assert.equal(at(3294.70), true, 'one stopped day in: $294.70 left, 9.8% — last stand');
assert.equal(at(800), true, 'floor nearer than the stop: last stand'); assert.equal(at(800), true, 'floor nearer than the limit: last stand');
assert.equal(at(null), false, 'no floor known'); assert.equal(at(null), false, 'no floor known');
// Measured against what's left of the day: $1,000 of room, $1,200 to the floor.
assert.equal(lastStand({ dllRoom: 1000, dailyLossLimit: 3000, maxLossRoom: 1200 }), false);
assert.equal(lastStand({ dllRoom: 1000, dailyLossLimit: 3000, maxLossRoom: 1150 }), true);
assert.equal(lastStand({ dllRoom: Infinity, dailyLossLimit: 0, maxLossRoom: 500 }), false, 'no daily limit, no daily stop to drop'); assert.equal(lastStand({ dllRoom: Infinity, dailyLossLimit: 0, maxLossRoom: 500 }), false, 'no daily limit, no daily stop to drop');
// The far side of the walk is the nearer floor, net of the entry fee. // The far side of the walk is the nearer floor, net of the entry fee.
assert.equal(breachDistance({ dllRoom: 3000, maxLossRoom: 2900, entryFee: 120 }), 2780); assert.equal(breachDistance({ dllRoom: 3000, maxLossRoom: 2900, entryFee: 120 }), 2780);