hedgequantx 2.6.142 → 2.6.144

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.142",
3
+ "version": "2.6.144",
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,20 +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
- stats.activeSymbols = contracts.length - disabledSymbols.size;
1627
-
1628
- // Check if ALL symbols are now disabled → stop algo
1629
- if (disabledSymbols.size >= contracts.length) {
1630
- ui.addLog('warning', `[${symbolName}] DISABLED - All symbols stopped`);
1631
- ui.addLog('info', '████ ALL SYMBOLS DISABLED - Session complete ████');
1632
- stopReason = 'all_disabled';
1633
- running = false;
1634
- } else {
1635
- ui.addLog('warning', `[${symbolName}] DISABLED - SL hit, ${stats.activeSymbols} symbols remaining`);
1636
- }
1619
+ // Symbol can trade again - no disable, continue until Target/Risk reached
1637
1620
  }
1638
1621
  }
1639
1622
  stats.symbolStats[symbolName].position = 0;
@@ -1657,7 +1640,6 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
1657
1640
  // ═══════════════════════════════════════════════════════════════════════
1658
1641
  strategy.on('signal', async (signal) => {
1659
1642
  if (!running) return;
1660
- if (disabledSymbols.has(symbolName)) return; // Skip disabled symbols (SL hit)
1661
1643
  if (pendingOrders[symbolName]) return;
1662
1644
  if (!pm.canEnter(symbolName)) return;
1663
1645
 
@@ -1943,7 +1925,7 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
1943
1925
  // Capture baseline on first update (P&L at session start)
1944
1926
  if (baselineClosedPnl === null) {
1945
1927
  baselineClosedPnl = accountClosedPnl;
1946
- algoLogger.info(ui, 'SESSION START', `Baseline P&L: $${baselineClosedPnl.toFixed(2)}`);
1928
+ // Baseline captured silently - no need to show to user
1947
1929
  }
1948
1930
 
1949
1931
  // stats.closedPnl shows ONLY this session's closed P&L (delta from baseline)
@@ -2011,20 +1993,27 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
2011
1993
  ui.addLog('warning', '████ EMERGENCY STOP ████');
2012
1994
 
2013
1995
  try {
2014
- // Use Rithmic emergencyStop to flatten all positions
2015
- if (service && typeof service.emergencyStop === 'function') {
2016
- await service.emergencyStop(rithmicAccountId);
2017
- ui.addLog('info', 'Emergency stop executed - all positions flattened');
2018
- } else if (service && typeof service.flattenAll === 'function') {
2019
- await service.flattenAll(rithmicAccountId);
2020
- ui.addLog('info', 'Flatten all executed - all positions closed');
2021
- } else {
2022
- // Fallback: cancel all orders
2023
- 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') {
2024
2005
  await service.cancelAllOrders(rithmicAccountId);
2025
2006
  ui.addLog('info', 'All orders cancelled');
2026
2007
  }
2027
- }
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]);
2028
2017
  } catch (e) {
2029
2018
  ui.addLog('error', `Emergency stop error: ${e.message}`);
2030
2019
  }
@@ -2084,8 +2073,12 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
2084
2073
  try { pm.stop(); } catch {}
2085
2074
  }
2086
2075
 
2087
- // Disconnect market feed
2088
- 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 {}
2089
2082
 
2090
2083
  // Cleanup keyboard
2091
2084
  try { if (cleanupKeys) cleanupKeys(); } catch {}