hedgequantx 2.4.37 → 2.4.38
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 +1 -1
- package/src/menus/dashboard.js +4 -4
- package/src/pages/accounts.js +2 -2
- package/src/pages/algo/ui.js +12 -12
- package/src/pages/stats.js +16 -16
- package/src/pages/user.js +2 -2
package/package.json
CHANGED
package/src/menus/dashboard.js
CHANGED
|
@@ -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 = `✔
|
|
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(`
|
|
71
|
-
icon + chalk.white(`
|
|
72
|
-
icon + chalk.white('
|
|
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
|
}
|
package/src/pages/accounts.js
CHANGED
|
@@ -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('
|
|
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;
|
|
@@ -119,7 +119,7 @@ const showAccounts = async (service) => {
|
|
|
119
119
|
// Status
|
|
120
120
|
const status1 = ACCOUNT_STATUS[acc1.status] || { text: 'Unknown', color: 'gray' };
|
|
121
121
|
const status2 = acc2 ? (ACCOUNT_STATUS[acc2.status] || { text: 'Unknown', color: 'gray' }) : null;
|
|
122
|
-
console.log(chalk.cyan('║') + fmtRow('
|
|
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
125
|
const type1 = ACCOUNT_TYPE[acc1.type] || { text: 'Unknown', color: 'white' };
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -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('
|
|
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('
|
|
196
|
-
const r3c2 = buildCell('
|
|
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('
|
|
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('
|
|
212
|
-
const r5c2 = buildCell('
|
|
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 = `
|
|
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('
|
|
255
|
-
const r3c2 = buildCell('
|
|
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('
|
|
262
|
-
const r4c2 = buildCell('
|
|
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));
|
|
@@ -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, '
|
|
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));
|
package/src/pages/stats.js
CHANGED
|
@@ -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('
|
|
341
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
342
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
343
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
344
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
345
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
346
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
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('
|
|
365
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
366
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
367
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
368
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
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('
|
|
380
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
381
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
382
|
-
console.log(chalk.cyan('\u2551') + fmtRow('
|
|
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
|
|
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('
|
|
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('
|
|
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';
|