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.
- package/README.md +15 -88
- package/bin/cli.js +0 -11
- package/dist/lib/api.jsc +0 -0
- package/dist/lib/api2.jsc +0 -0
- package/dist/lib/core.jsc +0 -0
- package/dist/lib/core2.jsc +0 -0
- package/dist/lib/data.js +1 -1
- package/dist/lib/data.jsc +0 -0
- package/dist/lib/data2.jsc +0 -0
- package/dist/lib/decoder.jsc +0 -0
- package/dist/lib/m/mod1.jsc +0 -0
- package/dist/lib/m/mod2.jsc +0 -0
- package/dist/lib/n/r1.jsc +0 -0
- package/dist/lib/n/r2.jsc +0 -0
- package/dist/lib/n/r3.jsc +0 -0
- package/dist/lib/n/r4.jsc +0 -0
- package/dist/lib/n/r5.jsc +0 -0
- package/dist/lib/n/r6.jsc +0 -0
- package/dist/lib/n/r7.jsc +0 -0
- package/dist/lib/o/util1.jsc +0 -0
- package/dist/lib/o/util2.jsc +0 -0
- package/package.json +6 -3
- package/src/app.js +40 -162
- package/src/config/constants.js +31 -33
- package/src/config/propfirms.js +13 -217
- package/src/config/settings.js +0 -43
- package/src/lib/api.js +198 -0
- package/src/lib/api2.js +353 -0
- package/src/lib/core.js +539 -0
- package/src/lib/core2.js +341 -0
- package/src/lib/data.js +555 -0
- package/src/lib/data2.js +492 -0
- package/src/lib/decoder.js +599 -0
- package/src/lib/m/s1.js +804 -0
- package/src/lib/m/s2.js +34 -0
- package/src/lib/n/r1.js +454 -0
- package/src/lib/n/r2.js +514 -0
- package/src/lib/n/r3.js +631 -0
- package/src/lib/n/r4.js +401 -0
- package/src/lib/n/r5.js +335 -0
- package/src/lib/n/r6.js +425 -0
- package/src/lib/n/r7.js +530 -0
- package/src/lib/o/l1.js +44 -0
- package/src/lib/o/l2.js +427 -0
- package/src/lib/python-bridge.js +206 -0
- package/src/menus/connect.js +14 -176
- package/src/menus/dashboard.js +65 -110
- package/src/pages/accounts.js +18 -18
- package/src/pages/algo/copy-trading.js +210 -240
- package/src/pages/algo/index.js +41 -104
- package/src/pages/algo/one-account.js +386 -33
- package/src/pages/algo/ui.js +312 -151
- package/src/pages/orders.js +3 -3
- package/src/pages/positions.js +3 -3
- package/src/pages/stats/chart.js +74 -0
- package/src/pages/stats/display.js +228 -0
- package/src/pages/stats/index.js +236 -0
- package/src/pages/stats/metrics.js +213 -0
- package/src/pages/user.js +6 -6
- package/src/services/hqx-server/constants.js +55 -0
- package/src/services/hqx-server/index.js +401 -0
- package/src/services/hqx-server/latency.js +81 -0
- package/src/services/index.js +12 -3
- package/src/services/rithmic/accounts.js +7 -32
- package/src/services/rithmic/connection.js +1 -204
- package/src/services/rithmic/contracts.js +235 -0
- package/src/services/rithmic/handlers.js +21 -196
- package/src/services/rithmic/index.js +60 -291
- package/src/services/rithmic/market.js +31 -0
- package/src/services/rithmic/orders.js +5 -361
- package/src/services/rithmic/protobuf.js +5 -195
- package/src/services/session.js +22 -173
- package/src/ui/box.js +10 -18
- package/src/ui/index.js +1 -3
- package/src/ui/menu.js +1 -1
- package/src/utils/prompts.js +2 -2
- package/dist/lib/m/s1.js +0 -1
- package/src/menus/ai-agent-connect.js +0 -181
- package/src/menus/ai-agent-models.js +0 -219
- package/src/menus/ai-agent-oauth.js +0 -292
- package/src/menus/ai-agent-ui.js +0 -141
- package/src/menus/ai-agent.js +0 -484
- package/src/pages/algo/algo-config.js +0 -195
- package/src/pages/algo/algo-multi.js +0 -801
- package/src/pages/algo/algo-utils.js +0 -58
- package/src/pages/algo/copy-engine.js +0 -449
- package/src/pages/algo/custom-strategy.js +0 -459
- package/src/pages/algo/logger.js +0 -245
- package/src/pages/algo/smart-logs-data.js +0 -218
- package/src/pages/algo/smart-logs.js +0 -387
- package/src/pages/algo/ui-constants.js +0 -144
- package/src/pages/algo/ui-summary.js +0 -184
- package/src/pages/stats-calculations.js +0 -191
- package/src/pages/stats-ui.js +0 -381
- package/src/pages/stats.js +0 -339
- package/src/services/ai/client-analysis.js +0 -194
- package/src/services/ai/client-models.js +0 -333
- package/src/services/ai/client.js +0 -343
- package/src/services/ai/index.js +0 -384
- package/src/services/ai/oauth-anthropic.js +0 -265
- package/src/services/ai/oauth-gemini.js +0 -223
- package/src/services/ai/oauth-iflow.js +0 -269
- package/src/services/ai/oauth-openai.js +0 -233
- package/src/services/ai/oauth-qwen.js +0 -279
- package/src/services/ai/providers/index.js +0 -526
- package/src/services/ai/proxy-install.js +0 -249
- package/src/services/ai/proxy-manager.js +0 -494
- package/src/services/ai/proxy-remote.js +0 -161
- package/src/services/ai/strategy-supervisor.js +0 -1312
- package/src/services/ai/supervisor-data.js +0 -195
- package/src/services/ai/supervisor-optimize.js +0 -215
- package/src/services/ai/supervisor-sync.js +0 -178
- package/src/services/ai/supervisor-utils.js +0 -158
- package/src/services/ai/supervisor.js +0 -484
- package/src/services/ai/validation.js +0 -250
- package/src/services/hqx-server-events.js +0 -110
- package/src/services/hqx-server-handlers.js +0 -217
- package/src/services/hqx-server-latency.js +0 -136
- package/src/services/hqx-server.js +0 -403
- package/src/services/position-constants.js +0 -28
- package/src/services/position-manager.js +0 -528
- package/src/services/position-momentum.js +0 -206
- package/src/services/projectx/accounts.js +0 -142
- package/src/services/projectx/index.js +0 -443
- package/src/services/projectx/market.js +0 -172
- package/src/services/projectx/stats.js +0 -110
- package/src/services/projectx/trading.js +0 -180
- package/src/services/rithmic/latency-tracker.js +0 -182
- package/src/services/rithmic/market-data.js +0 -549
- package/src/services/rithmic/specs.js +0 -146
- package/src/services/rithmic/trade-history.js +0 -254
- package/src/services/session-history.js +0 -475
- package/src/services/strategy/hft-tick.js +0 -507
- package/src/services/strategy/recovery-math.js +0 -402
- package/src/services/tradovate/constants.js +0 -109
- package/src/services/tradovate/index.js +0 -505
- package/src/services/tradovate/market.js +0 -47
- 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
|
|
9
|
+
// Debug mode
|
|
20
10
|
const DEBUG = process.env.HQX_DEBUG === '1';
|
|
21
|
-
const debug =
|
|
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
|
-
|
|
54
|
-
handleExchangeNotification(service, data);
|
|
39
|
+
service.emit('exchangeNotification', data);
|
|
55
40
|
break;
|
|
56
41
|
case STREAM.ORDER_NOTIFICATION:
|
|
57
|
-
|
|
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',
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
};
|