hedgequantx 2.7.99 → 2.8.0

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.
@@ -0,0 +1,167 @@
1
+ /**
2
+ * AI Supervision Directive - The 7 Phases
3
+ *
4
+ * This directive is sent to ALL AI agents for trading supervision.
5
+ * Each agent receives the same instructions and analyzes signals in parallel.
6
+ */
7
+
8
+ const DIRECTIVE_PHASES = {
9
+ phase1_strategy: `
10
+ ## PHASE 1: MAÎTRISER LA STRATÉGIE
11
+ Tu connais cette stratégie par coeur. Tu sais exactement:
12
+ - Les conditions d'entrée (setup patterns, confirmations requises)
13
+ - Les règles de sortie (targets, stops, trailing)
14
+ - La gestion du risque (sizing, max loss, drawdown limits)
15
+ - Les filtres de marché (sessions, volatilité, corrélations)
16
+ Tu ne devines jamais. Tu appliques la stratégie avec précision chirurgicale.
17
+ `,
18
+
19
+ phase2_role: `
20
+ ## PHASE 2: TON RÔLE
21
+ Tu es une arme de précision intégrée à l'algo de trading.
22
+ Tu n'es PAS un conseiller - tu es un avantage décisif.
23
+ Ton job: optimiser chaque signal pour maximiser le edge.
24
+ Tu travailles EN TEMPS RÉEL avec latence minimale.
25
+ Chaque milliseconde compte. Chaque tick compte.
26
+ `,
27
+
28
+ phase3_analysis: `
29
+ ## PHASE 3: CE QUE TU ANALYSES
30
+ Pour chaque signal reçu, tu analyses:
31
+ - DOM (Depth of Market): déséquilibres bid/ask, absorption, spoofing
32
+ - Order Flow: delta, CVD, volume profile, footprint
33
+ - Manipulations: stop hunts, fakeouts, liquidity grabs
34
+ - Patterns: structure de marché, S/R, pivots, VWAP
35
+ - Historique: trades récents, winrate par setup, performance horaire
36
+ - Corrélations: autres symboles liés (ES/NQ, GC/SI, etc.)
37
+ `,
38
+
39
+ phase4_output: `
40
+ ## PHASE 4: CE QUE TU FOURNIS
41
+ Pour chaque signal, tu retournes:
42
+ 1. DECISION: approve/reject/modify
43
+ 2. CONFIDENCE: score 0-100
44
+ 3. OPTIMIZATIONS (si approve/modify):
45
+ - entry: prix d'entrée optimisé (ou null)
46
+ - stopLoss: stop optimisé (ou null)
47
+ - takeProfit: target optimisé (ou null)
48
+ - size: ajustement de taille (-50% à +50%)
49
+ - timing: "now" | "wait" | "cancel"
50
+ 4. REASON: explication courte (max 50 chars)
51
+ 5. ALERTS: warnings importants (optionnel)
52
+ `,
53
+
54
+ phase5_restrictions: `
55
+ ## PHASE 5: CE QUE TU NE FAIS JAMAIS
56
+ - Tu ne BLOQUES jamais l'algo sans raison valide
57
+ - Tu ne RALENTIS jamais l'exécution (réponse < 2 secondes)
58
+ - Tu ne fais pas de VAGUE - décision claire et directe
59
+ - Tu n'INVENTES pas de données - utilise uniquement ce qui est fourni
60
+ - Tu ne CHANGES pas la stratégie - tu l'optimises dans ses règles
61
+ `,
62
+
63
+ phase6_symbols: `
64
+ ## PHASE 6: CONNAISSANCE DES SYMBOLES
65
+ Tu trades ces symboles avec leurs caractéristiques:
66
+ - NQ (Nasdaq): volatile, tech-driven, corrélé ES
67
+ - ES (S&P500): référence, plus stable, leader
68
+ - YM (Dow): value stocks, moins volatile
69
+ - RTY (Russell): small caps, plus volatile que ES
70
+ - GC (Gold): safe haven, inverse USD, sessions Asia/London
71
+ - SI (Silver): suit GC avec plus de volatilité
72
+ - CL (Crude): news-driven, inventories, géopolitique
73
+
74
+ Sessions importantes:
75
+ - Asia: 18:00-03:00 ET (GC/SI actifs)
76
+ - London: 03:00-08:00 ET (préparation US)
77
+ - US Open: 09:30-11:30 ET (max volatilité)
78
+ - US Close: 15:00-16:00 ET (rebalancing)
79
+ `,
80
+
81
+ phase7_mindset: `
82
+ ## PHASE 7: TA MENTALITÉ
83
+ - OBJECTIF: Gagner. Pas "essayer". Gagner.
84
+ - PRÉCISION: Chaque décision compte
85
+ - RAPIDITÉ: Temps = argent. Sois rapide.
86
+ - RESPONSABILITÉ: Tu assumes tes recommandations
87
+ - ADAPTATION: Le marché change, tu t'adaptes
88
+ - DISCIPLINE: Les règles sont les règles
89
+ `
90
+ };
91
+
92
+ /**
93
+ * Build the complete directive string
94
+ */
95
+ const buildDirective = () => {
96
+ return Object.values(DIRECTIVE_PHASES).join('\n');
97
+ };
98
+
99
+ /**
100
+ * Expected output format from AI agents
101
+ */
102
+ const OUTPUT_FORMAT = {
103
+ schema: {
104
+ decision: 'approve | reject | modify',
105
+ confidence: 'number 0-100',
106
+ optimizations: {
107
+ entry: 'number | null',
108
+ stopLoss: 'number | null',
109
+ takeProfit: 'number | null',
110
+ size: 'number (-0.5 to 0.5) | null',
111
+ timing: 'now | wait | cancel'
112
+ },
113
+ reason: 'string (max 50 chars)',
114
+ alerts: 'string[] | null'
115
+ },
116
+ example: {
117
+ decision: 'modify',
118
+ confidence: 85,
119
+ optimizations: {
120
+ entry: 21450.25,
121
+ stopLoss: 21445.00,
122
+ takeProfit: 21462.50,
123
+ size: 0,
124
+ timing: 'now'
125
+ },
126
+ reason: 'Strong bid stack, tighten stop',
127
+ alerts: null
128
+ }
129
+ };
130
+
131
+ /**
132
+ * Build the output format instructions
133
+ */
134
+ const buildOutputInstructions = () => {
135
+ return `
136
+ ## OUTPUT FORMAT (JSON STRICT)
137
+ Tu dois TOUJOURS répondre en JSON valide avec ce format exact:
138
+
139
+ \`\`\`json
140
+ ${JSON.stringify(OUTPUT_FORMAT.example, null, 2)}
141
+ \`\`\`
142
+
143
+ IMPORTANT:
144
+ - decision: "approve" (exécuter tel quel), "reject" (ne pas exécuter), "modify" (exécuter avec optimisations)
145
+ - confidence: 0-100, ton niveau de confiance dans la décision
146
+ - optimizations: null si decision="reject", sinon les ajustements
147
+ - size: 0 = garder la taille, -0.5 = réduire de 50%, +0.5 = augmenter de 50%
148
+ - timing: "now" = exécuter immédiatement, "wait" = attendre meilleur prix, "cancel" = annuler
149
+ - reason: TOUJOURS fournir une raison courte
150
+ - Pas de texte avant ou après le JSON
151
+ `;
152
+ };
153
+
154
+ /**
155
+ * Get the complete directive with output format
156
+ */
157
+ const getFullDirective = () => {
158
+ return buildDirective() + '\n' + buildOutputInstructions();
159
+ };
160
+
161
+ module.exports = {
162
+ DIRECTIVE_PHASES,
163
+ OUTPUT_FORMAT,
164
+ buildDirective,
165
+ buildOutputInstructions,
166
+ getFullDirective
167
+ };
@@ -0,0 +1,288 @@
1
+ /**
2
+ * AI Supervision Health Check
3
+ *
4
+ * Verifies that AI agents are properly connected and responding
5
+ * before allowing algo trading with AI supervision.
6
+ *
7
+ * Two verification points:
8
+ * 1. [T] TEST in AI Agents menu - manual verification
9
+ * 2. Pre-check before algo launch - automatic verification
10
+ */
11
+
12
+ const cliproxy = require('../cliproxy');
13
+
14
+ /** Test prompt to verify agent understands directive format */
15
+ const TEST_PROMPT = `You are being tested. Respond ONLY with this exact JSON, nothing else:
16
+ {"decision":"approve","confidence":100,"reason":"test-ok"}`;
17
+
18
+ /** Timeout for agent response (agents should respond in < 1 second) */
19
+ const AGENT_TIMEOUT = 2000;
20
+
21
+ /**
22
+ * Check if CLIProxy is running and responding
23
+ * @returns {Promise<Object>} { success, latency, error }
24
+ */
25
+ const checkCliproxyRunning = async () => {
26
+ const startTime = Date.now();
27
+
28
+ try {
29
+ const status = await cliproxy.isRunning();
30
+ const latency = Date.now() - startTime;
31
+
32
+ if (status.running) {
33
+ return { success: true, latency, error: null };
34
+ }
35
+
36
+ return { success: false, latency, error: 'CLIProxy not running' };
37
+ } catch (error) {
38
+ return { success: false, latency: Date.now() - startTime, error: error.message };
39
+ }
40
+ };
41
+
42
+ /**
43
+ * Test a single agent connection and response format
44
+ * @param {Object} agent - Agent config { id, provider, modelId, connectionType, ... }
45
+ * @returns {Promise<Object>} { success, latency, formatValid, error }
46
+ */
47
+ const testAgentConnection = async (agent) => {
48
+ const startTime = Date.now();
49
+
50
+ try {
51
+ // Only test CLIProxy connections for now
52
+ if (agent.connectionType !== 'cliproxy') {
53
+ // For API key connections, we would need different logic
54
+ // For now, mark as needing CLIProxy
55
+ return {
56
+ success: false,
57
+ latency: 0,
58
+ formatValid: false,
59
+ error: 'Only CLIProxy connections supported for pre-check'
60
+ };
61
+ }
62
+
63
+ // Send test prompt with short timeout
64
+ const result = await cliproxy.chat(agent.provider, agent.modelId, TEST_PROMPT, AGENT_TIMEOUT);
65
+ const latency = Date.now() - startTime;
66
+
67
+ if (!result.success) {
68
+ return {
69
+ success: false,
70
+ latency,
71
+ formatValid: false,
72
+ error: result.error || 'No response from agent'
73
+ };
74
+ }
75
+
76
+ // Validate response format
77
+ const formatResult = validateResponseFormat(result.content);
78
+
79
+ return {
80
+ success: formatResult.valid,
81
+ latency,
82
+ formatValid: formatResult.valid,
83
+ error: formatResult.valid ? null : formatResult.error,
84
+ response: result.content
85
+ };
86
+
87
+ } catch (error) {
88
+ return {
89
+ success: false,
90
+ latency: Date.now() - startTime,
91
+ formatValid: false,
92
+ error: error.message || 'Connection failed'
93
+ };
94
+ }
95
+ };
96
+
97
+ /**
98
+ * Validate that response matches expected JSON format
99
+ * @param {string} content - Response content from agent
100
+ * @returns {Object} { valid, error }
101
+ */
102
+ const validateResponseFormat = (content) => {
103
+ if (!content) {
104
+ return { valid: false, error: 'Empty response' };
105
+ }
106
+
107
+ try {
108
+ // Try to extract JSON from response
109
+ let json;
110
+
111
+ // Direct parse
112
+ try {
113
+ json = JSON.parse(content.trim());
114
+ } catch (e) {
115
+ // Try to find JSON in response
116
+ const match = content.match(/\{[\s\S]*\}/);
117
+ if (match) {
118
+ json = JSON.parse(match[0]);
119
+ } else {
120
+ return { valid: false, error: 'No JSON in response' };
121
+ }
122
+ }
123
+
124
+ // Check required fields
125
+ if (!json.decision) {
126
+ return { valid: false, error: 'Missing "decision" field' };
127
+ }
128
+
129
+ if (json.confidence === undefined) {
130
+ return { valid: false, error: 'Missing "confidence" field' };
131
+ }
132
+
133
+ if (!json.reason) {
134
+ return { valid: false, error: 'Missing "reason" field' };
135
+ }
136
+
137
+ // Validate decision value
138
+ const validDecisions = ['approve', 'reject', 'modify'];
139
+ if (!validDecisions.includes(json.decision)) {
140
+ return { valid: false, error: `Invalid decision: ${json.decision}` };
141
+ }
142
+
143
+ // Validate confidence is number 0-100
144
+ const conf = Number(json.confidence);
145
+ if (isNaN(conf) || conf < 0 || conf > 100) {
146
+ return { valid: false, error: `Invalid confidence: ${json.confidence}` };
147
+ }
148
+
149
+ return { valid: true, error: null };
150
+
151
+ } catch (error) {
152
+ return { valid: false, error: `Parse error: ${error.message}` };
153
+ }
154
+ };
155
+
156
+ /**
157
+ * Run pre-flight check on all agents
158
+ * @param {Array} agents - Array of agent configs
159
+ * @returns {Promise<Object>} { success, cliproxy, agents, summary }
160
+ */
161
+ const runPreflightCheck = async (agents) => {
162
+ const results = {
163
+ success: false,
164
+ cliproxy: null,
165
+ agents: [],
166
+ summary: { total: 0, passed: 0, failed: 0 }
167
+ };
168
+
169
+ // Step 1: Check CLIProxy
170
+ results.cliproxy = await checkCliproxyRunning();
171
+
172
+ if (!results.cliproxy.success) {
173
+ results.summary.total = agents.length;
174
+ results.summary.failed = agents.length;
175
+ return results;
176
+ }
177
+
178
+ // Step 2: Test each agent
179
+ results.summary.total = agents.length;
180
+
181
+ for (const agent of agents) {
182
+ const agentResult = await testAgentConnection(agent);
183
+
184
+ results.agents.push({
185
+ id: agent.id,
186
+ name: agent.name,
187
+ provider: agent.provider,
188
+ modelId: agent.modelId,
189
+ ...agentResult
190
+ });
191
+
192
+ if (agentResult.success) {
193
+ results.summary.passed++;
194
+ } else {
195
+ results.summary.failed++;
196
+ }
197
+ }
198
+
199
+ // Success only if ALL agents pass
200
+ results.success = results.summary.failed === 0 && results.summary.passed > 0;
201
+
202
+ return results;
203
+ };
204
+
205
+ /**
206
+ * Format pre-flight results for console display
207
+ * @param {Object} results - Results from runPreflightCheck
208
+ * @param {number} boxWidth - Width for formatting
209
+ * @returns {Array<string>} Lines to display
210
+ */
211
+ const formatPreflightResults = (results, boxWidth) => {
212
+ const chalk = require('chalk');
213
+ const lines = [];
214
+ const W = boxWidth - 2;
215
+
216
+ // CLIProxy status
217
+ if (results.cliproxy.success) {
218
+ lines.push(chalk.white(' CLIProxy Status') + chalk.gray('.'.repeat(Math.max(1, W - 35))) + chalk.green(' ✓ RUNNING'));
219
+ } else {
220
+ lines.push(chalk.white(' CLIProxy Status') + chalk.gray('.'.repeat(Math.max(1, W - 35))) + chalk.red(' ✗ NOT RUNNING'));
221
+ lines.push(chalk.red(` Error: ${results.cliproxy.error}`));
222
+ return lines;
223
+ }
224
+
225
+ lines.push('');
226
+ lines.push(chalk.white(` Testing ${results.summary.total} agent(s):`));
227
+ lines.push('');
228
+
229
+ // Each agent
230
+ for (let i = 0; i < results.agents.length; i++) {
231
+ const agent = results.agents[i];
232
+ const num = `[${i + 1}/${results.summary.total}]`;
233
+
234
+ lines.push(chalk.cyan(` ${num} ${agent.name} (${agent.modelId || agent.provider})`));
235
+
236
+ if (agent.success) {
237
+ const latencyStr = `${agent.latency}ms`;
238
+ lines.push(chalk.gray(' Connection') + chalk.gray('.'.repeat(Math.max(1, W - 40))) + chalk.green(` ✓ OK ${latencyStr}`));
239
+ lines.push(chalk.gray(' Format') + chalk.gray('.'.repeat(Math.max(1, W - 36))) + chalk.green(' ✓ VALID'));
240
+ } else {
241
+ lines.push(chalk.gray(' Connection') + chalk.gray('.'.repeat(Math.max(1, W - 38))) + chalk.red(' ✗ FAILED'));
242
+ lines.push(chalk.red(` Error: ${agent.error}`));
243
+ }
244
+
245
+ lines.push('');
246
+ }
247
+
248
+ return lines;
249
+ };
250
+
251
+ /**
252
+ * Get summary line for pre-flight results
253
+ * @param {Object} results - Results from runPreflightCheck
254
+ * @returns {Object} { text, success }
255
+ */
256
+ const getPreflightSummary = (results) => {
257
+ const chalk = require('chalk');
258
+
259
+ if (!results.cliproxy.success) {
260
+ return {
261
+ text: chalk.red('✗ CLIProxy not running - cannot verify agents'),
262
+ success: false
263
+ };
264
+ }
265
+
266
+ if (results.success) {
267
+ return {
268
+ text: chalk.green(`✓ ALL SYSTEMS GO - ${results.summary.passed}/${results.summary.total} agents ready`),
269
+ success: true
270
+ };
271
+ }
272
+
273
+ return {
274
+ text: chalk.red(`✗ FAILED - ${results.summary.passed}/${results.summary.total} agents passed (all must pass)`),
275
+ success: false
276
+ };
277
+ };
278
+
279
+ module.exports = {
280
+ checkCliproxyRunning,
281
+ testAgentConnection,
282
+ validateResponseFormat,
283
+ runPreflightCheck,
284
+ formatPreflightResults,
285
+ getPreflightSummary,
286
+ TEST_PROMPT,
287
+ AGENT_TIMEOUT
288
+ };