hedgequantx 2.5.13 → 2.5.14
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/app.js +9 -3
- package/src/menus/ai-agent.js +297 -50
- package/src/menus/dashboard.js +9 -13
- package/src/pages/algo/index.js +230 -35
- package/src/services/ai/index.js +294 -51
- package/src/services/ai/supervisor.js +713 -0
- package/src/services/ai/token-scanner.js +2 -1
package/src/pages/algo/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Algo Trading - Main Menu
|
|
2
|
+
* Algo Trading - Main Menu with AI Supervision
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const chalk = require('chalk');
|
|
6
|
-
const
|
|
6
|
+
const ora = require('ora');
|
|
7
|
+
const { getLogoWidth, drawBoxHeaderContinue, drawBoxFooter, displayBanner } = require('../../ui');
|
|
7
8
|
const { logger, prompts } = require('../../utils');
|
|
9
|
+
const aiService = require('../../services/ai');
|
|
10
|
+
const AISupervisor = require('../../services/ai/supervisor');
|
|
8
11
|
|
|
9
12
|
const log = logger.scope('AlgoMenu');
|
|
10
13
|
|
|
@@ -12,48 +15,240 @@ const { oneAccountMenu } = require('./one-account');
|
|
|
12
15
|
const { copyTradingMenu } = require('./copy-trading');
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
|
-
* Algo Trading Menu
|
|
18
|
+
* Algo Trading Menu with AI status
|
|
16
19
|
*/
|
|
17
20
|
const algoTradingMenu = async (service) => {
|
|
21
|
+
const boxWidth = getLogoWidth();
|
|
22
|
+
const W = boxWidth - 2;
|
|
23
|
+
|
|
24
|
+
const makeLine = (content, align = 'left') => {
|
|
25
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
26
|
+
const padding = W - plainLen;
|
|
27
|
+
if (align === 'center') {
|
|
28
|
+
const leftPad = Math.floor(padding / 2);
|
|
29
|
+
return chalk.cyan('║') + ' '.repeat(leftPad) + content + ' '.repeat(padding - leftPad) + chalk.cyan('║');
|
|
30
|
+
}
|
|
31
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
32
|
+
};
|
|
33
|
+
|
|
18
34
|
log.info('Algo Trading menu opened');
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
console.clear();
|
|
37
|
+
displayBanner();
|
|
38
|
+
drawBoxHeaderContinue('ALGO TRADING', boxWidth);
|
|
39
|
+
|
|
40
|
+
// Get AI status
|
|
41
|
+
const aiAgents = aiService.getAgents();
|
|
42
|
+
const aiConnected = aiAgents.length > 0;
|
|
43
|
+
const activeAgent = aiService.getActiveAgent();
|
|
44
|
+
const supervisionStatus = AISupervisor.getAllStatus();
|
|
45
|
+
|
|
46
|
+
// Show AI supervision status
|
|
47
|
+
if (aiConnected && activeAgent) {
|
|
48
|
+
console.log(makeLine(chalk.green(`AI SUPERVISION: ACTIVE`), 'center'));
|
|
49
|
+
console.log(makeLine(chalk.magenta(`AGENT: ${activeAgent.name}`), 'center'));
|
|
50
|
+
|
|
51
|
+
if (supervisionStatus.length > 0) {
|
|
52
|
+
const supervisor = supervisionStatus[0];
|
|
53
|
+
const duration = Math.floor(supervisor.duration / 1000);
|
|
54
|
+
console.log(makeLine(chalk.gray(`SESSION: ${duration}s | DECISIONS: ${supervisor.metrics.totalDecisions}`), 'center'));
|
|
55
|
+
|
|
56
|
+
if (supervisor.lastDecision) {
|
|
57
|
+
console.log(makeLine(chalk.yellow(`LAST: ${supervisor.lastDecision.reason.substring(0, 50)}...`), 'center'));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
console.log(makeLine(chalk.gray('AI SUPERVISION: INACTIVE'), 'center'));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
65
|
+
|
|
66
|
+
// Menu options
|
|
67
|
+
const options = [];
|
|
68
|
+
|
|
69
|
+
if (aiConnected && activeAgent) {
|
|
70
|
+
options.push({ label: chalk.cyan('[1] HQX ULTRA SCALPING (AI SUPERVISED)'), value: 'ai_supervised' });
|
|
71
|
+
options.push({ label: chalk.white('[2] HQX ULTRA SCALPING (MANUAL MODE)'), value: 'one_account' });
|
|
72
|
+
options.push({ label: chalk.magenta('[3] AI SUPERVISION DASHBOARD'), value: 'ai_dashboard' });
|
|
73
|
+
} else {
|
|
74
|
+
options.push({ label: chalk.cyan('[1] HQX ULTRA SCALPING (MANUAL MODE)'), value: 'one_account' });
|
|
75
|
+
options.push({ label: chalk.gray('[2] HQX ULTRA SCALPING (AI SUPERVISED) - NO AI AGENT'), value: 'no_agent' });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
options.push({ label: chalk.white('[C] COPY TRADING'), value: 'copy_trading' });
|
|
79
|
+
options.push({ label: chalk.gray('[<] BACK'), value: 'back' });
|
|
80
|
+
|
|
81
|
+
for (const opt of options) {
|
|
82
|
+
console.log(makeLine(opt.label));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
drawBoxFooter(boxWidth);
|
|
86
|
+
|
|
87
|
+
const choice = await prompts.textInput(chalk.cyan('SELECT:'));
|
|
88
|
+
|
|
89
|
+
switch (choice?.toLowerCase()) {
|
|
90
|
+
case '1':
|
|
91
|
+
if (aiConnected && activeAgent) {
|
|
92
|
+
return await startAISupervised(service, activeAgent);
|
|
93
|
+
} else {
|
|
94
|
+
await oneAccountMenu(service);
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
case '2':
|
|
99
|
+
if (aiConnected && activeAgent) {
|
|
100
|
+
await oneAccountMenu(service);
|
|
101
|
+
} else {
|
|
102
|
+
console.log(chalk.yellow('\n NO AI AGENT CONNECTED'));
|
|
103
|
+
console.log(chalk.gray(' Connect an AI agent first from [I] AI AGENTS menu'));
|
|
104
|
+
await prompts.waitForEnter();
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
|
|
108
|
+
case '3':
|
|
109
|
+
if (aiConnected && activeAgent) {
|
|
110
|
+
await showAIDashboard(activeAgent);
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
case 'c':
|
|
115
|
+
await copyTradingMenu();
|
|
116
|
+
break;
|
|
117
|
+
|
|
118
|
+
case '<':
|
|
119
|
+
case 'b':
|
|
120
|
+
return 'back';
|
|
121
|
+
|
|
122
|
+
default:
|
|
123
|
+
// Handle direct number input
|
|
124
|
+
const num = parseInt(choice);
|
|
125
|
+
if (num === 1) {
|
|
126
|
+
if (aiConnected && activeAgent) {
|
|
127
|
+
return await startAISupervised(service, activeAgent);
|
|
128
|
+
} else {
|
|
129
|
+
await oneAccountMenu(service);
|
|
130
|
+
}
|
|
131
|
+
} else if (num === 2) {
|
|
132
|
+
if (aiConnected && activeAgent) {
|
|
133
|
+
await oneAccountMenu(service);
|
|
134
|
+
} else {
|
|
135
|
+
console.log(chalk.yellow('\n NO AI AGENT CONNECTED'));
|
|
136
|
+
await prompts.waitForEnter();
|
|
137
|
+
}
|
|
138
|
+
} else if (num === 3 && aiConnected && activeAgent) {
|
|
139
|
+
await showAIDashboard(activeAgent);
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return algoTradingMenu(service);
|
|
145
|
+
};
|
|
32
146
|
|
|
33
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Start AI supervised trading
|
|
149
|
+
*/
|
|
150
|
+
const startAISupervised = async (service, agent) => {
|
|
151
|
+
const boxWidth = getLogoWidth();
|
|
152
|
+
const W = boxWidth - 2;
|
|
153
|
+
|
|
154
|
+
const makeLine = (content) => {
|
|
155
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
156
|
+
const padding = W - plainLen;
|
|
157
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
console.clear();
|
|
161
|
+
displayBanner();
|
|
162
|
+
drawBoxHeaderContinue('AI SUPERVISED TRADING', boxWidth);
|
|
163
|
+
|
|
164
|
+
console.log(makeLine(chalk.magenta(`AGENT: ${agent.name}`)));
|
|
165
|
+
console.log(makeLine(chalk.green('STATUS: STARTING SUPERVISION...')));
|
|
166
|
+
|
|
167
|
+
drawBoxFooter(boxWidth);
|
|
168
|
+
|
|
169
|
+
// Start AI supervision
|
|
170
|
+
const success = AISupervisor.start(agent.id, { /* algo target */ });
|
|
171
|
+
|
|
172
|
+
if (success) {
|
|
173
|
+
const spinner = ora({ text: 'INITIALIZING AI SUPERVISION...', color: 'cyan' }).start();
|
|
174
|
+
|
|
175
|
+
// Simulate initialization
|
|
176
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
177
|
+
|
|
178
|
+
spinner.succeed('AI SUPERVISION ACTIVE');
|
|
179
|
+
console.log(chalk.green('\n ✓ Agent is now monitoring HQX Ultra Scalping'));
|
|
180
|
+
console.log(chalk.gray(' ✓ AI will optimize parameters and manage risk'));
|
|
181
|
+
console.log(chalk.gray(' ✓ Supervision continues until agent is disconnected'));
|
|
182
|
+
|
|
183
|
+
await prompts.waitForEnter();
|
|
184
|
+
|
|
185
|
+
// Start the algo (placeholder for real implementation)
|
|
186
|
+
return await oneAccountMenu(service);
|
|
187
|
+
|
|
188
|
+
} else {
|
|
189
|
+
console.log(chalk.red('\n ✗ Failed to start AI supervision'));
|
|
190
|
+
await prompts.waitForEnter();
|
|
191
|
+
}
|
|
192
|
+
};
|
|
34
193
|
|
|
35
|
-
|
|
36
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Show AI Dashboard
|
|
196
|
+
*/
|
|
197
|
+
const showAIDashboard = async (agent) => {
|
|
198
|
+
const boxWidth = getLogoWidth();
|
|
199
|
+
const W = boxWidth - 2;
|
|
200
|
+
|
|
201
|
+
const makeLine = (content) => {
|
|
202
|
+
const plainLen = content.replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
203
|
+
const padding = W - plainLen;
|
|
204
|
+
return chalk.cyan('║') + ' ' + content + ' '.repeat(Math.max(0, padding - 1)) + chalk.cyan('║');
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const supervisionStatus = AISupervisor.getStatus(agent.id);
|
|
208
|
+
|
|
209
|
+
while (true) {
|
|
210
|
+
console.clear();
|
|
211
|
+
displayBanner();
|
|
212
|
+
drawBoxHeaderContinue('AI SUPERVISION DASHBOARD', boxWidth);
|
|
213
|
+
|
|
214
|
+
console.log(makeLine(chalk.magenta(`AGENT: ${agent.name}`)));
|
|
215
|
+
console.log(makeLine(chalk.green(`STATUS: ${supervisionStatus.active ? 'ACTIVE' : 'INACTIVE'}`)));
|
|
216
|
+
|
|
217
|
+
if (supervisionStatus.active) {
|
|
218
|
+
const duration = Math.floor(supervisionStatus.duration / 1000);
|
|
219
|
+
console.log(makeLine(chalk.gray(`SESSION: ${duration}s`)));
|
|
220
|
+
console.log(makeLine(chalk.gray(`DECISIONS: ${supervisionStatus.decisions}`)));
|
|
221
|
+
console.log(makeLine(chalk.yellow(`INTERVENTIONS: ${supervisionStatus.interventions}`)));
|
|
222
|
+
console.log(makeLine(chalk.cyan(`OPTIMIZATIONS: ${supervisionStatus.optimizations}`)));
|
|
223
|
+
|
|
224
|
+
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
225
|
+
|
|
226
|
+
if (supervisionStatus.lastDecision) {
|
|
227
|
+
const decision = supervisionStatus.lastDecision;
|
|
228
|
+
console.log(makeLine(chalk.white('LAST DECISION:')));
|
|
229
|
+
console.log(makeLine(chalk.gray(` Type: ${decision.type}`)));
|
|
230
|
+
console.log(makeLine(chalk.gray(` Reason: ${decision.reason}`)));
|
|
231
|
+
console.log(makeLine(chalk.gray(` Confidence: ${decision.confidence}%`)));
|
|
232
|
+
} else {
|
|
233
|
+
console.log(makeLine(chalk.gray('No decisions yet...')));
|
|
234
|
+
}
|
|
37
235
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
236
|
+
|
|
237
|
+
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
238
|
+
console.log(makeLine(chalk.gray('[<] BACK')));
|
|
239
|
+
|
|
240
|
+
drawBoxFooter(boxWidth);
|
|
241
|
+
|
|
242
|
+
const choice = await prompts.textInput(chalk.cyan('PRESS < TO GO BACK:'));
|
|
243
|
+
|
|
244
|
+
if (choice === '<' || choice?.toLowerCase() === 'b') {
|
|
245
|
+
break;
|
|
48
246
|
}
|
|
49
247
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
console.log(chalk.red(` ERROR: ${err.message}`));
|
|
54
|
-
await prompts.waitForEnter();
|
|
55
|
-
return 'back';
|
|
248
|
+
// Refresh data
|
|
249
|
+
const freshStatus = AISupervisor.getStatus(agent.id);
|
|
250
|
+
Object.assign(supervisionStatus, freshStatus);
|
|
56
251
|
}
|
|
57
252
|
};
|
|
58
253
|
|
|
59
|
-
module.exports = { algoTradingMenu };
|
|
254
|
+
module.exports = { algoTradingMenu };
|