hedgequantx 1.3.12 → 1.4.0

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/app.js +52 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "1.3.12",
3
+ "version": "1.4.0",
4
4
  "description": "Prop Futures Algo Trading CLI - Connect to Topstep, Alpha Futures, and other prop firms",
5
5
  "main": "src/app.js",
6
6
  "bin": {
package/src/app.js CHANGED
@@ -22,6 +22,9 @@ const { projectXMenu, rithmicMenu, tradovateMenu, addPropAccountMenu, dashboardM
22
22
  let currentService = null;
23
23
  let currentPlatform = null; // 'projectx' or 'rithmic'
24
24
 
25
+ // Cached stats for banner (avoid refetching on every screen)
26
+ let cachedStats = null;
27
+
25
28
  /**
26
29
  * Global terminal restoration - ensures terminal is always restored on exit
27
30
  */
@@ -58,20 +61,9 @@ process.on('unhandledRejection', (reason) => {
58
61
  });
59
62
 
60
63
  /**
61
- * Displays the application banner with stats if connected
64
+ * Refresh cached stats (call after connection/disconnection/add account)
62
65
  */
63
- const banner = async () => {
64
- console.clear();
65
- const termWidth = process.stdout.columns || 100;
66
- const isMobile = termWidth < 60;
67
- // Logo HEDGEQUANTX + X = 94 chars, need 98 for box (94 + 2 borders + 2 padding)
68
- const boxWidth = isMobile ? Math.max(termWidth - 2, 40) : Math.max(getLogoWidth(), 98);
69
- const innerWidth = boxWidth - 2;
70
- const version = require('../package.json').version;
71
-
72
- // Get stats if connected (only active accounts: status === 0)
73
- // STRICT: Only display values from API, no estimation
74
- let statsInfo = null;
66
+ const refreshStats = async () => {
75
67
  if (connections.count() > 0) {
76
68
  try {
77
69
  const allAccounts = await connections.getAllAccounts();
@@ -97,18 +89,35 @@ const banner = async () => {
97
89
  }
98
90
  });
99
91
 
100
- statsInfo = {
92
+ cachedStats = {
101
93
  connections: connections.count(),
102
94
  accounts: activeAccounts.length,
103
95
  balance: hasBalanceData ? totalBalance : null,
104
96
  pnl: hasPnlData ? totalPnl : null,
105
- // No percentage calculation if no verified data
106
97
  pnlPercent: null
107
98
  };
108
99
  } catch (e) {
109
100
  // Ignore errors
110
101
  }
102
+ } else {
103
+ cachedStats = null;
111
104
  }
105
+ };
106
+
107
+ /**
108
+ * Displays the application banner with stats if connected
109
+ */
110
+ const banner = async () => {
111
+ console.clear();
112
+ const termWidth = process.stdout.columns || 100;
113
+ const isMobile = termWidth < 60;
114
+ // Logo HEDGEQUANTX + X = 94 chars, need 98 for box (94 + 2 borders + 2 padding)
115
+ const boxWidth = isMobile ? Math.max(termWidth - 2, 40) : Math.max(getLogoWidth(), 98);
116
+ const innerWidth = boxWidth - 2;
117
+ const version = require('../package.json').version;
118
+
119
+ // Use cached stats (no refetch on every banner display)
120
+ const statsInfo = cachedStats;
112
121
 
113
122
  // Draw logo - compact for mobile, full for desktop
114
123
 
@@ -292,6 +301,8 @@ const run = async () => {
292
301
  if (restored) {
293
302
  spinner.succeed('Session restored');
294
303
  currentService = connections.getAll()[0].service;
304
+ // Refresh stats after session restore
305
+ await refreshStats();
295
306
  } else {
296
307
  spinner.info('No active session');
297
308
  }
@@ -302,7 +313,7 @@ const run = async () => {
302
313
  // Ensure stdin is ready for prompts (fixes input leaking to bash)
303
314
  prepareStdin();
304
315
 
305
- // Refresh banner with stats
316
+ // Display banner (uses cached stats, no refetch)
306
317
  await banner();
307
318
 
308
319
  if (!connections.isConnected()) {
@@ -315,17 +326,26 @@ const run = async () => {
315
326
 
316
327
  if (choice === 'projectx') {
317
328
  const service = await projectXMenu();
318
- if (service) currentService = service;
329
+ if (service) {
330
+ currentService = service;
331
+ await refreshStats(); // Refresh after new connection
332
+ }
319
333
  }
320
334
 
321
335
  if (choice === 'rithmic') {
322
336
  const service = await rithmicMenu();
323
- if (service) currentService = service;
337
+ if (service) {
338
+ currentService = service;
339
+ await refreshStats(); // Refresh after new connection
340
+ }
324
341
  }
325
342
 
326
343
  if (choice === 'tradovate') {
327
344
  const service = await tradovateMenu();
328
- if (service) currentService = service;
345
+ if (service) {
346
+ currentService = service;
347
+ await refreshStats(); // Refresh after new connection
348
+ }
329
349
  }
330
350
  } else {
331
351
  const action = await dashboardMenu(currentService);
@@ -343,13 +363,22 @@ const run = async () => {
343
363
  const platformChoice = await addPropAccountMenu();
344
364
  if (platformChoice === 'projectx') {
345
365
  const newService = await projectXMenu();
346
- if (newService) currentService = newService;
366
+ if (newService) {
367
+ currentService = newService;
368
+ await refreshStats(); // Refresh after adding account
369
+ }
347
370
  } else if (platformChoice === 'rithmic') {
348
371
  const newService = await rithmicMenu();
349
- if (newService) currentService = newService;
372
+ if (newService) {
373
+ currentService = newService;
374
+ await refreshStats(); // Refresh after adding account
375
+ }
350
376
  } else if (platformChoice === 'tradovate') {
351
377
  const newService = await tradovateMenu();
352
- if (newService) currentService = newService;
378
+ if (newService) {
379
+ currentService = newService;
380
+ await refreshStats(); // Refresh after adding account
381
+ }
353
382
  }
354
383
  break;
355
384
  case 'algotrading':
@@ -363,6 +392,7 @@ const run = async () => {
363
392
  const connCount = connections.count();
364
393
  connections.disconnectAll();
365
394
  currentService = null;
395
+ cachedStats = null; // Clear cached stats
366
396
  console.log(chalk.yellow(`Disconnected ${connCount} connection${connCount > 1 ? 's' : ''}`));
367
397
  break;
368
398
  case 'exit':