hedgequantx 2.9.231 → 2.9.233
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 +163 -145
package/package.json
CHANGED
|
@@ -1,38 +1,58 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Smart Logs Engine - Professional HF-Grade
|
|
3
|
-
*
|
|
2
|
+
* Smart Logs Engine - Professional HF-Grade Real-Time Logs
|
|
3
|
+
* =========================================================
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* 1.
|
|
7
|
-
* 2.
|
|
8
|
-
* 3.
|
|
9
|
-
* 4.
|
|
5
|
+
* REAL-TIME logs every second showing:
|
|
6
|
+
* 1. Current price action
|
|
7
|
+
* 2. QUANT model states (Z-Score, VPIN, OFI)
|
|
8
|
+
* 3. Why we're not entering (or why we ARE entering)
|
|
9
|
+
* 4. Market microstructure insights
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
* intelligent, context-aware logs that reflect the actual
|
|
13
|
-
* algorithmic decision process.
|
|
11
|
+
* NO fake messages - everything is derived from real tick data
|
|
14
12
|
*/
|
|
15
13
|
|
|
16
14
|
'use strict';
|
|
17
15
|
|
|
18
16
|
const chalk = require('chalk');
|
|
19
17
|
|
|
20
|
-
//
|
|
18
|
+
// Rich color helpers for professional HF display
|
|
21
19
|
const C = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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')('|'),
|
|
36
56
|
};
|
|
37
57
|
|
|
38
58
|
const CONFIG = {
|
|
@@ -76,151 +96,149 @@ class SmartLogsEngine {
|
|
|
76
96
|
setSymbol(s) { this.symbolCode = s; }
|
|
77
97
|
|
|
78
98
|
/**
|
|
79
|
-
* Main entry - returns log
|
|
80
|
-
*
|
|
99
|
+
* Main entry - ALWAYS returns a UNIQUE log showing real-time market state
|
|
100
|
+
* Each message is different based on actual changing market data
|
|
81
101
|
*/
|
|
82
102
|
getLog(state = {}) {
|
|
83
103
|
const sym = getSym(this.symbolCode);
|
|
84
104
|
const price = state.price > 0 ? state.price.toFixed(2) : null;
|
|
85
|
-
const { position = 0, zScore = 0, vpin = 0, ofi = 0, tickCount = 0, bars = 0 } = state;
|
|
105
|
+
const { position = 0, zScore = 0, vpin = 0, ofi = 0, tickCount = 0, bars = 0, delta = 0, buyPct = 50 } = state;
|
|
106
|
+
|
|
107
|
+
// Track price movement for context
|
|
108
|
+
const priceNum = state.price || 0;
|
|
109
|
+
const lastPrice = this._lastPrice || priceNum;
|
|
110
|
+
const priceDiff = priceNum - lastPrice;
|
|
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);
|
|
114
|
+
this._lastPrice = priceNum;
|
|
115
|
+
|
|
116
|
+
// Track tick velocity
|
|
117
|
+
const lastTicks = this._lastTicks || 0;
|
|
118
|
+
const tickVelocity = (tickCount || bars || 0) - lastTicks;
|
|
119
|
+
this._lastTicks = tickCount || bars || 0;
|
|
86
120
|
|
|
87
121
|
// Not enough data - still warming up
|
|
88
|
-
const dataPoints =
|
|
122
|
+
const dataPoints = bars || tickCount || 0;
|
|
89
123
|
if (dataPoints < 50 || !price) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const milestone = Math.floor(pct / 25) * 25;
|
|
94
|
-
const lastMilestone = this._lastWarmupMilestone || 0;
|
|
95
|
-
if (milestone > lastMilestone) {
|
|
96
|
-
this._lastWarmupMilestone = milestone;
|
|
97
|
-
return {
|
|
98
|
-
type: 'system',
|
|
99
|
-
message: `[${C.sym(sym)}] Calibrating QUANT models... ${C.val(pct + '%')} (${dataPoints} samples)`,
|
|
100
|
-
logToSession: false
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Mark as ready
|
|
108
|
-
if (!this.prev.ready) {
|
|
109
|
-
this.prev.ready = true;
|
|
124
|
+
const pct = Math.min(100, Math.round((dataPoints / 50) * 100));
|
|
125
|
+
const remaining = 50 - dataPoints;
|
|
126
|
+
const pctColor = pct < 50 ? C.warn : C.ok;
|
|
110
127
|
return {
|
|
111
128
|
type: 'system',
|
|
112
|
-
message: `[${C.sym(sym)}] ${C.price(price)}
|
|
113
|
-
logToSession:
|
|
129
|
+
message: `[${C.sym(sym)}] ${price ? C.price(price) : C.dim('-.--')} ${C.separator()} ${C.label('Calibrating')} ${pctColor(pct + '%')} ${C.separator()} ${C.val(remaining)} ${C.label('samples to ready')} ${C.separator()} ${C.dim('+' + tickVelocity + '/s')}`,
|
|
130
|
+
logToSession: false
|
|
114
131
|
};
|
|
115
132
|
}
|
|
116
133
|
|
|
117
|
-
//
|
|
134
|
+
// Compute current states with precision for uniqueness
|
|
135
|
+
const absZ = Math.abs(zScore);
|
|
136
|
+
const ofiPct = (ofi * 100).toFixed(0);
|
|
137
|
+
const vpinPct = (vpin * 100).toFixed(0);
|
|
138
|
+
const buyPctRound = Math.round(buyPct || 50);
|
|
139
|
+
const deltaRound = Math.round(delta || 0);
|
|
140
|
+
|
|
141
|
+
// Z-Score color based on level - more vivid
|
|
142
|
+
const zColor = absZ >= CONFIG.Z_EXTREME ? C.valHigh :
|
|
143
|
+
absZ >= CONFIG.Z_HIGH ? C.signal :
|
|
144
|
+
absZ >= CONFIG.Z_BUILDING ? C.zscore : C.muted;
|
|
145
|
+
const zStr = zColor(`${zScore.toFixed(2)}σ`);
|
|
146
|
+
|
|
147
|
+
// OFI color based on direction - more vivid
|
|
148
|
+
const ofiColor = ofi > CONFIG.OFI_STRONG ? C.long :
|
|
149
|
+
ofi > CONFIG.OFI_THRESHOLD ? C.bull :
|
|
150
|
+
ofi < -CONFIG.OFI_STRONG ? C.short :
|
|
151
|
+
ofi < -CONFIG.OFI_THRESHOLD ? C.bear : C.muted;
|
|
152
|
+
const ofiStr = ofiColor(`${ofi >= 0 ? '+' : ''}${ofiPct}%`);
|
|
153
|
+
|
|
154
|
+
// VPIN color based on toxicity - more vivid
|
|
155
|
+
const vpinColor = vpin > CONFIG.VPIN_TOXIC ? C.toxic :
|
|
156
|
+
vpin > CONFIG.VPIN_ELEVATED ? C.warn : C.ok;
|
|
157
|
+
const vpinStr = vpinColor(`${vpinPct}%`);
|
|
158
|
+
|
|
159
|
+
// Delta (buy-sell imbalance) display - more vivid
|
|
160
|
+
const deltaAbs = Math.abs(deltaRound);
|
|
161
|
+
const deltaColor = deltaRound > 50 ? C.long : deltaRound > 0 ? C.bull :
|
|
162
|
+
deltaRound < -50 ? C.short : deltaRound < 0 ? C.bear : C.muted;
|
|
163
|
+
const deltaStr = deltaColor(`${deltaRound > 0 ? '+' : ''}${deltaRound}`);
|
|
164
|
+
|
|
165
|
+
// Buy percentage color
|
|
166
|
+
const buyColor = buyPctRound > 60 ? C.bull : buyPctRound < 40 ? C.bear : C.muted;
|
|
167
|
+
const buyStr = buyColor(`${buyPctRound}%`);
|
|
168
|
+
|
|
169
|
+
// Active position - show position management with unique data
|
|
118
170
|
if (position !== 0) {
|
|
119
171
|
const isLong = position > 0;
|
|
120
|
-
const side = isLong ? C.long('LONG') : C.short('SHORT');
|
|
121
|
-
const
|
|
122
|
-
const flowLabel =
|
|
123
|
-
const
|
|
124
|
-
const
|
|
172
|
+
const side = isLong ? C.long('● LONG') : C.short('● SHORT');
|
|
173
|
+
const flowFavor = (isLong && ofi > 0) || (!isLong && ofi < 0);
|
|
174
|
+
const flowLabel = flowFavor ? C.ok('✓ aligned') : C.warn('⚠ adverse');
|
|
175
|
+
const exitClose = absZ < 0.5;
|
|
176
|
+
const exitInfo = exitClose ? C.warn('⚡ EXIT ZONE') : C.ok('holding');
|
|
125
177
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
type: 'trade',
|
|
132
|
-
message: `[${C.sym(sym)}] ${side} @ ${C.price(price)} | OFI:${ofiStr}% ${flowLabel} | Z:${zStr}σ`,
|
|
133
|
-
logToSession: true
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
return null;
|
|
178
|
+
return {
|
|
179
|
+
type: 'trade',
|
|
180
|
+
message: `[${C.sym(sym)}] ${side} ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${exitInfo} ${C.separator()} ${C.label('Δ:')}${deltaStr} ${C.separator()} ${flowLabel}`,
|
|
181
|
+
logToSession: false
|
|
182
|
+
};
|
|
137
183
|
}
|
|
138
184
|
|
|
139
|
-
//
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
absZ >= CONFIG.Z_HIGH ? 'high' :
|
|
143
|
-
absZ >= CONFIG.Z_BUILDING ? 'building' : 'neutral';
|
|
144
|
-
const ofiDir = ofi > CONFIG.OFI_STRONG ? 'strong-bull' :
|
|
145
|
-
ofi > CONFIG.OFI_THRESHOLD ? 'bull' :
|
|
146
|
-
ofi < -CONFIG.OFI_STRONG ? 'strong-bear' :
|
|
147
|
-
ofi < -CONFIG.OFI_THRESHOLD ? 'bear' : 'neutral';
|
|
148
|
-
const vpinLevel = vpin > CONFIG.VPIN_TOXIC ? 'toxic' :
|
|
149
|
-
vpin > CONFIG.VPIN_ELEVATED ? 'elevated' : 'normal';
|
|
185
|
+
// No position - show WHY we're not entering with unique context each time
|
|
186
|
+
const direction = zScore < 0 ? 'LONG' : 'SHORT';
|
|
187
|
+
const dirColor = zScore < 0 ? C.long : C.short;
|
|
150
188
|
|
|
151
|
-
// Detect events (changes in regime)
|
|
152
|
-
let event = null;
|
|
153
|
-
let message = null;
|
|
154
189
|
let logType = 'analysis';
|
|
190
|
+
let message;
|
|
155
191
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const ofiPct = (ofi * 100).toFixed(0);
|
|
161
|
-
const vpinPct = (vpin * 100).toFixed(0);
|
|
162
|
-
|
|
163
|
-
// EVENT 1: Z-Score regime change (most important)
|
|
164
|
-
if (zRegime !== this.prev.zRegime && this.prev.zRegime !== null) {
|
|
165
|
-
event = 'z_regime';
|
|
166
|
-
const dir = zScore < 0 ? 'LONG' : 'SHORT';
|
|
167
|
-
|
|
168
|
-
if (zRegime === 'extreme') {
|
|
169
|
-
logType = 'signal';
|
|
170
|
-
const ofiConfirm = (zScore < 0 && ofi > CONFIG.OFI_THRESHOLD) ||
|
|
171
|
-
(zScore > 0 && ofi < -CONFIG.OFI_THRESHOLD);
|
|
172
|
-
if (ofiConfirm) {
|
|
173
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | Z:${zStr} ${C.signal('EXTREME')} | ${C.long(dir)} | OFI:${ofiPct}% ${C.ok('CONFIRMS')}`;
|
|
174
|
-
} else {
|
|
175
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | Z:${zStr} ${C.signal('EXTREME')} | ${C.warn(dir + ' pending')} | OFI:${ofiPct}% awaiting`;
|
|
176
|
-
}
|
|
177
|
-
} else if (zRegime === 'high') {
|
|
178
|
-
logType = 'signal';
|
|
179
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | Z:${zStr} ${C.warn('building')} | ${dir} setup forming | OFI:${ofiPct}%`;
|
|
180
|
-
} else if (zRegime === 'building' && this.prev.zRegime === 'neutral') {
|
|
181
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | Z:${zStr} | Deviation detected | Monitoring`;
|
|
182
|
-
} else if (zRegime === 'neutral' && (this.prev.zRegime === 'high' || this.prev.zRegime === 'extreme')) {
|
|
183
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | Z:${C.ok('normalized')} | Mean reversion complete`;
|
|
184
|
-
}
|
|
192
|
+
// VPIN toxic - highest priority blocker
|
|
193
|
+
if (vpin > CONFIG.VPIN_TOXIC) {
|
|
194
|
+
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')}`;
|
|
195
|
+
logType = 'risk';
|
|
185
196
|
}
|
|
186
|
-
//
|
|
187
|
-
else if (
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const nowLong = ofiDir.includes('bull');
|
|
192
|
-
if (wasLong !== nowLong) {
|
|
193
|
-
const arrow = nowLong ? C.bull('▲') : C.bear('▼');
|
|
194
|
-
const newDir = nowLong ? C.bull('BUY') : C.bear('SELL');
|
|
195
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | ${arrow} OFI flip → ${newDir} pressure | ${ofiPct}% | Z:${zStr}`;
|
|
196
|
-
}
|
|
197
|
+
// Z-Score extreme + OFI confirms = SIGNAL
|
|
198
|
+
else if (absZ >= CONFIG.Z_EXTREME &&
|
|
199
|
+
((zScore < 0 && ofi > CONFIG.OFI_THRESHOLD) || (zScore > 0 && ofi < -CONFIG.OFI_THRESHOLD))) {
|
|
200
|
+
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')}`;
|
|
201
|
+
logType = 'signal';
|
|
197
202
|
}
|
|
198
|
-
//
|
|
199
|
-
else if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | VPIN:${C.danger(vpinPct + '% TOXIC')} | Informed flow detected | Hold`;
|
|
204
|
-
} else if (vpinLevel === 'elevated' && this.prev.vpinLevel === 'normal') {
|
|
205
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | VPIN:${C.warn(vpinPct + '%')} elevated | Monitoring toxicity`;
|
|
206
|
-
} else if (vpinLevel === 'normal' && this.prev.vpinLevel === 'toxic') {
|
|
207
|
-
message = `[${C.sym(sym)}] ${C.price(price)} | VPIN:${C.ok(vpinPct + '%')} normalized | Flow clean`;
|
|
208
|
-
}
|
|
203
|
+
// Z-Score extreme but OFI doesn't confirm
|
|
204
|
+
else if (absZ >= CONFIG.Z_EXTREME) {
|
|
205
|
+
const ofiNeed = zScore < 0 ? C.dim('need >15%') : C.dim('need <-15%');
|
|
206
|
+
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')}`;
|
|
207
|
+
logType = 'signal';
|
|
209
208
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
209
|
+
// Z-Score high - setup forming
|
|
210
|
+
else if (absZ >= CONFIG.Z_HIGH) {
|
|
211
|
+
const needed = (CONFIG.Z_EXTREME - absZ).toFixed(2);
|
|
212
|
+
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}`;
|
|
213
|
+
}
|
|
214
|
+
// Z-Score building
|
|
215
|
+
else if (absZ >= CONFIG.Z_BUILDING) {
|
|
216
|
+
const needed = (CONFIG.Z_HIGH - absZ).toFixed(2);
|
|
217
|
+
const bias = zScore < 0 ? C.bull('bid ↑') : C.bear('ask ↓');
|
|
218
|
+
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}`;
|
|
219
|
+
}
|
|
220
|
+
// Z-Score neutral - scanning
|
|
221
|
+
else {
|
|
222
|
+
// Cycle through different useful info each second to avoid repetition
|
|
223
|
+
const infoType = Math.floor(Date.now() / 1000) % 4;
|
|
224
|
+
let context;
|
|
225
|
+
switch (infoType) {
|
|
226
|
+
case 0:
|
|
227
|
+
context = `${C.label('Δ:')}${deltaStr} ${C.separator()} ${C.label('Buy:')}${buyStr}`;
|
|
228
|
+
break;
|
|
229
|
+
case 1:
|
|
230
|
+
context = `${C.label('VPIN:')}${vpinStr} ${C.separator()} ${C.label('OFI:')}${ofiStr}`;
|
|
231
|
+
break;
|
|
232
|
+
case 2:
|
|
233
|
+
context = `${C.val(tickVelocity)} ${C.label('ticks/s')} ${C.separator()} ${C.label('Δ:')}${deltaStr}`;
|
|
234
|
+
break;
|
|
235
|
+
default:
|
|
236
|
+
context = `${C.label('OFI:')}${ofiStr} ${C.separator()} ${C.label('Buy:')}${buyStr}`;
|
|
237
|
+
}
|
|
238
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${priceDisplay} ${C.separator()} ${C.label('Z:')}${zStr} ${C.muted('scanning')} ${C.separator()} ${context}`;
|
|
221
239
|
}
|
|
222
240
|
|
|
223
|
-
return
|
|
241
|
+
return { type: logType, message, logToSession: logType === 'signal' };
|
|
224
242
|
}
|
|
225
243
|
|
|
226
244
|
reset() {
|