hedgequantx 2.6.86 → 2.6.88

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.86",
3
+ "version": "2.6.88",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -39,7 +39,7 @@ const LOG_COLORS = {
39
39
  analysis: chalk.magenta
40
40
  };
41
41
 
42
- // Log type icons - Unicode icons with colors
42
+ // Log type icons - Unicode icons with colors (ALL 8 chars wide for alignment)
43
43
  const LOG_ICONS = {
44
44
  fill_buy: '⬆ BUY ',
45
45
  fill_sell: '⬇ SELL ',
@@ -48,19 +48,19 @@ const LOG_ICONS = {
48
48
  win: '✔ WIN ',
49
49
  loss: '✘ LOSS ',
50
50
  be: '★ BE ',
51
- entry: '➡ ENTRY',
51
+ entry: '➡ ENTRY ',
52
52
  filled: '✔ FILL ',
53
53
  connected: '✔ CONN ',
54
- ready: '✔ READY',
54
+ ready: '✔ READY ',
55
55
  error: '✘ ERR ',
56
56
  reject: '✘ REJ ',
57
57
  info: '➡ INFO ',
58
58
  system: '★ SYS ',
59
59
  signal: '★ SIG ',
60
- trade: '✔ TRADE',
60
+ trade: '✔ TRADE ',
61
61
  success: '✔ OK ',
62
62
  warning: '⬅ WARN ',
63
- analysis: '★ ANLYS'
63
+ analysis: '★ ANLYS '
64
64
  };
65
65
 
66
66
  /**
@@ -371,16 +371,24 @@ const handleInstrumentPnLUpdate = (service, data) => {
371
371
 
372
372
  // Build position data - ALWAYS emit, even when FLAT (netQty === 0)
373
373
  // This ensures Open P&L resets to 0 when position closes (like R Trader)
374
+ //
375
+ // OPEN PNL PRIORITY (real-time unrealized P&L):
376
+ // 1. dayOpenPnl (double) - most reliable from INSTRUMENT_PNL_UPDATE
377
+ // 2. openPositionPnl (string) - fallback
378
+ // 3. Calculate from price if available
379
+ const rawOpenPnl = pos.dayOpenPnl ?? pos.openPositionPnl;
380
+ const rawClosedPnl = pos.dayClosedPnl ?? pos.closedPositionPnl;
381
+
374
382
  const positionData = {
375
383
  accountId: pos.accountId,
376
384
  symbol: pos.symbol,
377
385
  exchange: pos.exchange || 'CME',
378
386
  quantity: netQty,
379
387
  averagePrice: netQty !== 0 ? (pos.avgOpenFillPrice || 0) : 0,
380
- // Open P&L from API - this is the real-time unrealized P&L (same as R Trader)
381
- openPnl: parseFloat(pos.openPositionPnl || pos.dayOpenPnl || 0),
382
- closedPnl: parseFloat(pos.closedPositionPnl || pos.dayClosedPnl || 0),
383
- dayPnl: parseFloat(pos.dayPnl || 0),
388
+ // Open P&L - parse as float, handle both double and string formats
389
+ openPnl: typeof rawOpenPnl === 'number' ? rawOpenPnl : parseFloat(rawOpenPnl || 0),
390
+ closedPnl: typeof rawClosedPnl === 'number' ? rawClosedPnl : parseFloat(rawClosedPnl || 0),
391
+ dayPnl: typeof pos.dayPnl === 'number' ? pos.dayPnl : parseFloat(pos.dayPnl || 0),
384
392
  isSnapshot: pos.isSnapshot || false,
385
393
  };
386
394
 
@@ -344,13 +344,34 @@ function decodeInstrumentPnL(buffer) {
344
344
  [result.closedPositionPnl, offset] = readLengthDelimited(buffer, offset);
345
345
  break;
346
346
  case INSTRUMENT_PNL_FIELDS.DAY_PNL:
347
- [result.dayPnl, offset] = readLengthDelimited(buffer, offset);
347
+ // DAY_PNL is a double (wireType 1 = 64-bit fixed)
348
+ if (wireType === 1) {
349
+ result.dayPnl = buffer.readDoubleLE(offset);
350
+ offset += 8;
351
+ } else {
352
+ // Fallback: try string
353
+ [result.dayPnl, offset] = readLengthDelimited(buffer, offset);
354
+ }
348
355
  break;
349
356
  case INSTRUMENT_PNL_FIELDS.DAY_OPEN_PNL:
350
- [result.dayOpenPnl, offset] = readLengthDelimited(buffer, offset);
357
+ // DAY_OPEN_PNL is a double (wireType 1 = 64-bit fixed)
358
+ if (wireType === 1) {
359
+ result.dayOpenPnl = buffer.readDoubleLE(offset);
360
+ offset += 8;
361
+ } else {
362
+ // Fallback: try string
363
+ [result.dayOpenPnl, offset] = readLengthDelimited(buffer, offset);
364
+ }
351
365
  break;
352
366
  case INSTRUMENT_PNL_FIELDS.DAY_CLOSED_PNL:
353
- [result.dayClosedPnl, offset] = readLengthDelimited(buffer, offset);
367
+ // DAY_CLOSED_PNL is a double (wireType 1 = 64-bit fixed)
368
+ if (wireType === 1) {
369
+ result.dayClosedPnl = buffer.readDoubleLE(offset);
370
+ offset += 8;
371
+ } else {
372
+ // Fallback: try string
373
+ [result.dayClosedPnl, offset] = readLengthDelimited(buffer, offset);
374
+ }
354
375
  break;
355
376
  case INSTRUMENT_PNL_FIELDS.SSBOE:
356
377
  [result.ssboe, offset] = readVarint(buffer, offset);