hedgequantx 2.6.161 → 2.6.162

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 (42) hide show
  1. package/package.json +1 -1
  2. package/src/menus/ai-agent-connect.js +181 -0
  3. package/src/menus/ai-agent-models.js +219 -0
  4. package/src/menus/ai-agent-oauth.js +292 -0
  5. package/src/menus/ai-agent-ui.js +141 -0
  6. package/src/menus/ai-agent.js +88 -1489
  7. package/src/pages/algo/copy-engine.js +449 -0
  8. package/src/pages/algo/copy-trading.js +11 -543
  9. package/src/pages/algo/smart-logs-data.js +218 -0
  10. package/src/pages/algo/smart-logs.js +9 -214
  11. package/src/pages/algo/ui-constants.js +144 -0
  12. package/src/pages/algo/ui-summary.js +184 -0
  13. package/src/pages/algo/ui.js +42 -526
  14. package/src/pages/stats-calculations.js +191 -0
  15. package/src/pages/stats-ui.js +381 -0
  16. package/src/pages/stats.js +14 -507
  17. package/src/services/ai/client-analysis.js +194 -0
  18. package/src/services/ai/client-models.js +333 -0
  19. package/src/services/ai/client.js +6 -489
  20. package/src/services/ai/index.js +2 -257
  21. package/src/services/ai/proxy-install.js +249 -0
  22. package/src/services/ai/proxy-manager.js +29 -411
  23. package/src/services/ai/proxy-remote.js +161 -0
  24. package/src/services/ai/supervisor-optimize.js +215 -0
  25. package/src/services/ai/supervisor-sync.js +178 -0
  26. package/src/services/ai/supervisor.js +50 -515
  27. package/src/services/ai/validation.js +250 -0
  28. package/src/services/hqx-server-events.js +110 -0
  29. package/src/services/hqx-server-handlers.js +217 -0
  30. package/src/services/hqx-server-latency.js +136 -0
  31. package/src/services/hqx-server.js +51 -403
  32. package/src/services/position-constants.js +28 -0
  33. package/src/services/position-manager.js +105 -554
  34. package/src/services/position-momentum.js +206 -0
  35. package/src/services/projectx/accounts.js +142 -0
  36. package/src/services/projectx/index.js +40 -289
  37. package/src/services/projectx/trading.js +180 -0
  38. package/src/services/rithmic/handlers.js +2 -208
  39. package/src/services/rithmic/index.js +32 -542
  40. package/src/services/rithmic/latency-tracker.js +182 -0
  41. package/src/services/rithmic/specs.js +146 -0
  42. package/src/services/rithmic/trade-history.js +254 -0
@@ -14,151 +14,12 @@
14
14
  const { proto, decodeAccountPnL, decodeInstrumentPnL } = require('./protobuf');
15
15
  const { RES, STREAM } = require('./constants');
16
16
  const { performance } = require('perf_hooks');
17
+ const { LatencyTracker, FillInfoPool } = require('./latency-tracker');
17
18
 
18
19
  // Debug mode - use no-op function when disabled for zero overhead
19
20
  const DEBUG = process.env.HQX_DEBUG === '1';
20
21
  const debug = DEBUG ? (...args) => console.log('[Rithmic:Handler]', ...args) : () => {};
21
22
 
22
- // ==================== HIGH-RESOLUTION TIMING ====================
23
- // Use process.hrtime.bigint for sub-millisecond precision
24
-
25
- /**
26
- * Get high-resolution timestamp in nanoseconds
27
- * @returns {bigint}
28
- */
29
- const hrNow = () => process.hrtime.bigint();
30
-
31
- /**
32
- * Convert nanoseconds to milliseconds with precision
33
- * @param {bigint} ns
34
- * @returns {number}
35
- */
36
- const nsToMs = (ns) => Number(ns) / 1_000_000;
37
-
38
- // ==================== LATENCY TRACKING ====================
39
- // Track order-to-fill latency for performance monitoring
40
- // OPTIMIZED: Circular buffer (no array.shift), high-resolution timing
41
-
42
- const LatencyTracker = {
43
- _pending: new Map(), // orderTag -> entryTime (bigint nanoseconds)
44
- _samples: null, // Pre-allocated Float64Array circular buffer
45
- _maxSamples: 100,
46
- _head: 0, // Next write position
47
- _count: 0, // Number of valid samples
48
- _initialized: false,
49
-
50
- /**
51
- * Initialize circular buffer (lazy init)
52
- * @private
53
- */
54
- _init() {
55
- if (this._initialized) return;
56
- this._samples = new Float64Array(this._maxSamples);
57
- this._initialized = true;
58
- },
59
-
60
- /**
61
- * Record order sent time with high-resolution timestamp
62
- * @param {string} orderTag
63
- * @param {number} entryTimeMs - Date.now() when order was sent (for compatibility)
64
- */
65
- recordEntry(orderTag, entryTimeMs) {
66
- // Store high-resolution time for precise measurement
67
- this._pending.set(orderTag, hrNow());
68
- },
69
-
70
- /**
71
- * Record fill received, calculate latency with sub-ms precision
72
- * @param {string} orderTag
73
- * @returns {number|null} Round-trip latency in ms (with decimal precision), or null if not tracked
74
- */
75
- recordFill(orderTag) {
76
- const entryTime = this._pending.get(orderTag);
77
- if (!entryTime) return null;
78
-
79
- this._pending.delete(orderTag);
80
- const latencyNs = hrNow() - entryTime;
81
- const latencyMs = nsToMs(latencyNs);
82
-
83
- // Store in circular buffer (no shift, O(1))
84
- this._init();
85
- this._samples[this._head] = latencyMs;
86
- this._head = (this._head + 1) % this._maxSamples;
87
- if (this._count < this._maxSamples) this._count++;
88
-
89
- return latencyMs;
90
- },
91
-
92
- /**
93
- * Get average latency
94
- * @returns {number|null}
95
- */
96
- getAverage() {
97
- if (this._count === 0) return null;
98
- let sum = 0;
99
- for (let i = 0; i < this._count; i++) {
100
- sum += this._samples[i];
101
- }
102
- return sum / this._count;
103
- },
104
-
105
- /**
106
- * Get min/max/avg stats with high precision
107
- * @returns {Object}
108
- */
109
- getStats() {
110
- if (this._count === 0) {
111
- return { min: null, max: null, avg: null, p50: null, p99: null, samples: 0 };
112
- }
113
-
114
- // Get valid samples
115
- const valid = [];
116
- for (let i = 0; i < this._count; i++) {
117
- valid.push(this._samples[i]);
118
- }
119
- valid.sort((a, b) => a - b);
120
-
121
- const sum = valid.reduce((a, b) => a + b, 0);
122
-
123
- return {
124
- min: valid[0],
125
- max: valid[valid.length - 1],
126
- avg: sum / valid.length,
127
- p50: valid[Math.floor(valid.length * 0.5)],
128
- p99: valid[Math.floor(valid.length * 0.99)] || valid[valid.length - 1],
129
- samples: this._count,
130
- };
131
- },
132
-
133
- /**
134
- * Get last N latency samples
135
- * @param {number} n
136
- * @returns {number[]}
137
- */
138
- getRecent(n = 10) {
139
- if (this._count === 0) return [];
140
- const result = [];
141
- const start = this._count < this._maxSamples ? 0 : this._head;
142
- for (let i = 0; i < Math.min(n, this._count); i++) {
143
- const idx = (start + this._count - 1 - i + this._maxSamples) % this._maxSamples;
144
- result.push(this._samples[idx]);
145
- }
146
- return result;
147
- },
148
-
149
- /**
150
- * Clear all tracking data
151
- */
152
- clear() {
153
- this._pending.clear();
154
- this._head = 0;
155
- this._count = 0;
156
- if (this._samples) {
157
- this._samples.fill(0);
158
- }
159
- }
160
- };
161
-
162
23
  /**
163
24
  * Create ORDER_PLANT message handler
164
25
  * @param {RithmicService} service - The Rithmic service instance
@@ -436,74 +297,7 @@ const handleNewOrderResponse = (service, data) => {
436
297
  }
437
298
  };
438
299
 
439
- // ==================== PRE-ALLOCATED OBJECTS ====================
440
- // Reusable objects for hot path to avoid GC pressure
441
-
442
- const FillInfoPool = {
443
- // Pre-allocated fill info template
444
- _template: {
445
- orderTag: null,
446
- basketId: null,
447
- orderId: null,
448
- status: null,
449
- symbol: null,
450
- exchange: null,
451
- accountId: null,
452
- fillQuantity: 0,
453
- totalFillQuantity: 0,
454
- remainingQuantity: 0,
455
- avgFillPrice: 0,
456
- lastFillPrice: 0,
457
- transactionType: 0,
458
- orderType: 0,
459
- quantity: 0,
460
- ssboe: 0,
461
- usecs: 0,
462
- localTimestamp: 0,
463
- roundTripLatencyMs: null,
464
- },
465
-
466
- /**
467
- * Fill template with notification data
468
- * @param {Object} notif - Decoded notification
469
- * @param {number} receiveTime - Local receive timestamp
470
- * @param {number|null} latency - Round-trip latency
471
- * @returns {Object}
472
- */
473
- fill(notif, receiveTime, latency) {
474
- const o = this._template;
475
- o.orderTag = notif.userTag || null; // userTag contains our order tag
476
- o.basketId = notif.basketId;
477
- o.orderId = notif.exchangeOrderId || notif.orderId;
478
- o.status = notif.status;
479
- o.symbol = notif.symbol;
480
- o.exchange = notif.exchange;
481
- o.accountId = notif.accountId;
482
- // Proto uses totalFillSize, not fillQuantity
483
- o.fillQuantity = notif.totalFillSize || notif.fillQuantity || 0;
484
- o.totalFillQuantity = notif.totalFillSize || notif.totalFillQuantity || 0;
485
- o.remainingQuantity = notif.totalUnfilledSize || notif.remainingQuantity || 0;
486
- o.avgFillPrice = parseFloat(notif.avgFillPrice || 0);
487
- o.lastFillPrice = parseFloat(notif.price || notif.fillPrice || 0);
488
- o.transactionType = notif.transactionType;
489
- o.orderType = notif.priceType || notif.orderType;
490
- o.quantity = notif.quantity;
491
- o.ssboe = notif.ssboe;
492
- o.usecs = notif.usecs;
493
- o.localTimestamp = receiveTime;
494
- o.roundTripLatencyMs = latency;
495
- return o;
496
- },
497
-
498
- /**
499
- * Create a copy for async operations that need to keep the data
500
- * @param {Object} fillInfo
501
- * @returns {Object}
502
- */
503
- clone(fillInfo) {
504
- return { ...fillInfo };
505
- }
506
- };
300
+ // FillInfoPool imported from ./latency-tracker
507
301
 
508
302
  /**
509
303
  * Handle order notification (351) - CRITICAL for fill tracking