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
@@ -0,0 +1,34 @@
1
+ /**
2
+ * M2 Module
3
+ */
4
+ const EventEmitter = require('events');
5
+ const DP = { et: 0.6, vrng: [0.8, 2.5], cth: 0.45, mxl: 3, stk: 6, tgt: 8, ctr: 1, roc: true, mht: 10000, cd: 30000 };
6
+
7
+ class S2 extends EventEmitter {
8
+ constructor(cfg = {}) { super(); this.p = { ...DP, ...cfg }; this.ts = cfg.tickSize || 0.25; this.cid = null; this.bh = []; this.cd = { v: 0, cv: 0, tpv: 0, sd: 0 }; this.of = { bd: 0, ad: 0, lt: null }; this.st = { s: 0, t: 0, w: 0, l: 0, pnl: 0 }; this.lst = 0; this.lss = 0; }
9
+ // tickSize for tick calculations, P&L comes from API
10
+ initialize(c, ts = 0.25) { this.cid = c; this.ts = ts; this.bh = []; this.cd = { v: 0, cv: 0, tpv: 0, sd: 0 }; this.of = { bd: 0, ad: 0, lt: null }; }
11
+ processTick(t) { const { price, volume, side, timestamp } = t; this.bh.push({ p: price, v: volume || 1, s: side, t: timestamp || Date.now() }); if (this.bh.length > 500) this.bh.shift(); const tp = price; this.cd.cv += volume || 1; this.cd.tpv += tp * (volume || 1); if (this.cd.cv > 0) this.cd.v = this.cd.tpv / this.cd.cv; if (side === 'buy') this.of.bd += volume || 1; else if (side === 'sell') this.of.ad += volume || 1; this.of.lt = side; }
12
+ onTick(t) { return this.processTick(t); }
13
+ onTrade(t) { this.processTick({ price: t.price, volume: t.size || t.volume || 1, side: t.side, timestamp: t.timestamp }); }
14
+ generateSignal(cp) { if (this.bh.length < 50) return null; if (Date.now() - this.lst < this.p.cd) return null; if (this.lss >= this.p.mxl) return null; const v = this.cd.v; if (v <= 0) return null; const sd = this.csd(); if (sd <= 0) return null; const dv = (cp - v) / sd; const ad = Math.abs(dv); if (ad < this.p.vrng[0] || ad > this.p.vrng[1]) return null; let dir = null; if (dv < -this.p.et) dir = 'long'; else if (dv > this.p.et) dir = 'short'; if (!dir) return null; if (this.p.roc) { const ofc = this.cof(dir); if (!ofc) return null; } const cf = Math.min(1.0, 0.5 + ad * 0.15); if (cf < this.p.cth) return null; this.lst = Date.now(); this.st.s++; return { direction: dir, confidence: cf, zScore: dv, stopTicks: this.p.stk, targetTicks: this.p.tgt }; }
15
+ csd() { if (this.bh.length < 20) return 0; const ps = this.bh.slice(-100).map(b => b.p); const m = ps.reduce((a, b) => a + b, 0) / ps.length; const va = ps.reduce((s, p) => s + Math.pow(p - m, 2), 0) / ps.length; return Math.sqrt(va); }
16
+ cof(dir) { const tb = this.of.bd + this.of.ad; if (tb < 10) return true; const br = this.of.bd / tb; if (dir === 'long' && br > 0.45) return true; if (dir === 'short' && br < 0.55) return true; if (this.of.lt === 'buy' && dir === 'long') return true; if (this.of.lt === 'sell' && dir === 'short') return true; return false; }
17
+ recordTradeResult(pnl) { this.st.t++; this.st.pnl += pnl; if (pnl > 0) { this.st.w++; this.lss = 0; } else { this.st.l++; this.lss++; } }
18
+ getStats() { return this.st; }
19
+ reset() { this.bh = []; this.cd = { v: 0, cv: 0, tpv: 0, sd: 0 }; this.of = { bd: 0, ad: 0, lt: null }; this.lss = 0; }
20
+ }
21
+
22
+ class M2 extends EventEmitter {
23
+ constructor(cfg = {}) { super(); this.s = new S2(cfg); }
24
+ initialize(c, ts, tv) { this.s.initialize(c, ts, tv); }
25
+ processTick(t) { this.s.processTick(t); }
26
+ onTick(t) { this.s.onTick(t); const sig = this.s.generateSignal(t.price); if (sig) this.emit('signal', { side: sig.direction === 'long' ? 'buy' : 'sell', action: 'open', ...sig }); }
27
+ onTrade(t) { this.s.onTrade(t); }
28
+ generateSignal(p) { return this.s.generateSignal(p); }
29
+ recordTradeResult(p) { this.s.recordTradeResult(p); }
30
+ getStats() { return this.s.getStats(); }
31
+ reset() { this.s.reset(); this.emit('log', { type: 'info', message: 'Reset' }); }
32
+ }
33
+
34
+ module.exports = { S2, M2, DP };
@@ -0,0 +1,454 @@
1
+ /**
2
+ * Rithmic Adapter - Main Entry Point
3
+ * Complete Rithmic integration for CLI
4
+ *
5
+ * Features:
6
+ * - Market Data (TICKER_PLANT): Real-time quotes and trades
7
+ * - Trading (ORDER_PLANT): Full order management
8
+ * - P&L (PNL_PLANT): Real-time account and position P&L
9
+ * - Connection Pool: Optimized connection reuse
10
+ *
11
+ * Supported PropFirms:
12
+ * - Apex Trader Funding
13
+ * - TopstepTrader (Rithmic)
14
+ * - Bulenox (Rithmic)
15
+ * - MES Capital
16
+ * - Earn2Trade
17
+ * - TradeFundrr
18
+ * - The Trading Pit
19
+ * - Funded Futures Network
20
+ * - PropShop Trader
21
+ * - 4PropTrader
22
+ * - DayTraders.com
23
+ * - 10X Futures
24
+ * - Lucid Trading
25
+ * - Thrive Trading
26
+ * - Legends Trading
27
+ * - TradeSea
28
+ * - UProfit
29
+ * - FastTrack Trading
30
+ * - My Funded Futures
31
+ */
32
+
33
+ const EventEmitter = require('events');
34
+
35
+ // Core modules
36
+ const { RithmicConnection } = require('./r2');
37
+ const { RithmicMarketData } = require('./r4');
38
+ const { RithmicTrading } = require('./r3');
39
+ const { RithmicPnL } = require('./r5');
40
+ const { RithmicConnectionPool, rithmicPool } = require('./r6');
41
+
42
+ // Constants
43
+ const constants = require('./r7');
44
+ const {
45
+ RITHMIC_GATEWAYS,
46
+ RITHMIC_PROPFIRMS,
47
+ TEMPLATE_IDS,
48
+ INFRA_TYPES,
49
+ ORDER_TYPES,
50
+ NOTIFY_TYPES,
51
+ EXCHANGES,
52
+ getPropFirmConfig,
53
+ isRithmicPropFirm,
54
+ getSupportedPropFirms,
55
+ buildRithmicSymbol,
56
+ getCurrentFrontMonth
57
+ } = constants;
58
+
59
+ /**
60
+ * RithmicAdapter - High-level adapter that manages all connections
61
+ */
62
+ class RithmicAdapter extends EventEmitter {
63
+ constructor(options = {}) {
64
+ super();
65
+
66
+ this.marketData = null;
67
+ this.trading = null;
68
+ this.pnl = null;
69
+
70
+ this.credentials = null;
71
+ this.propfirmConfig = null;
72
+
73
+ this.debug = options.debug || false;
74
+ this.usePool = options.usePool !== false; // Default true
75
+ }
76
+
77
+ /**
78
+ * Connect to all Rithmic plants
79
+ * @param {Object} credentials
80
+ * @param {string} credentials.userId - Rithmic username
81
+ * @param {string} credentials.password - Rithmic password
82
+ * @param {string} credentials.propfirm - PropFirm name (e.g., 'apex', 'topsteptrader')
83
+ * @param {Object} options
84
+ * @param {boolean} options.marketData - Connect to market data (default: true)
85
+ * @param {boolean} options.trading - Connect to trading (default: true)
86
+ * @param {boolean} options.pnl - Connect to P&L (default: true)
87
+ */
88
+ async connect(credentials, options = {}) {
89
+ const {
90
+ marketData = true,
91
+ trading = true,
92
+ pnl = true
93
+ } = options;
94
+
95
+ this.credentials = credentials;
96
+ this.propfirmConfig = getPropFirmConfig(credentials.propfirm);
97
+
98
+ if (!this.propfirmConfig) {
99
+ throw new Error(`Unknown PropFirm: ${credentials.propfirm}. Use getSupportedPropFirms() to see available options.`);
100
+ }
101
+
102
+ const fullCredentials = {
103
+ userId: credentials.userId,
104
+ password: credentials.password,
105
+ propfirm: credentials.propfirm,
106
+ systemName: this.propfirmConfig.systemName,
107
+ gateway: this.propfirmConfig.gateway
108
+ };
109
+
110
+ const connectPromises = [];
111
+
112
+ // Connect to market data
113
+ if (marketData) {
114
+ if (this.usePool) {
115
+ connectPromises.push(
116
+ rithmicPool.getMarketData(fullCredentials).then(client => {
117
+ this.marketData = client;
118
+ this._forwardEvents(client, 'marketData');
119
+ })
120
+ );
121
+ } else {
122
+ this.marketData = new RithmicMarketData({ debug: this.debug });
123
+ connectPromises.push(
124
+ this.marketData.connect(fullCredentials).then(() => {
125
+ this._forwardEvents(this.marketData, 'marketData');
126
+ })
127
+ );
128
+ }
129
+ }
130
+
131
+ // Connect to trading
132
+ if (trading) {
133
+ if (this.usePool) {
134
+ connectPromises.push(
135
+ rithmicPool.getTrading(fullCredentials).then(client => {
136
+ this.trading = client;
137
+ this._forwardEvents(client, 'trading');
138
+ })
139
+ );
140
+ } else {
141
+ this.trading = new RithmicTrading({ debug: this.debug });
142
+ connectPromises.push(
143
+ this.trading.connect(fullCredentials).then(() => {
144
+ this._forwardEvents(this.trading, 'trading');
145
+ })
146
+ );
147
+ }
148
+ }
149
+
150
+ // Connect to P&L
151
+ if (pnl) {
152
+ if (this.usePool) {
153
+ connectPromises.push(
154
+ rithmicPool.getPnL(fullCredentials).then(client => {
155
+ this.pnl = client;
156
+ this._forwardEvents(client, 'pnl');
157
+ })
158
+ );
159
+ } else {
160
+ this.pnl = new RithmicPnL({ debug: this.debug });
161
+ connectPromises.push(
162
+ this.pnl.connect(fullCredentials).then(() => {
163
+ this._forwardEvents(this.pnl, 'pnl');
164
+ })
165
+ );
166
+ }
167
+ }
168
+
169
+ // Wait for all connections
170
+ await Promise.all(connectPromises);
171
+
172
+ this.emit('connected', {
173
+ propfirm: this.propfirmConfig.displayName,
174
+ marketData: !!this.marketData,
175
+ trading: !!this.trading,
176
+ pnl: !!this.pnl
177
+ });
178
+
179
+ return true;
180
+ }
181
+
182
+ /**
183
+ * Forward events from sub-modules
184
+ */
185
+ _forwardEvents(module, prefix) {
186
+ const events = ['tick', 'quote', 'trade', 'order', 'fill', 'reject', 'cancel', 'position', 'accountPnL', 'instrumentPnL', 'error'];
187
+
188
+ for (const event of events) {
189
+ module.on(event, (data) => {
190
+ this.emit(`${prefix}:${event}`, data);
191
+ this.emit(event, data); // Also emit without prefix
192
+ });
193
+ }
194
+ }
195
+
196
+ // ===========================================================================
197
+ // MARKET DATA
198
+ // ===========================================================================
199
+
200
+ /**
201
+ * Subscribe to market data
202
+ * @param {string} symbol - Rithmic symbol (e.g., 'MNQH5')
203
+ * @param {string} exchange - Exchange (default: 'CME')
204
+ */
205
+ async subscribe(symbol, exchange = 'CME') {
206
+ if (!this.marketData) {
207
+ throw new Error('Market data not connected');
208
+ }
209
+ return this.marketData.subscribe(symbol, exchange);
210
+ }
211
+
212
+ /**
213
+ * Unsubscribe from market data
214
+ */
215
+ async unsubscribe(symbol, exchange = 'CME') {
216
+ if (!this.marketData) return false;
217
+ return this.marketData.unsubscribe(symbol, exchange);
218
+ }
219
+
220
+ /**
221
+ * Get last price
222
+ */
223
+ getLastPrice(symbol) {
224
+ if (!this.marketData) return 0;
225
+ return this.marketData.getLastPrice(symbol);
226
+ }
227
+
228
+ /**
229
+ * Get current quote
230
+ */
231
+ getQuote(symbol) {
232
+ if (!this.marketData) return null;
233
+ return this.marketData.getQuote(symbol);
234
+ }
235
+
236
+ // ===========================================================================
237
+ // TRADING
238
+ // ===========================================================================
239
+
240
+ /**
241
+ * Place a market order
242
+ * @param {string} accountId - Account ID
243
+ * @param {string} symbol - Symbol (e.g., 'MNQH6')
244
+ * @param {string} side - 'buy' or 'sell'
245
+ * @param {number} quantity - Number of contracts
246
+ * @param {string} exchange - Exchange (default: 'CME')
247
+ */
248
+ async placeMarketOrder(accountId, symbol, side, quantity, exchange = 'CME') {
249
+ if (!this.trading) {
250
+ throw new Error('Trading not connected');
251
+ }
252
+ // trading.placeMarketOrder expects: (accountId, symbol, exchange, side, quantity)
253
+ return this.trading.placeMarketOrder(accountId, symbol, exchange, side, quantity);
254
+ }
255
+
256
+ /**
257
+ * Place a limit order
258
+ */
259
+ async placeLimitOrder(accountId, symbol, side, quantity, price, exchange = 'CME') {
260
+ if (!this.trading) {
261
+ throw new Error('Trading not connected');
262
+ }
263
+ // trading.placeLimitOrder expects: (accountId, symbol, exchange, side, quantity, price)
264
+ return this.trading.placeLimitOrder(accountId, symbol, exchange, side, quantity, price);
265
+ }
266
+
267
+ /**
268
+ * Place a stop market order
269
+ */
270
+ async placeStopMarketOrder(accountId, symbol, side, quantity, stopPrice, exchange = 'CME') {
271
+ if (!this.trading) {
272
+ throw new Error('Trading not connected');
273
+ }
274
+ return this.trading.placeStopMarketOrder(accountId, symbol, exchange, side, quantity, stopPrice);
275
+ }
276
+
277
+ /**
278
+ * Place a stop limit order
279
+ */
280
+ async placeStopLimitOrder(accountId, symbol, side, quantity, stopPrice, limitPrice, exchange = 'CME') {
281
+ if (!this.trading) {
282
+ throw new Error('Trading not connected');
283
+ }
284
+ return this.trading.placeStopLimitOrder(accountId, symbol, exchange, side, quantity, stopPrice, limitPrice);
285
+ }
286
+
287
+ /**
288
+ * Cancel an order
289
+ */
290
+ async cancelOrder(basketId) {
291
+ if (!this.trading) {
292
+ throw new Error('Trading not connected');
293
+ }
294
+ return this.trading.cancelOrder(basketId);
295
+ }
296
+
297
+ /**
298
+ * Cancel all orders
299
+ */
300
+ async cancelAllOrders(accountId) {
301
+ if (!this.trading) {
302
+ throw new Error('Trading not connected');
303
+ }
304
+ return this.trading.cancelAllOrders(accountId);
305
+ }
306
+
307
+ /**
308
+ * Close a position
309
+ */
310
+ async closePosition(accountId, symbol, exchange = 'CME') {
311
+ if (!this.trading) {
312
+ throw new Error('Trading not connected');
313
+ }
314
+ return this.trading.closePosition(accountId, symbol, exchange);
315
+ }
316
+
317
+ /**
318
+ * Get open orders
319
+ */
320
+ getOpenOrders() {
321
+ if (!this.trading) return [];
322
+ return this.trading.getOpenOrders();
323
+ }
324
+
325
+ /**
326
+ * Get accounts
327
+ */
328
+ getAccounts() {
329
+ if (!this.trading) return [];
330
+ return this.trading.getAccounts();
331
+ }
332
+
333
+ // ===========================================================================
334
+ // P&L
335
+ // ===========================================================================
336
+
337
+ /**
338
+ * Subscribe to P&L updates
339
+ */
340
+ async subscribePnL(accountId) {
341
+ if (!this.pnl) {
342
+ throw new Error('P&L not connected');
343
+ }
344
+ return this.pnl.subscribe(accountId);
345
+ }
346
+
347
+ /**
348
+ * Get account P&L
349
+ */
350
+ getAccountPnL(accountId) {
351
+ if (!this.pnl) return null;
352
+ return this.pnl.getAccountPnL(accountId);
353
+ }
354
+
355
+ /**
356
+ * Get instrument P&L
357
+ */
358
+ getInstrumentPnL(accountId, symbol) {
359
+ if (!this.pnl) return null;
360
+ return this.pnl.getInstrumentPnL(accountId, symbol);
361
+ }
362
+
363
+ /**
364
+ * Get all positions
365
+ */
366
+ getPositions(accountId) {
367
+ if (!this.pnl) return [];
368
+ return this.pnl.getPositions(accountId);
369
+ }
370
+
371
+ // ===========================================================================
372
+ // STATUS
373
+ // ===========================================================================
374
+
375
+ /**
376
+ * Check if fully connected
377
+ */
378
+ get isConnected() {
379
+ return (
380
+ (!this.marketData || this.marketData.isConnected) &&
381
+ (!this.trading || this.trading.isConnected) &&
382
+ (!this.pnl || this.pnl.isConnected)
383
+ );
384
+ }
385
+
386
+ /**
387
+ * Get connection status
388
+ */
389
+ getStatus() {
390
+ return {
391
+ propfirm: this.propfirmConfig?.displayName || 'Not connected',
392
+ marketData: this.marketData?.isConnected || false,
393
+ trading: this.trading?.isConnected || false,
394
+ pnl: this.pnl?.isConnected || false,
395
+ pool: this.usePool ? rithmicPool.getStats() : null
396
+ };
397
+ }
398
+
399
+ /**
400
+ * Disconnect all
401
+ */
402
+ async disconnect() {
403
+ if (this.usePool && this.credentials) {
404
+ // Release to pool
405
+ rithmicPool.release(
406
+ this.credentials.userId,
407
+ this.propfirmConfig?.systemName || 'unknown'
408
+ );
409
+ } else {
410
+ // Disconnect directly
411
+ if (this.marketData) await this.marketData.disconnect();
412
+ if (this.trading) await this.trading.disconnect();
413
+ if (this.pnl) await this.pnl.disconnect();
414
+ }
415
+
416
+ this.marketData = null;
417
+ this.trading = null;
418
+ this.pnl = null;
419
+
420
+ this.emit('disconnected');
421
+ }
422
+ }
423
+
424
+ // Export everything
425
+ module.exports = {
426
+ // Main adapter
427
+ RithmicAdapter,
428
+
429
+ // Individual modules
430
+ RithmicConnection,
431
+ RithmicMarketData,
432
+ RithmicTrading,
433
+ RithmicPnL,
434
+ RithmicConnectionPool,
435
+
436
+ // Singleton pool
437
+ rithmicPool,
438
+
439
+ // Constants
440
+ RITHMIC_GATEWAYS,
441
+ RITHMIC_PROPFIRMS,
442
+ TEMPLATE_IDS,
443
+ INFRA_TYPES,
444
+ ORDER_TYPES,
445
+ NOTIFY_TYPES,
446
+ EXCHANGES,
447
+
448
+ // Helpers
449
+ getPropFirmConfig,
450
+ isRithmicPropFirm,
451
+ getSupportedPropFirms,
452
+ buildRithmicSymbol,
453
+ getCurrentFrontMonth
454
+ };