From 99e473c687b89c3428cae4c88d7bd769f9bebcb9 Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Thu, 16 Apr 2026 03:55:41 -0500 Subject: [PATCH] Block runTrade when positions are open on restart The POST handler calls runTrade() directly, bypassing the scheduler tick's position gate. If you stop and restart with open positions, other accounts could get new trades while existing ones haven't closed. Now runTrade itself checks for open positions before proceeding. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/auto-trade.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/auto-trade.ts b/lib/auto-trade.ts index 0ccd214..2180007 100644 --- a/lib/auto-trade.ts +++ b/lib/auto-trade.ts @@ -112,6 +112,20 @@ export async function runTrade(action: 'Buy' | 'Sell' | 'Auto', symbol: string) console.log('[auto-trade] CME market closed — skipping'); return []; } + + // Block if any account still has an open position (same gate as the scheduler tick) + const allClients = getClients(); + const allFirms = getFirms(); + const openPositions = allFirms.reduce((count, firm) => { + const c = allClients.get(firm.id); + if (!c) return count; + return count + c.accountList.filter(acc => !!c.positions[acc.id]).length; + }, 0); + if (openPositions > 0) { + console.log(`[auto-trade] ${openPositions} position(s) still open — skipping`); + return []; + } + // Resolve 'Auto' symbol once per batch so all accounts trade the same symbol let resolvedSymbol = symbol; if (symbol === 'Auto') {