hedgequantx 2.6.78 → 2.6.80

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.78",
3
+ "version": "2.6.80",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -981,8 +981,8 @@ const launchAlgo = async (service, account, contract, config) => {
981
981
  };
982
982
 
983
983
  // Start polling and UI refresh
984
- // UI refreshes every 500ms (reduced from 250ms to prevent flicker), P&L polling every 10s
985
- const refreshInterval = setInterval(() => { if (running) ui.render(stats); }, 500);
984
+ // UI refreshes every 1000ms (reduced to prevent flicker on VPS/SSH), P&L polling every 10s
985
+ const refreshInterval = setInterval(() => { if (running) ui.render(stats); }, 1000);
986
986
  const pnlInterval = setInterval(() => { if (running) pollPnL(); }, 10000);
987
987
  pollPnL(); // Initial poll
988
988
 
@@ -143,6 +143,9 @@ class AlgoUI {
143
143
  this.isDrawing = false;
144
144
  this.lines = [];
145
145
  this.lastOutput = '';
146
+ this.lastStatsHash = ''; // Track stats changes
147
+ this.lastLogsHash = ''; // Track logs changes
148
+ this.lastSpinnerUpdate = 0; // Rate limit spinner updates
146
149
  }
147
150
 
148
151
  addLog(type, message) {
@@ -326,14 +329,17 @@ class AlgoUI {
326
329
  _drawLogs() {
327
330
  const { W, logs, maxLogs } = this;
328
331
 
329
- // Activity header - HF style
330
- this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER.length;
331
- const spinner = SPINNER[this.spinnerFrame];
332
- const now = new Date();
333
- const timeStr = now.toLocaleTimeString('en-US', { hour12: false });
334
- const dateStr = now.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
332
+ // Activity header - HF style (NO SPINNER/TIME - causes flicker on VPS/SSH)
333
+ // Date is cached on first draw to prevent changes
334
+ if (!this.cachedDate) {
335
+ const nowDate = new Date();
336
+ this.cachedDate = nowDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).toUpperCase();
337
+ }
338
+ const dateStr = this.cachedDate;
335
339
 
336
- const leftText = ` EXECUTION LOG ${spinner}`;
340
+ // Static indicator instead of spinner
341
+ const indicator = '●';
342
+ const leftText = ` EXECUTION LOG ${indicator}`;
337
343
  const rightText = `[X] STOP `;
338
344
 
339
345
  const totalFixed = leftText.length + rightText.length;
@@ -341,8 +347,8 @@ class AlgoUI {
341
347
  const centerPadLeft = Math.floor((centerSpace - dateStr.length) / 2);
342
348
  const centerPadRight = centerSpace - dateStr.length - centerPadLeft;
343
349
 
344
- const left = ` ${chalk.bold('EXECUTION LOG')} ${chalk.yellow(spinner)}`;
345
- const center = ' '.repeat(Math.max(0, centerPadLeft)) + chalk.white.bold(dateStr.toUpperCase()) + ' '.repeat(Math.max(0, centerPadRight));
350
+ const left = ` ${chalk.bold('EXECUTION LOG')} ${chalk.green(indicator)}`;
351
+ const center = ' '.repeat(Math.max(0, centerPadLeft)) + chalk.white.bold(dateStr) + ' '.repeat(Math.max(0, centerPadRight));
346
352
  const right = chalk.yellow.bold('[X] STOP') + ' ';
347
353
 
348
354
  this._line(chalk.cyan(BOX.V) + chalk.white(left) + center + right + chalk.cyan(BOX.V));
@@ -380,27 +386,49 @@ class AlgoUI {
380
386
  if (this.isDrawing) return;
381
387
  this.isDrawing = true;
382
388
 
383
- this.lines = [];
384
-
385
- if (this.firstDraw) {
386
- // Enter alternate screen, hide cursor, clear once
387
- process.stdout.write('\x1B[?1049h\x1B[?25l\x1B[2J');
388
- this.firstDraw = false;
389
- }
390
-
391
- this._line('');
392
- this._drawHeader();
393
- this._drawStats(stats);
394
- this._drawLogs();
395
-
396
- // Build output with fixed line positions
397
- const output = this.lines.join('\n');
398
-
399
- // Only write if content changed (reduces flicker significantly)
400
- if (output !== this.lastOutput) {
401
- // Move cursor to home, then write all lines
402
- process.stdout.write('\x1B[H' + output);
403
- this.lastOutput = output;
389
+ // Quick hash to detect meaningful changes (skip spinner in hash)
390
+ const statsHash = JSON.stringify({
391
+ pnl: stats.pnl,
392
+ openPnl: stats.openPnl,
393
+ closedPnl: stats.closedPnl,
394
+ position: stats.position,
395
+ trades: stats.trades,
396
+ wins: stats.wins,
397
+ losses: stats.losses,
398
+ connected: stats.connected,
399
+ });
400
+ const logsHash = this.logs.length + (this.logs[this.logs.length - 1]?.message || '');
401
+
402
+ // Check if anything meaningful changed
403
+ const hasChanges = statsHash !== this.lastStatsHash || logsHash !== this.lastLogsHash;
404
+
405
+ // First draw or changes detected
406
+ if (this.firstDraw || hasChanges) {
407
+ this.lastStatsHash = statsHash;
408
+ this.lastLogsHash = logsHash;
409
+
410
+ this.lines = [];
411
+
412
+ if (this.firstDraw) {
413
+ // Enter alternate screen, hide cursor, clear once
414
+ process.stdout.write('\x1B[?1049h\x1B[?25l\x1B[2J');
415
+ this.firstDraw = false;
416
+ }
417
+
418
+ this._line('');
419
+ this._drawHeader();
420
+ this._drawStats(stats);
421
+ this._drawLogs();
422
+
423
+ // Build output with fixed line positions
424
+ const output = this.lines.join('\n');
425
+
426
+ // Only write if content changed (reduces flicker significantly)
427
+ if (output !== this.lastOutput) {
428
+ // Move cursor to home, then write all lines
429
+ process.stdout.write('\x1B[H' + output);
430
+ this.lastOutput = output;
431
+ }
404
432
  }
405
433
 
406
434
  this.isDrawing = false;