Speed up copyTrade symbol resolution + add entry/progress logs

The symbol resolution loop iterated every firm × every enabled symbol
calling findFrontMonthContract (Tradovate + Yahoo APIs), causing the
endpoint to hang for 30+ seconds with no logs. Now only checks the
client that actually holds the position.

Added logs at function entry and after each major resolution step so
hangs are visible in stdout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-04-27 00:41:07 -05:00
co-authored by Claude Opus 4.6
parent d6344061b6
commit 7b27de6d61
+10 -7
View File
@@ -333,6 +333,7 @@ export async function runTrade(action: 'Buy' | 'Sell' | 'Auto', symbol: string)
* orders for eligible accounts that haven't traded yet.
*/
export async function copyTrade() {
console.log('[copy-trade] called');
if (isInNoTradeWindow()) {
console.log('[copy-trade] outside trading hours — skipping');
return [];
@@ -346,6 +347,8 @@ export async function copyTrade() {
let resolvedAction: 'Buy' | 'Sell' | null = null;
let positionContractId: number | null = null;
let positionedCount = 0;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let positionedClient: any = null;
for (const firm of firms) {
const client = clients.get(firm.id);
@@ -357,6 +360,7 @@ export async function copyTrade() {
if (!resolvedAction) {
resolvedAction = pos.netPos > 0 ? 'Buy' : 'Sell';
positionContractId = pos.contractId;
positionedClient = client;
}
}
}
@@ -365,25 +369,24 @@ export async function copyTrade() {
console.log('[copy-trade] no open positions to copy from');
return [];
}
console.log(`[copy-trade] found ${positionedCount} open position(s), action=${resolvedAction}, contractId=${positionContractId}`);
// Resolve symbol from the positioned contract's contractId
// Resolve symbol from the positioned contract's contractId — only check the client that
// actually has the position. Iterating every firm × every symbol can take 30+ seconds.
let resolvedSymbol: string | null = null;
const instruments = getInstruments();
const enabledSymbols = instruments.filter(i => i.enabled).map(i => i.symbol);
// Try each enabled symbol to find which one matches the positioned contractId
for (const firm of firms) {
const client = clients.get(firm.id);
if (!client) continue;
if (positionedClient) {
for (const sym of enabledSymbols) {
const contract = await client.findFrontMonthContract(sym);
const contract = await positionedClient.findFrontMonthContract(sym);
if (contract && contract.id === positionContractId) {
resolvedSymbol = sym;
break;
}
}
if (resolvedSymbol) break;
}
console.log(`[copy-trade] resolved symbol: ${resolvedSymbol ?? '(none, using fallback)'}`);
// Fall back to scheduler symbol or first enabled
if (!resolvedSymbol) {