hedgequantx 2.9.231 → 2.9.232
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 +115 -129
package/package.json
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
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';
|
|
@@ -76,151 +74,139 @@ class SmartLogsEngine {
|
|
|
76
74
|
setSymbol(s) { this.symbolCode = s; }
|
|
77
75
|
|
|
78
76
|
/**
|
|
79
|
-
* Main entry - returns log
|
|
80
|
-
*
|
|
77
|
+
* Main entry - ALWAYS returns a UNIQUE log showing real-time market state
|
|
78
|
+
* Each message is different based on actual changing market data
|
|
81
79
|
*/
|
|
82
80
|
getLog(state = {}) {
|
|
83
81
|
const sym = getSym(this.symbolCode);
|
|
84
82
|
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;
|
|
83
|
+
const { position = 0, zScore = 0, vpin = 0, ofi = 0, tickCount = 0, bars = 0, delta = 0, buyPct = 50 } = state;
|
|
84
|
+
|
|
85
|
+
// Track price movement for context
|
|
86
|
+
const priceNum = state.price || 0;
|
|
87
|
+
const lastPrice = this._lastPrice || priceNum;
|
|
88
|
+
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.dim;
|
|
91
|
+
this._lastPrice = priceNum;
|
|
92
|
+
|
|
93
|
+
// Track tick velocity
|
|
94
|
+
const lastTicks = this._lastTicks || 0;
|
|
95
|
+
const tickVelocity = (tickCount || bars || 0) - lastTicks;
|
|
96
|
+
this._lastTicks = tickCount || bars || 0;
|
|
86
97
|
|
|
87
98
|
// Not enough data - still warming up
|
|
88
|
-
const dataPoints =
|
|
99
|
+
const dataPoints = bars || tickCount || 0;
|
|
89
100
|
if (dataPoints < 50 || !price) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const pct = Math.min(100, Math.round((dataPoints / 50) * 100));
|
|
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;
|
|
101
|
+
const pct = Math.min(100, Math.round((dataPoints / 50) * 100));
|
|
102
|
+
const remaining = 50 - dataPoints;
|
|
110
103
|
return {
|
|
111
104
|
type: 'system',
|
|
112
|
-
message: `[${C.sym(sym)}] ${C.price(price)} | ${C.
|
|
113
|
-
logToSession:
|
|
105
|
+
message: `[${C.sym(sym)}] ${price ? C.price(price) : '-.--'} | Calibrating ${C.val(pct + '%')} | ${remaining} samples to ready | +${tickVelocity}/s`,
|
|
106
|
+
logToSession: false
|
|
114
107
|
};
|
|
115
108
|
}
|
|
116
109
|
|
|
117
|
-
//
|
|
110
|
+
// Compute current states with precision for uniqueness
|
|
111
|
+
const absZ = Math.abs(zScore);
|
|
112
|
+
const ofiPct = (ofi * 100).toFixed(0);
|
|
113
|
+
const vpinPct = (vpin * 100).toFixed(0);
|
|
114
|
+
const buyPctRound = Math.round(buyPct || 50);
|
|
115
|
+
const deltaRound = Math.round(delta || 0);
|
|
116
|
+
|
|
117
|
+
// Z-Score color based on level
|
|
118
|
+
const zColor = absZ >= CONFIG.Z_EXTREME ? C.valHigh :
|
|
119
|
+
absZ >= CONFIG.Z_HIGH ? C.warn :
|
|
120
|
+
absZ >= CONFIG.Z_BUILDING ? C.val : C.dim;
|
|
121
|
+
const zStr = zColor(`${zScore.toFixed(2)}σ`);
|
|
122
|
+
|
|
123
|
+
// OFI color based on direction
|
|
124
|
+
const ofiColor = ofi > CONFIG.OFI_THRESHOLD ? C.bull :
|
|
125
|
+
ofi < -CONFIG.OFI_THRESHOLD ? C.bear : C.dim;
|
|
126
|
+
const ofiStr = ofiColor(`${ofi >= 0 ? '+' : ''}${ofiPct}%`);
|
|
127
|
+
|
|
128
|
+
// VPIN color based on toxicity
|
|
129
|
+
const vpinColor = vpin > CONFIG.VPIN_TOXIC ? C.danger :
|
|
130
|
+
vpin > CONFIG.VPIN_ELEVATED ? C.warn : C.ok;
|
|
131
|
+
const vpinStr = vpinColor(`${vpinPct}%`);
|
|
132
|
+
|
|
133
|
+
// Delta (buy-sell imbalance) display
|
|
134
|
+
const deltaColor = deltaRound > 0 ? C.bull : deltaRound < 0 ? C.bear : C.dim;
|
|
135
|
+
const deltaStr = deltaColor(`${deltaRound > 0 ? '+' : ''}${deltaRound}`);
|
|
136
|
+
|
|
137
|
+
// Active position - show position management with unique data
|
|
118
138
|
if (position !== 0) {
|
|
119
139
|
const isLong = position > 0;
|
|
120
140
|
const side = isLong ? C.long('LONG') : C.short('SHORT');
|
|
121
|
-
const
|
|
122
|
-
const flowLabel =
|
|
123
|
-
const
|
|
124
|
-
const
|
|
141
|
+
const flowFavor = (isLong && ofi > 0) || (!isLong && ofi < 0);
|
|
142
|
+
const flowLabel = flowFavor ? C.ok('aligned') : C.warn('adverse');
|
|
143
|
+
const exitClose = absZ < 0.5;
|
|
144
|
+
const exitInfo = exitClose ? C.warn('EXIT ZONE') : 'holding';
|
|
125
145
|
|
|
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;
|
|
146
|
+
return {
|
|
147
|
+
type: 'trade',
|
|
148
|
+
message: `[${C.sym(sym)}] ${side} ${priceDirColor(priceDir)} ${C.price(price)} | Z:${zStr} ${exitInfo} | Δ:${deltaStr} | Flow:${flowLabel}`,
|
|
149
|
+
logToSession: false
|
|
150
|
+
};
|
|
137
151
|
}
|
|
138
152
|
|
|
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';
|
|
153
|
+
// No position - show WHY we're not entering with unique context each time
|
|
154
|
+
const direction = zScore < 0 ? 'LONG' : 'SHORT';
|
|
155
|
+
const dirColor = zScore < 0 ? C.long : C.short;
|
|
150
156
|
|
|
151
|
-
// Detect events (changes in regime)
|
|
152
|
-
let event = null;
|
|
153
|
-
let message = null;
|
|
154
157
|
let logType = 'analysis';
|
|
158
|
+
let message;
|
|
155
159
|
|
|
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
|
-
}
|
|
160
|
+
// VPIN toxic - highest priority blocker
|
|
161
|
+
if (vpin > CONFIG.VPIN_TOXIC) {
|
|
162
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.price(price)} | VPIN:${vpinStr} ${C.danger('TOXIC')} | Z:${zStr} | Δ:${deltaStr} | Hold`;
|
|
163
|
+
logType = 'risk';
|
|
185
164
|
}
|
|
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
|
-
}
|
|
165
|
+
// Z-Score extreme + OFI confirms = SIGNAL
|
|
166
|
+
else if (absZ >= CONFIG.Z_EXTREME &&
|
|
167
|
+
((zScore < 0 && ofi > CONFIG.OFI_THRESHOLD) || (zScore > 0 && ofi < -CONFIG.OFI_THRESHOLD))) {
|
|
168
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.price(price)} | Z:${zStr} ${C.signal('EXTREME')} | OFI:${ofiStr} ${C.ok('✓')} | ${dirColor(direction)} SIGNAL`;
|
|
169
|
+
logType = 'signal';
|
|
197
170
|
}
|
|
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
|
-
}
|
|
171
|
+
// Z-Score extreme but OFI doesn't confirm
|
|
172
|
+
else if (absZ >= CONFIG.Z_EXTREME) {
|
|
173
|
+
const ofiNeed = zScore < 0 ? `need >${15}%` : `need <-${15}%`;
|
|
174
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.price(price)} | Z:${zStr} ${C.signal('!')} | OFI:${ofiStr} ${ofiNeed} | ${C.warn('pending')}`;
|
|
175
|
+
logType = 'signal';
|
|
209
176
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
177
|
+
// Z-Score high - setup forming
|
|
178
|
+
else if (absZ >= CONFIG.Z_HIGH) {
|
|
179
|
+
const needed = (CONFIG.Z_EXTREME - absZ).toFixed(2);
|
|
180
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.price(price)} | Z:${zStr} +${needed}σ to signal | OFI:${ofiStr} | Δ:${deltaStr}`;
|
|
181
|
+
}
|
|
182
|
+
// Z-Score building
|
|
183
|
+
else if (absZ >= CONFIG.Z_BUILDING) {
|
|
184
|
+
const needed = (CONFIG.Z_HIGH - absZ).toFixed(2);
|
|
185
|
+
const bias = zScore < 0 ? 'bid' : 'ask';
|
|
186
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.price(price)} | Z:${zStr} ${bias} pressure | +${needed}σ to setup | Δ:${deltaStr}`;
|
|
187
|
+
}
|
|
188
|
+
// Z-Score neutral - scanning
|
|
189
|
+
else {
|
|
190
|
+
// Cycle through different useful info each second to avoid repetition
|
|
191
|
+
const infoType = Math.floor(Date.now() / 1000) % 4;
|
|
192
|
+
let context;
|
|
193
|
+
switch (infoType) {
|
|
194
|
+
case 0:
|
|
195
|
+
context = `Δ:${deltaStr} | Buy:${buyPctRound}%`;
|
|
196
|
+
break;
|
|
197
|
+
case 1:
|
|
198
|
+
context = `VPIN:${vpinStr} | OFI:${ofiStr}`;
|
|
199
|
+
break;
|
|
200
|
+
case 2:
|
|
201
|
+
context = `${tickVelocity} ticks/s | Δ:${deltaStr}`;
|
|
202
|
+
break;
|
|
203
|
+
default:
|
|
204
|
+
context = `OFI:${ofiStr} | Buy:${buyPctRound}%`;
|
|
205
|
+
}
|
|
206
|
+
message = `[${C.sym(sym)}] ${priceDirColor(priceDir)} ${C.price(price)} | Z:${zStr} scanning | ${context}`;
|
|
221
207
|
}
|
|
222
208
|
|
|
223
|
-
return
|
|
209
|
+
return { type: logType, message, logToSession: logType === 'signal' };
|
|
224
210
|
}
|
|
225
211
|
|
|
226
212
|
reset() {
|