hedgequantx 2.6.149 → 2.6.150

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.149",
3
+ "version": "2.6.150",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -2022,78 +2022,58 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
2022
2022
  ]);
2023
2023
 
2024
2024
  try {
2025
- // Step 1: Cancel all pending orders
2025
+ // CRITICAL: Use ONLY Rithmic API to get REAL positions from exchange
2026
+ // DO NOT use local stats which can be corrupted
2027
+
2028
+ // Step 1: Cancel all pending orders first
2026
2029
  ui.addLog('info', 'Cancelling all orders...');
2027
2030
  ui.render(stats);
2028
2031
  try {
2029
2032
  if (service && typeof service.cancelAllOrders === 'function') {
2030
2033
  await withTimeout(service.cancelAllOrders(rithmicAccountId), TIMEOUT_MS);
2034
+ ui.addLog('success', 'All orders cancelled');
2031
2035
  }
2032
2036
  } catch (e) {
2033
2037
  ui.addLog('warning', `Cancel orders: ${e.message}`);
2034
2038
  }
2035
2039
 
2036
- // Step 2: Force close each symbol's position via fastExit
2037
- ui.addLog('info', 'Closing all positions...');
2040
+ // Step 2: Use Rithmic flattenAll - reads REAL positions from exchange
2041
+ ui.addLog('info', 'Flattening all positions via Rithmic API...');
2038
2042
  ui.render(stats);
2039
2043
 
2040
- for (const [symbolName, symStats] of Object.entries(stats.symbolStats)) {
2041
- // Get position from positionManager (more reliable than stats)
2042
- const pm = positionManagers[symbolName];
2043
- const pmPosition = pm?.currentPosition;
2044
-
2045
- // Use PM position if available, otherwise fallback to stats
2046
- let posQty = 0;
2047
- let closeSide = 0;
2048
-
2049
- if (pmPosition && pmPosition.size > 0) {
2050
- posQty = pmPosition.size;
2051
- closeSide = pmPosition.side === 0 ? 1 : 0; // Sell if long (0), Buy if short (1)
2052
- } else if (symStats.position && symStats.position !== 0) {
2053
- // Fallback: use stats but sanitize the value
2054
- posQty = Math.min(Math.abs(Number(symStats.position) || 0), 10); // Max 10 contracts safety
2055
- if (posQty === 0) posQty = 1; // Default to 1 if we think there's a position
2056
- closeSide = symStats.position > 0 ? 1 : 0;
2057
- }
2058
-
2059
- if (posQty === 0) continue;
2060
-
2061
- const sideStr = closeSide === 1 ? 'SELL' : 'BUY';
2062
-
2063
- ui.addLog('info', `Closing [${symbolName}] ${sideStr} ${posQty}x...`);
2064
- ui.render(stats);
2065
-
2066
- try {
2067
- // Try fastExit first (fastest)
2068
- if (service && typeof service.fastExit === 'function') {
2069
- const result = await withTimeout(service.fastExit({
2070
- accountId: rithmicAccountId,
2071
- symbol: symbolName,
2072
- exchange: contractInfoMap[symbolName]?.exchange || 'CME',
2073
- size: posQty,
2074
- side: closeSide,
2075
- }), TIMEOUT_MS);
2076
-
2077
- if (result.success) {
2078
- ui.addLog('success', `[${symbolName}] FLATTENED`);
2079
- symStats.position = 0;
2080
- } else {
2081
- ui.addLog('error', `[${symbolName}] Exit failed: ${result.error}`);
2044
+ try {
2045
+ if (service && typeof service.flattenAll === 'function') {
2046
+ const result = await withTimeout(service.flattenAll(rithmicAccountId), TIMEOUT_MS);
2047
+ if (result && result.results) {
2048
+ for (const r of result.results) {
2049
+ if (r.success) {
2050
+ ui.addLog('success', `[${r.symbol}] FLATTENED`);
2051
+ } else {
2052
+ ui.addLog('error', `[${r.symbol}] ${r.error || 'Failed'}`);
2053
+ }
2082
2054
  }
2083
2055
  }
2084
- } catch (e) {
2085
- ui.addLog('error', `[${symbolName}] Exit error: ${e.message}`);
2056
+ ui.addLog('success', 'Flatten all complete');
2057
+ } else if (service && typeof service.emergencyStop === 'function') {
2058
+ // Fallback to emergencyStop
2059
+ await withTimeout(service.emergencyStop(rithmicAccountId), TIMEOUT_MS);
2060
+ ui.addLog('success', 'Emergency stop complete');
2086
2061
  }
2062
+ } catch (e) {
2063
+ ui.addLog('warning', `Flatten: ${e.message}`);
2087
2064
  }
2088
2065
 
2089
- // Step 3: Fallback - call service.emergencyStop for any remaining
2090
- try {
2091
- if (service && typeof service.emergencyStop === 'function') {
2092
- await withTimeout(service.emergencyStop(rithmicAccountId), TIMEOUT_MS);
2066
+ // Step 3: Reset local state
2067
+ for (const [symbolName, symStats] of Object.entries(stats.symbolStats)) {
2068
+ symStats.position = 0;
2069
+ symStats.openPnl = 0;
2070
+ // Also reset position manager
2071
+ const pm = positionManagers[symbolName];
2072
+ if (pm) {
2073
+ try { pm.reset?.(); } catch {}
2093
2074
  }
2094
- } catch (e) {
2095
- // Silent - already tried individual closes
2096
2075
  }
2076
+ stats.openPnl = 0;
2097
2077
 
2098
2078
  ui.addLog('success', '████ EMERGENCY STOP COMPLETE ████');
2099
2079