hedgequantx 2.6.38 → 2.6.39

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.38",
3
+ "version": "2.6.39",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -449,20 +449,21 @@ const FillInfoPool = {
449
449
  */
450
450
  fill(notif, receiveTime, latency) {
451
451
  const o = this._template;
452
- o.orderTag = notif.userMsg?.[0] || null;
452
+ o.orderTag = notif.userTag || null; // userTag contains our order tag
453
453
  o.basketId = notif.basketId;
454
- o.orderId = notif.orderId;
454
+ o.orderId = notif.exchangeOrderId || notif.orderId;
455
455
  o.status = notif.status;
456
456
  o.symbol = notif.symbol;
457
457
  o.exchange = notif.exchange;
458
458
  o.accountId = notif.accountId;
459
- o.fillQuantity = notif.fillQuantity || 0;
460
- o.totalFillQuantity = notif.totalFillQuantity || 0;
461
- o.remainingQuantity = notif.remainingQuantity || 0;
459
+ // Proto uses totalFillSize, not fillQuantity
460
+ o.fillQuantity = notif.totalFillSize || notif.fillQuantity || 0;
461
+ o.totalFillQuantity = notif.totalFillSize || notif.totalFillQuantity || 0;
462
+ o.remainingQuantity = notif.totalUnfilledSize || notif.remainingQuantity || 0;
462
463
  o.avgFillPrice = parseFloat(notif.avgFillPrice || 0);
463
- o.lastFillPrice = parseFloat(notif.fillPrice || 0);
464
+ o.lastFillPrice = parseFloat(notif.price || notif.fillPrice || 0);
464
465
  o.transactionType = notif.transactionType;
465
- o.orderType = notif.orderType;
466
+ o.orderType = notif.priceType || notif.orderType;
466
467
  o.quantity = notif.quantity;
467
468
  o.ssboe = notif.ssboe;
468
469
  o.usecs = notif.usecs;
@@ -495,11 +496,13 @@ const handleOrderNotification = (service, data) => {
495
496
 
496
497
  try {
497
498
  const notif = proto.decode('RithmicOrderNotification', data);
498
- const orderTag = notif.userMsg?.[0] || null;
499
+ // userTag contains our order tag (userMsg is not in this proto)
500
+ const orderTag = notif.userTag || null;
499
501
 
500
502
  // FAST PATH: Check for fill immediately
501
- const fillQty = notif.fillQuantity || notif.totalFillQuantity || 0;
502
- const isFill = fillQty > 0;
503
+ // Proto uses total_fill_size (camelCase: totalFillSize), not fillQuantity
504
+ const fillQty = notif.totalFillSize || notif.totalFillQuantity || notif.fillQuantity || 0;
505
+ const isFill = fillQty > 0 || notif.status === 'complete';
503
506
 
504
507
  // Calculate round-trip latency if this is a fill we're tracking
505
508
  let roundTripLatency = null;
@@ -521,15 +524,18 @@ const handleOrderNotification = (service, data) => {
521
524
  // Emit raw notification
522
525
  service.emit('orderNotification', fillInfo);
523
526
 
524
- // Emit fill event if this is a fill
527
+ // Emit fill event if this is a fill (status=complete means order is fully filled)
525
528
  if (isFill) {
526
- console.log(`[FILL] Received: ${orderTag} | ${fillInfo.transactionType === 1 ? 'BUY' : 'SELL'} ${fillQty}x @ ${fillInfo.avgFillPrice} | latency=${roundTripLatency}ms`);
529
+ const actualFillQty = fillInfo.totalFillQuantity || fillInfo.fillQuantity || notif.quantity || 0;
530
+ const fillPrice = fillInfo.avgFillPrice || fillInfo.lastFillPrice || 0;
531
+
532
+ console.log(`[FILL] Received: ${orderTag} | ${fillInfo.transactionType === 1 ? 'BUY' : 'SELL'} ${actualFillQty}x @ ${fillPrice} | latency=${roundTripLatency}ms`);
527
533
 
528
534
  debug('ORDER FILLED:', {
529
535
  orderTag,
530
536
  side: fillInfo.transactionType === 1 ? 'BUY' : 'SELL',
531
- qty: fillQty,
532
- avgPrice: fillInfo.avgFillPrice,
537
+ qty: actualFillQty,
538
+ avgPrice: fillPrice,
533
539
  latencyMs: roundTripLatency,
534
540
  });
535
541
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  const EventEmitter = require('events');
9
9
  const { RithmicConnection } = require('./connection');
10
- const { RITHMIC_ENDPOINTS, RITHMIC_SYSTEMS } = require('./constants');
10
+ const { RITHMIC_ENDPOINTS, RITHMIC_SYSTEMS, REQ } = require('./constants');
11
11
  const { createOrderHandler, createPnLHandler, LatencyTracker } = require('./handlers');
12
12
  const {
13
13
  fetchAccounts,
@@ -192,15 +192,18 @@ class RithmicService extends EventEmitter {
192
192
  log.warn('Failed to fetch accounts', { error: err.message });
193
193
  }
194
194
 
195
- // Subscribe to order updates (required to receive fill notifications)
195
+ // Subscribe to order updates for each account (required to receive fill notifications)
196
196
  try {
197
- this.orderConn.send('RequestSubscribeForOrderUpdates', {
198
- templateId: REQ.ORDER_UPDATES,
199
- userMsg: ['HQX'],
200
- fcmId: data.fcmId,
201
- ibId: data.ibId,
202
- });
203
- log.debug('Subscribed to order updates');
197
+ for (const acc of this.accounts) {
198
+ this.orderConn.send('RequestSubscribeForOrderUpdates', {
199
+ templateId: REQ.ORDER_UPDATES,
200
+ userMsg: ['HQX'],
201
+ fcmId: acc.fcmId || data.fcmId,
202
+ ibId: acc.ibId || data.ibId,
203
+ accountId: acc.accountId,
204
+ });
205
+ log.debug('Subscribed to order updates for account', { accountId: acc.accountId });
206
+ }
204
207
  } catch (err) {
205
208
  log.warn('Failed to subscribe to order updates', { error: err.message });
206
209
  }
@@ -40,6 +40,7 @@ const OrderPool = {
40
40
  _template: {
41
41
  templateId: REQ.NEW_ORDER,
42
42
  userMsg: [''],
43
+ userTag: '', // Our order tag - returned in RithmicOrderNotification
43
44
  fcmId: '',
44
45
  ibId: '',
45
46
  accountId: '',
@@ -63,6 +64,7 @@ const OrderPool = {
63
64
  fill(orderTag, loginInfo, orderData) {
64
65
  const o = this._template;
65
66
  o.userMsg[0] = orderTag;
67
+ o.userTag = orderTag; // Set userTag for notification tracking
66
68
  o.fcmId = loginInfo.fcmId;
67
69
  o.ibId = loginInfo.ibId;
68
70
  o.accountId = orderData.accountId;