hedgequantx 2.6.162 → 2.7.0

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.
Files changed (138) hide show
  1. package/README.md +15 -88
  2. package/bin/cli.js +0 -11
  3. package/dist/lib/api.jsc +0 -0
  4. package/dist/lib/api2.jsc +0 -0
  5. package/dist/lib/core.jsc +0 -0
  6. package/dist/lib/core2.jsc +0 -0
  7. package/dist/lib/data.js +1 -1
  8. package/dist/lib/data.jsc +0 -0
  9. package/dist/lib/data2.jsc +0 -0
  10. package/dist/lib/decoder.jsc +0 -0
  11. package/dist/lib/m/mod1.jsc +0 -0
  12. package/dist/lib/m/mod2.jsc +0 -0
  13. package/dist/lib/n/r1.jsc +0 -0
  14. package/dist/lib/n/r2.jsc +0 -0
  15. package/dist/lib/n/r3.jsc +0 -0
  16. package/dist/lib/n/r4.jsc +0 -0
  17. package/dist/lib/n/r5.jsc +0 -0
  18. package/dist/lib/n/r6.jsc +0 -0
  19. package/dist/lib/n/r7.jsc +0 -0
  20. package/dist/lib/o/util1.jsc +0 -0
  21. package/dist/lib/o/util2.jsc +0 -0
  22. package/package.json +6 -3
  23. package/src/app.js +40 -162
  24. package/src/config/constants.js +31 -33
  25. package/src/config/propfirms.js +13 -217
  26. package/src/config/settings.js +0 -43
  27. package/src/lib/api.js +198 -0
  28. package/src/lib/api2.js +353 -0
  29. package/src/lib/core.js +539 -0
  30. package/src/lib/core2.js +341 -0
  31. package/src/lib/data.js +555 -0
  32. package/src/lib/data2.js +492 -0
  33. package/src/lib/decoder.js +599 -0
  34. package/src/lib/m/s1.js +804 -0
  35. package/src/lib/m/s2.js +34 -0
  36. package/src/lib/n/r1.js +454 -0
  37. package/src/lib/n/r2.js +514 -0
  38. package/src/lib/n/r3.js +631 -0
  39. package/src/lib/n/r4.js +401 -0
  40. package/src/lib/n/r5.js +335 -0
  41. package/src/lib/n/r6.js +425 -0
  42. package/src/lib/n/r7.js +530 -0
  43. package/src/lib/o/l1.js +44 -0
  44. package/src/lib/o/l2.js +427 -0
  45. package/src/lib/python-bridge.js +206 -0
  46. package/src/menus/connect.js +14 -176
  47. package/src/menus/dashboard.js +65 -110
  48. package/src/pages/accounts.js +18 -18
  49. package/src/pages/algo/copy-trading.js +210 -240
  50. package/src/pages/algo/index.js +41 -104
  51. package/src/pages/algo/one-account.js +386 -33
  52. package/src/pages/algo/ui.js +312 -151
  53. package/src/pages/orders.js +3 -3
  54. package/src/pages/positions.js +3 -3
  55. package/src/pages/stats/chart.js +74 -0
  56. package/src/pages/stats/display.js +228 -0
  57. package/src/pages/stats/index.js +236 -0
  58. package/src/pages/stats/metrics.js +213 -0
  59. package/src/pages/user.js +6 -6
  60. package/src/services/hqx-server/constants.js +55 -0
  61. package/src/services/hqx-server/index.js +401 -0
  62. package/src/services/hqx-server/latency.js +81 -0
  63. package/src/services/index.js +12 -3
  64. package/src/services/rithmic/accounts.js +7 -32
  65. package/src/services/rithmic/connection.js +1 -204
  66. package/src/services/rithmic/contracts.js +235 -0
  67. package/src/services/rithmic/handlers.js +21 -196
  68. package/src/services/rithmic/index.js +60 -291
  69. package/src/services/rithmic/market.js +31 -0
  70. package/src/services/rithmic/orders.js +5 -361
  71. package/src/services/rithmic/protobuf.js +5 -195
  72. package/src/services/session.js +22 -173
  73. package/src/ui/box.js +10 -18
  74. package/src/ui/index.js +1 -3
  75. package/src/ui/menu.js +1 -1
  76. package/src/utils/prompts.js +2 -2
  77. package/dist/lib/m/s1.js +0 -1
  78. package/src/menus/ai-agent-connect.js +0 -181
  79. package/src/menus/ai-agent-models.js +0 -219
  80. package/src/menus/ai-agent-oauth.js +0 -292
  81. package/src/menus/ai-agent-ui.js +0 -141
  82. package/src/menus/ai-agent.js +0 -484
  83. package/src/pages/algo/algo-config.js +0 -195
  84. package/src/pages/algo/algo-multi.js +0 -801
  85. package/src/pages/algo/algo-utils.js +0 -58
  86. package/src/pages/algo/copy-engine.js +0 -449
  87. package/src/pages/algo/custom-strategy.js +0 -459
  88. package/src/pages/algo/logger.js +0 -245
  89. package/src/pages/algo/smart-logs-data.js +0 -218
  90. package/src/pages/algo/smart-logs.js +0 -387
  91. package/src/pages/algo/ui-constants.js +0 -144
  92. package/src/pages/algo/ui-summary.js +0 -184
  93. package/src/pages/stats-calculations.js +0 -191
  94. package/src/pages/stats-ui.js +0 -381
  95. package/src/pages/stats.js +0 -339
  96. package/src/services/ai/client-analysis.js +0 -194
  97. package/src/services/ai/client-models.js +0 -333
  98. package/src/services/ai/client.js +0 -343
  99. package/src/services/ai/index.js +0 -384
  100. package/src/services/ai/oauth-anthropic.js +0 -265
  101. package/src/services/ai/oauth-gemini.js +0 -223
  102. package/src/services/ai/oauth-iflow.js +0 -269
  103. package/src/services/ai/oauth-openai.js +0 -233
  104. package/src/services/ai/oauth-qwen.js +0 -279
  105. package/src/services/ai/providers/index.js +0 -526
  106. package/src/services/ai/proxy-install.js +0 -249
  107. package/src/services/ai/proxy-manager.js +0 -494
  108. package/src/services/ai/proxy-remote.js +0 -161
  109. package/src/services/ai/strategy-supervisor.js +0 -1312
  110. package/src/services/ai/supervisor-data.js +0 -195
  111. package/src/services/ai/supervisor-optimize.js +0 -215
  112. package/src/services/ai/supervisor-sync.js +0 -178
  113. package/src/services/ai/supervisor-utils.js +0 -158
  114. package/src/services/ai/supervisor.js +0 -484
  115. package/src/services/ai/validation.js +0 -250
  116. package/src/services/hqx-server-events.js +0 -110
  117. package/src/services/hqx-server-handlers.js +0 -217
  118. package/src/services/hqx-server-latency.js +0 -136
  119. package/src/services/hqx-server.js +0 -403
  120. package/src/services/position-constants.js +0 -28
  121. package/src/services/position-manager.js +0 -528
  122. package/src/services/position-momentum.js +0 -206
  123. package/src/services/projectx/accounts.js +0 -142
  124. package/src/services/projectx/index.js +0 -443
  125. package/src/services/projectx/market.js +0 -172
  126. package/src/services/projectx/stats.js +0 -110
  127. package/src/services/projectx/trading.js +0 -180
  128. package/src/services/rithmic/latency-tracker.js +0 -182
  129. package/src/services/rithmic/market-data.js +0 -549
  130. package/src/services/rithmic/specs.js +0 -146
  131. package/src/services/rithmic/trade-history.js +0 -254
  132. package/src/services/session-history.js +0 -475
  133. package/src/services/strategy/hft-tick.js +0 -507
  134. package/src/services/strategy/recovery-math.js +0 -402
  135. package/src/services/tradovate/constants.js +0 -109
  136. package/src/services/tradovate/index.js +0 -505
  137. package/src/services/tradovate/market.js +0 -47
  138. package/src/services/tradovate/websocket.js +0 -97
@@ -1,24 +1,14 @@
1
1
  /**
2
2
  * Rithmic Message Handlers
3
3
  * Handles ORDER_PLANT and PNL_PLANT messages
4
- *
5
- * FAST SCALPING: Handles order fill notifications (351) for position tracking
6
- *
7
- * OPTIMIZED FOR LOW LATENCY:
8
- * - Fast path for order notifications (351)
9
- * - Minimal object creation in hot path
10
- * - Template ID check before proto decode
11
- * - Latency tracking for fills
12
4
  */
13
5
 
14
6
  const { proto, decodeAccountPnL, decodeInstrumentPnL } = require('./protobuf');
15
7
  const { RES, STREAM } = require('./constants');
16
- const { performance } = require('perf_hooks');
17
- const { LatencyTracker, FillInfoPool } = require('./latency-tracker');
18
8
 
19
- // Debug mode - use no-op function when disabled for zero overhead
9
+ // Debug mode
20
10
  const DEBUG = process.env.HQX_DEBUG === '1';
21
- const debug = DEBUG ? (...args) => console.log('[Rithmic:Handler]', ...args) : () => {};
11
+ const debug = (...args) => DEBUG && console.log('[Rithmic:Handler]', ...args);
22
12
 
23
13
  /**
24
14
  * Create ORDER_PLANT message handler
@@ -45,40 +35,16 @@ const createOrderHandler = (service) => {
45
35
  case RES.SHOW_ORDERS:
46
36
  handleShowOrdersResponse(service, data);
47
37
  break;
48
- case RES.NEW_ORDER:
49
- debug('Handling NEW_ORDER response (313)');
50
- handleNewOrderResponse(service, data);
51
- break;
52
38
  case STREAM.EXCHANGE_NOTIFICATION:
53
- debug('Handling EXCHANGE_NOTIFICATION (352)');
54
- handleExchangeNotification(service, data);
39
+ service.emit('exchangeNotification', data);
55
40
  break;
56
41
  case STREAM.ORDER_NOTIFICATION:
57
- debug('Handling ORDER_NOTIFICATION (351)');
58
- handleOrderNotification(service, data);
59
- break;
60
- case RES.SHOW_ORDER_HISTORY:
61
- debug('Handling SHOW_ORDER_HISTORY (325)');
62
- handleOrderHistoryResponse(service, data);
42
+ service.emit('orderNotification', data);
63
43
  break;
64
44
  }
65
45
  };
66
46
  };
67
47
 
68
- /**
69
- * Handle order history response (325) - signals end of history snapshot
70
- */
71
- const handleOrderHistoryResponse = (service, data) => {
72
- try {
73
- const res = proto.decode('ResponseShowOrderHistory', data);
74
- debug('Order history complete:', { userMsg: res.userMsg, rpCode: res.rpCode });
75
- service.emit('orderHistoryComplete', { userMsg: res.userMsg, rpCode: res.rpCode });
76
- } catch (e) {
77
- debug('Error decoding order history response:', e.message);
78
- service.emit('orderHistoryComplete', {});
79
- }
80
- };
81
-
82
48
  /**
83
49
  * Create PNL_PLANT message handler
84
50
  * @param {RithmicService} service - The Rithmic service instance
@@ -193,23 +159,17 @@ const handleAccountPnLUpdate = (service, data) => {
193
159
  debug('Decoded Account PNL:', JSON.stringify(pnl));
194
160
 
195
161
  if (pnl.accountId) {
196
- // Store ALL R Trader metrics from ACCOUNT_PNL_UPDATE (451)
197
162
  const pnlData = {
198
- // Core P&L
199
163
  accountBalance: parseFloat(pnl.accountBalance || 0),
164
+ cashOnHand: parseFloat(pnl.cashOnHand || 0),
165
+ marginBalance: parseFloat(pnl.marginBalance || 0),
200
166
  openPositionPnl: parseFloat(pnl.openPositionPnl || 0),
201
167
  closedPositionPnl: parseFloat(pnl.closedPositionPnl || 0),
202
168
  dayPnl: parseFloat(pnl.dayPnl || 0),
203
- // R Trader additional metrics
204
- availableBuyingPower: parseFloat(pnl.availableBuyingPower || 0),
205
- marginBalance: parseFloat(pnl.marginBalance || 0),
206
- cashOnHand: parseFloat(pnl.cashOnHand || 0),
207
- // Net Liquidation = Account Balance + Open P&L (same as R Trader)
208
- netLiquidation: parseFloat(pnl.accountBalance || 0) + parseFloat(pnl.openPositionPnl || 0),
209
169
  };
210
170
  debug('Storing PNL for account:', pnl.accountId, pnlData);
211
171
  service.accountPnL.set(pnl.accountId, pnlData);
212
- service.emit('pnlUpdate', { accountId: pnl.accountId, ...pnlData });
172
+ service.emit('pnlUpdate', pnl);
213
173
  } else {
214
174
  debug('No accountId in PNL response');
215
175
  }
@@ -220,8 +180,6 @@ const handleAccountPnLUpdate = (service, data) => {
220
180
 
221
181
  /**
222
182
  * Handle instrument PnL update (positions)
223
- * INSTRUMENT_PNL_UPDATE (450) - Real-time position and P&L per instrument
224
- * This is the PRIMARY source for unrealized P&L (same as R Trader Positions panel)
225
183
  */
226
184
  const handleInstrumentPnLUpdate = (service, data) => {
227
185
  try {
@@ -230,163 +188,30 @@ const handleInstrumentPnLUpdate = (service, data) => {
230
188
  const key = `${pos.accountId}:${pos.symbol}:${pos.exchange}`;
231
189
  const netQty = pos.netQuantity || pos.openPositionQuantity || ((pos.buyQty || 0) - (pos.sellQty || 0));
232
190
 
233
- // Build position data - ALWAYS emit, even when FLAT (netQty === 0)
234
- // This ensures Open P&L resets to 0 when position closes (like R Trader)
235
- //
236
- // OPEN PNL PRIORITY (real-time unrealized P&L):
237
- // 1. dayOpenPnl (double) - most reliable from INSTRUMENT_PNL_UPDATE
238
- // 2. openPositionPnl (string) - fallback
239
- // 3. Calculate from price if available
240
- const rawOpenPnl = pos.dayOpenPnl ?? pos.openPositionPnl;
241
- const rawClosedPnl = pos.dayClosedPnl ?? pos.closedPositionPnl;
242
-
243
- const positionData = {
244
- accountId: pos.accountId,
245
- symbol: pos.symbol,
246
- exchange: pos.exchange || 'CME',
247
- quantity: netQty,
248
- averagePrice: netQty !== 0 ? (pos.avgOpenFillPrice || 0) : 0,
249
- // Open P&L - parse as float, handle both double and string formats
250
- openPnl: typeof rawOpenPnl === 'number' ? rawOpenPnl : parseFloat(rawOpenPnl || 0),
251
- closedPnl: typeof rawClosedPnl === 'number' ? rawClosedPnl : parseFloat(rawClosedPnl || 0),
252
- dayPnl: typeof pos.dayPnl === 'number' ? pos.dayPnl : parseFloat(pos.dayPnl || 0),
253
- isSnapshot: pos.isSnapshot || false,
254
- };
255
-
256
191
  if (netQty !== 0) {
257
- service.positions.set(key, positionData);
192
+ service.positions.set(key, {
193
+ accountId: pos.accountId,
194
+ symbol: pos.symbol,
195
+ exchange: pos.exchange || 'CME',
196
+ quantity: netQty,
197
+ averagePrice: pos.avgOpenFillPrice || 0,
198
+ openPnl: parseFloat(pos.openPositionPnl || pos.dayOpenPnl || 0),
199
+ closedPnl: parseFloat(pos.closedPositionPnl || pos.dayClosedPnl || 0),
200
+ dayPnl: parseFloat(pos.dayPnl || 0),
201
+ isSnapshot: pos.isSnapshot || false,
202
+ });
258
203
  } else {
259
204
  service.positions.delete(key);
260
205
  }
261
206
 
262
- // ALWAYS emit positionUpdate - even when FLAT
263
- // This ensures UI updates Open P&L to 0 when position closes
264
- service.emit('positionUpdate', positionData);
207
+ service.emit('positionUpdate', service.positions.get(key));
265
208
  }
266
209
  } catch (e) {
267
- debug('Error decoding Instrument PNL:', e.message);
268
- }
269
- };
270
-
271
- /**
272
- * Handle new order response (313) - confirms order accepted
273
- */
274
- const handleNewOrderResponse = (service, data) => {
275
- try {
276
- const res = proto.decode('ResponseNewOrder', data);
277
- const orderTag = res.userMsg?.[0] || null;
278
- const timestamp = performance.now();
279
-
280
- debug('New order response:', {
281
- orderTag,
282
- rpCode: res.rpCode,
283
- basketId: res.basketId,
284
- ssboe: res.ssboe,
285
- usecs: res.usecs,
286
- });
287
-
288
- // Emit for position manager tracking
289
- service.emit('orderAccepted', {
290
- orderTag,
291
- basketId: res.basketId,
292
- rpCode: res.rpCode,
293
- timestamp,
294
- });
295
- } catch (e) {
296
- debug('Error decoding new order response:', e.message);
297
- }
298
- };
299
-
300
- // FillInfoPool imported from ./latency-tracker
301
-
302
- /**
303
- * Handle order notification (351) - CRITICAL for fill tracking
304
- * This is the primary notification for order status changes including FILLS
305
- *
306
- * ULTRA-OPTIMIZED:
307
- * - Pre-allocated fill info object (zero allocation in hot path)
308
- * - Fast path for fill detection
309
- * - High-resolution latency tracking
310
- */
311
- const handleOrderNotification = (service, data) => {
312
- const receiveTime = Date.now();
313
-
314
- try {
315
- const notif = proto.decode('RithmicOrderNotification', data);
316
- // userTag contains our order tag (userMsg is not in this proto)
317
- const orderTag = notif.userTag || null;
318
-
319
- // FAST PATH: Check for fill immediately
320
- // Proto uses total_fill_size (camelCase: totalFillSize), not fillQuantity
321
- const fillQty = notif.totalFillSize || notif.totalFillQuantity || notif.fillQuantity || 0;
322
- const isFill = fillQty > 0 || notif.status === 'complete';
323
-
324
- // Calculate round-trip latency if this is a fill we're tracking
325
- let roundTripLatency = null;
326
- if (isFill && orderTag) {
327
- roundTripLatency = LatencyTracker.recordFill(orderTag);
328
- }
329
-
330
- debug('Order notification:', {
331
- orderTag,
332
- status: notif.status,
333
- filledQty: fillQty,
334
- avgFillPrice: notif.avgFillPrice,
335
- roundTripLatency,
336
- });
337
-
338
- // OPTIMIZED: Use pre-allocated object
339
- const fillInfo = FillInfoPool.fill(notif, receiveTime, roundTripLatency);
340
-
341
- // Emit raw notification
342
- service.emit('orderNotification', fillInfo);
343
-
344
- // Emit fill event if this is a fill (status=complete means order is fully filled)
345
- if (isFill) {
346
- const actualFillQty = fillInfo.totalFillQuantity || fillInfo.fillQuantity || notif.quantity || 0;
347
- const fillPrice = fillInfo.avgFillPrice || fillInfo.lastFillPrice || 0;
348
-
349
- // Debug only - UI handles display via orderFilled event
350
- debug('FILL Received:', orderTag, fillInfo.transactionType === 1 ? 'BUY' : 'SELL', actualFillQty, '@', fillPrice, 'latency:', roundTripLatency, 'ms');
351
-
352
- // Clone for fill event (async handlers may need to keep the data)
353
- service.emit('orderFilled', FillInfoPool.clone(fillInfo));
354
- } else {
355
- // Debug only - UI handles display via orderNotification event
356
- debug('ORDER STATUS:', orderTag, 'status:', fillInfo.status, 'text:', fillInfo.text || 'N/A');
357
- }
358
- } catch (e) {
359
- debug('Error decoding order notification:', e.message);
360
- }
361
- };
362
-
363
- /**
364
- * Handle exchange notification (352) - exchange-level order updates
365
- */
366
- const handleExchangeNotification = (service, data) => {
367
- try {
368
- const notif = proto.decode('ExchangeOrderNotification', data);
369
- const timestamp = performance.now();
370
-
371
- debug('Exchange notification:', {
372
- orderTag: notif.userMsg?.[0],
373
- text: notif.text,
374
- reportType: notif.reportType,
375
- });
376
-
377
- service.emit('exchangeNotification', {
378
- orderTag: notif.userMsg?.[0] || null,
379
- text: notif.text,
380
- reportType: notif.reportType,
381
- timestamp,
382
- });
383
- } catch (e) {
384
- debug('Error decoding exchange notification:', e.message);
210
+ // Ignore decode errors
385
211
  }
386
212
  };
387
213
 
388
214
  module.exports = {
389
215
  createOrderHandler,
390
- createPnLHandler,
391
- LatencyTracker,
216
+ createPnLHandler
392
217
  };