hedgequantx 1.2.70 → 1.2.72
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.js +125 -27
package/package.json
CHANGED
package/src/pages/algo.js
CHANGED
|
@@ -379,14 +379,14 @@ const launchAlgo = async (service, account, contract, numContracts, dailyTarget,
|
|
|
379
379
|
// Display full UI with logs (newest first)
|
|
380
380
|
const displayUI = () => {
|
|
381
381
|
console.clear();
|
|
382
|
-
const marketStatus = checkMarketStatus();
|
|
383
382
|
|
|
384
383
|
// Stats
|
|
385
384
|
const pnlColor = stats.pnl >= 0 ? chalk.green : chalk.red;
|
|
386
385
|
const pnlStr = (stats.pnl >= 0 ? '+$' : '-$') + Math.abs(stats.pnl).toFixed(2);
|
|
387
386
|
const latencyStr = hqxConnected ? (latency > 0 ? `${latency}ms` : '---') : '---';
|
|
388
387
|
const latencyColor = latency < 100 ? chalk.green : (latency < 300 ? chalk.yellow : chalk.red);
|
|
389
|
-
const serverStatus = hqxConnected ?
|
|
388
|
+
const serverStatus = hqxConnected ? 'ON' : 'OFF';
|
|
389
|
+
const serverColor = hqxConnected ? chalk.green : chalk.red;
|
|
390
390
|
|
|
391
391
|
// Current date
|
|
392
392
|
const now = new Date();
|
|
@@ -395,40 +395,138 @@ const launchAlgo = async (service, account, contract, numContracts, dailyTarget,
|
|
|
395
395
|
// Get package version
|
|
396
396
|
const version = require('../../package.json').version;
|
|
397
397
|
|
|
398
|
-
//
|
|
398
|
+
// Fixed width = 96 inner chars
|
|
399
|
+
const W = 96;
|
|
400
|
+
const TOP = '\u2554' + '\u2550'.repeat(W) + '\u2557';
|
|
401
|
+
const MID = '\u2560' + '\u2550'.repeat(W) + '\u2563';
|
|
402
|
+
const BOT = '\u255A' + '\u2550'.repeat(W) + '\u255D';
|
|
403
|
+
const V = '\u2551';
|
|
404
|
+
|
|
405
|
+
// Center text helper
|
|
406
|
+
const center = (text, width) => {
|
|
407
|
+
const pad = Math.floor((width - text.length) / 2);
|
|
408
|
+
return ' '.repeat(pad) + text + ' '.repeat(width - pad - text.length);
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// Pad text to exact width
|
|
412
|
+
const padRight = (text, width) => {
|
|
413
|
+
if (text.length >= width) return text.substring(0, width);
|
|
414
|
+
return text + ' '.repeat(width - text.length);
|
|
415
|
+
};
|
|
416
|
+
|
|
399
417
|
console.log();
|
|
400
|
-
console.log(chalk.cyan(
|
|
401
|
-
console.log(chalk.cyan(
|
|
402
|
-
console.log(chalk.cyan(
|
|
403
|
-
console.log(chalk.cyan(
|
|
404
|
-
console.log(chalk.cyan(
|
|
405
|
-
console.log(chalk.cyan(
|
|
406
|
-
console.log(chalk.cyan(
|
|
407
|
-
console.log(chalk.cyan(
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
console.log(chalk.cyan(
|
|
412
|
-
console.log(chalk.cyan(
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
console.log(chalk.cyan(
|
|
418
|
+
console.log(chalk.cyan(TOP));
|
|
419
|
+
console.log(chalk.cyan(V) + chalk.cyan(' \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 ') + chalk.cyan(V));
|
|
420
|
+
console.log(chalk.cyan(V) + chalk.cyan(' \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D ') + chalk.cyan(V));
|
|
421
|
+
console.log(chalk.cyan(V) + chalk.cyan(' \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D ') + chalk.cyan(V));
|
|
422
|
+
console.log(chalk.cyan(V) + chalk.cyan(' \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u2584\u2584 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 ') + chalk.cyan(V));
|
|
423
|
+
console.log(chalk.cyan(V) + chalk.cyan(' \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2557 ') + chalk.cyan(V));
|
|
424
|
+
console.log(chalk.cyan(V) + chalk.cyan(' \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D ') + chalk.cyan(V));
|
|
425
|
+
console.log(chalk.cyan(MID));
|
|
426
|
+
|
|
427
|
+
// Centered title
|
|
428
|
+
const title1 = `Prop Futures Algo Trading v${version}`;
|
|
429
|
+
console.log(chalk.cyan(V) + chalk.white(center(title1, W)) + chalk.cyan(V));
|
|
430
|
+
console.log(chalk.cyan(MID));
|
|
431
|
+
|
|
432
|
+
// Centered subtitle
|
|
433
|
+
const title2 = 'HQX Ultra-Scalping Algorithm';
|
|
434
|
+
console.log(chalk.cyan(V) + chalk.white(center(title2, W)) + chalk.cyan(V));
|
|
435
|
+
console.log(chalk.cyan(MID));
|
|
436
|
+
|
|
437
|
+
// Grid layout for metrics - each in its own cell
|
|
438
|
+
// Row 1: Account | Symbol | Qty | Server | Latency
|
|
439
|
+
// Row 2: Target | Risk | P&L | Trades | W/L
|
|
440
|
+
const VS = '\u2502'; // Vertical separator (thin)
|
|
441
|
+
|
|
442
|
+
// Prepare values with fixed widths
|
|
443
|
+
const accLabel = 'Account';
|
|
444
|
+
const accVal = accountName.length > 26 ? accountName.substring(0, 26) : accountName;
|
|
445
|
+
const symLabel = 'Symbol';
|
|
446
|
+
const symVal = symbolName.length > 10 ? symbolName.substring(0, 10) : symbolName;
|
|
447
|
+
const qtyLabel = 'Qty';
|
|
448
|
+
const qtyVal = numContracts.toString();
|
|
449
|
+
const srvLabel = 'Server';
|
|
450
|
+
const srvVal = serverStatus;
|
|
451
|
+
const latLabel = 'Latency';
|
|
452
|
+
const latVal = latencyStr;
|
|
453
|
+
|
|
454
|
+
// Row 1 cells: widths = 36 + 18 + 10 + 14 + 14 = 92 + 4 separators = 96
|
|
455
|
+
const c1w = 36, c2w = 18, c3w = 10, c4w = 14, c5w = 14;
|
|
456
|
+
|
|
457
|
+
const cell1 = ` ${accLabel}: ${chalk.cyan(accVal)}`;
|
|
458
|
+
const cell1plain = ` ${accLabel}: ${accVal}`;
|
|
459
|
+
const cell2 = ` ${symLabel}: ${chalk.yellow(symVal)}`;
|
|
460
|
+
const cell2plain = ` ${symLabel}: ${symVal}`;
|
|
461
|
+
const cell3 = ` ${qtyLabel}: ${chalk.cyan(qtyVal)}`;
|
|
462
|
+
const cell3plain = ` ${qtyLabel}: ${qtyVal}`;
|
|
463
|
+
const cell4 = ` ${srvLabel}: ${serverColor(srvVal)}`;
|
|
464
|
+
const cell4plain = ` ${srvLabel}: ${srvVal}`;
|
|
465
|
+
const cell5 = ` ${latLabel}: ${latencyColor(latVal)}`;
|
|
466
|
+
const cell5plain = ` ${latLabel}: ${latVal}`;
|
|
417
467
|
|
|
418
|
-
|
|
468
|
+
const row1 = cell1 + ' '.repeat(c1w - cell1plain.length) + chalk.cyan(VS) +
|
|
469
|
+
cell2 + ' '.repeat(c2w - cell2plain.length) + chalk.cyan(VS) +
|
|
470
|
+
cell3 + ' '.repeat(c3w - cell3plain.length) + chalk.cyan(VS) +
|
|
471
|
+
cell4 + ' '.repeat(c4w - cell4plain.length) + chalk.cyan(VS) +
|
|
472
|
+
cell5 + ' '.repeat(c5w - cell5plain.length);
|
|
473
|
+
|
|
474
|
+
console.log(chalk.cyan(V) + row1 + chalk.cyan(V));
|
|
475
|
+
|
|
476
|
+
// Separator with intersections
|
|
477
|
+
const SEP = '\u2560' + '\u2550'.repeat(c1w) + '\u256A' + '\u2550'.repeat(c2w) + '\u256A' + '\u2550'.repeat(c3w) + '\u256A' + '\u2550'.repeat(c4w) + '\u256A' + '\u2550'.repeat(c5w) + '\u2563';
|
|
478
|
+
console.log(chalk.cyan(SEP));
|
|
479
|
+
|
|
480
|
+
// Row 2: Target | Risk | P&L | Trades | W/L
|
|
481
|
+
const tgtLabel = 'Target';
|
|
482
|
+
const tgtVal = '$' + dailyTarget.toFixed(2);
|
|
483
|
+
const rskLabel = 'Risk';
|
|
484
|
+
const rskVal = '$' + maxRisk.toFixed(2);
|
|
485
|
+
const pnlLabel = 'P&L';
|
|
486
|
+
const pnlVal = pnlStr;
|
|
487
|
+
const trdLabel = 'Trades';
|
|
488
|
+
const trdVal = stats.trades.toString();
|
|
489
|
+
const wlLabel = 'W/L';
|
|
490
|
+
const wlVal = `${stats.wins}/${stats.losses}`;
|
|
491
|
+
|
|
492
|
+
const cell6 = ` ${tgtLabel}: ${chalk.green(tgtVal)}`;
|
|
493
|
+
const cell6plain = ` ${tgtLabel}: ${tgtVal}`;
|
|
494
|
+
const cell7 = ` ${rskLabel}: ${chalk.red(rskVal)}`;
|
|
495
|
+
const cell7plain = ` ${rskLabel}: ${rskVal}`;
|
|
496
|
+
const cell8 = ` ${pnlLabel}: ${pnlColor(pnlVal)}`;
|
|
497
|
+
const cell8plain = ` ${pnlLabel}: ${pnlVal}`;
|
|
498
|
+
const cell9 = ` ${trdLabel}: ${chalk.cyan(trdVal)}`;
|
|
499
|
+
const cell9plain = ` ${trdLabel}: ${trdVal}`;
|
|
500
|
+
const cell10 = ` ${wlLabel}: ${chalk.green(stats.wins.toString())}/${chalk.red(stats.losses.toString())}`;
|
|
501
|
+
const cell10plain = ` ${wlLabel}: ${wlVal}`;
|
|
502
|
+
|
|
503
|
+
const row2 = cell6 + ' '.repeat(c1w - cell6plain.length) + chalk.cyan(VS) +
|
|
504
|
+
cell7 + ' '.repeat(c2w - cell7plain.length) + chalk.cyan(VS) +
|
|
505
|
+
cell8 + ' '.repeat(c3w - cell8plain.length) + chalk.cyan(VS) +
|
|
506
|
+
cell9 + ' '.repeat(c4w - cell9plain.length) + chalk.cyan(VS) +
|
|
507
|
+
cell10 + ' '.repeat(c5w - cell10plain.length);
|
|
508
|
+
|
|
509
|
+
console.log(chalk.cyan(V) + row2 + chalk.cyan(V));
|
|
510
|
+
console.log(chalk.cyan(MID));
|
|
511
|
+
|
|
512
|
+
// Activity log header
|
|
513
|
+
const actLeft = ` Activity Log - ${dateStr}`;
|
|
514
|
+
const actRight = 'Press X to stop ';
|
|
515
|
+
const actMid = W - actLeft.length - actRight.length;
|
|
516
|
+
console.log(chalk.cyan(V) + chalk.white(actLeft) + ' '.repeat(actMid) + chalk.yellow(actRight) + chalk.cyan(V));
|
|
517
|
+
console.log(chalk.cyan(BOT));
|
|
518
|
+
|
|
519
|
+
// Logs (without borders)
|
|
520
|
+
console.log();
|
|
419
521
|
if (logs.length === 0) {
|
|
420
|
-
console.log(chalk.
|
|
522
|
+
console.log(chalk.gray(' Waiting for activity...'));
|
|
421
523
|
} else {
|
|
422
524
|
logs.forEach(log => {
|
|
423
525
|
const color = typeColors[log.type] || chalk.white;
|
|
424
526
|
const icon = getIcon(log.type);
|
|
425
|
-
|
|
426
|
-
const truncated = logLine.length > 93 ? logLine.substring(0, 90) + '...' : logLine;
|
|
427
|
-
console.log(chalk.cyan('\u2551') + ' ' + color(truncated.padEnd(94)) + chalk.cyan('\u2551'));
|
|
527
|
+
console.log(color(` [${log.timestamp}] ${icon} ${log.message}`));
|
|
428
528
|
});
|
|
429
529
|
}
|
|
430
|
-
|
|
431
|
-
console.log(chalk.cyan('\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D'));
|
|
432
530
|
};
|
|
433
531
|
|
|
434
532
|
// Connect to HQX Server
|