From d6344061b65c6c7686639f48eb245646b8a5f07a Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Mon, 27 Apr 2026 00:33:21 -0500 Subject: [PATCH] Add per-account skip logging to copyTrade Surfaces exactly which gate caught each ineligible account during copy-to-max so we can debug which filter is excluding accounts. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/auto-trade.ts | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/auto-trade.ts b/lib/auto-trade.ts index 62677a3..763ef12 100644 --- a/lib/auto-trade.ts +++ b/lib/auto-trade.ts @@ -418,22 +418,31 @@ export async function copyTrade() { await Promise.all(firms.map(async (firm) => { const client = clients.get(firm.id); - if (!client || client.accountList.length === 0) return; - if (isSymbolBanned(firm.id, resolvedSymbol!)) return; + if (!client || client.accountList.length === 0) { + console.log(`[copy-trade] ${firm.name}: no client or empty account list — skip firm`); + return; + } + if (isSymbolBanned(firm.id, resolvedSymbol!)) { + console.log(`[copy-trade] ${firm.name}: ${resolvedSymbol} is banned — skip firm`); + return; + } const firmConfig = mapFirmConfig(firm); const contract = await client.findFrontMonthContract(resolvedSymbol!); - if (!contract) return; + if (!contract) { + console.log(`[copy-trade] ${firm.name}: cannot resolve front-month contract for ${resolvedSymbol} — skip firm`); + return; + } for (const acc of client.accountList) { - if (client.positions[acc.id]) continue; // already in a trade + if (client.positions[acc.id]) { console.log(`[copy-trade] ${acc.name}: already in trade — skip`); continue; } const cash = client.accountCashBalances[acc.id] ?? { amount: 0, realizedPnL: 0 }; const autoLiqThreshold = client.autoLiqThresholds[acc.id] ?? 0; - if (isAccountDead(cash.amount, autoLiqThreshold)) continue; - if (!acc.active) continue; + if (isAccountDead(cash.amount, autoLiqThreshold)) { console.log(`[copy-trade] ${acc.name}: dead — skip`); continue; } + if (!acc.active) { console.log(`[copy-trade] ${acc.name}: inactive (DLL) — skip`); continue; } const cfg = getAccountConfig(acc.name, firmConfig); - if (!cfg) continue; - if (cash.realizedPnL !== 0) continue; // already traded today + if (!cfg) { console.log(`[copy-trade] ${acc.name}: no matching config prefix — skip`); continue; } + if (cash.realizedPnL !== 0) { console.log(`[copy-trade] ${acc.name}: already traded today (realizedPnL=${cash.realizedPnL}) — skip`); continue; } const dailyPnL: { date: string; pnl: number }[] = client.dailyPnL[acc.id] ?? []; const daysTraded: number = client.daysTraded[acc.id] ?? 0; @@ -447,7 +456,8 @@ export async function copyTrade() { const equityProfit = cash.amount - cfg.accountSize; const target = computeDailyTarget(effective.profitTarget, effective.consistency, dailyPnL, cfg.minDayPnL, effective.minTradingDays, equityProfit); - if (!target || target.amount <= 0) continue; + if (!target) { console.log(`[copy-trade] ${acc.name}: target=null (invalid balance) — skip`); continue; } + if (target.amount <= 0) { console.log(`[copy-trade] ${acc.name}: target=$${target.amount} (challenge complete) — skip`); continue; } eligible.push({ firmName: firm.name, client, acc, contract, firmConfig, cash, dailyPnL, daysTraded }); }