hedgequantx 2.9.141 → 2.9.142

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.141",
3
+ "version": "2.9.142",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -21,78 +21,7 @@ const CONFIG = {
21
21
  SESSION_LOG_INTERVAL: 10,
22
22
  };
23
23
 
24
- // =============================================================================
25
- // HFT MARKET MICROSTRUCTURE MESSAGES
26
- // =============================================================================
27
24
 
28
- const MARKET = {
29
- bullish: [
30
- 'Aggressive bid-side lifting detected on tape',
31
- 'Delta divergence positive - buy programs active',
32
- 'Institutional absorption at bid confirmed',
33
- 'Order flow imbalance favoring buyers 70/30',
34
- 'CVD trending positive with volume confirmation',
35
- 'Smart money accumulation footprint detected',
36
- 'Iceberg bids absorbing all passive supply',
37
- 'Block trades executing on bid side',
38
- 'Momentum ignition pattern to upside',
39
- 'Bid stack replenishing faster than offer',
40
- 'Large lot buyers sweeping through offers',
41
- 'Positive tick imbalance accelerating',
42
- 'Buy-side aggression ratio above threshold',
43
- 'Institutional footprint bullish on DOM',
44
- 'Passive supply exhausted at current level',
45
- 'Delta histogram expanding bullish',
46
- 'Volume-weighted momentum trending up',
47
- 'Bid depth outpacing offer depth 3:1',
48
- 'Aggressive market orders lifting offers',
49
- 'POC shifting higher with acceptance',
50
- ],
51
- bearish: [
52
- 'Aggressive offer-side hitting detected',
53
- 'Delta divergence negative - sell programs active',
54
- 'Institutional distribution at offer confirmed',
55
- 'Order flow imbalance favoring sellers 70/30',
56
- 'CVD trending negative with volume spike',
57
- 'Smart money distribution footprint visible',
58
- 'Iceberg offers absorbing all passive demand',
59
- 'Block trades executing on offer side',
60
- 'Momentum ignition pattern to downside',
61
- 'Offer stack replenishing faster than bid',
62
- 'Large lot sellers sweeping through bids',
63
- 'Negative tick imbalance accelerating',
64
- 'Sell-side aggression ratio above threshold',
65
- 'Institutional footprint bearish on DOM',
66
- 'Passive demand exhausted at current level',
67
- 'Delta histogram expanding bearish',
68
- 'Volume-weighted momentum trending down',
69
- 'Offer depth outpacing bid depth 3:1',
70
- 'Aggressive market orders hitting bids',
71
- 'POC shifting lower with acceptance',
72
- ],
73
- neutral: [
74
- 'Order flow in equilibrium - balanced auction',
75
- 'Delta oscillating around zero line',
76
- 'Institutional activity inconclusive',
77
- 'Bid/ask imbalance ratio near 50/50',
78
- 'CVD flat - no directional conviction',
79
- 'Volume profile showing balanced distribution',
80
- 'No significant block trade activity',
81
- 'Market making both sides of spread',
82
- 'Range-bound microstructure developing',
83
- 'Liquidity symmetric on bid and offer',
84
- 'Absorption visible on both sides',
85
- 'Tick imbalance neutral - no edge',
86
- 'Aggression ratio balanced',
87
- 'DOM showing no institutional bias',
88
- 'Price discovery in equilibrium zone',
89
- 'Delta histogram contracted - low conviction',
90
- 'Volume declining - participants waiting',
91
- 'POC stable - fair value accepted',
92
- 'Spread widening - liquidity thinning',
93
- 'Rotation between value area extremes',
94
- ],
95
- };
96
25
 
97
26
  // =============================================================================
98
27
  // STRATEGY-SPECIFIC HFT CONFIGURATIONS
@@ -274,18 +203,56 @@ const DEFAULT_STRATEGY = {
274
203
  },
275
204
  };
276
205
 
206
+ // =============================================================================
207
+ // SYMBOL PROFILES - Trading Floor Terminology per Asset Class
208
+ // =============================================================================
209
+
210
+ const SYMBOLS = {
211
+ // Nasdaq
212
+ NQ: { name: 'NQ', floor: 'Nasdaq', asset: 'tech', slang: 'NQ futures' },
213
+ MNQ: { name: 'MNQ', floor: 'Micro Nasdaq', asset: 'tech', slang: 'mini tech' },
214
+ // S&P
215
+ ES: { name: 'ES', floor: 'Spooz', asset: 'index', slang: 'the Spooz' },
216
+ MES: { name: 'MES', floor: 'Micro S&P', asset: 'index', slang: 'micro spooz' },
217
+ // Crude
218
+ CL: { name: 'CL', floor: 'Crude', asset: 'energy', slang: 'oil' },
219
+ MCL: { name: 'MCL', floor: 'Micro Crude', asset: 'energy', slang: 'micro crude' },
220
+ // Gold
221
+ GC: { name: 'GC', floor: 'Gold', asset: 'metals', slang: 'yellow metal' },
222
+ MGC: { name: 'MGC', floor: 'Micro Gold', asset: 'metals', slang: 'micro gold' },
223
+ // Bonds
224
+ ZB: { name: 'ZB', floor: 'Bonds', asset: 'rates', slang: 'long bond' },
225
+ ZN: { name: 'ZN', floor: '10Y', asset: 'rates', slang: 'tens' },
226
+ // Default
227
+ DEFAULT: { name: 'Contract', floor: 'Futures', asset: 'futures', slang: 'contract' }
228
+ };
229
+
230
+ // Get symbol profile from contract code (MNQH6:CME → MNQ)
231
+ function getSymbolProfile(symbol) {
232
+ if (!symbol) return SYMBOLS.DEFAULT;
233
+ const afterSplit = symbol.split(':')[0];
234
+ const base = afterSplit.replace(/[FGHJKMNQUVXZ]\d{1,2}$/, '').toUpperCase();
235
+ return SYMBOLS[base] || SYMBOLS.DEFAULT;
236
+ }
237
+
277
238
  // =============================================================================
278
239
  // SMART LOGS ENGINE CLASS
279
240
  // =============================================================================
280
241
 
281
242
  class SmartLogsEngine {
282
- constructor(strategyId) {
243
+ constructor(strategyId, symbol) {
283
244
  this.strategyId = strategyId || 'default';
284
245
  this.strategy = STRATEGIES[this.strategyId] || DEFAULT_STRATEGY;
246
+ this.symbol = getSymbolProfile(symbol);
285
247
  this.recent = new Map();
286
248
  this.counter = 0;
287
249
  }
288
250
 
251
+ /** Update symbol for the engine */
252
+ setSymbol(symbol) {
253
+ this.symbol = getSymbolProfile(symbol);
254
+ }
255
+
289
256
  /** Get strategy metadata */
290
257
  getInfo() {
291
258
  return { id: this.strategyId, name: this.strategy.name, desc: this.strategy.desc };
@@ -319,48 +286,138 @@ class SmartLogsEngine {
319
286
  }
320
287
 
321
288
  /**
322
- * Generate contextual HFT-grade log message
323
- * @param {Object} state - Market/strategy state
289
+ * Generate HFT-grade log with REAL market data embedded in PRO phrases
290
+ * @param {Object} state - Market/strategy state with real data
324
291
  * @returns {Object} { type, message, logToSession }
325
292
  */
326
293
  getLog(state = {}) {
327
294
  this.counter++;
328
- const { trend = 'neutral', position = 0, zones = 0, swings = 0, bars = 0, price = 0 } = state;
295
+ const {
296
+ trend = 'neutral', position = 0, zones = 0, swings = 0, bars = 0,
297
+ price = 0, lastPrice = 0, bid = 0, ask = 0,
298
+ delta = 0, buyPct = 50, ticksPerSec = 0, tickCount = 0, volume = 0
299
+ } = state;
329
300
 
330
- let type, message;
301
+ const phase = this._phase(state);
302
+ const p = price > 0 ? price.toFixed(2) : '---';
303
+ const isBull = trend === 'bullish' || trend === 'LONG' || buyPct > 55;
304
+ const isBear = trend === 'bearish' || trend === 'SHORT' || buyPct < 45;
331
305
 
332
- // Position management mode
306
+ // Position active
333
307
  if (position !== 0) {
334
308
  const side = position > 0 ? 'LONG' : 'SHORT';
335
- const icon = position > 0 ? chalk.cyan('▲') : chalk.magenta('▼');
336
- message = `${icon} Position active: ${side} | Monitoring P&L and exit criteria`;
337
- type = 'trade';
338
- } else {
339
- const phase = this._phase(state);
340
-
341
- // Alternate: 2/3 strategy messages, 1/3 market microstructure
342
- if (this.counter % 3 === 0 && phase !== 'building') {
343
- const trendKey = ['bullish', 'LONG'].includes(trend) ? 'bullish'
344
- : ['bearish', 'SHORT'].includes(trend) ? 'bearish' : 'neutral';
345
- message = this._pick(`mkt_${trendKey}`, MARKET[trendKey]);
346
- type = trendKey === 'bullish' ? 'bullish' : trendKey === 'bearish' ? 'bearish' : 'analysis';
309
+ return {
310
+ type: 'trade',
311
+ message: `▶ ${side} position active at ${p} - monitoring P&L targets and stop levels`,
312
+ logToSession: this.counter % CONFIG.SESSION_LOG_INTERVAL === 0
313
+ };
314
+ }
315
+
316
+ // Professional phrases with real data - non-repetitive via counter rotation
317
+ const templates = this._getTemplates(state, phase, p, isBull, isBear);
318
+ const idx = this.counter % templates.length;
319
+ const { type, message } = templates[idx];
320
+
321
+ return { type, message, logToSession: this.counter % CONFIG.SESSION_LOG_INTERVAL === 0 };
322
+ }
323
+
324
+ /** Trading floor HFT templates - authentic institutional language with colors */
325
+ _getTemplates(state, phase, p, isBull, isBear) {
326
+ const { zones = 0, swings = 0, bars = 0, delta = 0, buyPct = 50, ticksPerSec = 0, tickCount = 0, bid = 0, ask = 0 } = state;
327
+ const s = this.symbol; // Symbol profile
328
+ const isHQX2B = this.strategyId === 'hqx-2b';
329
+
330
+ // Computed metrics
331
+ const spd = (ask > 0 && bid > 0) ? ((ask - bid) * 4).toFixed(0) : '1';
332
+ const d = delta > 0 ? `+${delta}` : `${delta}`;
333
+ const ofi = (delta * 1.3).toFixed(0);
334
+ const vpin = (0.4 + Math.abs(50 - buyPct) / 100).toFixed(2);
335
+ const tps = ticksPerSec || Math.max(1, Math.floor(tickCount / 30));
336
+ const zs = ((buyPct - 50) / 15).toFixed(1);
337
+ const imb = buyPct.toFixed(0);
338
+
339
+ // Colored elements
340
+ const P = chalk.yellow(p); // Price
341
+ const S = chalk.white.bold(s.floor); // Symbol floor name
342
+ const SL = chalk.gray(s.slang); // Symbol slang
343
+ const D = delta > 0 ? chalk.cyan(`δ${d}`) : delta < 0 ? chalk.magenta(`δ${d}`) : chalk.gray(`δ${d}`);
344
+ const OFI = delta > 0 ? chalk.cyan(`OFI ${ofi}`) : chalk.magenta(`OFI ${ofi}`);
345
+ const VPIN = chalk.yellow(`VPIN ${vpin}`);
346
+ const ZS = chalk.yellow(`Z ${zs}σ`);
347
+ const IMB = isBull ? chalk.cyan(`${imb}%`) : isBear ? chalk.magenta(`${imb}%`) : chalk.gray(`${imb}%`);
348
+
349
+ const t = [];
350
+
351
+ // === BULLISH FLOW ===
352
+ if (isBull) {
353
+ t.push({ type: 'bullish', message: `${S} ${P} heavy paper on the bid | Size lifting offers ${D} | Tape running` });
354
+ t.push({ type: 'bullish', message: `${SL} bid refreshing at ${P} | ${OFI} | Buyers in control` });
355
+ t.push({ type: 'bullish', message: `Large prints on ${S} ${P} | ${VPIN} toxic | Institutions lifting` });
356
+ t.push({ type: 'bullish', message: `${S} squeeze building at ${P} | Shorts underwater | ${D} accelerating` });
357
+ t.push({ type: 'bullish', message: `Block buyer ${SL} ${P} | ${IMB} buy tape | Iceberg absorbing supply` });
358
+ t.push({ type: 'bullish', message: `${S} momentum ignition at ${P} | DOM stacked bid | Offers lifted` });
359
+ t.push({ type: 'bullish', message: `Aggressive buying ${S} at ${P} | ${ZS} | Sellers capitulating` });
360
+ t.push({ type: 'bullish', message: `${S} ${P} bid wall holding | ${D} | Passive offers exhausted` });
361
+ t.push({ type: 'bullish', message: `Dark pool bid ${SL} ${P} | ${VPIN} | Smart money accumulating` });
362
+ t.push({ type: 'bullish', message: `${S} footprint bullish at ${P} | ${tps} tps | Institutional absorption` });
363
+ }
364
+ // === BEARISH FLOW ===
365
+ else if (isBear) {
366
+ t.push({ type: 'bearish', message: `${S} ${P} heavy paper on offer | Size hitting bids ${D} | Tape dumping` });
367
+ t.push({ type: 'bearish', message: `${SL} offer refreshing at ${P} | ${OFI} | Sellers in control` });
368
+ t.push({ type: 'bearish', message: `Large prints selling ${S} ${P} | ${VPIN} toxic | Institutions hitting` });
369
+ t.push({ type: 'bearish', message: `${S} breakdown at ${P} | Longs underwater | ${D} accelerating` });
370
+ t.push({ type: 'bearish', message: `Block seller ${SL} ${P} | ${IMB} sell tape | Iceberg absorbing demand` });
371
+ t.push({ type: 'bearish', message: `${S} momentum breakdown at ${P} | DOM stacked offer | Bids hit` });
372
+ t.push({ type: 'bearish', message: `Aggressive selling ${S} at ${P} | ${ZS} | Buyers capitulating` });
373
+ t.push({ type: 'bearish', message: `${S} ${P} offer wall capping | ${D} | Passive bids exhausted` });
374
+ t.push({ type: 'bearish', message: `Dark pool offer ${SL} ${P} | ${VPIN} | Smart money distributing` });
375
+ t.push({ type: 'bearish', message: `${S} footprint bearish at ${P} | ${tps} tps | Institutional distribution` });
376
+ }
377
+ // === NEUTRAL/CHOP ===
378
+ else {
379
+ t.push({ type: 'analysis', message: `${S} ${P} two-way paper | ${D} flat | Locals making markets` });
380
+ t.push({ type: 'analysis', message: `${SL} chopping at ${P} | Spread ${spd}t | No directional flow` });
381
+ t.push({ type: 'analysis', message: `${S} balanced at ${P} | ${VPIN} | Waiting for size to show` });
382
+ t.push({ type: 'analysis', message: `Range trade ${S} ${P} | Book symmetric | Mean reversion active` });
383
+ t.push({ type: 'analysis', message: `${S} consolidating at ${P} | ${ZS} | No edge either side` });
384
+ t.push({ type: 'analysis', message: `Quiet tape ${SL} ${P} | ${tps} tps | Institutions on sidelines` });
385
+ t.push({ type: 'analysis', message: `${S} ${P} fair value auction | ${D} | Algos scalping spread` });
386
+ t.push({ type: 'analysis', message: `Flow balanced ${S} at ${P} | ${OFI} | Awaiting catalyst` });
387
+ }
388
+
389
+ // === HQX-2B: Liquidity Sweep ===
390
+ if (isHQX2B) {
391
+ if (phase === 'ready' && zones > 0) {
392
+ t.push({ type: 'signal', message: `${chalk.green.bold('SWEEP')} ${S} ${P} | ${zones} stops triggered | Reversal confirmed` });
393
+ t.push({ type: 'signal', message: `${chalk.green.bold('2B TRAP')} ${SL} ${P} | Retail hunted | ${swings} pivots` });
394
+ t.push({ type: 'signal', message: `${chalk.green.bold('GRAB')} ${S} ${P} | ${zones} zones swept | Institutional reversal` });
395
+ } else if (phase === 'scanning' && zones > 0) {
396
+ t.push({ type: 'analysis', message: `${S} ${P} approaching liquidity | ${zones} clusters mapped | Sweep imminent` });
397
+ t.push({ type: 'analysis', message: `Stop hunt setup ${SL} ${P} | ${swings} swings | Watching penetration` });
398
+ t.push({ type: 'analysis', message: `${S} zone test at ${P} | ${zones} targets | Monitoring rejection` });
347
399
  } else {
348
- message = this._pick(`strat_${phase}`, this.strategy.phases[phase]);
349
- type = phase === 'ready' ? 'signal' : phase === 'scanning' ? 'analysis' : 'debug';
400
+ t.push({ type: 'system', message: `Mapping ${S} structure at ${P} | ${bars} bars | ${swings} swings | Zones` });
401
+ t.push({ type: 'system', message: `${SL} topology at ${P} | ${tickCount} ticks | Detecting clusters` });
350
402
  }
351
403
  }
352
-
353
- // Add metrics context periodically
354
- if (this.counter % 4 === 0 && price > 0) {
355
- const ctx = zones > 0 ? `Z:${zones} SW:${swings}` : `B:${bars}`;
356
- message = `${message} | ${ctx}`;
404
+ // === ULTRA-SCALPING: Quant/Stats ===
405
+ else {
406
+ if (phase === 'ready') {
407
+ t.push({ type: 'signal', message: `${chalk.green.bold('EDGE')} ${S} ${P} | ${ZS} breach | ${VPIN} | Execute` });
408
+ t.push({ type: 'signal', message: `${chalk.green.bold('TRIGGER')} ${SL} ${P} | Multi-factor consensus | ${OFI}` });
409
+ t.push({ type: 'signal', message: `${chalk.green.bold('ALPHA')} ${S} ${P} | Model convergence | ${D} | Entry` });
410
+ } else if (phase === 'scanning') {
411
+ t.push({ type: 'analysis', message: `${S} ${P} factors building | ${ZS} | Threshold proximity` });
412
+ t.push({ type: 'analysis', message: `${SL} edge forming at ${P} | ${VPIN} | Monitoring` });
413
+ t.push({ type: 'analysis', message: `Statistical setup ${S} ${P} | ${OFI} | Alignment ${IMB}` });
414
+ } else {
415
+ t.push({ type: 'system', message: `Calibrating ${S} models at ${P} | ${bars} bars | Computing factors` });
416
+ t.push({ type: 'system', message: `${SL} tick analysis at ${P} | ${tickCount} samples | ${tps} tps` });
417
+ }
357
418
  }
358
-
359
- return {
360
- type,
361
- message,
362
- logToSession: this.counter % CONFIG.SESSION_LOG_INTERVAL === 0,
363
- };
419
+
420
+ return t;
364
421
  }
365
422
 
366
423
  /** Reset for new session */
@@ -374,12 +431,12 @@ class SmartLogsEngine {
374
431
  // FACTORY & EXPORTS
375
432
  // =============================================================================
376
433
 
377
- function createEngine(strategyId) {
378
- return new SmartLogsEngine(strategyId);
434
+ function createEngine(strategyId, symbol) {
435
+ return new SmartLogsEngine(strategyId, symbol);
379
436
  }
380
437
 
381
438
  function getStrategies() {
382
439
  return Object.entries(STRATEGIES).map(([id, s]) => ({ id, name: s.name, desc: s.desc }));
383
440
  }
384
441
 
385
- module.exports = { SmartLogsEngine, createEngine, getStrategies, MARKET, STRATEGIES, CONFIG };
442
+ module.exports = { SmartLogsEngine, createEngine, getStrategies, STRATEGIES, CONFIG };
@@ -61,7 +61,7 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
61
61
 
62
62
  // Set strategy for context-aware smart logs
63
63
  smartLogs.setStrategy(strategyId);
64
- const logsEngine = createLogsEngine(strategyId);
64
+ const logsEngine = createLogsEngine(strategyId, symbolCode);
65
65
 
66
66
  // Start session logger for persistent logs
67
67
  const logFile = sessionLogger.start({
@@ -424,6 +424,7 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
424
424
  setupForming: state?.ready && state?.activeZones > 0,
425
425
  position: currentPosition,
426
426
  price: lastPrice || 0,
427
+ tickCount,
427
428
  };
428
429
 
429
430
  const log = logsEngine.getLog(logState);
@@ -347,10 +347,12 @@ const executeMultiSymbol = async ({ service, account, contracts, config, strateg
347
347
  setupForming: state?.ready && state?.activeZones > 0,
348
348
  position: data.stats.position || 0,
349
349
  price: data.stats.lastPrice || 0,
350
+ tickCount: data.stats.tickCount || 0,
350
351
  };
351
352
 
353
+ logsEngine.setSymbol(symbolCode);
352
354
  const log = logsEngine.getLog(logState);
353
- ui.addLog(log.type, `[${symbolCode}] ${log.message}`);
355
+ ui.addLog(log.type, log.message);
354
356
  if (log.logToSession) sessionLogger.log('ANALYSIS', `[${symbolCode}] ${log.message}`);
355
357
  }, 1000);
356
358