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
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
1-Step: $6,000 on 100K). When a daily-loss stop-out would leave the account
within 15% of that loss above its max-drawdown floor, the leg is a *last
stand*: no daily-loss stop, running to its take-profit or the firm's breach.
1-Step: $6,000 on 100K). When hitting the day's loss limit would leave the
account within 15% of that loss above its max-drawdown floor, the leg is a
*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
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>
)}
{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' && (
<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;
}
/** A daily-loss stop is kept only while a stop-out would leave at least this
* share of its loss above the max-drawdown floor. */
/** A daily-loss stop is kept only while the max-drawdown floor lies more than
* this share of a full daily loss beyond it. */
export const LAST_STAND_FRACTION = 0.15;
/**
* 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
* within 15% of that loss of its max-drawdown floor — or the floor is nearer
* than the stop — there is no useful day after, and the stop only gives up
* room (the reserve, and whatever the floor allows past it) for nothing. The
* leg then runs until its take-profit or the firm's own breach.
* keep the account alive for another day; when hitting the day's loss limit
* would leave it within 15% of that loss of its max-drawdown floor — or the
* floor is nearer than the limit — there is no useful day after, and the stop
* only gives up room (the reserve, and whatever the floor allows past it)
* 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 {
if (o.maxLossRoom === null || !(o.dailyLossLimit > 0) || !Number.isFinite(o.dllRoom)) return false;
const stopOut = o.dllRoom - DLL_RESERVE_FRACTION * o.dailyLossLimit;
if (!(stopOut > 0)) return false;
return o.maxLossRoom - stopOut <= LAST_STAND_FRACTION * stopOut;
if (o.maxLossRoom === null || !(o.dailyLossLimit > 0) || !Number.isFinite(o.dllRoom) || !(o.dllRoom > 0)) return false;
return o.maxLossRoom - o.dllRoom <= LAST_STAND_FRACTION * o.dllRoom;
}
/** 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);
});
test('last stand: no daily-loss stop once a stop-out would leave under 15% of it', () => {
// Full day: a stop-out spends $2,700 (room less the $300 reserve).
test('last stand: no daily-loss stop once hitting the daily limit would leave 15% of it or less', () => {
// A full day's $3,000 of room.
const at = (maxRoom) => lastStand({ dllRoom: 3000, dailyLossLimit: 3000, maxLossRoom: maxRoom });
assert.equal(LAST_STAND_FRACTION, 0.15);
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(2700 * 1.15), true, '15% left: last stand');
assert.equal(at(3000), true, 'two stopped days in: last stand');
assert.equal(at(800), true, 'floor nearer than the stop: last stand');
assert.equal(at(3000 * 1.15 + 1), false, 'just over 15% left: keep the stop');
assert.equal(at(3000 * 1.15), true, '15% left: 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 limit: last stand');
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');
// 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);