hedgequantx 2.6.132 → 2.6.133
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/pages/algo/ui.js +52 -37
package/package.json
CHANGED
package/src/pages/algo/ui.js
CHANGED
|
@@ -549,11 +549,18 @@ const renderSessionSummary = (stats, stopReason) => {
|
|
|
549
549
|
|
|
550
550
|
/**
|
|
551
551
|
* Render Multi-Symbol Session Summary - Same style as single-symbol
|
|
552
|
+
* All columns centered
|
|
552
553
|
*/
|
|
553
554
|
const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
554
555
|
const W = 96;
|
|
555
556
|
const version = require('../../../package.json').version;
|
|
556
557
|
|
|
558
|
+
// Helper: center text in column width
|
|
559
|
+
const centerCol = (text, width) => {
|
|
560
|
+
const pad = Math.floor((width - text.length) / 2);
|
|
561
|
+
return ' '.repeat(pad) + text + ' '.repeat(width - pad - text.length);
|
|
562
|
+
};
|
|
563
|
+
|
|
557
564
|
console.clear();
|
|
558
565
|
console.log();
|
|
559
566
|
|
|
@@ -575,22 +582,21 @@ const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
|
575
582
|
console.log(chalk.cyan(BOX.V) + chalk.yellow.bold(center('MULTI-SYMBOL SESSION SUMMARY', W)) + chalk.cyan(BOX.V));
|
|
576
583
|
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
577
584
|
|
|
578
|
-
//
|
|
579
|
-
const colSymbol =
|
|
580
|
-
const colTrades =
|
|
581
|
-
const colWR =
|
|
582
|
-
const colWins =
|
|
583
|
-
const colLosses =
|
|
584
|
-
const colPnL =
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
const
|
|
589
|
-
const
|
|
590
|
-
const
|
|
591
|
-
const
|
|
592
|
-
const
|
|
593
|
-
const headerPnL = 'P&L'.padEnd(colPnL + remaining);
|
|
585
|
+
// Column widths (total = 96 - 5 separators = 91)
|
|
586
|
+
const colSymbol = 14;
|
|
587
|
+
const colTrades = 12;
|
|
588
|
+
const colWR = 14;
|
|
589
|
+
const colWins = 12;
|
|
590
|
+
const colLosses = 12;
|
|
591
|
+
const colPnL = W - colSymbol - colTrades - colWR - colWins - colLosses - 5; // remaining
|
|
592
|
+
|
|
593
|
+
// Header row - centered
|
|
594
|
+
const headerSymbol = centerCol('SYMBOL', colSymbol);
|
|
595
|
+
const headerTrades = centerCol('TRADES', colTrades);
|
|
596
|
+
const headerWR = centerCol('WIN RATE', colWR);
|
|
597
|
+
const headerWins = centerCol('WINS', colWins);
|
|
598
|
+
const headerLosses = centerCol('LOSSES', colLosses);
|
|
599
|
+
const headerPnL = centerCol('P&L', colPnL);
|
|
594
600
|
|
|
595
601
|
console.log(chalk.cyan(BOX.V) + chalk.bold.white(headerSymbol) + chalk.cyan(BOX.VS) +
|
|
596
602
|
chalk.bold.white(headerTrades) + chalk.cyan(BOX.VS) +
|
|
@@ -601,7 +607,7 @@ const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
|
601
607
|
|
|
602
608
|
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
603
609
|
|
|
604
|
-
// Per-symbol rows
|
|
610
|
+
// Per-symbol rows - centered
|
|
605
611
|
for (const [symbol, symStats] of Object.entries(symbolStats)) {
|
|
606
612
|
const winRate = symStats.trades > 0 ? ((symStats.wins / symStats.trades) * 100).toFixed(0) + '%' : '0%';
|
|
607
613
|
const pnl = symStats.pnl || 0;
|
|
@@ -609,12 +615,12 @@ const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
|
609
615
|
const pnlColor = pnl >= 0 ? chalk.green : chalk.red;
|
|
610
616
|
const wrColor = symStats.wins >= symStats.losses ? chalk.green : chalk.red;
|
|
611
617
|
|
|
612
|
-
const cellSymbol = (
|
|
613
|
-
const cellTrades = String(symStats.trades || 0)
|
|
614
|
-
const cellWR = winRate
|
|
615
|
-
const cellWins = String(symStats.wins || 0)
|
|
616
|
-
const cellLosses = String(symStats.losses || 0)
|
|
617
|
-
const cellPnL = pnlStr
|
|
618
|
+
const cellSymbol = centerCol(symbol, colSymbol);
|
|
619
|
+
const cellTrades = centerCol(String(symStats.trades || 0), colTrades);
|
|
620
|
+
const cellWR = centerCol(winRate, colWR);
|
|
621
|
+
const cellWins = centerCol(String(symStats.wins || 0), colWins);
|
|
622
|
+
const cellLosses = centerCol(String(symStats.losses || 0), colLosses);
|
|
623
|
+
const cellPnL = centerCol(pnlStr, colPnL);
|
|
618
624
|
|
|
619
625
|
console.log(chalk.cyan(BOX.V) + chalk.yellow(cellSymbol) + chalk.cyan(BOX.VS) +
|
|
620
626
|
chalk.white(cellTrades) + chalk.cyan(BOX.VS) +
|
|
@@ -627,21 +633,21 @@ const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
|
627
633
|
// Separator before totals
|
|
628
634
|
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
629
635
|
|
|
630
|
-
// Total row
|
|
636
|
+
// Total row - centered
|
|
631
637
|
const totalWinRate = stats.trades > 0 ? ((stats.wins / stats.trades) * 100).toFixed(0) + '%' : '0%';
|
|
632
638
|
const totalPnl = stats.sessionPnl || 0;
|
|
633
639
|
const totalPnlStr = (totalPnl >= 0 ? '+$' : '-$') + Math.abs(totalPnl).toFixed(2);
|
|
634
640
|
const totalPnlColor = totalPnl >= 0 ? chalk.green : chalk.red;
|
|
635
641
|
const totalWrColor = stats.wins >= stats.losses ? chalk.green : chalk.red;
|
|
636
642
|
|
|
637
|
-
const totalCellSymbol = '
|
|
638
|
-
const totalCellTrades = String(stats.trades || 0)
|
|
639
|
-
const totalCellWR = totalWinRate
|
|
640
|
-
const totalCellWins = String(stats.wins || 0)
|
|
641
|
-
const totalCellLosses = String(stats.losses || 0)
|
|
642
|
-
const totalCellPnL = totalPnlStr
|
|
643
|
+
const totalCellSymbol = centerCol('TOTAL', colSymbol);
|
|
644
|
+
const totalCellTrades = centerCol(String(stats.trades || 0), colTrades);
|
|
645
|
+
const totalCellWR = centerCol(totalWinRate, colWR);
|
|
646
|
+
const totalCellWins = centerCol(String(stats.wins || 0), colWins);
|
|
647
|
+
const totalCellLosses = centerCol(String(stats.losses || 0), colLosses);
|
|
648
|
+
const totalCellPnL = centerCol(totalPnlStr, colPnL);
|
|
643
649
|
|
|
644
|
-
console.log(chalk.cyan(BOX.V) + chalk.bold.
|
|
650
|
+
console.log(chalk.cyan(BOX.V) + chalk.bold.cyan(totalCellSymbol) + chalk.cyan(BOX.VS) +
|
|
645
651
|
chalk.bold.white(totalCellTrades) + chalk.cyan(BOX.VS) +
|
|
646
652
|
totalWrColor.bold(totalCellWR) + chalk.cyan(BOX.VS) +
|
|
647
653
|
chalk.bold.green(totalCellWins) + chalk.cyan(BOX.VS) +
|
|
@@ -651,15 +657,24 @@ const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
|
651
657
|
// Separator
|
|
652
658
|
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
653
659
|
|
|
654
|
-
// Stop Reason & Duration row
|
|
660
|
+
// Stop Reason & Duration row - centered
|
|
655
661
|
const duration = stats.duration || '--';
|
|
656
662
|
const reasonColor = stopReason === 'target' ? chalk.green : stopReason === 'risk' ? chalk.red : chalk.yellow;
|
|
657
663
|
const reasonStr = (stopReason || 'manual').toUpperCase();
|
|
658
|
-
const
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
664
|
+
const infoPlain = `STOP: ${reasonStr} | DURATION: ${duration} | TARGET: $${(stats.target || 0).toFixed(2)} | RISK: $${(stats.risk || 0).toFixed(2)}`;
|
|
665
|
+
const infoPadded = center(infoPlain, W);
|
|
666
|
+
|
|
667
|
+
// Build colored version with same centering
|
|
668
|
+
const padLeft = Math.floor((W - infoPlain.length) / 2);
|
|
669
|
+
const padRight = W - infoPlain.length - padLeft;
|
|
670
|
+
const infoColored = ' '.repeat(padLeft) +
|
|
671
|
+
chalk.bold('STOP') + ': ' + reasonColor.bold(reasonStr) + ' | ' +
|
|
672
|
+
chalk.bold('DURATION') + ': ' + chalk.white(duration) + ' | ' +
|
|
673
|
+
chalk.bold('TARGET') + ': ' + chalk.cyan('$' + (stats.target || 0).toFixed(2)) + ' | ' +
|
|
674
|
+
chalk.bold('RISK') + ': ' + chalk.red('$' + (stats.risk || 0).toFixed(2)) +
|
|
675
|
+
' '.repeat(padRight);
|
|
676
|
+
|
|
677
|
+
console.log(chalk.cyan(BOX.V) + infoColored + chalk.cyan(BOX.V));
|
|
663
678
|
|
|
664
679
|
// Bottom border
|
|
665
680
|
console.log(chalk.cyan(BOX.BOT + BOX.H.repeat(W) + BOX.BR));
|