hedgequantx 2.4.37 → 2.4.39

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.4.37",
3
+ "version": "2.4.39",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
package/src/app.js CHANGED
@@ -140,7 +140,7 @@ const banner = async () => {
140
140
 
141
141
  console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
142
142
 
143
- const tagline = isMobile ? `HQX v${version}` : `Prop Futures Algo Trading v${version}`;
143
+ const tagline = isMobile ? `HQX v${version}` : `PROP FUTURES ALGO TRADING v${version}`;
144
144
  console.log(chalk.cyan('║') + chalk.white(centerText(tagline, innerWidth)) + chalk.cyan('║'));
145
145
  };
146
146
 
@@ -4,49 +4,49 @@
4
4
 
5
5
  // Account Status Codes (ProjectX UserAPI)
6
6
  const ACCOUNT_STATUS = {
7
- 0: { text: 'Active', color: 'green' },
8
- 1: { text: 'End Of Day', color: 'cyan' },
9
- 2: { text: 'Halted', color: 'red' },
10
- 3: { text: 'Paused', color: 'yellow' },
11
- 4: { text: 'Holiday', color: 'blue' },
12
- 5: { text: 'Expired', color: 'gray' },
13
- 6: { text: 'Terminated', color: 'red' },
14
- 7: { text: 'Cancelled', color: 'red' },
15
- 8: { text: 'Failed', color: 'red' },
16
- 9: { text: 'Passed', color: 'green' }
7
+ 0: { text: 'ACTIVE', color: 'green' },
8
+ 1: { text: 'END OF DAY', color: 'cyan' },
9
+ 2: { text: 'HALTED', color: 'red' },
10
+ 3: { text: 'PAUSED', color: 'yellow' },
11
+ 4: { text: 'HOLIDAY', color: 'blue' },
12
+ 5: { text: 'EXPIRED', color: 'gray' },
13
+ 6: { text: 'TERMINATED', color: 'red' },
14
+ 7: { text: 'CANCELLED', color: 'red' },
15
+ 8: { text: 'FAILED', color: 'red' },
16
+ 9: { text: 'PASSED', color: 'green' }
17
17
  };
18
18
 
19
19
  // Account Types (ProjectX UserAPI)
20
20
  const ACCOUNT_TYPE = {
21
- 0: { text: 'Practice', color: 'blue' },
22
- 1: { text: 'Evaluation', color: 'yellow' },
23
- 2: { text: 'Live', color: 'green' },
24
- 3: { text: 'Express', color: 'magenta' },
25
- 4: { text: 'Sim', color: 'gray' }
21
+ 0: { text: 'PRACTICE', color: 'blue' },
22
+ 1: { text: 'EVALUATION', color: 'yellow' },
23
+ 2: { text: 'LIVE', color: 'green' },
24
+ 3: { text: 'EXPRESS', color: 'magenta' },
25
+ 4: { text: 'SIM', color: 'gray' }
26
26
  };
27
27
 
28
28
  // Order Status
29
29
  const ORDER_STATUS = {
30
- 0: { text: 'Pending', color: 'yellow', icon: '[~]' },
31
- 1: { text: 'Working', color: 'cyan', icon: '[>]' },
32
- 2: { text: 'Filled', color: 'green', icon: '[OK]' },
33
- 3: { text: 'Cancelled', color: 'gray', icon: '[X]' },
34
- 4: { text: 'Rejected', color: 'red', icon: '[!]' },
35
- 5: { text: 'Expired', color: 'gray', icon: '[-]' }
30
+ 0: { text: 'PENDING', color: 'yellow', icon: '[~]' },
31
+ 1: { text: 'WORKING', color: 'cyan', icon: '[>]' },
32
+ 2: { text: 'FILLED', color: 'green', icon: '[OK]' },
33
+ 3: { text: 'CANCELLED', color: 'gray', icon: '[X]' },
34
+ 4: { text: 'REJECTED', color: 'red', icon: '[!]' },
35
+ 5: { text: 'EXPIRED', color: 'gray', icon: '[-]' }
36
36
  };
37
37
 
38
38
  // Order Types
39
39
  const ORDER_TYPE = {
40
- 1: 'Market',
41
- 2: 'Limit',
42
- 3: 'Stop',
43
- 4: 'Stop Limit'
40
+ 1: 'MARKET',
41
+ 2: 'LIMIT',
42
+ 3: 'STOP',
43
+ 4: 'STOP LIMIT'
44
44
  };
45
45
 
46
46
  // Order Side
47
47
  const ORDER_SIDE = {
48
- 0: { text: 'Buy', color: 'green' },
49
- 1: { text: 'Sell', color: 'red' }
48
+ 0: { text: 'BUY', color: 'green' },
49
+ 1: { text: 'SELL', color: 'red' }
50
50
  };
51
51
 
52
52
  // NO STATIC CONTRACT DATA - All symbols/contracts come from API
@@ -38,7 +38,7 @@ const dashboardMenu = async (service) => {
38
38
  // Show connected propfirms
39
39
  const allConns = connections.getAll();
40
40
  if (allConns.length > 0) {
41
- const propfirms = allConns.slice(0, 3).map(c => c.propfirm || c.type || 'Connected');
41
+ const propfirms = allConns.slice(0, 3).map(c => (c.propfirm || c.type || 'CONNECTED').toUpperCase());
42
42
  const propfirmText = propfirms.map(p => chalk.green('● ') + chalk.white(p)).join(' ');
43
43
  console.log(makeLine(propfirmText, 'center'));
44
44
  }
@@ -62,14 +62,14 @@ const dashboardMenu = async (service) => {
62
62
 
63
63
  // Yellow icons: ✔ for each stat
64
64
  const icon = chalk.yellow('✔ ');
65
- const statsPlain = `✔ Connections: ${statsInfo.connections} ✔ Accounts: ${statsInfo.accounts} ✔ Balance: ${balStr} ✔ P&L: ${pnlDisplay}`;
65
+ const statsPlain = `✔ CONNECTIONS: ${statsInfo.connections} ✔ ACCOUNTS: ${statsInfo.accounts} ✔ BALANCE: ${balStr} ✔ P&L: ${pnlDisplay}`;
66
66
  const statsLeftPad = Math.max(0, Math.floor((W - statsPlain.length) / 2));
67
67
  const statsRightPad = Math.max(0, W - statsPlain.length - statsLeftPad);
68
68
 
69
69
  console.log(chalk.cyan('║') + ' '.repeat(statsLeftPad) +
70
- icon + chalk.white(`Connections: ${statsInfo.connections}`) + ' ' +
71
- icon + chalk.white(`Accounts: ${statsInfo.accounts}`) + ' ' +
72
- icon + chalk.white('Balance: ') + balColor(balStr) + ' ' +
70
+ icon + chalk.white(`CONNECTIONS: ${statsInfo.connections}`) + ' ' +
71
+ icon + chalk.white(`ACCOUNTS: ${statsInfo.accounts}`) + ' ' +
72
+ icon + chalk.white('BALANCE: ') + balColor(balStr) + ' ' +
73
73
  icon + chalk.white('P&L: ') + pnlColor(pnlDisplay) +
74
74
  ' '.repeat(Math.max(0, statsRightPad)) + chalk.cyan('║'));
75
75
  }
@@ -31,7 +31,7 @@ const showAccounts = async (service) => {
31
31
  // Single spinner for loading (appears below the dashboard header)
32
32
  spinner = ora({ text: 'LOADING ACCOUNTS...', color: 'yellow' }).start();
33
33
 
34
- const allConns = connections.count() > 0 ? connections.getAll() : (service ? [{ service, propfirm: service.propfirm?.name || 'Unknown', type: 'single' }] : []);
34
+ const allConns = connections.count() > 0 ? connections.getAll() : (service ? [{ service, propfirm: service.propfirm?.name || 'UNKNOWN', type: 'single' }] : []);
35
35
 
36
36
  if (allConns.length === 0) {
37
37
  spinner.fail('NO CONNECTIONS FOUND');
@@ -41,7 +41,7 @@ const showAccounts = async (service) => {
41
41
 
42
42
  // Fetch accounts from each connection
43
43
  for (const conn of allConns) {
44
- const propfirmName = conn.propfirm || conn.type || 'Unknown';
44
+ const propfirmName = conn.propfirm || conn.type || 'UNKNOWN';
45
45
 
46
46
  try {
47
47
  const result = await conn.service.getTradingAccounts();
@@ -94,9 +94,9 @@ const showAccounts = async (service) => {
94
94
  draw2ColHeader(name1.substring(0, col1 - 4), name2 ? name2.substring(0, col2 - 4) : '', boxWidth);
95
95
 
96
96
  // PropFirm
97
- const pf1 = chalk.magenta(acc1.propfirm || 'Unknown');
98
- const pf2 = acc2 ? chalk.magenta(acc2.propfirm || 'Unknown') : '';
99
- console.log(chalk.cyan('║') + fmtRow('PropFirm:', pf1, col1) + chalk.cyan('│') + (acc2 ? fmtRow('PropFirm:', pf2, col2) : ' '.repeat(col2)) + chalk.cyan('║'));
97
+ const pf1 = chalk.magenta(acc1.propfirm || 'UNKNOWN');
98
+ const pf2 = acc2 ? chalk.magenta(acc2.propfirm || 'UNKNOWN') : '';
99
+ console.log(chalk.cyan('║') + fmtRow('PROPFIRM:', pf1, col1) + chalk.cyan('│') + (acc2 ? fmtRow('PROPFIRM:', pf2, col2) : ' '.repeat(col2)) + chalk.cyan('║'));
100
100
 
101
101
  // Balance
102
102
  const bal1 = acc1.balance;
@@ -105,7 +105,7 @@ const showAccounts = async (service) => {
105
105
  const balStr2 = bal2 !== null && bal2 !== undefined ? '$' + Number(bal2).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) : '--';
106
106
  const balColor1 = bal1 === null || bal1 === undefined ? chalk.gray : (bal1 >= 0 ? chalk.green : chalk.red);
107
107
  const balColor2 = bal2 === null || bal2 === undefined ? chalk.gray : (bal2 >= 0 ? chalk.green : chalk.red);
108
- console.log(chalk.cyan('║') + fmtRow('Balance:', balColor1(balStr1), col1) + chalk.cyan('│') + (acc2 ? fmtRow('Balance:', balColor2(balStr2), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
108
+ console.log(chalk.cyan('║') + fmtRow('BALANCE:', balColor1(balStr1), col1) + chalk.cyan('│') + (acc2 ? fmtRow('BALANCE:', balColor2(balStr2), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
109
109
 
110
110
  // P&L
111
111
  const pnl1 = acc1.profitAndLoss;
@@ -117,14 +117,14 @@ const showAccounts = async (service) => {
117
117
  console.log(chalk.cyan('║') + fmtRow('P&L:', pnlColor1(pnlStr1), col1) + chalk.cyan('│') + (acc2 ? fmtRow('P&L:', pnlColor2(pnlStr2), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
118
118
 
119
119
  // Status
120
- const status1 = ACCOUNT_STATUS[acc1.status] || { text: 'Unknown', color: 'gray' };
121
- const status2 = acc2 ? (ACCOUNT_STATUS[acc2.status] || { text: 'Unknown', color: 'gray' }) : null;
122
- console.log(chalk.cyan('║') + fmtRow('Status:', chalk[status1.color](status1.text), col1) + chalk.cyan('│') + (acc2 ? fmtRow('Status:', chalk[status2.color](status2.text), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
120
+ const status1 = ACCOUNT_STATUS[acc1.status] || { text: 'UNKNOWN', color: 'gray' };
121
+ const status2 = acc2 ? (ACCOUNT_STATUS[acc2.status] || { text: 'UNKNOWN', color: 'gray' }) : null;
122
+ console.log(chalk.cyan('║') + fmtRow('STATUS:', chalk[status1.color](status1.text), col1) + chalk.cyan('│') + (acc2 ? fmtRow('STATUS:', chalk[status2.color](status2.text), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
123
123
 
124
124
  // Type
125
- const type1 = ACCOUNT_TYPE[acc1.type] || { text: 'Unknown', color: 'white' };
126
- const type2 = acc2 ? (ACCOUNT_TYPE[acc2.type] || { text: 'Unknown', color: 'white' }) : null;
127
- console.log(chalk.cyan('║') + fmtRow('Type:', chalk[type1.color](type1.text), col1) + chalk.cyan('│') + (acc2 ? fmtRow('Type:', chalk[type2.color](type2.text), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
125
+ const type1 = ACCOUNT_TYPE[acc1.type] || { text: 'UNKNOWN', color: 'white' };
126
+ const type2 = acc2 ? (ACCOUNT_TYPE[acc2.type] || { text: 'UNKNOWN', color: 'white' }) : null;
127
+ console.log(chalk.cyan('║') + fmtRow('TYPE:', chalk[type1.color](type1.text), col1) + chalk.cyan('│') + (acc2 ? fmtRow('TYPE:', chalk[type2.color](type2.text), col2) : ' '.repeat(col2)) + chalk.cyan('║'));
128
128
 
129
129
  if (i + 2 < allAccounts.length) {
130
130
  console.log(chalk.cyan('╠') + chalk.cyan('═'.repeat(col1)) + chalk.cyan('╪') + chalk.cyan('═'.repeat(col2)) + chalk.cyan('╣'));
@@ -136,7 +136,7 @@ class AlgoUI {
136
136
 
137
137
  // Separator + title
138
138
  this._line(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
139
- this._line(chalk.cyan(BOX.V) + chalk.white(center(`Prop Futures Algo Trading v${version}`, W)) + chalk.cyan(BOX.V));
139
+ this._line(chalk.cyan(BOX.V) + chalk.white(center(`PROP FUTURES ALGO TRADING v${version}`, W)) + chalk.cyan(BOX.V));
140
140
  this._line(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
141
141
  this._line(chalk.cyan(BOX.V) + chalk.yellow.bold(center((this.config.subtitle || 'HQX ALGO TRADING').toUpperCase(), W)) + chalk.cyan(BOX.V));
142
142
  }
@@ -183,7 +183,7 @@ class AlgoUI {
183
183
  this._line(chalk.cyan(GM));
184
184
 
185
185
  // Row 2: Qty | P&L
186
- const r2c1 = buildCell('Qty', (stats.qty || '1').toString(), chalk.cyan, colL);
186
+ const r2c1 = buildCell('QTY', (stats.qty || '1').toString(), chalk.cyan, colL);
187
187
  const r2c2 = buildCell('P&L', pnlStr, pnlColor, colR);
188
188
  row(r2c1.padded, r2c2.padded);
189
189
 
@@ -192,8 +192,8 @@ class AlgoUI {
192
192
  // Row 3: Target | Risk
193
193
  const targetStr = stats.target !== null && stats.target !== undefined ? '$' + stats.target.toFixed(2) : '--';
194
194
  const riskStr = stats.risk !== null && stats.risk !== undefined ? '$' + stats.risk.toFixed(2) : '--';
195
- const r3c1 = buildCell('Target', targetStr, chalk.green, colL);
196
- const r3c2 = buildCell('Risk', riskStr, chalk.red, colR);
195
+ const r3c1 = buildCell('TARGET', targetStr, chalk.green, colL);
196
+ const r3c2 = buildCell('RISK', riskStr, chalk.red, colR);
197
197
  row(r3c1.padded, r3c2.padded);
198
198
 
199
199
  this._line(chalk.cyan(GM));
@@ -201,15 +201,15 @@ class AlgoUI {
201
201
  // Row 4: Trades | Latency (API response time) - UPPERCASE BOLD
202
202
  const r4c1t = ` ${chalk.bold('TRADES')}: ${chalk.cyan.bold(stats.trades || 0)} ${chalk.bold('W/L')}: ${chalk.green.bold(stats.wins || 0)}/${chalk.red.bold(stats.losses || 0)}`;
203
203
  const r4c1p = ` TRADES: ${stats.trades || 0} W/L: ${stats.wins || 0}/${stats.losses || 0}`;
204
- const r4c2 = buildCell('Latency', `${stats.latency || 0}MS`, latencyColor, colR);
204
+ const r4c2 = buildCell('LATENCY', `${stats.latency || 0}MS`, latencyColor, colR);
205
205
  row(r4c1t + pad(colL - r4c1p.length), r4c2.padded);
206
206
 
207
207
  this._line(chalk.cyan(GM));
208
208
 
209
209
  // Row 5: Connection | Propfirm
210
210
  const connection = stats.platform || 'ProjectX';
211
- const r5c1 = buildCell('Connection', connection, chalk.cyan, colL);
212
- const r5c2 = buildCell('Propfirm', stats.propfirm || 'N/A', chalk.cyan, colR);
211
+ const r5c1 = buildCell('CONNECTION', connection, chalk.cyan, colL);
212
+ const r5c2 = buildCell('PROPFIRM', stats.propfirm || 'N/A', chalk.cyan, colR);
213
213
  row(r5c1.padded, r5c2.padded);
214
214
 
215
215
  this._line(chalk.cyan(GB));
@@ -244,22 +244,22 @@ class AlgoUI {
244
244
 
245
245
  // Row 2: Symbol (centered, single row)
246
246
  const symbol = (stats.symbol || stats.leadSymbol || 'N/A').substring(0, 60);
247
- const symbolText = `Symbol: ${symbol}`;
247
+ const symbolText = `SYMBOL: ${symbol}`;
248
248
  const symbolPadded = center(symbolText, W);
249
249
  this._line(chalk.cyan(BOX.V) + chalk.yellow(symbolPadded) + chalk.cyan(BOX.V));
250
250
 
251
251
  this._line(chalk.cyan(GT));
252
252
 
253
253
  // Row 3: Lead Qty | Follower Qty
254
- const r3c1 = buildCell('Qty', (stats.leadQty || '1').toString(), chalk.cyan, colL);
255
- const r3c2 = buildCell('Qty', (stats.followerQty || '1').toString(), chalk.cyan, colR);
254
+ const r3c1 = buildCell('QTY', (stats.leadQty || '1').toString(), chalk.cyan, colL);
255
+ const r3c2 = buildCell('QTY', (stats.followerQty || '1').toString(), chalk.cyan, colR);
256
256
  row(r3c1.padded, r3c2.padded);
257
257
 
258
258
  this._line(chalk.cyan(GM));
259
259
 
260
260
  // Row 4: Target | Risk
261
- const r4c1 = buildCell('Target', '$' + (stats.target || 0).toFixed(2), chalk.green, colL);
262
- const r4c2 = buildCell('Risk', '$' + (stats.risk || 0).toFixed(2), chalk.red, colR);
261
+ const r4c1 = buildCell('TARGET', '$' + (stats.target || 0).toFixed(2), chalk.green, colL);
262
+ const r4c2 = buildCell('RISK', '$' + (stats.risk || 0).toFixed(2), chalk.red, colR);
263
263
  row(r4c1.padded, r4c2.padded);
264
264
 
265
265
  this._line(chalk.cyan(GM));
@@ -396,7 +396,7 @@ const renderSessionSummary = (stats, stopReason) => {
396
396
 
397
397
  // Separator + title
398
398
  console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
399
- console.log(chalk.cyan(BOX.V) + chalk.white(center(`Prop Futures Algo Trading v${version}`, W)) + chalk.cyan(BOX.V));
399
+ console.log(chalk.cyan(BOX.V) + chalk.white(center(`PROP FUTURES ALGO TRADING v${version}`, W)) + chalk.cyan(BOX.V));
400
400
  console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
401
401
  console.log(chalk.cyan(BOX.V) + chalk.yellow.bold(center('SESSION SUMMARY', W)) + chalk.cyan(BOX.V));
402
402
 
@@ -443,7 +443,7 @@ const renderSessionSummary = (stats, stopReason) => {
443
443
  const pnlStr = `${pnl >= 0 ? '+' : ''}$${Math.abs(pnl).toFixed(2)}`;
444
444
  const pnlColor = pnl >= 0 ? chalk.green : chalk.red;
445
445
  const targetStr = `$${(stats.target || 0).toFixed(2)}`;
446
- row('P&L', pnlStr, pnlColor, 'Target', targetStr, chalk.cyan);
446
+ row('P&L', pnlStr, pnlColor, 'TARGET', targetStr, chalk.cyan);
447
447
 
448
448
  // Bottom border
449
449
  console.log(chalk.cyan(BOX.BOT + BOX.H.repeat(W) + BOX.BR));
@@ -337,13 +337,13 @@ const showStats = async (service) => {
337
337
  : 'N/A';
338
338
  const startBalStr = totalStartingBalance > 0 ? '$' + totalStartingBalance.toLocaleString(undefined, {minimumFractionDigits: 2}) : 'N/A';
339
339
 
340
- console.log(chalk.cyan('\u2551') + fmtRow('Connections:', chalk.cyan(connTypeStr.join(', ') || String(connections.count() || 1)), col1) + chalk.cyan('\u2502') + fmtRow('Total Trades:', hasTradeData || stats.totalTrades > 0 ? chalk.white(String(stats.totalTrades)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
341
- console.log(chalk.cyan('\u2551') + fmtRow('Total Accounts:', chalk.cyan(String(activeAccounts.length)), col1) + chalk.cyan('\u2502') + fmtRow('Winning Trades:', hasTradeData || stats.winningTrades > 0 ? chalk.green(String(stats.winningTrades)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
342
- console.log(chalk.cyan('\u2551') + fmtRow('Total Balance:', totalBalanceColor(balanceStr), col1) + chalk.cyan('\u2502') + fmtRow('Losing Trades:', hasTradeData || stats.losingTrades > 0 ? chalk.red(String(stats.losingTrades)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
343
- console.log(chalk.cyan('\u2551') + fmtRow('Starting Balance:', chalk.white(startBalStr), col1) + chalk.cyan('\u2502') + fmtRow('Win Rate:', winRate !== 'N/A' ? (parseFloat(winRate) >= 50 ? chalk.green(winRate + '%') : chalk.yellow(winRate + '%')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
344
- console.log(chalk.cyan('\u2551') + fmtRow('Total P&L:', pnlColor(pnlStr), col1) + chalk.cyan('\u2502') + fmtRow('Long Trades:', hasTradeData ? chalk.white(stats.longTrades + (longWinRate !== 'N/A' ? ' (' + longWinRate + '%)' : '')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
345
- console.log(chalk.cyan('\u2551') + fmtRow('Open Positions:', chalk.white(String(totalOpenPositions)), col1) + chalk.cyan('\u2502') + fmtRow('Short Trades:', hasTradeData ? chalk.white(stats.shortTrades + (shortWinRate !== 'N/A' ? ' (' + shortWinRate + '%)' : '')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
346
- console.log(chalk.cyan('\u2551') + fmtRow('Open Orders:', chalk.white(String(totalOpenOrders)), col1) + chalk.cyan('\u2502') + fmtRow('Volume:', hasTradeData ? chalk.white(stats.totalVolume + ' contracts') : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
340
+ console.log(chalk.cyan('\u2551') + fmtRow('CONNECTIONS:', chalk.cyan(connTypeStr.join(', ') || String(connections.count() || 1)), col1) + chalk.cyan('\u2502') + fmtRow('TOTAL TRADES:', hasTradeData || stats.totalTrades > 0 ? chalk.white(String(stats.totalTrades)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
341
+ console.log(chalk.cyan('\u2551') + fmtRow('TOTAL ACCOUNTS:', chalk.cyan(String(activeAccounts.length)), col1) + chalk.cyan('\u2502') + fmtRow('WINNING TRADES:', hasTradeData || stats.winningTrades > 0 ? chalk.green(String(stats.winningTrades)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
342
+ console.log(chalk.cyan('\u2551') + fmtRow('TOTAL BALANCE:', totalBalanceColor(balanceStr), col1) + chalk.cyan('\u2502') + fmtRow('LOSING TRADES:', hasTradeData || stats.losingTrades > 0 ? chalk.red(String(stats.losingTrades)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
343
+ console.log(chalk.cyan('\u2551') + fmtRow('STARTING BALANCE:', chalk.white(startBalStr), col1) + chalk.cyan('\u2502') + fmtRow('WIN RATE:', winRate !== 'N/A' ? (parseFloat(winRate) >= 50 ? chalk.green(winRate + '%') : chalk.yellow(winRate + '%')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
344
+ console.log(chalk.cyan('\u2551') + fmtRow('TOTAL P&L:', pnlColor(pnlStr), col1) + chalk.cyan('\u2502') + fmtRow('LONG TRADES:', hasTradeData ? chalk.white(stats.longTrades + (longWinRate !== 'N/A' ? ' (' + longWinRate + '%)' : '')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
345
+ console.log(chalk.cyan('\u2551') + fmtRow('OPEN POSITIONS:', chalk.white(String(totalOpenPositions)), col1) + chalk.cyan('\u2502') + fmtRow('SHORT TRADES:', hasTradeData ? chalk.white(stats.shortTrades + (shortWinRate !== 'N/A' ? ' (' + shortWinRate + '%)' : '')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
346
+ console.log(chalk.cyan('\u2551') + fmtRow('OPEN ORDERS:', chalk.white(String(totalOpenOrders)), col1) + chalk.cyan('\u2502') + fmtRow('VOLUME:', hasTradeData ? chalk.white(stats.totalVolume + ' CONTRACTS') : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
347
347
 
348
348
  // ========== P&L METRICS ==========
349
349
  draw2ColSeparator(boxWidth);
@@ -361,11 +361,11 @@ const showStats = async (service) => {
361
361
 
362
362
  const netPnLStr = hasTradeData ? (netPnL >= 0 ? chalk.green('$' + netPnL.toFixed(2)) : chalk.red('-$' + Math.abs(netPnL).toFixed(2))) : chalk.gray('N/A');
363
363
 
364
- console.log(chalk.cyan('\u2551') + fmtRow('Net P&L:', netPnLStr, col1) + chalk.cyan('\u2502') + fmtRow('Profit Factor:', pfColor, col2) + chalk.cyan('\u2551'));
365
- console.log(chalk.cyan('\u2551') + fmtRow('Gross Profit:', hasTradeData ? chalk.green('$' + stats.totalWinAmount.toFixed(2)) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('Max Consec. Wins:', hasTradeData ? chalk.green(String(stats.maxConsecutiveWins)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
366
- console.log(chalk.cyan('\u2551') + fmtRow('Gross Loss:', hasTradeData ? chalk.red('-$' + stats.totalLossAmount.toFixed(2)) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('Max Consec. Loss:', hasTradeData ? (stats.maxConsecutiveLosses > 0 ? chalk.red(String(stats.maxConsecutiveLosses)) : chalk.green('0')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
367
- console.log(chalk.cyan('\u2551') + fmtRow('Avg Win:', hasTradeData ? chalk.green('$' + avgWin) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('Best Trade:', hasTradeData ? chalk.green('$' + stats.bestTrade.toFixed(2)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
368
- console.log(chalk.cyan('\u2551') + fmtRow('Avg Loss:', hasTradeData ? (stats.losingTrades > 0 ? chalk.red('-$' + avgLoss) : chalk.green('$0.00')) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('Worst Trade:', hasTradeData ? (stats.worstTrade < 0 ? chalk.red(worstTradeStr) : chalk.green(worstTradeStr)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
364
+ console.log(chalk.cyan('\u2551') + fmtRow('NET P&L:', netPnLStr, col1) + chalk.cyan('\u2502') + fmtRow('PROFIT FACTOR:', pfColor, col2) + chalk.cyan('\u2551'));
365
+ console.log(chalk.cyan('\u2551') + fmtRow('GROSS PROFIT:', hasTradeData ? chalk.green('$' + stats.totalWinAmount.toFixed(2)) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('MAX CONSEC. WINS:', hasTradeData ? chalk.green(String(stats.maxConsecutiveWins)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
366
+ console.log(chalk.cyan('\u2551') + fmtRow('GROSS LOSS:', hasTradeData ? chalk.red('-$' + stats.totalLossAmount.toFixed(2)) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('MAX CONSEC. LOSS:', hasTradeData ? (stats.maxConsecutiveLosses > 0 ? chalk.red(String(stats.maxConsecutiveLosses)) : chalk.green('0')) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
367
+ console.log(chalk.cyan('\u2551') + fmtRow('AVG WIN:', hasTradeData ? chalk.green('$' + avgWin) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('BEST TRADE:', hasTradeData ? chalk.green('$' + stats.bestTrade.toFixed(2)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
368
+ console.log(chalk.cyan('\u2551') + fmtRow('AVG LOSS:', hasTradeData ? (stats.losingTrades > 0 ? chalk.red('-$' + avgLoss) : chalk.green('$0.00')) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('WORST TRADE:', hasTradeData ? (stats.worstTrade < 0 ? chalk.red(worstTradeStr) : chalk.green(worstTradeStr)) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
369
369
 
370
370
  // ========== QUANTITATIVE METRICS ==========
371
371
  draw2ColSeparator(boxWidth);
@@ -376,10 +376,10 @@ const showStats = async (service) => {
376
376
  const ddColor = maxDrawdown === 0 ? chalk.gray : maxDrawdown <= 5 ? chalk.green : maxDrawdown <= 15 ? chalk.yellow : chalk.red;
377
377
  const rrColor = riskRewardRatio === 'N/A' ? chalk.gray : parseFloat(riskRewardRatio) >= 2 ? chalk.green : parseFloat(riskRewardRatio) >= 1 ? chalk.yellow : chalk.red;
378
378
 
379
- console.log(chalk.cyan('\u2551') + fmtRow('Sharpe Ratio:', sharpeColor(sharpeRatio), col1) + chalk.cyan('\u2502') + fmtRow('Risk/Reward:', rrColor(riskRewardRatio), col2) + chalk.cyan('\u2551'));
380
- console.log(chalk.cyan('\u2551') + fmtRow('Sortino Ratio:', sortinoColor(sortinoRatio), col1) + chalk.cyan('\u2502') + fmtRow('Calmar Ratio:', calmarRatio === 'N/A' ? chalk.gray(calmarRatio) : chalk.white(calmarRatio), col2) + chalk.cyan('\u2551'));
381
- console.log(chalk.cyan('\u2551') + fmtRow('Max Drawdown:', hasTradeData && maxDrawdown > 0 ? ddColor(maxDrawdown.toFixed(2) + '%') : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('Expectancy:', hasTradeData ? (expectancy >= 0 ? chalk.green('$' + expectancy.toFixed(2)) : chalk.red('$' + expectancy.toFixed(2))) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
382
- console.log(chalk.cyan('\u2551') + fmtRow('Std Deviation:', hasTradeData ? chalk.white('$' + stdDev.toFixed(2)) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('Avg Trade:', hasTradeData ? (avgReturn >= 0 ? chalk.green('$' + avgReturn.toFixed(2)) : chalk.red('$' + avgReturn.toFixed(2))) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
379
+ console.log(chalk.cyan('\u2551') + fmtRow('SHARPE RATIO:', sharpeColor(sharpeRatio), col1) + chalk.cyan('\u2502') + fmtRow('RISK/REWARD:', rrColor(riskRewardRatio), col2) + chalk.cyan('\u2551'));
380
+ console.log(chalk.cyan('\u2551') + fmtRow('SORTINO RATIO:', sortinoColor(sortinoRatio), col1) + chalk.cyan('\u2502') + fmtRow('CALMAR RATIO:', calmarRatio === 'N/A' ? chalk.gray(calmarRatio) : chalk.white(calmarRatio), col2) + chalk.cyan('\u2551'));
381
+ console.log(chalk.cyan('\u2551') + fmtRow('MAX DRAWDOWN:', hasTradeData && maxDrawdown > 0 ? ddColor(maxDrawdown.toFixed(2) + '%') : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('EXPECTANCY:', hasTradeData ? (expectancy >= 0 ? chalk.green('$' + expectancy.toFixed(2)) : chalk.red('$' + expectancy.toFixed(2))) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
382
+ console.log(chalk.cyan('\u2551') + fmtRow('STD DEVIATION:', hasTradeData ? chalk.white('$' + stdDev.toFixed(2)) : chalk.gray('N/A'), col1) + chalk.cyan('\u2502') + fmtRow('AVG TRADE:', hasTradeData ? (avgReturn >= 0 ? chalk.green('$' + avgReturn.toFixed(2)) : chalk.red('$' + avgReturn.toFixed(2))) : chalk.gray('N/A'), col2) + chalk.cyan('\u2551'));
383
383
 
384
384
  drawBoxFooter(boxWidth);
385
385
 
@@ -421,8 +421,8 @@ const showStats = async (service) => {
421
421
  });
422
422
  } else {
423
423
  const msg = connectionTypes.rithmic > 0
424
- ? ' No trade history (Rithmic does not provide trade history API)'
425
- : ' No trade data available';
424
+ ? ' NO TRADE HISTORY (RITHMIC DOES NOT PROVIDE TRADE HISTORY API)'
425
+ : ' NO TRADE DATA AVAILABLE';
426
426
  console.log(chalk.cyan('\u2551') + chalk.gray(msg) + ' '.repeat(Math.max(0, chartInnerWidth - msg.length)) + chalk.cyan('\u2551'));
427
427
  }
428
428
 
@@ -467,13 +467,13 @@ const showStats = async (service) => {
467
467
 
468
468
  // Header - build with exact spacing
469
469
  const headerParts = [
470
- ' ' + 'Time'.padEnd(colTime),
471
- 'Symbol'.padEnd(colSymbol),
472
- 'Side'.padEnd(colSide),
470
+ ' ' + 'TIME'.padEnd(colTime),
471
+ 'SYMBOL'.padEnd(colSymbol),
472
+ 'SIDE'.padEnd(colSide),
473
473
  'P&L'.padEnd(colPnl),
474
- 'Fees'.padEnd(colFees),
475
- 'Net'.padEnd(colNet),
476
- 'Account'.padEnd(colAccount)
474
+ 'FEES'.padEnd(colFees),
475
+ 'NET'.padEnd(colNet),
476
+ 'ACCOUNT'.padEnd(colAccount)
477
477
  ];
478
478
  const header = headerParts.join('| ');
479
479
  console.log(chalk.cyan('\u2551') + chalk.white(header) + chalk.cyan('\u2551'));
@@ -540,13 +540,13 @@ const showStats = async (service) => {
540
540
  }
541
541
 
542
542
  if (sortedTrades.length === 0) {
543
- const msg = ' No completed trades yet';
543
+ const msg = ' NO COMPLETED TRADES YET';
544
544
  console.log(chalk.cyan('\u2551') + chalk.gray(msg.padEnd(innerWidth)) + chalk.cyan('\u2551'));
545
545
  }
546
546
  } else {
547
547
  const msg = connectionTypes.rithmic > 0
548
- ? ' No trade history (Rithmic API limitation)'
549
- : ' No trade history available';
548
+ ? ' NO TRADE HISTORY (RITHMIC API LIMITATION)'
549
+ : ' NO TRADE HISTORY AVAILABLE';
550
550
  console.log(chalk.cyan('\u2551') + chalk.gray(msg.padEnd(innerWidth)) + chalk.cyan('\u2551'));
551
551
  }
552
552
 
@@ -581,18 +581,18 @@ const showStats = async (service) => {
581
581
  };
582
582
 
583
583
  const metricsDisplay = [
584
- { name: 'Win Rate', score: winRateScore },
585
- { name: 'Profit Factor', score: profitFactorScore },
586
- { name: 'Consistency', score: consistencyScore },
587
- { name: 'Risk Management', score: riskScore },
588
- { name: 'Volume', score: volumeScore },
589
- { name: 'Returns', score: returnScore }
584
+ { name: 'WIN RATE', score: winRateScore },
585
+ { name: 'PROFIT FACTOR', score: profitFactorScore },
586
+ { name: 'CONSISTENCY', score: consistencyScore },
587
+ { name: 'RISK MANAGEMENT', score: riskScore },
588
+ { name: 'VOLUME', score: volumeScore },
589
+ { name: 'RETURNS', score: returnScore }
590
590
  ];
591
591
 
592
592
  const barWidth = 30;
593
593
  const labelWidth = 18;
594
594
 
595
- const overallLine = ` OVERALL SCORE: ${scoreColor(String(hqxScore))} / 100 [Grade: ${scoreColor(scoreGrade)}]`;
595
+ const overallLine = ` OVERALL SCORE: ${scoreColor(String(hqxScore))} / 100 [GRADE: ${scoreColor(scoreGrade)}]`;
596
596
  const overallVisLen = overallLine.replace(/\x1b\[[0-9;]*m/g, '').length;
597
597
  console.log(chalk.cyan('\u2551') + overallLine + ' '.repeat(innerWidth - overallVisLen) + chalk.cyan('\u2551'));
598
598
  console.log(chalk.cyan('\u2551') + chalk.gray('\u2500'.repeat(innerWidth)) + chalk.cyan('\u2551'));
@@ -613,9 +613,9 @@ const showStats = async (service) => {
613
613
 
614
614
  // Show data source notice
615
615
  if (connectionTypes.rithmic > 0 && connectionTypes.projectx === 0) {
616
- console.log(chalk.gray(' Note: Rithmic API provides balance/P&L only. Trade history not available.'));
616
+ console.log(chalk.gray(' NOTE: RITHMIC API PROVIDES BALANCE/P&L ONLY. TRADE HISTORY NOT AVAILABLE.'));
617
617
  } else if (connectionTypes.rithmic > 0 && connectionTypes.projectx > 0) {
618
- console.log(chalk.gray(' Note: Trade history shown from ProjectX accounts only.'));
618
+ console.log(chalk.gray(' NOTE: TRADE HISTORY SHOWN FROM PROJECTX ACCOUNTS ONLY.'));
619
619
  }
620
620
 
621
621
  } catch (error) {
package/src/pages/user.js CHANGED
@@ -71,10 +71,10 @@ const showUserInfo = async (service) => {
71
71
 
72
72
  const username = userInfo.userName || userInfo.username || 'Unknown';
73
73
  const connCount = connections.count() || 1;
74
- console.log(chalk.cyan('║') + fmtRow('Username:', chalk.cyan(username.toUpperCase()), col1) + chalk.cyan('│') + fmtRow('Connections:', chalk.cyan(String(connCount)), col2) + chalk.cyan('║'));
74
+ console.log(chalk.cyan('║') + fmtRow('USERNAME:', chalk.cyan(username.toUpperCase()), col1) + chalk.cyan('│') + fmtRow('CONNECTIONS:', chalk.cyan(String(connCount)), col2) + chalk.cyan('║'));
75
75
 
76
76
  const email = userInfo.email || 'N/A';
77
- console.log(chalk.cyan('║') + fmtRow('Email:', chalk.white(email), col1) + chalk.cyan('│') + fmtRow('Accounts:', chalk.cyan(String(accountCount)), col2) + chalk.cyan('║'));
77
+ console.log(chalk.cyan('║') + fmtRow('EMAIL:', chalk.white(email), col1) + chalk.cyan('│') + fmtRow('ACCOUNTS:', chalk.cyan(String(accountCount)), col2) + chalk.cyan('║'));
78
78
 
79
79
  const userId = userInfo.userId || userInfo.id || 'N/A';
80
80
  const platform = service?.propfirm?.name || 'ProjectX';
package/src/ui/box.js CHANGED
@@ -97,7 +97,7 @@ const drawBoxSeparator = (width) => {
97
97
  const printLogo = () => {
98
98
  const logoText = figlet.textSync('HEDGEQUANTX', { font: 'ANSI Shadow' });
99
99
  console.log(chalk.cyan(logoText));
100
- console.log(chalk.gray.italic(' Prop Futures Algo Trading CLI'));
100
+ console.log(chalk.gray.italic(' PROP FUTURES ALGO TRADING CLI'));
101
101
  console.log();
102
102
  };
103
103
 
package/src/ui/index.js CHANGED
@@ -70,7 +70,7 @@ const displayBanner = () => {
70
70
  }
71
71
 
72
72
  console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
73
- const tagline = isMobile ? `HQX v${version}` : `Prop Futures Algo Trading v${version}`;
73
+ const tagline = isMobile ? `HQX v${version}` : `PROP FUTURES ALGO TRADING v${version}`;
74
74
  console.log(chalk.cyan('║') + chalk.white(centerText(tagline, innerWidth)) + chalk.cyan('║'));
75
75
  };
76
76
 
package/src/ui/menu.js CHANGED
@@ -48,7 +48,7 @@ const createBoxMenu = async (title, items, options = {}) => {
48
48
  });
49
49
 
50
50
  console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
51
- console.log(chalk.cyan('║') + chalk.white(centerText(`Prop Futures Algo Trading v${version}`, innerWidth)) + chalk.cyan('║'));
51
+ console.log(chalk.cyan('║') + chalk.white(centerText(`PROP FUTURES ALGO TRADING v${version}`, innerWidth)) + chalk.cyan('║'));
52
52
 
53
53
  // Stats bar if provided
54
54
  if (options.statsLine) {
@@ -85,6 +85,7 @@ const nativePrompt = (message) => {
85
85
  */
86
86
  const waitForEnter = async (message = 'PRESS ENTER TO CONTINUE...') => {
87
87
  await nativePrompt(message);
88
+ console.clear();
88
89
  };
89
90
 
90
91
  /**