Mark TopstepX accounts dead only off landed fills and settled books
The MLL floor no longer recomputes while a position is open or while the balance disagrees with the books beyond fee noise — the last settled floor stands, so balance ≤ floor can only come true when a booked fill crosses a settled floor (Topstep's own liquidation fill included). The floor also survives canTrade flipping off, so a blown account stays ☠ instead of demoting to inactive. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5e14daa669
commit
1996937ef2
+16
-1
@@ -584,12 +584,24 @@ export class TopstepXClient implements PlatformClient {
|
||||
* accounts are skipped: the platform has already retired them.
|
||||
*/
|
||||
private updateMllFloor(account: PlatformAccount): void {
|
||||
if (!account.active) { this.autoLiqThresholds[account.id] = 0; return; }
|
||||
// Deliberately computed for canTrade=false accounts too: when Topstep
|
||||
// liquidates a breach and disables the account, the floor must SURVIVE
|
||||
// so the dashboards show it as blown (☠), not merely inactive. Retired
|
||||
// accounts without an assigned type fall out below via dd = 0.
|
||||
const dd = getAccountConfig(account.id).accountType?.trailingDrawdown ?? 0;
|
||||
const history = this.fullDailyPnL[account.id];
|
||||
const cash = this.accountCashBalances[account.id];
|
||||
if (!(dd > 0) || !history || !cash) { this.autoLiqThresholds[account.id] = 0; return; }
|
||||
|
||||
// Only move the floor on SETTLED books: never mid-trade (the fill
|
||||
// hasn't landed — the dead check must not fire off half-processed
|
||||
// state), and never while the balance disagrees with the books by
|
||||
// more than fee noise (a fill or fund event is still being absorbed;
|
||||
// reconcileFunds or the next sync settles it). The previous floor
|
||||
// stands until then, so `balance ≤ floor` can only come true off a
|
||||
// landed, booked fill.
|
||||
if (this.positions[account.id]) return;
|
||||
|
||||
const today = currentTradeDateCT();
|
||||
const fees = this.dailyFees[account.id] ?? new Map<string, number>();
|
||||
|
||||
@@ -608,6 +620,9 @@ export class TopstepXClient implements PlatformClient {
|
||||
const booked = dates.reduce((s, d) => s + events.get(d)!, 0);
|
||||
const todayFund = (this.fundTransactions[account.id] ?? []).find((f) => f.date === today)?.amount ?? 0;
|
||||
const residual = Math.round((cash.amount - cash.realizedPnL - todayFund - booked) * 100) / 100;
|
||||
// Books not settled (an unabsorbed fill or an unbooked fund event) —
|
||||
// keep the previous floor rather than skewing the curve with it.
|
||||
if (Math.abs(residual) >= 200) return;
|
||||
const totalFees = dates.reduce((s, d) => s + (fees.get(d) ?? 0), 0);
|
||||
|
||||
let bal = 0;
|
||||
|
||||
Reference in New Issue
Block a user