hedgequantx 2.6.141 → 2.6.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.6.141",
3
+ "version": "2.6.143",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -1528,7 +1528,7 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
1528
1528
  const positionManagers = {};
1529
1529
  const strategies = {};
1530
1530
  const pendingOrders = {}; // Track pending orders per symbol
1531
- const disabledSymbols = new Set(); // Symbols disabled after SL hit
1531
+ // No disabled symbols - all symbols can trade until Target/Risk reached
1532
1532
 
1533
1533
  contracts.forEach(contract => {
1534
1534
  const symbolName = contract.name || contract.symbol;
@@ -1602,11 +1602,7 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
1602
1602
  stats.losses++;
1603
1603
  stats.symbolStats[symbolName].losses++;
1604
1604
  ui.addLog('loss', `[${symbolName}] -$${Math.abs(pnlDollars).toFixed(2)} @ ${exitPrice} | ${holdSec}s`);
1605
-
1606
- // Disable symbol after loss (SL hit) - other symbols continue
1607
- disabledSymbols.add(symbolName);
1608
- ui.addLog('warning', `[${symbolName}] DISABLED - SL hit, other symbols continue`);
1609
- stats.activeSymbols = contracts.length - disabledSymbols.size;
1605
+ // Symbol can trade again - no disable, continue until Target/Risk reached
1610
1606
  }
1611
1607
  } else if (pnlTicks !== null) {
1612
1608
  // Log with ticks only
@@ -1620,11 +1616,7 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
1620
1616
  stats.losses++;
1621
1617
  stats.symbolStats[symbolName].losses++;
1622
1618
  ui.addLog('loss', `[${symbolName}] ${pnlTicks} ticks | ${holdSec}s`);
1623
-
1624
- // Disable symbol after loss (SL hit) - other symbols continue
1625
- disabledSymbols.add(symbolName);
1626
- ui.addLog('warning', `[${symbolName}] DISABLED - SL hit, other symbols continue`);
1627
- stats.activeSymbols = contracts.length - disabledSymbols.size;
1619
+ // Symbol can trade again - no disable, continue until Target/Risk reached
1628
1620
  }
1629
1621
  }
1630
1622
  stats.symbolStats[symbolName].position = 0;
@@ -1648,7 +1640,6 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
1648
1640
  // ═══════════════════════════════════════════════════════════════════════
1649
1641
  strategy.on('signal', async (signal) => {
1650
1642
  if (!running) return;
1651
- if (disabledSymbols.has(symbolName)) return; // Skip disabled symbols (SL hit)
1652
1643
  if (pendingOrders[symbolName]) return;
1653
1644
  if (!pm.canEnter(symbolName)) return;
1654
1645
 
@@ -2002,20 +1993,27 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
2002
1993
  ui.addLog('warning', '████ EMERGENCY STOP ████');
2003
1994
 
2004
1995
  try {
2005
- // Use Rithmic emergencyStop to flatten all positions
2006
- if (service && typeof service.emergencyStop === 'function') {
2007
- await service.emergencyStop(rithmicAccountId);
2008
- ui.addLog('info', 'Emergency stop executed - all positions flattened');
2009
- } else if (service && typeof service.flattenAll === 'function') {
2010
- await service.flattenAll(rithmicAccountId);
2011
- ui.addLog('info', 'Flatten all executed - all positions closed');
2012
- } else {
2013
- // Fallback: cancel all orders
2014
- if (service && typeof service.cancelAllOrders === 'function') {
1996
+ // Use Rithmic emergencyStop to flatten all positions with timeout
1997
+ const stopPromise = (async () => {
1998
+ if (service && typeof service.emergencyStop === 'function') {
1999
+ await service.emergencyStop(rithmicAccountId);
2000
+ ui.addLog('info', 'Emergency stop executed - all positions flattened');
2001
+ } else if (service && typeof service.flattenAll === 'function') {
2002
+ await service.flattenAll(rithmicAccountId);
2003
+ ui.addLog('info', 'Flatten all executed - all positions closed');
2004
+ } else if (service && typeof service.cancelAllOrders === 'function') {
2015
2005
  await service.cancelAllOrders(rithmicAccountId);
2016
2006
  ui.addLog('info', 'All orders cancelled');
2017
2007
  }
2018
- }
2008
+ })();
2009
+
2010
+ // Timeout after 3 seconds
2011
+ const timeoutPromise = new Promise(resolve => setTimeout(() => {
2012
+ ui.addLog('warning', 'Emergency stop timeout - proceeding to summary');
2013
+ resolve();
2014
+ }, 3000));
2015
+
2016
+ await Promise.race([stopPromise, timeoutPromise]);
2019
2017
  } catch (e) {
2020
2018
  ui.addLog('error', `Emergency stop error: ${e.message}`);
2021
2019
  }
@@ -2075,8 +2073,12 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
2075
2073
  try { pm.stop(); } catch {}
2076
2074
  }
2077
2075
 
2078
- // Disconnect market feed
2079
- try { await marketFeed.disconnect(); } catch {}
2076
+ // Disconnect market feed with timeout
2077
+ try {
2078
+ const disconnectPromise = marketFeed.disconnect();
2079
+ const timeoutPromise = new Promise(resolve => setTimeout(resolve, 2000));
2080
+ await Promise.race([disconnectPromise, timeoutPromise]);
2081
+ } catch {}
2080
2082
 
2081
2083
  // Cleanup keyboard
2082
2084
  try { if (cleanupKeys) cleanupKeys(); } catch {}