hedgequantx 2.6.58 → 2.6.59

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.6.58",
3
+ "version": "2.6.59",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -315,68 +315,53 @@ const launchAlgo = async (service, account, contract, config) => {
315
315
 
316
316
  positionManager.start();
317
317
 
318
- // Listen for position manager events
318
+ // Listen for position manager events - CLEAN LOGS (no verbose order status)
319
319
  positionManager.on('entryFilled', ({ orderTag, position, fillLatencyMs }) => {
320
320
  stats.entryLatencies.push(fillLatencyMs);
321
321
  stats.avgFillLatency = stats.entryLatencies.reduce((a, b) => a + b, 0) / stats.entryLatencies.length;
322
- algoLogger.info(ui, 'FAST FILL', `${fillLatencyMs}ms | avg=${stats.avgFillLatency.toFixed(1)}ms`);
322
+ const side = position.side === 0 ? 'LONG' : 'SHORT';
323
+ algoLogger.info(ui, 'FILLED', `${side} ${position.size}x ${symbolName} @ ${position.entryPrice} | ${fillLatencyMs}ms`);
323
324
  });
324
325
 
325
326
  positionManager.on('exitFilled', ({ orderTag, exitPrice, pnlTicks, holdDurationMs }) => {
327
+ const holdSec = (holdDurationMs / 1000).toFixed(1);
326
328
  // Calculate PnL in dollars only if tickValue is available from API
327
329
  if (pnlTicks !== null && tickValue !== null) {
328
330
  const pnlDollars = pnlTicks * tickValue;
329
331
  stats.sessionPnl += pnlDollars; // Track session P&L
330
332
  if (pnlDollars >= 0) {
331
333
  stats.wins++;
332
- algoLogger.targetHit(ui, symbolName, exitPrice, pnlDollars);
334
+ algoLogger.info(ui, 'WIN', `+$${pnlDollars.toFixed(2)} @ ${exitPrice} | ${holdSec}s`);
333
335
  } else {
334
336
  stats.losses++;
335
- algoLogger.stopHit(ui, symbolName, exitPrice, Math.abs(pnlDollars));
337
+ algoLogger.info(ui, 'LOSS', `-$${Math.abs(pnlDollars).toFixed(2)} @ ${exitPrice} | ${holdSec}s`);
336
338
  }
337
339
  } else {
338
340
  // Log with ticks only if tickValue unavailable
339
341
  if (pnlTicks !== null && pnlTicks >= 0) {
340
342
  stats.wins++;
341
- algoLogger.info(ui, 'TARGET', `+${pnlTicks} ticks`);
343
+ algoLogger.info(ui, 'WIN', `+${pnlTicks} ticks | ${holdSec}s`);
342
344
  } else if (pnlTicks !== null) {
343
345
  stats.losses++;
344
- algoLogger.info(ui, 'STOP', `${pnlTicks} ticks`);
346
+ algoLogger.info(ui, 'LOSS', `${pnlTicks} ticks | ${holdSec}s`);
345
347
  }
346
348
  }
347
349
  stats.trades++;
348
350
  currentPosition = 0;
349
351
  stats.position = 0; // Reset UI position display
350
352
  pendingOrder = false;
351
- algoLogger.info(ui, 'HOLD TIME', `${(holdDurationMs / 1000).toFixed(1)}s`);
352
353
  });
353
354
 
354
355
  positionManager.on('holdComplete', ({ orderTag, position }) => {
355
- algoLogger.info(ui, 'HOLD COMPLETE', `${FAST_SCALPING.MIN_HOLD_MS / 1000}s minimum reached`);
356
+ algoLogger.info(ui, 'READY', `Hold complete - monitoring exit`);
356
357
  });
357
358
 
358
359
  positionManager.on('exitOrderFired', ({ orderTag, exitReason, latencyMs }) => {
359
- algoLogger.info(ui, 'EXIT FIRED', `${exitReason.reason} | ${latencyMs.toFixed(1)}ms`);
360
+ // Don't log here - exitFilled will log the result
360
361
  });
361
362
 
362
- // DEBUG: Listen for raw order notifications from Rithmic
363
- service.on('orderAccepted', (data) => {
364
- algoLogger.info(ui, 'ORDER ACCEPTED', `tag=${data.orderTag} basket=${data.basketId}`);
365
- });
366
-
367
- service.on('orderNotification', (data) => {
368
- const status = data.status || 'unknown';
369
- const fillQty = data.fillQuantity || data.totalFillQuantity || 0;
370
- if (fillQty > 0) {
371
- algoLogger.info(ui, 'ORDER FILL', `tag=${data.orderTag} qty=${fillQty} @ ${data.avgFillPrice}`);
372
- } else {
373
- algoLogger.info(ui, 'ORDER STATUS', `tag=${data.orderTag} status=${status}`);
374
- }
375
- });
376
-
377
- service.on('orderFilled', (data) => {
378
- algoLogger.info(ui, 'FILL CONFIRMED', `${data.transactionType === 1 ? 'BUY' : 'SELL'} ${data.fillQuantity}x @ ${data.avgFillPrice}`);
379
- });
363
+ // NOTE: Removed verbose DEBUG logs (ORDER ACCEPTED, ORDER STATUS, ORDER FILL, FILL CONFIRMED)
364
+ // Entry/Exit fills are logged by positionManager events (entryFilled, exitFilled)
380
365
  }
381
366
 
382
367
  // ═══════════════════════════════════════════════════════════════════════════
@@ -539,11 +524,11 @@ const launchAlgo = async (service, account, contract, config) => {
539
524
  }
540
525
 
541
526
  const riskPct = Math.round((riskAmount / maxRisk) * 100);
542
- algoLogger.positionSized(ui, contracts, kelly, riskAmount, riskPct);
543
527
 
544
528
  // Place order via API
545
529
  pendingOrder = true;
546
530
  const orderSide = direction === 'long' ? 0 : 1; // 0=Buy, 1=Sell
531
+ const sideStr = direction === 'long' ? 'LONG' : 'SHORT';
547
532
 
548
533
  try {
549
534
  // ═══════════════════════════════════════════════════════════════
@@ -559,49 +544,29 @@ const launchAlgo = async (service, account, contract, config) => {
559
544
  };
560
545
 
561
546
  // CRITICAL: Use rithmicAccountId (original) not accountId (hash) for Rithmic orders
562
- // The accountId field is hashed for display, but Rithmic API needs the original
563
547
  if (account.rithmicAccountId) {
564
548
  orderData.accountId = account.rithmicAccountId;
565
549
  }
566
550
 
567
- // Log order details before sending
568
- algoLogger.info(ui, 'ORDER DATA', `acct=${orderData.accountId} sym=${orderData.symbol} side=${orderData.side} qty=${orderData.size}`);
551
+ // Log entry attempt (single line)
552
+ algoLogger.info(ui, 'ENTRY', `${sideStr} ${contracts}x ${symbolName} | risk: $${riskAmount} (${riskPct}%)`);
569
553
 
570
554
  // Fire-and-forget entry (no await on fill)
571
555
  const entryResult = service.fastEntry(orderData);
572
556
 
573
- // Log the order tag for tracking
574
- algoLogger.info(ui, 'ORDER TAG', `${entryResult.orderTag} | success=${entryResult.success}`);
575
-
576
557
  if (entryResult.success) {
577
558
  // Register with position manager for lifecycle tracking
578
- // Pass contract info from API (NOT hardcoded)
579
- const contractInfo = {
580
- tickSize,
581
- tickValue,
582
- contractId,
583
- };
559
+ const contractInfo = { tickSize, tickValue, contractId };
584
560
  positionManager.registerEntry(entryResult, orderData, contractInfo);
585
561
 
586
562
  currentPosition = direction === 'long' ? contracts : -contracts;
587
- const sideStr = direction === 'long' ? 'BUY' : 'SELL';
588
-
589
- // Log with latency
590
- const latencyColor = entryResult.latencyMs < FAST_SCALPING.LATENCY_TARGET_MS
591
- ? chalk.green
592
- : entryResult.latencyMs < FAST_SCALPING.LATENCY_WARN_MS
593
- ? chalk.yellow
594
- : chalk.red;
595
563
 
564
+ // Update avg entry latency
596
565
  stats.avgEntryLatency = stats.entryLatencies.length > 0
597
566
  ? (stats.avgEntryLatency * stats.entryLatencies.length + entryResult.latencyMs) / (stats.entryLatencies.length + 1)
598
567
  : entryResult.latencyMs;
599
568
 
600
- algoLogger.info(ui, 'FAST ENTRY', `${sideStr} ${contracts}x ${symbolName} | ${latencyColor(entryResult.latencyMs.toFixed(2) + 'ms')}`);
601
- algoLogger.info(ui, 'HOLD START', `Min ${FAST_SCALPING.MIN_HOLD_MS / 1000}s before exit`);
602
-
603
- // Note: NO bracket orders in fast path
604
- // PositionManager handles exit logic after 10s hold
569
+ // Note: Fill confirmation logged by positionManager.on('entryFilled')
605
570
 
606
571
  } else {
607
572
  algoLogger.orderRejected(ui, symbolName, entryResult.error || 'Fast entry failed');