hedgequantx 2.9.214 → 2.9.216
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/lib/smart-logs-engine.js +83 -86
package/package.json
CHANGED
|
@@ -8,6 +8,16 @@
|
|
|
8
8
|
* - Uses smartLogs.getLiveAnalysisLog() for varied, non-repetitive messages
|
|
9
9
|
*
|
|
10
10
|
* Only logs when something SIGNIFICANT happens - no spam, no repetitive messages
|
|
11
|
+
*
|
|
12
|
+
* COLOR SCHEME:
|
|
13
|
+
* - Symbols: cyan (NQ, ES, CL, GC)
|
|
14
|
+
* - Prices: white bold
|
|
15
|
+
* - Bullish/Long: green
|
|
16
|
+
* - Bearish/Short: red
|
|
17
|
+
* - Neutral/System: gray/dim
|
|
18
|
+
* - Signals: yellow/magenta
|
|
19
|
+
* - Risk/Warnings: red bold
|
|
20
|
+
* - Values: blue (Z-Score, VPIN, OFI numbers)
|
|
11
21
|
*/
|
|
12
22
|
|
|
13
23
|
'use strict';
|
|
@@ -16,6 +26,39 @@ const chalk = require('chalk');
|
|
|
16
26
|
const smartLogs = require('./smart-logs');
|
|
17
27
|
const { getContextualMessage } = require('./smart-logs-context');
|
|
18
28
|
|
|
29
|
+
// Color helpers for consistent styling
|
|
30
|
+
const C = {
|
|
31
|
+
// Symbols & identifiers
|
|
32
|
+
sym: (s) => chalk.cyan.bold(s),
|
|
33
|
+
|
|
34
|
+
// Prices
|
|
35
|
+
price: (p) => chalk.white.bold(p),
|
|
36
|
+
|
|
37
|
+
// Direction
|
|
38
|
+
long: (s) => chalk.green.bold(s),
|
|
39
|
+
short: (s) => chalk.red.bold(s),
|
|
40
|
+
bull: (s) => chalk.green(s),
|
|
41
|
+
bear: (s) => chalk.red(s),
|
|
42
|
+
|
|
43
|
+
// Values & metrics
|
|
44
|
+
val: (v) => chalk.blue(v),
|
|
45
|
+
valHigh: (v) => chalk.magenta.bold(v),
|
|
46
|
+
|
|
47
|
+
// Status
|
|
48
|
+
ok: (s) => chalk.green(s),
|
|
49
|
+
warn: (s) => chalk.yellow(s),
|
|
50
|
+
danger: (s) => chalk.red.bold(s),
|
|
51
|
+
|
|
52
|
+
// System/neutral
|
|
53
|
+
dim: (s) => chalk.dim(s),
|
|
54
|
+
info: (s) => chalk.gray(s),
|
|
55
|
+
|
|
56
|
+
// Special
|
|
57
|
+
signal: (s) => chalk.yellow.bold(s),
|
|
58
|
+
zone: (s) => chalk.magenta(s),
|
|
59
|
+
regime: (s) => chalk.cyan(s),
|
|
60
|
+
};
|
|
61
|
+
|
|
19
62
|
const CONFIG = {
|
|
20
63
|
SESSION_LOG_INTERVAL: 10,
|
|
21
64
|
// HQX-2B thresholds
|
|
@@ -54,7 +97,6 @@ class SmartLogsEngine {
|
|
|
54
97
|
this.symbolCode = symbol;
|
|
55
98
|
this.counter = 0;
|
|
56
99
|
this.lastState = null;
|
|
57
|
-
this.lastLogTime = 0;
|
|
58
100
|
|
|
59
101
|
// State tracking for event detection (both strategies)
|
|
60
102
|
this.lastBias = null;
|
|
@@ -69,10 +111,6 @@ class SmartLogsEngine {
|
|
|
69
111
|
// QUANT specific
|
|
70
112
|
this.lastZRegime = null;
|
|
71
113
|
this.lastVpinToxic = false;
|
|
72
|
-
this.lastPrice = 0;
|
|
73
|
-
this.lastLoggedZ = null;
|
|
74
|
-
this.lastLoggedOfi = null;
|
|
75
|
-
this.recentMessages = [];
|
|
76
114
|
}
|
|
77
115
|
|
|
78
116
|
setSymbol(s) { this.symbolCode = s; }
|
|
@@ -89,11 +127,14 @@ class SmartLogsEngine {
|
|
|
89
127
|
|
|
90
128
|
// Active position - same for all strategies
|
|
91
129
|
if (position !== 0) {
|
|
92
|
-
const
|
|
93
|
-
const
|
|
130
|
+
const isLong = position > 0;
|
|
131
|
+
const side = isLong ? C.long('LONG') : C.short('SHORT');
|
|
132
|
+
const flowFavor = (isLong && delta > 0) || (!isLong && delta < 0);
|
|
133
|
+
const flowLabel = flowFavor ? C.ok('FAVOR') : C.danger('ADVERSE');
|
|
134
|
+
const deltaStr = delta > 0 ? C.bull(`+${delta}`) : C.bear(`${delta}`);
|
|
94
135
|
return {
|
|
95
136
|
type: 'trade',
|
|
96
|
-
message: `[${sym}] ${side} ACTIVE @ ${price} | Delta: ${
|
|
137
|
+
message: `[${C.sym(sym)}] ${side} ACTIVE @ ${C.price(price)} | Delta: ${deltaStr} | Flow: ${flowLabel}`,
|
|
97
138
|
logToSession: true
|
|
98
139
|
};
|
|
99
140
|
}
|
|
@@ -121,35 +162,37 @@ class SmartLogsEngine {
|
|
|
121
162
|
this.warmupLogged = true;
|
|
122
163
|
event = 'warmup';
|
|
123
164
|
const warmupMsg = getContextualMessage(this.symbolCode, this.strategyId, 'warmup');
|
|
124
|
-
message = `[${sym}] 2B ready | ${bars} bars | ${warmupMsg}`;
|
|
165
|
+
message = `[${C.sym(sym)}] ${C.ok('2B ready')} | ${C.val(bars)} bars | ${C.dim(warmupMsg)}`;
|
|
125
166
|
logType = 'system';
|
|
126
167
|
}
|
|
127
168
|
// EVENT 2: New zone created
|
|
128
169
|
else if (zones > this.lastZones && zones > 0) {
|
|
129
170
|
event = 'new_zone';
|
|
130
171
|
const signalMsg = getContextualMessage(this.symbolCode, this.strategyId, 'signal');
|
|
131
|
-
message = `[${sym}] ${price} | Zone
|
|
172
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | ${C.zone('Zone #' + zones)} | ${C.signal(signalMsg)}`;
|
|
132
173
|
logType = 'signal';
|
|
133
174
|
}
|
|
134
175
|
// EVENT 3: New swing detected
|
|
135
176
|
else if (swings > this.lastSwings && swings > 0) {
|
|
136
177
|
event = 'new_swing';
|
|
137
178
|
const scanMsg = getContextualMessage(this.symbolCode, this.strategyId, 'scanning');
|
|
138
|
-
message = `[${sym}] ${price} | Swing
|
|
179
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | ${C.info('Swing #' + swings)} | ${C.dim(scanMsg)}`;
|
|
139
180
|
}
|
|
140
181
|
// EVENT 4: Zone approach (price near zone)
|
|
141
182
|
else if (nearZone && !this.lastNearZone && zones > 0) {
|
|
142
183
|
event = 'zone_approach';
|
|
143
184
|
const signalMsg = getContextualMessage(this.symbolCode, this.strategyId, 'signal');
|
|
144
|
-
message = `[${sym}] ${price} | Zone approach | ${signalMsg}`;
|
|
185
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | ${C.warn('Zone approach')} | ${C.signal(signalMsg)}`;
|
|
145
186
|
logType = 'signal';
|
|
146
187
|
}
|
|
147
188
|
// EVENT 5: Bias flip
|
|
148
189
|
else if (this.lastBias && trend !== this.lastBias && trend !== 'neutral' && this.lastBias !== 'neutral') {
|
|
149
190
|
event = 'bias_flip';
|
|
150
|
-
const arrow = trend === 'bullish' ?
|
|
191
|
+
const arrow = trend === 'bullish' ? C.bull('▲') : C.bear('▼');
|
|
192
|
+
const oldBias = this.lastBias === 'bullish' ? C.bull(this.lastBias) : C.bear(this.lastBias);
|
|
193
|
+
const newBias = trend === 'bullish' ? C.bull(trend) : C.bear(trend);
|
|
151
194
|
const flipMsg = getContextualMessage(this.symbolCode, this.strategyId, trend);
|
|
152
|
-
message = `[${sym}] ${arrow} ${
|
|
195
|
+
message = `[${C.sym(sym)}] ${arrow} ${oldBias} → ${newBias} | ${C.dim(flipMsg)}`;
|
|
153
196
|
}
|
|
154
197
|
|
|
155
198
|
// Update state tracking
|
|
@@ -181,12 +224,22 @@ class SmartLogsEngine {
|
|
|
181
224
|
let logType = 'analysis';
|
|
182
225
|
let message = null;
|
|
183
226
|
|
|
227
|
+
// Helper for Z-Score color
|
|
228
|
+
const zColor = (z) => {
|
|
229
|
+
const absVal = Math.abs(z);
|
|
230
|
+
const formatted = `${z.toFixed(1)}σ`;
|
|
231
|
+
if (absVal >= CONFIG.Z_EXTREME) return C.valHigh(formatted);
|
|
232
|
+
if (absVal >= CONFIG.Z_HIGH) return C.warn(formatted);
|
|
233
|
+
if (absVal >= CONFIG.Z_BUILDING) return C.val(formatted);
|
|
234
|
+
return C.dim(formatted);
|
|
235
|
+
};
|
|
236
|
+
|
|
184
237
|
// EVENT 1: Warmup complete (250 ticks for QUANT models)
|
|
185
238
|
if (ticks >= CONFIG.QUANT_WARMUP_TICKS && !this.warmupLogged) {
|
|
186
239
|
this.warmupLogged = true;
|
|
187
240
|
event = 'warmup';
|
|
188
241
|
const warmupMsg = getContextualMessage(this.symbolCode, this.strategyId, 'warmup');
|
|
189
|
-
message = `[${sym}] QUANT ready | ${ticks} ticks | ${warmupMsg}`;
|
|
242
|
+
message = `[${C.sym(sym)}] ${C.ok('QUANT ready')} | ${C.val(ticks)} ticks | ${C.dim(warmupMsg)}`;
|
|
190
243
|
logType = 'system';
|
|
191
244
|
}
|
|
192
245
|
// EVENT 2: Z-Score regime change
|
|
@@ -198,34 +251,37 @@ class SmartLogsEngine {
|
|
|
198
251
|
|
|
199
252
|
if (zRegime === 'extreme') {
|
|
200
253
|
logType = 'signal';
|
|
201
|
-
const dir = zScore < 0 ? 'LONG' : 'SHORT';
|
|
254
|
+
const dir = zScore < 0 ? C.long('LONG') : C.short('SHORT');
|
|
202
255
|
const signalMsg = getContextualMessage(this.symbolCode, this.strategyId, 'signal');
|
|
203
|
-
message = `[${sym}] ${price} | Z: ${zScore.
|
|
256
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | Z: ${zColor(zScore)} ${C.signal('EXTREME')} | ${dir} | ${C.signal(signalMsg)}`;
|
|
204
257
|
} else if (zRegime === 'high') {
|
|
205
258
|
logType = 'signal';
|
|
206
|
-
message = `[${sym}] ${price} | Z: ${zScore.
|
|
259
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | Z: ${zColor(zScore)} ${C.warn('HIGH')} | ${C.dim(instrumentMsg)}`;
|
|
207
260
|
} else if (zRegime === 'building') {
|
|
208
|
-
message = `[${sym}] ${price} | Z
|
|
261
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | Z: ${zColor(zScore)} ${C.info('building')} | ${C.dim(instrumentMsg)}`;
|
|
209
262
|
} else {
|
|
210
263
|
const scanMsg = getContextualMessage(this.symbolCode, this.strategyId, 'scanning');
|
|
211
|
-
message = `[${sym}] ${price} | Z normalized | ${scanMsg}`;
|
|
264
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | Z: ${C.ok('normalized')} | ${C.dim(scanMsg)}`;
|
|
212
265
|
}
|
|
213
266
|
}
|
|
214
267
|
// EVENT 3: Bias flip (OFI direction change)
|
|
215
268
|
else if (this.lastBias !== null && bias !== this.lastBias && bias !== 'neutral' && this.lastBias !== 'neutral') {
|
|
216
269
|
event = 'bias_flip';
|
|
217
|
-
const arrow = bias === 'bullish' ?
|
|
270
|
+
const arrow = bias === 'bullish' ? C.bull('▲') : C.bear('▼');
|
|
271
|
+
const oldBias = this.lastBias === 'bullish' ? C.bull(this.lastBias) : C.bear(this.lastBias);
|
|
272
|
+
const newBias = bias === 'bullish' ? C.bull(bias) : C.bear(bias);
|
|
218
273
|
const flipMsg = getContextualMessage(this.symbolCode, this.strategyId, bias);
|
|
219
|
-
message = `[${sym}] ${arrow} OFI: ${
|
|
274
|
+
message = `[${C.sym(sym)}] ${arrow} OFI: ${oldBias} → ${newBias} | ${C.dim(flipMsg)}`;
|
|
220
275
|
}
|
|
221
276
|
// EVENT 4: VPIN toxicity change
|
|
222
277
|
else if (this.lastVpinToxic !== null && vpinToxic !== this.lastVpinToxic) {
|
|
223
278
|
event = 'vpin';
|
|
279
|
+
const vpinPct = (vpin * 100).toFixed(0);
|
|
224
280
|
if (vpinToxic) {
|
|
225
|
-
message = `[${sym}] ${price} | VPIN
|
|
281
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | VPIN: ${C.danger(vpinPct + '%')} ${C.danger('TOXIC')} - informed flow`;
|
|
226
282
|
logType = 'risk';
|
|
227
283
|
} else {
|
|
228
|
-
message = `[${sym}] ${price} | VPIN
|
|
284
|
+
message = `[${C.sym(sym)}] ${C.price(price)} | VPIN: ${C.ok(vpinPct + '%')} ${C.ok('clean')} - normal flow`;
|
|
229
285
|
}
|
|
230
286
|
}
|
|
231
287
|
|
|
@@ -235,66 +291,12 @@ class SmartLogsEngine {
|
|
|
235
291
|
this.lastVpinToxic = vpinToxic;
|
|
236
292
|
|
|
237
293
|
if (event && message) {
|
|
238
|
-
this.lastLogTime = Date.now();
|
|
239
|
-
this.lastPrice = state.price;
|
|
240
|
-
this.lastLoggedZ = zScore;
|
|
241
|
-
this.lastLoggedOfi = ofi;
|
|
242
294
|
return { type: logType, message, logToSession: event === 'z_regime' || event === 'bias_flip' };
|
|
243
295
|
}
|
|
244
296
|
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const price = state.price || 0;
|
|
249
|
-
const priceChange = this.lastPrice ? price - this.lastPrice : 0;
|
|
250
|
-
const zChange = this.lastLoggedZ !== null ? zScore - this.lastLoggedZ : 0;
|
|
251
|
-
const ofiChange = this.lastLoggedOfi !== null ? ofi - this.lastLoggedOfi : 0;
|
|
252
|
-
|
|
253
|
-
this.lastLogTime = now;
|
|
254
|
-
this.lastPrice = price;
|
|
255
|
-
this.lastLoggedZ = zScore;
|
|
256
|
-
this.lastLoggedOfi = ofi;
|
|
257
|
-
|
|
258
|
-
// Build contextual message based on what's actually happening
|
|
259
|
-
const zStr = zScore >= 0 ? `+${zScore.toFixed(1)}` : zScore.toFixed(1);
|
|
260
|
-
const ofiPct = (ofi * 100).toFixed(0);
|
|
261
|
-
const vpinPct = (vpin * 100).toFixed(0);
|
|
262
|
-
|
|
263
|
-
// Determine what's notable RIGHT NOW
|
|
264
|
-
let context;
|
|
265
|
-
if (Math.abs(priceChange) >= 0.5) {
|
|
266
|
-
// Price moved significantly
|
|
267
|
-
const dir = priceChange > 0 ? 'uptick' : 'downtick';
|
|
268
|
-
const ticks = Math.abs(priceChange / 0.25).toFixed(0);
|
|
269
|
-
context = `${dir} ${ticks}t`;
|
|
270
|
-
} else if (Math.abs(zChange) >= 0.3) {
|
|
271
|
-
// Z-Score shifting
|
|
272
|
-
context = zChange > 0 ? 'Z expanding' : 'Z contracting';
|
|
273
|
-
} else if (Math.abs(ofiChange) >= 0.05) {
|
|
274
|
-
// OFI shifting
|
|
275
|
-
context = ofiChange > 0 ? 'buying pressure' : 'selling pressure';
|
|
276
|
-
} else if (absZ >= 1.5) {
|
|
277
|
-
// In signal zone
|
|
278
|
-
const dir = zScore < 0 ? 'LONG zone' : 'SHORT zone';
|
|
279
|
-
context = dir;
|
|
280
|
-
} else if (Math.abs(ofi) >= 0.15) {
|
|
281
|
-
// Strong flow
|
|
282
|
-
context = ofi > 0 ? 'bid strength' : 'offer strength';
|
|
283
|
-
} else if (vpin > 0.4) {
|
|
284
|
-
// Elevated VPIN
|
|
285
|
-
context = 'elevated toxicity';
|
|
286
|
-
} else {
|
|
287
|
-
// Get instrument-specific neutral message
|
|
288
|
-
context = getContextualMessage(this.symbolCode, this.strategyId, 'neutral');
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return {
|
|
292
|
-
type: 'analysis',
|
|
293
|
-
message: `[${sym}] ${price.toFixed(2)} | Z: ${zStr}σ | OFI: ${ofiPct}% | ${context}`,
|
|
294
|
-
logToSession: false
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
|
|
297
|
+
// EVENT-DRIVEN ONLY: No spam, no repetitive logs
|
|
298
|
+
// Silence = system is scanning, nothing notable happening
|
|
299
|
+
// This is professional HF behavior
|
|
298
300
|
return null;
|
|
299
301
|
}
|
|
300
302
|
|
|
@@ -303,7 +305,6 @@ class SmartLogsEngine {
|
|
|
303
305
|
this.counter = 0;
|
|
304
306
|
this.lastBias = null;
|
|
305
307
|
this.warmupLogged = false;
|
|
306
|
-
this.lastLogTime = 0;
|
|
307
308
|
// HQX-2B
|
|
308
309
|
this.lastBars = 0;
|
|
309
310
|
this.lastSwings = 0;
|
|
@@ -312,10 +313,6 @@ class SmartLogsEngine {
|
|
|
312
313
|
// QUANT
|
|
313
314
|
this.lastZRegime = null;
|
|
314
315
|
this.lastVpinToxic = false;
|
|
315
|
-
this.lastPrice = 0;
|
|
316
|
-
this.lastLoggedZ = null;
|
|
317
|
-
this.lastLoggedOfi = null;
|
|
318
|
-
this.recentMessages = [];
|
|
319
316
|
}
|
|
320
317
|
}
|
|
321
318
|
|