hedgequantx 2.5.38 → 2.5.39
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/stats.js +126 -70
package/package.json
CHANGED
package/src/pages/stats.js
CHANGED
|
@@ -481,84 +481,140 @@ const showStats = async (service) => {
|
|
|
481
481
|
|
|
482
482
|
drawBoxFooter(boxWidth);
|
|
483
483
|
|
|
484
|
-
// ========== AI BEHAVIOR
|
|
485
|
-
const behaviorData = StrategySupervisor.getBehaviorHistory(
|
|
484
|
+
// ========== AI BEHAVIOR DIAGRAM ==========
|
|
485
|
+
const behaviorData = StrategySupervisor.getBehaviorHistory(100);
|
|
486
486
|
const learningStats = StrategySupervisor.getLearningStats();
|
|
487
487
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
const newValues = [];
|
|
502
|
-
for (let i = 0; i < scaledValues.length - 1; i++) {
|
|
503
|
-
newValues.push(scaledValues[i]);
|
|
504
|
-
// Smooth interpolation
|
|
505
|
-
const diff = scaledValues[i + 1] - scaledValues[i];
|
|
506
|
-
newValues.push(scaledValues[i] + diff * 0.33);
|
|
507
|
-
newValues.push(scaledValues[i] + diff * 0.66);
|
|
508
|
-
}
|
|
509
|
-
newValues.push(scaledValues[scaledValues.length - 1]);
|
|
510
|
-
scaledValues = newValues;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Limit data points to chart width
|
|
514
|
-
if (scaledValues.length > chartWidth) {
|
|
515
|
-
const step = Math.ceil(scaledValues.length / chartWidth);
|
|
516
|
-
scaledValues = scaledValues.filter((_, i) => i % step === 0);
|
|
488
|
+
console.log();
|
|
489
|
+
drawBoxHeader('AI AGENTS BEHAVIOR', boxWidth);
|
|
490
|
+
|
|
491
|
+
const behaviorInnerWidth = boxWidth - 2;
|
|
492
|
+
|
|
493
|
+
// Count behavior occurrences
|
|
494
|
+
const behaviorCounts = { AGGRESSIVE: 0, NORMAL: 0, CAUTIOUS: 0, PAUSE: 0 };
|
|
495
|
+
const valueToAction = { 3: 'AGGRESSIVE', 2: 'NORMAL', 1: 'CAUTIOUS', 0: 'PAUSE' };
|
|
496
|
+
|
|
497
|
+
if (behaviorData.values.length > 0) {
|
|
498
|
+
for (const val of behaviorData.values) {
|
|
499
|
+
const action = valueToAction[Math.round(val)] || 'NORMAL';
|
|
500
|
+
behaviorCounts[action]++;
|
|
517
501
|
}
|
|
502
|
+
} else {
|
|
503
|
+
behaviorCounts.NORMAL = 1; // Default
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const total = Object.values(behaviorCounts).reduce((a, b) => a + b, 0) || 1;
|
|
507
|
+
const percentages = {
|
|
508
|
+
AGGRESSIVE: Math.round((behaviorCounts.AGGRESSIVE / total) * 100),
|
|
509
|
+
NORMAL: Math.round((behaviorCounts.NORMAL / total) * 100),
|
|
510
|
+
CAUTIOUS: Math.round((behaviorCounts.CAUTIOUS / total) * 100),
|
|
511
|
+
PAUSE: Math.round((behaviorCounts.PAUSE / total) * 100)
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// Bar chart configuration
|
|
515
|
+
const labelWidth = 12;
|
|
516
|
+
const percentWidth = 6;
|
|
517
|
+
const barMaxWidth = behaviorInnerWidth - labelWidth - percentWidth - 6;
|
|
518
|
+
|
|
519
|
+
// Get current behavior
|
|
520
|
+
const currentValue = behaviorData.values.length > 0 ? behaviorData.values[behaviorData.values.length - 1] : 2;
|
|
521
|
+
const currentAction = valueToAction[Math.round(currentValue)] || 'NORMAL';
|
|
522
|
+
|
|
523
|
+
// Draw vertical bar chart (bars going up)
|
|
524
|
+
const chartHeight = 8;
|
|
525
|
+
const barWidth = Math.floor((barMaxWidth - 12) / 4); // 4 bars with spacing
|
|
526
|
+
|
|
527
|
+
// Calculate bar heights (max height = chartHeight)
|
|
528
|
+
const maxPercent = Math.max(...Object.values(percentages), 1);
|
|
529
|
+
const barHeights = {
|
|
530
|
+
AGGRESSIVE: Math.round((percentages.AGGRESSIVE / 100) * chartHeight),
|
|
531
|
+
NORMAL: Math.round((percentages.NORMAL / 100) * chartHeight),
|
|
532
|
+
CAUTIOUS: Math.round((percentages.CAUTIOUS / 100) * chartHeight),
|
|
533
|
+
PAUSE: Math.round((percentages.PAUSE / 100) * chartHeight)
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
// Colors for each behavior
|
|
537
|
+
const barColors = {
|
|
538
|
+
AGGRESSIVE: chalk.green,
|
|
539
|
+
NORMAL: chalk.cyan,
|
|
540
|
+
CAUTIOUS: chalk.yellow,
|
|
541
|
+
PAUSE: chalk.red
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// Draw bars from top to bottom
|
|
545
|
+
const barLabels = ['AGGRESSIVE', 'NORMAL', 'CAUTIOUS', 'PAUSE'];
|
|
546
|
+
const shortLabels = ['AGR', 'NOR', 'CAU', 'PAU'];
|
|
547
|
+
|
|
548
|
+
// Calculate left padding to center the chart
|
|
549
|
+
const totalBarWidth = (barWidth * 4) + 9; // 4 bars + 3 spaces of 3 chars
|
|
550
|
+
const leftPad = Math.floor((behaviorInnerWidth - totalBarWidth - 4) / 2);
|
|
551
|
+
|
|
552
|
+
for (let row = chartHeight; row >= 1; row--) {
|
|
553
|
+
let line = ' '.repeat(leftPad);
|
|
518
554
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
format: (x) => {
|
|
533
|
-
if (x >= 75) return 'AGGRESSIVE'.padStart(yAxisWidth);
|
|
534
|
-
if (x >= 50) return ' NORMAL'.padStart(yAxisWidth);
|
|
535
|
-
if (x >= 25) return ' CAUTIOUS'.padStart(yAxisWidth);
|
|
536
|
-
return ' PAUSE'.padStart(yAxisWidth);
|
|
555
|
+
for (let i = 0; i < 4; i++) {
|
|
556
|
+
const label = barLabels[i];
|
|
557
|
+
const height = barHeights[label];
|
|
558
|
+
const color = barColors[label];
|
|
559
|
+
const isCurrent = label === currentAction;
|
|
560
|
+
|
|
561
|
+
if (row <= height) {
|
|
562
|
+
// Draw filled bar
|
|
563
|
+
const block = isCurrent ? '█' : '▓';
|
|
564
|
+
line += color(block.repeat(barWidth));
|
|
565
|
+
} else {
|
|
566
|
+
// Empty space
|
|
567
|
+
line += ' '.repeat(barWidth);
|
|
537
568
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
try {
|
|
541
|
-
const behaviorChart = asciichart.plot(scaledValues, behaviorConfig);
|
|
542
|
-
behaviorChart.split('\n').forEach(line => {
|
|
543
|
-
let chartLine = ' ' + line;
|
|
544
|
-
const len = chartLine.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
545
|
-
if (len < behaviorInnerWidth) chartLine += ' '.repeat(behaviorInnerWidth - len);
|
|
546
|
-
console.log(chalk.cyan('\u2551') + chartLine + chalk.cyan('\u2551'));
|
|
547
|
-
});
|
|
548
|
-
} catch (e) {
|
|
549
|
-
// Fallback if chart fails
|
|
550
|
-
const msg = ' BEHAVIOR DATA INSUFFICIENT';
|
|
551
|
-
console.log(chalk.cyan('\u2551') + chalk.white(msg) + ' '.repeat(Math.max(0, behaviorInnerWidth - msg.length)) + chalk.cyan('\u2551'));
|
|
569
|
+
|
|
570
|
+
if (i < 3) line += ' '; // Space between bars
|
|
552
571
|
}
|
|
553
572
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
573
|
+
const lineLen = line.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
574
|
+
line += ' '.repeat(Math.max(0, behaviorInnerWidth - lineLen));
|
|
575
|
+
console.log(chalk.cyan('\u2551') + line + chalk.cyan('\u2551'));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Draw baseline
|
|
579
|
+
let baseLine = ' '.repeat(leftPad) + '─'.repeat(totalBarWidth);
|
|
580
|
+
const baseLen = baseLine.length;
|
|
581
|
+
baseLine += ' '.repeat(Math.max(0, behaviorInnerWidth - baseLen));
|
|
582
|
+
console.log(chalk.cyan('\u2551') + chalk.white(baseLine) + chalk.cyan('\u2551'));
|
|
583
|
+
|
|
584
|
+
// Draw labels
|
|
585
|
+
let labelLine = ' '.repeat(leftPad);
|
|
586
|
+
for (let i = 0; i < 4; i++) {
|
|
587
|
+
const lbl = shortLabels[i];
|
|
588
|
+
const pad = Math.floor((barWidth - lbl.length) / 2);
|
|
589
|
+
labelLine += ' '.repeat(pad) + barColors[barLabels[i]](lbl) + ' '.repeat(barWidth - pad - lbl.length);
|
|
590
|
+
if (i < 3) labelLine += ' ';
|
|
591
|
+
}
|
|
592
|
+
const lblLen = labelLine.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
593
|
+
labelLine += ' '.repeat(Math.max(0, behaviorInnerWidth - lblLen));
|
|
594
|
+
console.log(chalk.cyan('\u2551') + labelLine + chalk.cyan('\u2551'));
|
|
595
|
+
|
|
596
|
+
// Draw percentages
|
|
597
|
+
let pctLine = ' '.repeat(leftPad);
|
|
598
|
+
for (let i = 0; i < 4; i++) {
|
|
599
|
+
const pct = percentages[barLabels[i]] + '%';
|
|
600
|
+
const pad = Math.floor((barWidth - pct.length) / 2);
|
|
601
|
+
pctLine += ' '.repeat(pad) + chalk.white(pct) + ' '.repeat(barWidth - pad - pct.length);
|
|
602
|
+
if (i < 3) pctLine += ' ';
|
|
561
603
|
}
|
|
604
|
+
const pctLen = pctLine.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
605
|
+
pctLine += ' '.repeat(Math.max(0, behaviorInnerWidth - pctLen));
|
|
606
|
+
console.log(chalk.cyan('\u2551') + pctLine + chalk.cyan('\u2551'));
|
|
607
|
+
|
|
608
|
+
// Empty line
|
|
609
|
+
console.log(chalk.cyan('\u2551') + ' '.repeat(behaviorInnerWidth) + chalk.cyan('\u2551'));
|
|
610
|
+
|
|
611
|
+
// Stats line
|
|
612
|
+
const durationMin = behaviorData.duration ? Math.floor(behaviorData.duration / 60000) : 0;
|
|
613
|
+
const statsLine = ` CURRENT: ${barColors[currentAction](currentAction)} | PATTERNS: ${learningStats.patternsLearned.total} (${learningStats.patternsLearned.winning}W/${learningStats.patternsLearned.losing}L) | OPTIMIZATIONS: ${learningStats.optimizations}`;
|
|
614
|
+
const statsLen = statsLine.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
615
|
+
console.log(chalk.cyan('\u2551') + statsLine + ' '.repeat(Math.max(0, behaviorInnerWidth - statsLen)) + chalk.cyan('\u2551'));
|
|
616
|
+
|
|
617
|
+
drawBoxFooter(boxWidth);
|
|
562
618
|
}
|
|
563
619
|
|
|
564
620
|
// ========== EQUITY CURVE ==========
|