hedgequantx 2.9.122 → 2.9.124

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.9.122",
3
+ "version": "2.9.124",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -277,11 +277,18 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
277
277
  else if (price < lastPrice) sellVolume += volume;
278
278
  }
279
279
 
280
- // Log first tick
280
+ // Log first tick and periodic tick count
281
281
  if (tickCount === 1) {
282
282
  ui.addLog('connected', `First tick @ ${price?.toFixed(2) || 'N/A'}`);
283
283
  }
284
284
 
285
+ // Log tick count every 10 seconds to confirm data flow
286
+ if (tickCount % 1000 === 0 || (currentSecond % 10 === 0 && currentSecond !== lastLogSecond)) {
287
+ const state = strategy.getAnalysisState?.(contractId, price);
288
+ const bars = state?.barsProcessed || 0;
289
+ ui.addLog('debug', `Ticks: ${tickCount} | Bars: ${bars} | Price: ${price?.toFixed(2)}`);
290
+ }
291
+
285
292
  // === SMART LOGS - REDUCED FREQUENCY ===
286
293
  if (currentSecond !== lastLogSecond && tickCount > 1) {
287
294
  lastLogSecond = currentSecond;
@@ -291,12 +298,15 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
291
298
  const delta = buyVolume - sellVolume;
292
299
 
293
300
  let bias = buyPressure > 55 ? 'LONG' : buyPressure < 45 ? 'SHORT' : 'FLAT';
294
- const strongSignal = Math.abs(delta) > 20 || buyPressure > 65 || buyPressure < 35;
295
- if (bias !== lastBias || (strongSignal && currentSecond % 5 === 0) || (!strongSignal && currentSecond % 15 === 0)) {
301
+ // Log bias every 5 seconds or when it changes
302
+ if (bias !== lastBias || currentSecond % 5 === 0) {
296
303
  const biasLog = smartLogs.getMarketBiasLog(bias, delta, buyPressure);
297
304
  const biasType = bias === 'LONG' ? 'bullish' : bias === 'SHORT' ? 'bearish' : 'analysis';
298
305
  ui.addLog(biasType, `${biasLog.message} ${biasLog.details || ''}`);
299
306
  lastBias = bias;
307
+ // Reset volume after logging
308
+ buyVolume = 0;
309
+ sellVolume = 0;
300
310
  }
301
311
 
302
312
  // Strategy state log every 30 seconds (reduced frequency)
@@ -329,28 +339,8 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
329
339
  }
330
340
  }
331
341
 
332
- // Scanning log every 20 seconds
333
- if (currentSecond % 20 === 0 && currentPosition === 0) ui.addLog('system', smartLogs.getScanningLog(true).message);
334
- // Tick flow log every 45 seconds
335
- if (currentSecond % 45 === 0) { const t = smartLogs.getTickFlowLog(tickCount, ticksPerSecond); ui.addLog('debug', `${t.message} ${t.details}`); }
336
- // AI Agents status every 60 seconds
337
- if (currentSecond % 60 === 0 && supervisionEnabled && supervisionEngine) {
338
- const status = supervisionEngine.getStatus();
339
- const agentNames = status.agents.map(a => a.name.split(' ')[0]).join(', ');
340
- ui.addLog('analysis', `AI Supervision active: ${agentNames} (${status.availableAgents} agents monitoring)`);
341
- }
342
-
343
- // Strategy health status every 2 minutes (confirms strategy is working)
344
- if (currentSecond % 120 === 0 && strategy.getHealthStatus) {
345
- const health = strategy.getHealthStatus(contractId);
346
- const uptime = Math.floor(health.uptime / 60000);
347
- const status = health.healthy ? 'OK' : 'WARMING';
348
- ui.addLog('ready', `HEALTH: ${status} | Bars: ${health.barsTotal} | Zones: ${health.zonesTotal} (R:${health.zonesResistance}/S:${health.zonesSupport}) | Swings: ${health.swingsTotal} | Uptime: ${uptime}m`);
349
- }
350
-
351
- // Reset volume counters
352
- buyVolume = 0;
353
- sellVolume = 0;
342
+ // AI status every 60s
343
+ if (currentSecond % 60 === 0 && supervisionEnabled && supervisionEngine) ui.addLog('analysis', `AI: ${supervisionEngine.getStatus().agents.map(a => a.name.split(' ')[0]).join(', ')}`);
354
344
  }
355
345
 
356
346
  lastPrice = price;
@@ -98,6 +98,18 @@ class RithmicService extends EventEmitter {
98
98
 
99
99
  await this.orderConn.connect(config);
100
100
  this.orderConn.on('message', createOrderHandler(this));
101
+
102
+ // Auto-reconnect on disconnect
103
+ this.orderConn.on('disconnected', async ({ code, reason }) => {
104
+ log.warn('ORDER_PLANT disconnected', { code, reason });
105
+ this.emit('disconnected', { plant: 'ORDER', code, reason });
106
+
107
+ // Auto-reconnect if we have credentials (not manual disconnect)
108
+ if (this.credentials && code !== 1000) {
109
+ log.info('Attempting auto-reconnect in 3s...');
110
+ setTimeout(() => this._autoReconnect(), 3000);
111
+ }
112
+ });
101
113
 
102
114
  return new Promise((resolve) => {
103
115
  const timeout = setTimeout(() => {
@@ -163,6 +175,13 @@ class RithmicService extends EventEmitter {
163
175
 
164
176
  await this.pnlConn.connect(config);
165
177
  this.pnlConn.on('message', createPnLHandler(this));
178
+
179
+ // Auto-reconnect PnL on disconnect
180
+ this.pnlConn.on('disconnected', ({ code }) => {
181
+ if (this.credentials && code !== 1000) {
182
+ setTimeout(() => this.connectPnL(this.credentials.username, this.credentials.password), 3000);
183
+ }
184
+ });
166
185
 
167
186
  return new Promise((resolve) => {
168
187
  const timeout = setTimeout(() => resolve(false), TIMEOUTS.RITHMIC_PNL);
@@ -200,6 +219,13 @@ class RithmicService extends EventEmitter {
200
219
  };
201
220
 
202
221
  await this.tickerConn.connect(config);
222
+
223
+ // Auto-reconnect Ticker on disconnect
224
+ this.tickerConn.on('disconnected', ({ code }) => {
225
+ if (this.credentials && code !== 1000) {
226
+ setTimeout(() => this.connectTicker(this.credentials.username, this.credentials.password), 3000);
227
+ }
228
+ });
203
229
 
204
230
  return new Promise((resolve) => {
205
231
  const timeout = setTimeout(() => {
@@ -383,9 +409,42 @@ class RithmicService extends EventEmitter {
383
409
  return { isOpen: true, message: 'Market is open' };
384
410
  }
385
411
 
412
+ // ==================== AUTO-RECONNECT ====================
413
+
414
+ async _autoReconnect() {
415
+ if (!this.credentials) {
416
+ log.warn('Cannot auto-reconnect: no credentials');
417
+ return;
418
+ }
419
+
420
+ const { username, password } = this.credentials;
421
+ log.info('Auto-reconnecting...');
422
+ this.emit('reconnecting');
423
+
424
+ try {
425
+ const result = await this.login(username, password);
426
+ if (result.success) {
427
+ log.info('Auto-reconnect successful');
428
+ this.emit('reconnected', { accounts: result.accounts });
429
+ } else {
430
+ log.warn('Auto-reconnect failed', { error: result.error });
431
+ this.emit('reconnectFailed', { error: result.error });
432
+ // Retry in 10s
433
+ setTimeout(() => this._autoReconnect(), 10000);
434
+ }
435
+ } catch (err) {
436
+ log.error('Auto-reconnect error', { error: err.message });
437
+ this.emit('reconnectFailed', { error: err.message });
438
+ // Retry in 10s
439
+ setTimeout(() => this._autoReconnect(), 10000);
440
+ }
441
+ }
442
+
386
443
  // ==================== CLEANUP ====================
387
444
 
388
445
  async disconnect() {
446
+ // Clear credentials to prevent auto-reconnect on manual disconnect
447
+ this.credentials = null;
389
448
  const connections = [this.orderConn, this.pnlConn, this.tickerConn];
390
449
 
391
450
  for (const conn of connections) {