hedgequantx 2.6.163 → 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 (146) 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 +116 -99
  67. package/src/services/rithmic/handlers.js +21 -196
  68. package/src/services/rithmic/index.js +63 -120
  69. package/src/services/rithmic/market.js +31 -0
  70. package/src/services/rithmic/orders.js +5 -111
  71. package/src/services/rithmic/protobuf.js +384 -138
  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/direct-providers.js +0 -323
  106. package/src/services/ai/providers/index.js +0 -62
  107. package/src/services/ai/providers/other-providers.js +0 -104
  108. package/src/services/ai/proxy-install.js +0 -249
  109. package/src/services/ai/proxy-manager.js +0 -494
  110. package/src/services/ai/proxy-remote.js +0 -161
  111. package/src/services/ai/strategy-supervisor.js +0 -1312
  112. package/src/services/ai/supervisor-data.js +0 -195
  113. package/src/services/ai/supervisor-optimize.js +0 -215
  114. package/src/services/ai/supervisor-sync.js +0 -178
  115. package/src/services/ai/supervisor-utils.js +0 -158
  116. package/src/services/ai/supervisor.js +0 -484
  117. package/src/services/ai/validation.js +0 -250
  118. package/src/services/hqx-server-events.js +0 -110
  119. package/src/services/hqx-server-handlers.js +0 -217
  120. package/src/services/hqx-server-latency.js +0 -136
  121. package/src/services/hqx-server.js +0 -403
  122. package/src/services/position-constants.js +0 -28
  123. package/src/services/position-exit-logic.js +0 -174
  124. package/src/services/position-manager.js +0 -438
  125. package/src/services/position-momentum.js +0 -206
  126. package/src/services/projectx/accounts.js +0 -142
  127. package/src/services/projectx/index.js +0 -443
  128. package/src/services/projectx/market.js +0 -172
  129. package/src/services/projectx/stats.js +0 -110
  130. package/src/services/projectx/trading.js +0 -180
  131. package/src/services/rithmic/latency-tracker.js +0 -182
  132. package/src/services/rithmic/market-data-decoders.js +0 -229
  133. package/src/services/rithmic/market-data.js +0 -272
  134. package/src/services/rithmic/orders-fast.js +0 -246
  135. package/src/services/rithmic/proto-decoders.js +0 -403
  136. package/src/services/rithmic/specs.js +0 -146
  137. package/src/services/rithmic/trade-history.js +0 -254
  138. package/src/services/session-history.js +0 -475
  139. package/src/services/strategy/hft-signal-calc.js +0 -147
  140. package/src/services/strategy/hft-tick.js +0 -407
  141. package/src/services/strategy/recovery-math.js +0 -402
  142. package/src/services/tradovate/constants.js +0 -109
  143. package/src/services/tradovate/index.js +0 -392
  144. package/src/services/tradovate/market.js +0 -47
  145. package/src/services/tradovate/orders.js +0 -145
  146. 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
+ };