hedgequantx 2.6.131 → 2.6.132
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/one-account.js +4 -22
- package/src/pages/algo/ui.js +120 -1
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ const ora = require('ora');
|
|
|
10
10
|
const readline = require('readline');
|
|
11
11
|
|
|
12
12
|
const { connections } = require('../../services');
|
|
13
|
-
const { AlgoUI, renderSessionSummary } = require('./ui');
|
|
13
|
+
const { AlgoUI, renderSessionSummary, renderMultiSymbolSummary } = require('./ui');
|
|
14
14
|
const { prompts } = require('../../utils');
|
|
15
15
|
const { checkMarketHours } = require('../../services/projectx/market');
|
|
16
16
|
const { FAST_SCALPING } = require('../../config/settings');
|
|
@@ -1974,32 +1974,14 @@ const launchMultiSymbolRithmic = async (service, account, contracts, config) =>
|
|
|
1974
1974
|
const hours = Math.floor(durationMs / 3600000);
|
|
1975
1975
|
const minutes = Math.floor((durationMs % 3600000) / 60000);
|
|
1976
1976
|
const seconds = Math.floor((durationMs % 60000) / 1000);
|
|
1977
|
-
|
|
1977
|
+
stats.duration = hours > 0
|
|
1978
1978
|
? `${hours}h ${minutes}m ${seconds}s`
|
|
1979
1979
|
: minutes > 0
|
|
1980
1980
|
? `${minutes}m ${seconds}s`
|
|
1981
1981
|
: `${seconds}s`;
|
|
1982
1982
|
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
console.log(chalk.cyan(' MULTI-SYMBOL SESSION SUMMARY'));
|
|
1986
|
-
console.log(chalk.cyan('═══════════════════════════════════════════════════════════════'));
|
|
1987
|
-
console.log();
|
|
1988
|
-
|
|
1989
|
-
for (const [symbol, symStats] of Object.entries(stats.symbolStats)) {
|
|
1990
|
-
const winRate = symStats.trades > 0 ? ((symStats.wins / symStats.trades) * 100).toFixed(0) : 0;
|
|
1991
|
-
const pnlColor = symStats.pnl >= 0 ? chalk.green : chalk.red;
|
|
1992
|
-
console.log(chalk.white(` ${symbol}:`));
|
|
1993
|
-
console.log(` Trades: ${symStats.trades} | WR: ${winRate}% | P&L: ${pnlColor('$' + symStats.pnl.toFixed(2))}`);
|
|
1994
|
-
}
|
|
1995
|
-
|
|
1996
|
-
console.log();
|
|
1997
|
-
const totalPnlColor = stats.sessionPnl >= 0 ? chalk.green : chalk.red;
|
|
1998
|
-
console.log(chalk.white(` TOTAL: ${stats.trades} trades | ${stats.wins}W/${stats.losses}L`));
|
|
1999
|
-
console.log(chalk.white(` Session P&L: ${totalPnlColor('$' + stats.sessionPnl.toFixed(2))}`));
|
|
2000
|
-
console.log(chalk.white(` Duration: ${duration}`));
|
|
2001
|
-
console.log();
|
|
2002
|
-
console.log(chalk.cyan('═══════════════════════════════════════════════════════════════'));
|
|
1983
|
+
// Render multi-symbol summary with same style as single-symbol
|
|
1984
|
+
renderMultiSymbolSummary(stats, stopReason, stats.symbolStats);
|
|
2003
1985
|
|
|
2004
1986
|
await prompts.waitForEnter();
|
|
2005
1987
|
};
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -547,4 +547,123 @@ const renderSessionSummary = (stats, stopReason) => {
|
|
|
547
547
|
console.log();
|
|
548
548
|
};
|
|
549
549
|
|
|
550
|
-
|
|
550
|
+
/**
|
|
551
|
+
* Render Multi-Symbol Session Summary - Same style as single-symbol
|
|
552
|
+
*/
|
|
553
|
+
const renderMultiSymbolSummary = (stats, stopReason, symbolStats) => {
|
|
554
|
+
const W = 96;
|
|
555
|
+
const version = require('../../../package.json').version;
|
|
556
|
+
|
|
557
|
+
console.clear();
|
|
558
|
+
console.log();
|
|
559
|
+
|
|
560
|
+
// Top border
|
|
561
|
+
console.log(chalk.cyan(BOX.TOP + BOX.H.repeat(W) + BOX.TR));
|
|
562
|
+
|
|
563
|
+
// Logo
|
|
564
|
+
console.log(chalk.cyan(BOX.V) + chalk.cyan(' ██╗ ██╗███████╗██████╗ ██████╗ ███████╗ ██████╗ ██╗ ██╗ █████╗ ███╗ ██╗████████╗') + chalk.yellow('██╗ ██╗') + ' ' + chalk.cyan(BOX.V));
|
|
565
|
+
console.log(chalk.cyan(BOX.V) + chalk.cyan(' ██║ ██║██╔════╝██╔══██╗██╔════╝ ██╔════╝██╔═══██╗██║ ██║██╔══██╗████╗ ██║╚══██╔══╝') + chalk.yellow('╚██╗██╔╝') + ' ' + chalk.cyan(BOX.V));
|
|
566
|
+
console.log(chalk.cyan(BOX.V) + chalk.cyan(' ███████║█████╗ ██║ ██║██║ ███╗█████╗ ██║ ██║██║ ██║███████║██╔██╗ ██║ ██║ ') + chalk.yellow(' ╚███╔╝ ') + ' ' + chalk.cyan(BOX.V));
|
|
567
|
+
console.log(chalk.cyan(BOX.V) + chalk.cyan(' ██╔══██║██╔══╝ ██║ ██║██║ ██║██╔══╝ ██║▄▄ ██║██║ ██║██╔══██║██║╚██╗██║ ██║ ') + chalk.yellow(' ██╔██╗ ') + ' ' + chalk.cyan(BOX.V));
|
|
568
|
+
console.log(chalk.cyan(BOX.V) + chalk.cyan(' ██║ ██║███████╗██████╔╝╚██████╔╝███████╗╚██████╔╝╚██████╔╝██║ ██║██║ ╚████║ ██║ ') + chalk.yellow('██╔╝ ██╗') + ' ' + chalk.cyan(BOX.V));
|
|
569
|
+
console.log(chalk.cyan(BOX.V) + chalk.cyan(' ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚══════╝ ╚══▀▀═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ') + chalk.yellow('╚═╝ ╚═╝') + ' ' + chalk.cyan(BOX.V));
|
|
570
|
+
|
|
571
|
+
// Separator + title
|
|
572
|
+
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
573
|
+
console.log(chalk.cyan(BOX.V) + chalk.white(center(`PROP FUTURES ALGO TRADING v${version}`, W)) + chalk.cyan(BOX.V));
|
|
574
|
+
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
575
|
+
console.log(chalk.cyan(BOX.V) + chalk.yellow.bold(center('MULTI-SYMBOL SESSION SUMMARY', W)) + chalk.cyan(BOX.V));
|
|
576
|
+
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
577
|
+
|
|
578
|
+
// Per-symbol stats header
|
|
579
|
+
const colSymbol = 12;
|
|
580
|
+
const colTrades = 10;
|
|
581
|
+
const colWR = 10;
|
|
582
|
+
const colWins = 8;
|
|
583
|
+
const colLosses = 8;
|
|
584
|
+
const colPnL = 14;
|
|
585
|
+
const remaining = W - colSymbol - colTrades - colWR - colWins - colLosses - colPnL - 5; // 5 separators
|
|
586
|
+
|
|
587
|
+
// Header row
|
|
588
|
+
const headerSymbol = ' SYMBOL'.padEnd(colSymbol);
|
|
589
|
+
const headerTrades = 'TRADES'.padEnd(colTrades);
|
|
590
|
+
const headerWR = 'WIN RATE'.padEnd(colWR);
|
|
591
|
+
const headerWins = 'WINS'.padEnd(colWins);
|
|
592
|
+
const headerLosses = 'LOSSES'.padEnd(colLosses);
|
|
593
|
+
const headerPnL = 'P&L'.padEnd(colPnL + remaining);
|
|
594
|
+
|
|
595
|
+
console.log(chalk.cyan(BOX.V) + chalk.bold.white(headerSymbol) + chalk.cyan(BOX.VS) +
|
|
596
|
+
chalk.bold.white(headerTrades) + chalk.cyan(BOX.VS) +
|
|
597
|
+
chalk.bold.white(headerWR) + chalk.cyan(BOX.VS) +
|
|
598
|
+
chalk.bold.white(headerWins) + chalk.cyan(BOX.VS) +
|
|
599
|
+
chalk.bold.white(headerLosses) + chalk.cyan(BOX.VS) +
|
|
600
|
+
chalk.bold.white(headerPnL) + chalk.cyan(BOX.V));
|
|
601
|
+
|
|
602
|
+
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
603
|
+
|
|
604
|
+
// Per-symbol rows
|
|
605
|
+
for (const [symbol, symStats] of Object.entries(symbolStats)) {
|
|
606
|
+
const winRate = symStats.trades > 0 ? ((symStats.wins / symStats.trades) * 100).toFixed(0) + '%' : '0%';
|
|
607
|
+
const pnl = symStats.pnl || 0;
|
|
608
|
+
const pnlStr = (pnl >= 0 ? '+$' : '-$') + Math.abs(pnl).toFixed(2);
|
|
609
|
+
const pnlColor = pnl >= 0 ? chalk.green : chalk.red;
|
|
610
|
+
const wrColor = symStats.wins >= symStats.losses ? chalk.green : chalk.red;
|
|
611
|
+
|
|
612
|
+
const cellSymbol = (' ' + symbol).padEnd(colSymbol);
|
|
613
|
+
const cellTrades = String(symStats.trades || 0).padEnd(colTrades);
|
|
614
|
+
const cellWR = winRate.padEnd(colWR);
|
|
615
|
+
const cellWins = String(symStats.wins || 0).padEnd(colWins);
|
|
616
|
+
const cellLosses = String(symStats.losses || 0).padEnd(colLosses);
|
|
617
|
+
const cellPnL = pnlStr.padEnd(colPnL + remaining);
|
|
618
|
+
|
|
619
|
+
console.log(chalk.cyan(BOX.V) + chalk.yellow(cellSymbol) + chalk.cyan(BOX.VS) +
|
|
620
|
+
chalk.white(cellTrades) + chalk.cyan(BOX.VS) +
|
|
621
|
+
wrColor(cellWR) + chalk.cyan(BOX.VS) +
|
|
622
|
+
chalk.green(cellWins) + chalk.cyan(BOX.VS) +
|
|
623
|
+
chalk.red(cellLosses) + chalk.cyan(BOX.VS) +
|
|
624
|
+
pnlColor.bold(cellPnL) + chalk.cyan(BOX.V));
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Separator before totals
|
|
628
|
+
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
629
|
+
|
|
630
|
+
// Total row
|
|
631
|
+
const totalWinRate = stats.trades > 0 ? ((stats.wins / stats.trades) * 100).toFixed(0) + '%' : '0%';
|
|
632
|
+
const totalPnl = stats.sessionPnl || 0;
|
|
633
|
+
const totalPnlStr = (totalPnl >= 0 ? '+$' : '-$') + Math.abs(totalPnl).toFixed(2);
|
|
634
|
+
const totalPnlColor = totalPnl >= 0 ? chalk.green : chalk.red;
|
|
635
|
+
const totalWrColor = stats.wins >= stats.losses ? chalk.green : chalk.red;
|
|
636
|
+
|
|
637
|
+
const totalCellSymbol = ' TOTAL'.padEnd(colSymbol);
|
|
638
|
+
const totalCellTrades = String(stats.trades || 0).padEnd(colTrades);
|
|
639
|
+
const totalCellWR = totalWinRate.padEnd(colWR);
|
|
640
|
+
const totalCellWins = String(stats.wins || 0).padEnd(colWins);
|
|
641
|
+
const totalCellLosses = String(stats.losses || 0).padEnd(colLosses);
|
|
642
|
+
const totalCellPnL = totalPnlStr.padEnd(colPnL + remaining);
|
|
643
|
+
|
|
644
|
+
console.log(chalk.cyan(BOX.V) + chalk.bold.white(totalCellSymbol) + chalk.cyan(BOX.VS) +
|
|
645
|
+
chalk.bold.white(totalCellTrades) + chalk.cyan(BOX.VS) +
|
|
646
|
+
totalWrColor.bold(totalCellWR) + chalk.cyan(BOX.VS) +
|
|
647
|
+
chalk.bold.green(totalCellWins) + chalk.cyan(BOX.VS) +
|
|
648
|
+
chalk.bold.red(totalCellLosses) + chalk.cyan(BOX.VS) +
|
|
649
|
+
totalPnlColor.bold(totalCellPnL) + chalk.cyan(BOX.V));
|
|
650
|
+
|
|
651
|
+
// Separator
|
|
652
|
+
console.log(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
653
|
+
|
|
654
|
+
// Stop Reason & Duration row
|
|
655
|
+
const duration = stats.duration || '--';
|
|
656
|
+
const reasonColor = stopReason === 'target' ? chalk.green : stopReason === 'risk' ? chalk.red : chalk.yellow;
|
|
657
|
+
const reasonStr = (stopReason || 'manual').toUpperCase();
|
|
658
|
+
const infoText = ` STOP: ${reasonStr} | DURATION: ${duration} | TARGET: $${(stats.target || 0).toFixed(2)} | RISK: $${(stats.risk || 0).toFixed(2)}`;
|
|
659
|
+
const infoPlain = ` STOP: ${reasonStr} | DURATION: ${duration} | TARGET: $${(stats.target || 0).toFixed(2)} | RISK: $${(stats.risk || 0).toFixed(2)}`;
|
|
660
|
+
const infoColored = ` ${chalk.bold('STOP')}: ${reasonColor.bold(reasonStr)} | ${chalk.bold('DURATION')}: ${chalk.white(duration)} | ${chalk.bold('TARGET')}: ${chalk.cyan('$' + (stats.target || 0).toFixed(2))} | ${chalk.bold('RISK')}: ${chalk.red('$' + (stats.risk || 0).toFixed(2))}`;
|
|
661
|
+
|
|
662
|
+
console.log(chalk.cyan(BOX.V) + infoColored + ' '.repeat(Math.max(0, W - infoPlain.length)) + chalk.cyan(BOX.V));
|
|
663
|
+
|
|
664
|
+
// Bottom border
|
|
665
|
+
console.log(chalk.cyan(BOX.BOT + BOX.H.repeat(W) + BOX.BR));
|
|
666
|
+
console.log();
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
module.exports = { AlgoUI, checkMarketStatus, renderSessionSummary, renderMultiSymbolSummary, LOG_COLORS, LOG_ICONS, stripAnsi, center, fitToWidth };
|