Vest: a split day's next leg gives back the day's gain plus the limit
On a split day the next Vest leg's daily-loss room now adds the day's gain still in the account to the bot's limit (floorRoom's `gain`), never past Vest's own floor, and the leg sizes up for the same target hold (Dingo's next eval leg: $455k -> $842k at 1.5 h, win 28% -> 56%). Other platforms are unchanged: dllRoom still never widens on a green day. The gain only widens a leg all but sure to close before Vest's 8 PM ET reset (resetClearStop, held to the shortest leg the day may carve), and none of a hand claim's profit counts. The last-stand margin is measured against the limit, so a green day can't drop a leg's stop. Around the reset: no new Vest position opens in the last 7 minutes, and the guard re-fits every 15 s on fresh positions instead of one pass. An account's positions share the next-day room (stops first, least at risk first; locked-in profit counts), a hand-moved stop is fitted again, and a close or profit-side stop that doesn't take is retried or closed. The dashboard's next stop now reserves for the leg's notional, as fireLeg does, so DXtrade labels read smaller (display only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1e844178de
commit
f0c1569d96
+13
-4
@@ -112,15 +112,20 @@ export function nextVestResetMs(now: number): number {
|
||||
* 'none' — its stop is already at least that tight;
|
||||
* 'stop' — move (or place) the stop at `price`, on the tick grid, rounded
|
||||
* toward the position's safe side;
|
||||
* 'close' — no room at all, or the mark is already past that price.
|
||||
* 'close' — the mark is already past that price (with no room left by
|
||||
* the account's other positions, it sits on the profit side),
|
||||
* or no room and no mark to tell.
|
||||
*/
|
||||
export function resetSafeStop(o: {
|
||||
side: 'long' | 'short';
|
||||
quantity: number;
|
||||
openPrice: number;
|
||||
mark: number;
|
||||
/** Realized balance, collateral included — what the reset captures. */
|
||||
/** Realized balance, collateral included — what the reset captures —
|
||||
* less what the account's other positions may lose at their stops. */
|
||||
balance: number;
|
||||
/** The realized balance the floor is set from; default `balance`. */
|
||||
floorBalance?: number;
|
||||
dailyLossPct: number;
|
||||
maxDrawdownFloor: number | undefined;
|
||||
reserve: number;
|
||||
@@ -129,10 +134,14 @@ export function resetSafeStop(o: {
|
||||
currentStop: number | null;
|
||||
tick: number;
|
||||
}): { action: 'none' } | { action: 'stop'; price: number } | { action: 'close' } {
|
||||
const floor = Math.max(o.balance * (1 - o.dailyLossPct), o.maxDrawdownFloor ?? -Infinity);
|
||||
const floor = Math.max((o.floorBalance ?? o.balance) * (1 - o.dailyLossPct), o.maxDrawdownFloor ?? -Infinity);
|
||||
const exitFee = o.exitFeeRate * o.quantity * (Number.isFinite(o.mark) && o.mark > 0 ? o.mark : o.openPrice);
|
||||
const allowed = o.balance - floor - o.reserve - exitFee;
|
||||
if (!(allowed > 0) || !(o.quantity > 0)) return { action: 'close' };
|
||||
if (!(o.quantity > 0)) return { action: 'close' };
|
||||
// No room to lose (the account's other positions took it): the stop must
|
||||
// lock in at least the shortfall — on the profit side of the entry,
|
||||
// which a position already that far up can still carry.
|
||||
if (!(allowed > 0) && !Number.isFinite(o.mark)) return { action: 'close' };
|
||||
const long = o.side === 'long';
|
||||
const raw = long ? o.openPrice - allowed / o.quantity : o.openPrice + allowed / o.quantity;
|
||||
const price = o.tick > 0
|
||||
|
||||
Reference in New Issue
Block a user