hedgequantx 2.3.4 → 2.3.6

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/dist/lib/api.jsc CHANGED
Binary file
package/dist/lib/api2.jsc CHANGED
Binary file
package/dist/lib/core.jsc CHANGED
Binary file
Binary file
package/dist/lib/data.jsc CHANGED
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/lib/n/r1.jsc CHANGED
Binary file
package/dist/lib/n/r2.jsc CHANGED
Binary file
package/dist/lib/n/r3.jsc CHANGED
Binary file
package/dist/lib/n/r4.jsc CHANGED
Binary file
package/dist/lib/n/r5.jsc CHANGED
Binary file
package/dist/lib/n/r6.jsc CHANGED
Binary file
package/dist/lib/n/r7.jsc CHANGED
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -230,7 +230,7 @@ const showStats = async (service) => {
230
230
  const winRate = stats.totalTrades > 0 ? ((stats.winningTrades / stats.totalTrades) * 100).toFixed(1) : '0.0';
231
231
  const avgWin = stats.winningTrades > 0 ? (stats.totalWinAmount / stats.winningTrades).toFixed(2) : '0.00';
232
232
  const avgLoss = stats.losingTrades > 0 ? (stats.totalLossAmount / stats.losingTrades).toFixed(2) : '0.00';
233
- const profitFactor = stats.totalLossAmount > 0 ? (stats.totalWinAmount / stats.totalLossAmount).toFixed(2) : '0.00';
233
+ const profitFactor = stats.totalLossAmount > 0 ? (stats.totalWinAmount / stats.totalLossAmount).toFixed(2) : (stats.totalWinAmount > 0 ? '∞' : '0.00');
234
234
  const netPnL = stats.totalWinAmount - stats.totalLossAmount;
235
235
  const returnPercent = totalStartingBalance > 0 ? ((totalPnL / totalStartingBalance) * 100).toFixed(2) : '0.00';
236
236
  const longWinRate = stats.longTrades > 0 ? ((stats.longWins / stats.longTrades) * 100).toFixed(1) : '0.0';
@@ -291,13 +291,18 @@ const showStats = async (service) => {
291
291
  draw2ColSeparator(boxWidth);
292
292
  draw2ColHeader('P&L METRICS', 'RISK METRICS', boxWidth);
293
293
 
294
- const pfColor = parseFloat(profitFactor) >= 1.5 ? chalk.green(profitFactor) : parseFloat(profitFactor) >= 1 ? chalk.yellow(profitFactor) : chalk.red(profitFactor);
294
+ // Profit Factor coloring - is best (green)
295
+ const pfNum = profitFactor === '∞' ? Infinity : parseFloat(profitFactor);
296
+ const pfColor = pfNum === Infinity ? chalk.green(profitFactor) : pfNum >= 1.5 ? chalk.green(profitFactor) : pfNum >= 1 ? chalk.yellow(profitFactor) : chalk.red(profitFactor);
295
297
 
296
- console.log(chalk.cyan('\u2551') + fmtRow('Net P&L:', netPnL >= 0 ? chalk.green('$' + netPnL.toFixed(2)) : chalk.red('$' + netPnL.toFixed(2)), col1) + chalk.cyan('\u2502') + fmtRow('Profit Factor:', pfColor, col2) + chalk.cyan('\u2551'));
298
+ // Worst trade display - show as negative if it's a loss
299
+ const worstTradeStr = stats.worstTrade < 0 ? '-$' + Math.abs(stats.worstTrade).toFixed(2) : '$' + stats.worstTrade.toFixed(2);
300
+
301
+ console.log(chalk.cyan('\u2551') + fmtRow('Net P&L:', netPnL >= 0 ? chalk.green('$' + netPnL.toFixed(2)) : chalk.red('-$' + Math.abs(netPnL).toFixed(2)), col1) + chalk.cyan('\u2502') + fmtRow('Profit Factor:', pfColor, col2) + chalk.cyan('\u2551'));
297
302
  console.log(chalk.cyan('\u2551') + fmtRow('Gross Profit:', chalk.green('$' + stats.totalWinAmount.toFixed(2)), col1) + chalk.cyan('\u2502') + fmtRow('Max Consec. Wins:', chalk.green(String(stats.maxConsecutiveWins)), col2) + chalk.cyan('\u2551'));
298
- console.log(chalk.cyan('\u2551') + fmtRow('Gross Loss:', chalk.red('-$' + stats.totalLossAmount.toFixed(2)), col1) + chalk.cyan('\u2502') + fmtRow('Max Consec. Loss:', chalk.red(String(stats.maxConsecutiveLosses)), col2) + chalk.cyan('\u2551'));
303
+ console.log(chalk.cyan('\u2551') + fmtRow('Gross Loss:', chalk.red('-$' + stats.totalLossAmount.toFixed(2)), col1) + chalk.cyan('\u2502') + fmtRow('Max Consec. Loss:', stats.maxConsecutiveLosses > 0 ? chalk.red(String(stats.maxConsecutiveLosses)) : chalk.green('0'), col2) + chalk.cyan('\u2551'));
299
304
  console.log(chalk.cyan('\u2551') + fmtRow('Avg Win:', chalk.green('$' + avgWin), col1) + chalk.cyan('\u2502') + fmtRow('Best Trade:', chalk.green('$' + stats.bestTrade.toFixed(2)), col2) + chalk.cyan('\u2551'));
300
- console.log(chalk.cyan('\u2551') + fmtRow('Avg Loss:', chalk.red('-$' + avgLoss), col1) + chalk.cyan('\u2502') + fmtRow('Worst Trade:', chalk.red('$' + stats.worstTrade.toFixed(2)), col2) + chalk.cyan('\u2551'));
305
+ console.log(chalk.cyan('\u2551') + fmtRow('Avg Loss:', stats.losingTrades > 0 ? chalk.red('-$' + avgLoss) : chalk.green('$0.00'), col1) + chalk.cyan('\u2502') + fmtRow('Worst Trade:', stats.worstTrade < 0 ? chalk.red(worstTradeStr) : chalk.green(worstTradeStr), col2) + chalk.cyan('\u2551'));
301
306
 
302
307
  // Quantitative Metrics
303
308
  draw2ColSeparator(boxWidth);
@@ -358,75 +363,63 @@ const showStats = async (service) => {
358
363
 
359
364
  drawBoxFooter(boxWidth);
360
365
 
361
- // Trades History
366
+ // Trades History - Simplified table
362
367
  console.log();
363
368
  drawBoxHeader('TRADES HISTORY', boxWidth);
364
369
 
365
370
  const innerWidth = boxWidth - 2;
366
371
 
372
+ // Helper to extract symbol from contractId (e.g., "CON.F.US.EP.H25" -> "ES H25")
373
+ const extractSymbol = (contractId) => {
374
+ if (!contractId) return 'N/A';
375
+ // Format: CON.F.US.{SYMBOL}.{MONTH} -> extract symbol and month
376
+ const parts = contractId.split('.');
377
+ if (parts.length >= 5) {
378
+ const sym = parts[3]; // EP, ENQ, etc.
379
+ const month = parts[4]; // H25, M25, etc.
380
+ // Map common symbols
381
+ const symbolMap = { 'EP': 'ES', 'ENQ': 'NQ', 'MES': 'MES', 'MNQ': 'MNQ', 'YM': 'YM', 'NKD': 'NKD', 'RTY': 'RTY' };
382
+ return (symbolMap[sym] || sym) + ' ' + month;
383
+ }
384
+ return contractId.substring(0, 10);
385
+ };
386
+
367
387
  if (allTrades.length > 0) {
368
- const colTime = 12;
369
- const colSymbol = 10;
370
- const colEntry = 10;
371
- const colExit = 10;
372
- const colEntryP = 10;
373
- const colExitP = 10;
374
- const colPnL = 10;
375
- const colDir = 6;
376
- const colID = innerWidth - colTime - colSymbol - colEntry - colExit - colEntryP - colExitP - colPnL - colDir - 9;
377
-
378
- const header =
379
- chalk.white(' Time'.padEnd(colTime)) + chalk.gray('|') +
380
- chalk.white('Symbol'.padEnd(colSymbol)) + chalk.gray('|') +
381
- chalk.white('Entry'.padEnd(colEntry)) + chalk.gray('|') +
382
- chalk.white('Exit'.padEnd(colExit)) + chalk.gray('|') +
383
- chalk.white('Entry $'.padEnd(colEntryP)) + chalk.gray('|') +
384
- chalk.white('Exit $'.padEnd(colExitP)) + chalk.gray('|') +
385
- chalk.white('P&L'.padEnd(colPnL)) + chalk.gray('|') +
386
- chalk.white('Dir'.padEnd(colDir)) + chalk.gray('|') +
387
- chalk.white('ID'.padEnd(colID));
388
-
389
- console.log(chalk.cyan('\u2551') + header + chalk.cyan('\u2551'));
388
+ // Simple format: Time | Symbol | Price | P&L | Side
389
+ const header = ' Time | Symbol | Price | P&L | Side ';
390
+ console.log(chalk.cyan('\u2551') + chalk.white(header.padEnd(innerWidth)) + chalk.cyan('\u2551'));
390
391
  console.log(chalk.cyan('\u2551') + chalk.gray('\u2500'.repeat(innerWidth)) + chalk.cyan('\u2551'));
391
392
 
392
393
  const recentTrades = allTrades.slice(-10).reverse();
393
394
 
394
395
  for (const trade of recentTrades) {
395
- const time = trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) : '--:--';
396
- const symbol = (trade.contractName || trade.symbol || 'N/A').substring(0, colSymbol - 1);
397
- const entryTime = trade.entryTime ? new Date(trade.entryTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) : '--:--';
398
- const exitTime = trade.exitTime ? new Date(trade.exitTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) : '--:--';
399
- const entryPrice = trade.entryPrice ? trade.entryPrice.toFixed(2) : 'N/A';
400
- const exitPrice = trade.exitPrice ? trade.exitPrice.toFixed(2) : 'N/A';
396
+ const timestamp = trade.creationTimestamp || trade.timestamp;
397
+ const time = timestamp ? new Date(timestamp).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true }) : '--:--';
398
+ const symbol = extractSymbol(trade.contractId || trade.symbol);
399
+ const price = (trade.price || 0).toFixed(2);
401
400
  const pnl = trade.profitAndLoss || trade.pnl || 0;
402
- const pnlStr = pnl >= 0 ? chalk.green('+$' + pnl.toFixed(0)) : chalk.red('-$' + Math.abs(pnl).toFixed(0));
403
- const direction = trade.side === 0 ? chalk.green('LONG') : trade.side === 1 ? chalk.red('SHORT') : chalk.gray('N/A');
404
- const tradeId = String(trade.id || trade.tradeId || 'N/A').substring(0, colID - 1);
401
+ const pnlText = pnl >= 0 ? `+$${pnl.toFixed(0)}` : `-$${Math.abs(pnl).toFixed(0)}`;
402
+ const pnlColored = pnl >= 0 ? chalk.green(pnlText.padEnd(10)) : chalk.red(pnlText.padEnd(10));
403
+ const side = trade.side === 0 ? 'BUY' : trade.side === 1 ? 'SELL' : 'N/A';
404
+ const sideColored = trade.side === 0 ? chalk.green(side.padEnd(6)) : chalk.red(side.padEnd(6));
405
405
 
406
- const row =
407
- (' ' + time).padEnd(colTime) + chalk.gray('|') +
408
- symbol.padEnd(colSymbol) + chalk.gray('|') +
409
- entryTime.padEnd(colEntry) + chalk.gray('|') +
410
- exitTime.padEnd(colExit) + chalk.gray('|') +
411
- entryPrice.padEnd(colEntryP) + chalk.gray('|') +
412
- exitPrice.padEnd(colExitP) + chalk.gray('|') +
413
- pnlStr.padEnd(colPnL + 10) + chalk.gray('|') +
414
- direction.padEnd(colDir + 10) + chalk.gray('|') +
415
- tradeId.padEnd(colID);
406
+ const row = ` ${time.padEnd(9)} | ${symbol.padEnd(9)} | ${price.padEnd(10)} | ${pnlText.padEnd(10)} | ${side.padEnd(6)}`;
407
+ const coloredRow = ` ${time.padEnd(9)} | ${symbol.padEnd(9)} | ${price.padEnd(10)} | ${pnlColored} | ${sideColored}`;
416
408
 
417
- const visLen = row.replace(/\x1b\[[0-9;]*m/g, '').length;
418
- const padding = innerWidth - visLen;
409
+ // Calculate visible length without ANSI codes
410
+ const visLen = row.length;
411
+ const padding = Math.max(0, innerWidth - visLen);
419
412
 
420
- console.log(chalk.cyan('\u2551') + row + ' '.repeat(Math.max(0, padding)) + chalk.cyan('\u2551'));
413
+ console.log(chalk.cyan('\u2551') + coloredRow + ' '.repeat(padding) + chalk.cyan('\u2551'));
421
414
  }
422
415
 
423
416
  if (allTrades.length > 10) {
424
417
  const moreMsg = ` ... and ${allTrades.length - 10} more trades`;
425
- console.log(chalk.cyan('\u2551') + chalk.gray(moreMsg) + ' '.repeat(innerWidth - moreMsg.length) + chalk.cyan('\u2551'));
418
+ console.log(chalk.cyan('\u2551') + chalk.gray(moreMsg.padEnd(innerWidth)) + chalk.cyan('\u2551'));
426
419
  }
427
420
  } else {
428
421
  const msg = ' No trade history available';
429
- console.log(chalk.cyan('\u2551') + chalk.gray(msg) + ' '.repeat(innerWidth - msg.length) + chalk.cyan('\u2551'));
422
+ console.log(chalk.cyan('\u2551') + chalk.gray(msg.padEnd(innerWidth)) + chalk.cyan('\u2551'));
430
423
  }
431
424
 
432
425
  drawBoxFooter(boxWidth);
@@ -436,7 +429,7 @@ const showStats = async (service) => {
436
429
  drawBoxHeader('HQX SCORE', boxWidth);
437
430
 
438
431
  const winRateScore = Math.min(100, parseFloat(winRate) * 1.5);
439
- const profitFactorScore = Math.min(100, parseFloat(profitFactor) * 40);
432
+ const profitFactorScore = profitFactor === '∞' ? 100 : Math.min(100, parseFloat(profitFactor) * 40);
440
433
  const consistencyScore = stats.maxConsecutiveLosses > 0 ? Math.max(0, 100 - (stats.maxConsecutiveLosses * 15)) : 100;
441
434
  const riskScore = stats.worstTrade !== 0 && totalStartingBalance > 0
442
435
  ? Math.max(0, 100 - (Math.abs(stats.worstTrade) / totalStartingBalance * 1000))