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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.9.231",
3
+ "version": "2.9.232",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -1,16 +1,14 @@
1
1
  /**
2
- * Smart Logs Engine - Professional HF-Grade Adaptive Logs
3
- * ========================================================
2
+ * Smart Logs Engine - Professional HF-Grade Real-Time Logs
3
+ * =========================================================
4
4
  *
5
- * PRINCIPLES:
6
- * 1. NO repetitive messages - each log must be unique and meaningful
7
- * 2. Adaptive to real market context - uses actual QUANT metrics
8
- * 3. Professional HF language - precise, technical, actionable
9
- * 4. Event-driven only - silence means scanning, no spam
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
- * This replaces the old rotating generic messages with
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 only when meaningful event occurs
80
- * Returns null for silence (professional: no news = scanning)
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 = tickCount || bars || 0;
99
+ const dataPoints = bars || tickCount || 0;
89
100
  if (dataPoints < 50 || !price) {
90
- // Only log warmup progress at milestones
91
- if (!this.prev.ready && dataPoints > 0) {
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.ok('QUANT models calibrated')} | Scanning for alpha`,
113
- logToSession: true
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
- // Active position - always show
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 deltaFavor = (isLong && ofi > 0) || (!isLong && ofi < 0);
122
- const flowLabel = deltaFavor ? C.ok('ALIGNED') : C.warn('ADVERSE');
123
- const ofiStr = (ofi * 100).toFixed(0);
124
- const zStr = zScore.toFixed(2);
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
- // Only log position updates when something changes
127
- const posHash = `pos-${position}-${Math.round(ofi * 10)}`;
128
- if (posHash !== this.lastLogHash) {
129
- this.lastLogHash = posHash;
130
- return {
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
- // Compute current regimes
140
- const absZ = Math.abs(zScore);
141
- const zRegime = absZ >= CONFIG.Z_EXTREME ? 'extreme' :
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
- const zColor = absZ >= CONFIG.Z_EXTREME ? C.valHigh :
157
- absZ >= CONFIG.Z_HIGH ? C.warn :
158
- absZ >= CONFIG.Z_BUILDING ? C.val : C.dim;
159
- const zStr = zColor(`${zScore.toFixed(2)}σ`);
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
- // EVENT 2: OFI direction flip (significant)
187
- else if (ofiDir !== this.prev.ofiDir && this.prev.ofiDir !== null &&
188
- ofiDir !== 'neutral' && this.prev.ofiDir !== 'neutral') {
189
- event = 'ofi_flip';
190
- const wasLong = this.prev.ofiDir.includes('bull');
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
- // EVENT 3: VPIN level change (toxicity warning)
199
- else if (vpinLevel !== this.prev.vpinLevel && this.prev.vpinLevel !== null) {
200
- event = 'vpin_change';
201
- if (vpinLevel === 'toxic') {
202
- logType = 'risk';
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
- // Update state tracking
212
- this.prev.zRegime = zRegime;
213
- this.prev.ofiDir = ofiDir;
214
- this.prev.vpinLevel = vpinLevel;
215
- this.prev.position = position;
216
-
217
- // Return event or null (silence = professional scanning)
218
- if (event && message) {
219
- this.lastLogHash = `${event}-${zRegime}-${ofiDir}-${vpinLevel}`;
220
- return { type: logType, message, logToSession: logType === 'signal' || logType === 'risk' };
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 null;
209
+ return { type: logType, message, logToSession: logType === 'signal' };
224
210
  }
225
211
 
226
212
  reset() {