hedgequantx 2.9.232 → 2.9.234
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 -48
package/package.json
CHANGED
|
@@ -15,22 +15,44 @@
|
|
|
15
15
|
|
|
16
16
|
const chalk = require('chalk');
|
|
17
17
|
|
|
18
|
-
//
|
|
18
|
+
// Rich color helpers for professional HF display
|
|
19
19
|
const C = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
// Symbol - bright cyan
|
|
21
|
+
sym: (s) => chalk.hex('#00FFFF').bold(s),
|
|
22
|
+
|
|
23
|
+
// Price - bright white/yellow
|
|
24
|
+
price: (p) => chalk.hex('#FFFFFF').bold(p),
|
|
25
|
+
priceUp: (p) => chalk.hex('#00FF00').bold(p),
|
|
26
|
+
priceDown: (p) => chalk.hex('#FF4444').bold(p),
|
|
27
|
+
|
|
28
|
+
// Direction
|
|
29
|
+
long: (s) => chalk.hex('#00FF00').bold(s),
|
|
30
|
+
short: (s) => chalk.hex('#FF4444').bold(s),
|
|
31
|
+
bull: (s) => chalk.hex('#00DD00')(s),
|
|
32
|
+
bear: (s) => chalk.hex('#FF6666')(s),
|
|
33
|
+
|
|
34
|
+
// Values & metrics
|
|
35
|
+
val: (v) => chalk.hex('#00BFFF')(v), // Deep sky blue
|
|
36
|
+
valHigh: (v) => chalk.hex('#FF00FF').bold(v), // Magenta for extreme
|
|
37
|
+
zscore: (v) => chalk.hex('#FFD700')(v), // Gold for Z-score
|
|
38
|
+
|
|
39
|
+
// Status indicators
|
|
40
|
+
ok: (s) => chalk.hex('#00FF00')(s),
|
|
41
|
+
warn: (s) => chalk.hex('#FFA500').bold(s), // Orange warning
|
|
42
|
+
danger: (s) => chalk.hex('#FF0000').bold(s), // Red danger
|
|
43
|
+
|
|
44
|
+
// Neutral/info
|
|
45
|
+
dim: (s) => chalk.hex('#888888')(s),
|
|
46
|
+
info: (s) => chalk.hex('#AAAAAA')(s),
|
|
47
|
+
muted: (s) => chalk.hex('#666666')(s),
|
|
48
|
+
|
|
49
|
+
// Special states
|
|
50
|
+
signal: (s) => chalk.hex('#FFFF00').bold(s), // Bright yellow signal
|
|
51
|
+
toxic: (s) => chalk.hex('#FF0000').bgHex('#330000').bold(s),
|
|
52
|
+
|
|
53
|
+
// Labels
|
|
54
|
+
label: (s) => chalk.hex('#888888')(s),
|
|
55
|
+
separator: () => chalk.hex('#444444')('|'),
|
|
34
56
|
};
|
|
35
57
|
|
|
36
58
|
const CONFIG = {
|
|
@@ -86,8 +108,9 @@ class SmartLogsEngine {
|
|
|
86
108
|
const priceNum = state.price || 0;
|
|
87
109
|
const lastPrice = this._lastPrice || priceNum;
|
|
88
110
|
const priceDiff = priceNum - lastPrice;
|
|
89
|
-
const priceDir = priceDiff > 0.01 ? '▲' : priceDiff < -0.01 ? '▼' : '
|
|
90
|
-
const priceDirColor = priceDiff > 0 ? C.bull : priceDiff < 0 ? C.bear : C.
|
|
111
|
+
const priceDir = priceDiff > 0.01 ? '▲' : priceDiff < -0.01 ? '▼' : '─';
|
|
112
|
+
const priceDirColor = priceDiff > 0 ? C.bull : priceDiff < 0 ? C.bear : C.muted;
|
|
113
|
+
const priceDisplay = priceDiff > 0 ? C.priceUp(price) : priceDiff < 0 ? C.priceDown(price) : C.price(price);
|
|
91
114
|
this._lastPrice = priceNum;
|
|
92
115
|
|
|
93
116
|
// Track tick velocity
|
|
@@ -96,13 +119,17 @@ class SmartLogsEngine {
|
|
|
96
119
|
this._lastTicks = tickCount || bars || 0;
|
|
97
120
|
|
|
98
121
|
// Not enough data - still warming up
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
122
|
+
// HQX Scalping is a TICK strategy - needs minimum ticks for QUANT models
|
|
123
|
+
const tickTotal = tickCount || 0;
|
|
124
|
+
const minTicks = 500; // Minimum ticks needed for Z-score, VPIN, OFI calculations
|
|
125
|
+
|
|
126
|
+
if (tickTotal < minTicks || !price) {
|
|
127
|
+
const pct = Math.min(100, Math.round((tickTotal / minTicks) * 100));
|
|
128
|
+
const remaining = minTicks - tickTotal;
|
|
129
|
+
const pctColor = pct < 30 ? C.warn : pct < 70 ? C.val : C.ok;
|
|
103
130
|
return {
|
|
104
131
|
type: 'system',
|
|
105
|
-
message: `[${C.sym(sym)}] ${price ? C.price(price) : '-.--'}
|
|
132
|
+
message: `[${C.sym(sym)}] ${price ? C.price(price) : C.dim('-.--')} ${C.separator()} ${C.label('Calibrating')} ${pctColor(pct + '%')} ${C.separator()} ${C.val(tickTotal + '/' + minTicks)} ${C.label('ticks')} ${C.separator()} ${C.val('+' + tickVelocity + '/s')}`,
|
|
106
133
|
logToSession: false
|
|
107
134
|
};
|
|
108
135
|
}
|
|
@@ -114,38 +141,46 @@ class SmartLogsEngine {
|
|
|
114
141
|
const buyPctRound = Math.round(buyPct || 50);
|
|
115
142
|
const deltaRound = Math.round(delta || 0);
|
|
116
143
|
|
|
117
|
-
// Z-Score color based on level
|
|
144
|
+
// Z-Score color based on level - more vivid
|
|
118
145
|
const zColor = absZ >= CONFIG.Z_EXTREME ? C.valHigh :
|
|
119
|
-
absZ >= CONFIG.Z_HIGH ? C.
|
|
120
|
-
absZ >= CONFIG.Z_BUILDING ? C.
|
|
146
|
+
absZ >= CONFIG.Z_HIGH ? C.signal :
|
|
147
|
+
absZ >= CONFIG.Z_BUILDING ? C.zscore : C.muted;
|
|
121
148
|
const zStr = zColor(`${zScore.toFixed(2)}σ`);
|
|
122
149
|
|
|
123
|
-
// OFI color based on direction
|
|
124
|
-
const ofiColor = ofi > CONFIG.
|
|
125
|
-
ofi
|
|
150
|
+
// OFI color based on direction - more vivid
|
|
151
|
+
const ofiColor = ofi > CONFIG.OFI_STRONG ? C.long :
|
|
152
|
+
ofi > CONFIG.OFI_THRESHOLD ? C.bull :
|
|
153
|
+
ofi < -CONFIG.OFI_STRONG ? C.short :
|
|
154
|
+
ofi < -CONFIG.OFI_THRESHOLD ? C.bear : C.muted;
|
|
126
155
|
const ofiStr = ofiColor(`${ofi >= 0 ? '+' : ''}${ofiPct}%`);
|
|
127
156
|
|
|
128
|
-
// VPIN color based on toxicity
|
|
129
|
-
const vpinColor = vpin > CONFIG.VPIN_TOXIC ? C.
|
|
157
|
+
// VPIN color based on toxicity - more vivid
|
|
158
|
+
const vpinColor = vpin > CONFIG.VPIN_TOXIC ? C.toxic :
|
|
130
159
|
vpin > CONFIG.VPIN_ELEVATED ? C.warn : C.ok;
|
|
131
160
|
const vpinStr = vpinColor(`${vpinPct}%`);
|
|
132
161
|
|
|
133
|
-
// Delta (buy-sell imbalance) display
|
|
134
|
-
const
|
|
162
|
+
// Delta (buy-sell imbalance) display - more vivid
|
|
163
|
+
const deltaAbs = Math.abs(deltaRound);
|
|
164
|
+
const deltaColor = deltaRound > 50 ? C.long : deltaRound > 0 ? C.bull :
|
|
165
|
+
deltaRound < -50 ? C.short : deltaRound < 0 ? C.bear : C.muted;
|
|
135
166
|
const deltaStr = deltaColor(`${deltaRound > 0 ? '+' : ''}${deltaRound}`);
|
|
136
167
|
|
|
168
|
+
// Buy percentage color
|
|
169
|
+
const buyColor = buyPctRound > 60 ? C.bull : buyPctRound < 40 ? C.bear : C.muted;
|
|
170
|
+
const buyStr = buyColor(`${buyPctRound}%`);
|
|
171
|
+
|
|
137
172
|
// Active position - show position management with unique data
|
|
138
173
|
if (position !== 0) {
|
|
139
174
|
const isLong = position > 0;
|
|
140
|
-
const side = isLong ? C.long('LONG') : C.short('SHORT');
|
|
175
|
+
const side = isLong ? C.long('● LONG') : C.short('● SHORT');
|
|
141
176
|
const flowFavor = (isLong && ofi > 0) || (!isLong && ofi < 0);
|
|
142
|
-
const flowLabel = flowFavor ? C.ok('aligned') : C.warn('adverse');
|
|
177
|
+
const flowLabel = flowFavor ? C.ok('✓ aligned') : C.warn('⚠ adverse');
|
|
143
178
|
const exitClose = absZ < 0.5;
|
|
144
|
-
const exitInfo = exitClose ? C.warn('EXIT ZONE') : 'holding';
|
|
179
|
+
const exitInfo = exitClose ? C.warn('⚡ EXIT ZONE') : C.ok('holding');
|
|
145
180
|
|
|
146
181
|
return {
|
|
147
182
|
type: 'trade',
|
|
148
|
-
message: `[${C.sym(sym)}] ${side} ${priceDirColor(priceDir)} ${C.
|
|
183
|
+
message: `[${C.sym(sym)}] ${side} ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${exitInfo} ${C.separator()} ${C.label('Δ:')}${deltaStr} ${C.separator()} ${flowLabel}`,
|
|
149
184
|
logToSession: false
|
|
150
185
|
};
|
|
151
186
|
}
|
|
@@ -159,31 +194,31 @@ class SmartLogsEngine {
|
|
|
159
194
|
|
|
160
195
|
// VPIN toxic - highest priority blocker
|
|
161
196
|
if (vpin > CONFIG.VPIN_TOXIC) {
|
|
162
|
-
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.
|
|
197
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('VPIN:')}${vpinStr} ${C.toxic('☠ TOXIC')} ${C.separator()} ${C.label('Z:')}${zStr} ${C.separator()} ${C.label('Δ:')}${deltaStr} ${C.separator()} ${C.danger('NO ENTRY')}`;
|
|
163
198
|
logType = 'risk';
|
|
164
199
|
}
|
|
165
200
|
// Z-Score extreme + OFI confirms = SIGNAL
|
|
166
201
|
else if (absZ >= CONFIG.Z_EXTREME &&
|
|
167
202
|
((zScore < 0 && ofi > CONFIG.OFI_THRESHOLD) || (zScore > 0 && ofi < -CONFIG.OFI_THRESHOLD))) {
|
|
168
|
-
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.
|
|
203
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${C.signal('★ EXTREME')} ${C.separator()} ${C.label('OFI:')}${ofiStr} ${C.ok('✓')} ${C.separator()} ${dirColor('► ' + direction + ' SIGNAL')}`;
|
|
169
204
|
logType = 'signal';
|
|
170
205
|
}
|
|
171
206
|
// Z-Score extreme but OFI doesn't confirm
|
|
172
207
|
else if (absZ >= CONFIG.Z_EXTREME) {
|
|
173
|
-
const ofiNeed = zScore < 0 ?
|
|
174
|
-
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.
|
|
208
|
+
const ofiNeed = zScore < 0 ? C.dim('need >15%') : C.dim('need <-15%');
|
|
209
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${C.signal('!')} ${C.separator()} ${C.label('OFI:')}${ofiStr} ${ofiNeed} ${C.separator()} ${C.warn('◐ PENDING')}`;
|
|
175
210
|
logType = 'signal';
|
|
176
211
|
}
|
|
177
212
|
// Z-Score high - setup forming
|
|
178
213
|
else if (absZ >= CONFIG.Z_HIGH) {
|
|
179
214
|
const needed = (CONFIG.Z_EXTREME - absZ).toFixed(2);
|
|
180
|
-
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.
|
|
215
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${C.val('+' + needed + 'σ')} ${C.label('to signal')} ${C.separator()} ${C.label('OFI:')}${ofiStr} ${C.separator()} ${C.label('Δ:')}${deltaStr}`;
|
|
181
216
|
}
|
|
182
217
|
// Z-Score building
|
|
183
218
|
else if (absZ >= CONFIG.Z_BUILDING) {
|
|
184
219
|
const needed = (CONFIG.Z_HIGH - absZ).toFixed(2);
|
|
185
|
-
const bias = zScore < 0 ? 'bid' : 'ask';
|
|
186
|
-
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.
|
|
220
|
+
const bias = zScore < 0 ? C.bull('bid ↑') : C.bear('ask ↓');
|
|
221
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${bias} ${C.separator()} ${C.val('+' + needed + 'σ')} ${C.label('to setup')} ${C.separator()} ${C.label('Δ:')}${deltaStr}`;
|
|
187
222
|
}
|
|
188
223
|
// Z-Score neutral - scanning
|
|
189
224
|
else {
|
|
@@ -192,18 +227,18 @@ class SmartLogsEngine {
|
|
|
192
227
|
let context;
|
|
193
228
|
switch (infoType) {
|
|
194
229
|
case 0:
|
|
195
|
-
context =
|
|
230
|
+
context = `${C.label('Δ:')}${deltaStr} ${C.separator()} ${C.label('Buy:')}${buyStr}`;
|
|
196
231
|
break;
|
|
197
232
|
case 1:
|
|
198
|
-
context =
|
|
233
|
+
context = `${C.label('VPIN:')}${vpinStr} ${C.separator()} ${C.label('OFI:')}${ofiStr}`;
|
|
199
234
|
break;
|
|
200
235
|
case 2:
|
|
201
|
-
context = `${tickVelocity} ticks/s
|
|
236
|
+
context = `${C.val(tickVelocity)} ${C.label('ticks/s')} ${C.separator()} ${C.label('Δ:')}${deltaStr}`;
|
|
202
237
|
break;
|
|
203
238
|
default:
|
|
204
|
-
context =
|
|
239
|
+
context = `${C.label('OFI:')}${ofiStr} ${C.separator()} ${C.label('Buy:')}${buyStr}`;
|
|
205
240
|
}
|
|
206
|
-
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.
|
|
241
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${C.muted('scanning')} ${C.separator()} ${context}`;
|
|
207
242
|
}
|
|
208
243
|
|
|
209
244
|
return { type: logType, message, logToSession: logType === 'signal' };
|