hedgequantx 2.6.163 → 2.7.1

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 +8 -5
  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
@@ -1,250 +0,0 @@
1
- /**
2
- * AI Provider Validation Functions
3
- * @module services/ai/validation
4
- *
5
- * API key and endpoint validation for all AI providers.
6
- */
7
-
8
- const { getProvider } = require('./providers');
9
-
10
- /**
11
- * Validate API key with provider
12
- */
13
- const validateConnection = async (providerId, optionId, credentials) => {
14
- const provider = getProvider(providerId);
15
- if (!provider) return { valid: false, error: 'Invalid provider' };
16
-
17
- try {
18
- switch (providerId) {
19
- case 'anthropic':
20
- return await validateAnthropic(credentials);
21
- case 'openai':
22
- return await validateOpenAI(credentials);
23
- case 'gemini':
24
- return await validateGemini(credentials);
25
- case 'deepseek':
26
- return await validateDeepSeek(credentials);
27
- case 'groq':
28
- return await validateGroq(credentials);
29
- case 'ollama':
30
- return await validateOllama(credentials);
31
- case 'lmstudio':
32
- return await validateLMStudio(credentials);
33
- case 'custom':
34
- return await validateCustom(credentials);
35
- case 'openrouter':
36
- return await validateOpenRouter(credentials);
37
- case 'xai':
38
- case 'mistral':
39
- case 'perplexity':
40
- case 'together':
41
- case 'qwen':
42
- case 'moonshot':
43
- case 'yi':
44
- case 'zhipu':
45
- case 'baichuan':
46
- return await validateOpenAICompatible(provider, credentials);
47
- default:
48
- return { valid: false, error: 'Unknown provider' };
49
- }
50
- } catch (error) {
51
- return { valid: false, error: error.message };
52
- }
53
- };
54
-
55
- /** Validate Anthropic API key */
56
- const validateAnthropic = async (credentials) => {
57
- try {
58
- const token = credentials.apiKey || credentials.sessionKey || credentials.accessToken;
59
- if (!token) return { valid: false, error: 'No API key provided' };
60
-
61
- const response = await fetch('https://api.anthropic.com/v1/models', {
62
- method: 'GET',
63
- headers: {
64
- 'x-api-key': token,
65
- 'anthropic-version': '2023-06-01'
66
- }
67
- });
68
-
69
- if (response.ok) {
70
- const data = await response.json();
71
- if (data.data && Array.isArray(data.data) && data.data.length > 0) {
72
- return { valid: true, tokenType: 'api_key' };
73
- }
74
- return { valid: false, error: 'API returned no models' };
75
- }
76
-
77
- const error = await response.json();
78
- return { valid: false, error: error.error?.message || 'Invalid API key' };
79
- } catch (e) {
80
- return { valid: false, error: e.message };
81
- }
82
- };
83
-
84
- /** Validate OpenAI API key */
85
- const validateOpenAI = async (credentials) => {
86
- try {
87
- const response = await fetch('https://api.openai.com/v1/models', {
88
- headers: {
89
- 'Authorization': `Bearer ${credentials.apiKey || credentials.accessToken}`
90
- }
91
- });
92
-
93
- if (response.ok) return { valid: true };
94
- return { valid: false, error: 'Invalid API key' };
95
- } catch (e) {
96
- return { valid: false, error: e.message };
97
- }
98
- };
99
-
100
- /** Validate Gemini API key */
101
- const validateGemini = async (credentials) => {
102
- try {
103
- const response = await fetch(
104
- `https://generativelanguage.googleapis.com/v1/models?key=${credentials.apiKey}`
105
- );
106
-
107
- if (response.ok) return { valid: true };
108
- return { valid: false, error: 'Invalid API key' };
109
- } catch (e) {
110
- return { valid: false, error: e.message };
111
- }
112
- };
113
-
114
- /** Validate DeepSeek API key */
115
- const validateDeepSeek = async (credentials) => {
116
- try {
117
- const response = await fetch('https://api.deepseek.com/v1/models', {
118
- headers: { 'Authorization': `Bearer ${credentials.apiKey}` }
119
- });
120
-
121
- if (response.ok) return { valid: true };
122
- return { valid: false, error: 'Invalid API key' };
123
- } catch (e) {
124
- return { valid: false, error: e.message };
125
- }
126
- };
127
-
128
- /** Validate Groq API key */
129
- const validateGroq = async (credentials) => {
130
- try {
131
- const response = await fetch('https://api.groq.com/openai/v1/models', {
132
- headers: { 'Authorization': `Bearer ${credentials.apiKey}` }
133
- });
134
-
135
- if (response.ok) return { valid: true };
136
- return { valid: false, error: 'Invalid API key' };
137
- } catch (e) {
138
- return { valid: false, error: e.message };
139
- }
140
- };
141
-
142
- /** Validate Ollama local instance */
143
- const validateOllama = async (credentials) => {
144
- try {
145
- const endpoint = credentials.endpoint || 'http://localhost:11434';
146
- const response = await fetch(`${endpoint}/api/tags`);
147
-
148
- if (response.ok) {
149
- const data = await response.json();
150
- return { valid: true, models: data.models?.map(m => m.name) || [] };
151
- }
152
-
153
- return { valid: false, error: 'Cannot connect to Ollama' };
154
- } catch (e) {
155
- return { valid: false, error: 'Ollama not running. Start with: ollama serve' };
156
- }
157
- };
158
-
159
- /** Validate LM Studio local instance */
160
- const validateLMStudio = async (credentials) => {
161
- try {
162
- const endpoint = credentials.endpoint || 'http://localhost:1234/v1';
163
- const response = await fetch(`${endpoint}/models`);
164
-
165
- if (response.ok) {
166
- const data = await response.json();
167
- return { valid: true, models: data.data?.map(m => m.id) || [] };
168
- }
169
-
170
- return { valid: false, error: 'Cannot connect to LM Studio' };
171
- } catch (e) {
172
- return { valid: false, error: 'LM Studio not running. Start local server first.' };
173
- }
174
- };
175
-
176
- /** Validate custom endpoint */
177
- const validateCustom = async (credentials) => {
178
- try {
179
- const response = await fetch(`${credentials.endpoint}/models`, {
180
- headers: credentials.apiKey ? { 'Authorization': `Bearer ${credentials.apiKey}` } : {}
181
- });
182
-
183
- if (response.ok) return { valid: true };
184
- return { valid: false, error: 'Cannot connect to endpoint' };
185
- } catch (e) {
186
- return { valid: false, error: e.message };
187
- }
188
- };
189
-
190
- /** Validate OpenRouter API key */
191
- const validateOpenRouter = async (credentials) => {
192
- try {
193
- const response = await fetch('https://openrouter.ai/api/v1/models', {
194
- headers: { 'Authorization': `Bearer ${credentials.apiKey}` }
195
- });
196
-
197
- if (response.ok) return { valid: true };
198
- return { valid: false, error: 'Invalid API key' };
199
- } catch (e) {
200
- return { valid: false, error: e.message };
201
- }
202
- };
203
-
204
- /** Validate OpenAI-compatible providers */
205
- const validateOpenAICompatible = async (provider, credentials) => {
206
- try {
207
- const endpoint = provider.endpoint;
208
- const response = await fetch(`${endpoint}/models`, {
209
- headers: {
210
- 'Authorization': `Bearer ${credentials.apiKey}`,
211
- 'Content-Type': 'application/json'
212
- }
213
- });
214
-
215
- if (response.ok) return { valid: true };
216
-
217
- // Some providers don't have /models endpoint, try a simple chat
218
- const chatResponse = await fetch(`${endpoint}/chat/completions`, {
219
- method: 'POST',
220
- headers: {
221
- 'Authorization': `Bearer ${credentials.apiKey}`,
222
- 'Content-Type': 'application/json'
223
- },
224
- body: JSON.stringify({
225
- model: provider.defaultModel,
226
- messages: [{ role: 'user', content: 'hi' }],
227
- max_tokens: 5
228
- })
229
- });
230
-
231
- if (chatResponse.ok) return { valid: true };
232
- return { valid: false, error: 'Invalid API key or endpoint' };
233
- } catch (e) {
234
- return { valid: false, error: e.message };
235
- }
236
- };
237
-
238
- module.exports = {
239
- validateConnection,
240
- validateAnthropic,
241
- validateOpenAI,
242
- validateGemini,
243
- validateDeepSeek,
244
- validateGroq,
245
- validateOllama,
246
- validateLMStudio,
247
- validateCustom,
248
- validateOpenRouter,
249
- validateOpenAICompatible,
250
- };
@@ -1,110 +0,0 @@
1
- /**
2
- * @fileoverview HQX Server Event Management
3
- * @module services/hqx-server-events
4
- *
5
- * Lightweight event emitter for HQX WebSocket service.
6
- * Optimized for performance with inlined loops.
7
- */
8
-
9
- /**
10
- * Event emitter mixin for HQXServerService
11
- * These functions should be called with .call(this) to bind to service instance
12
- */
13
-
14
- /**
15
- * Register event listener
16
- * @param {Map} listeners - Listeners map
17
- * @param {string} event - Event name
18
- * @param {Function} callback - Callback function
19
- */
20
- function on(listeners, event, callback) {
21
- if (!listeners.has(event)) {
22
- listeners.set(event, []);
23
- }
24
- listeners.get(event).push(callback);
25
- }
26
-
27
- /**
28
- * Remove event listener
29
- * @param {Map} listeners - Listeners map
30
- * @param {string} event - Event name
31
- * @param {Function} callback - Callback function
32
- */
33
- function off(listeners, event, callback) {
34
- const callbacks = listeners.get(event);
35
- if (callbacks) {
36
- const index = callbacks.indexOf(callback);
37
- if (index > -1) callbacks.splice(index, 1);
38
- }
39
- }
40
-
41
- /**
42
- * Emit event (inlined for speed)
43
- * @param {Map} listeners - Listeners map
44
- * @param {string} event - Event name
45
- * @param {*} data - Event data
46
- */
47
- function emit(listeners, event, data) {
48
- const callbacks = listeners.get(event);
49
- if (!callbacks) return;
50
-
51
- for (let i = 0; i < callbacks.length; i++) {
52
- try {
53
- callbacks[i](data);
54
- } catch {
55
- // Don't let callback errors break the loop
56
- }
57
- }
58
- }
59
-
60
- /**
61
- * Clear all listeners
62
- * @param {Map} listeners - Listeners map
63
- */
64
- function clearAll(listeners) {
65
- listeners.clear();
66
- }
67
-
68
- /**
69
- * Remove all listeners for a specific event
70
- * @param {Map} listeners - Listeners map
71
- * @param {string} event - Event name
72
- */
73
- function removeAllListeners(listeners, event) {
74
- if (event) {
75
- listeners.delete(event);
76
- } else {
77
- listeners.clear();
78
- }
79
- }
80
-
81
- /**
82
- * Get listener count for an event
83
- * @param {Map} listeners - Listeners map
84
- * @param {string} event - Event name
85
- * @returns {number}
86
- */
87
- function listenerCount(listeners, event) {
88
- const callbacks = listeners.get(event);
89
- return callbacks ? callbacks.length : 0;
90
- }
91
-
92
- /**
93
- * Check if event has listeners
94
- * @param {Map} listeners - Listeners map
95
- * @param {string} event - Event name
96
- * @returns {boolean}
97
- */
98
- function hasListeners(listeners, event) {
99
- return listenerCount(listeners, event) > 0;
100
- }
101
-
102
- module.exports = {
103
- on,
104
- off,
105
- emit,
106
- clearAll,
107
- removeAllListeners,
108
- listenerCount,
109
- hasListeners,
110
- };
@@ -1,217 +0,0 @@
1
- /**
2
- * @fileoverview HQX Server Message Handlers
3
- * @module services/hqx-server-handlers
4
- *
5
- * Message parsing and handling for HQX WebSocket.
6
- * Optimized for ultra-low latency trading signals.
7
- */
8
-
9
- const { logger } = require('../utils/logger');
10
- const log = logger.scope('HQX');
11
-
12
- /** Message types as bytes for faster switching */
13
- const MSG_TYPE = {
14
- // Outgoing
15
- PING: 0x01,
16
- START_ALGO: 0x10,
17
- STOP_ALGO: 0x11,
18
- START_COPY: 0x12,
19
- ORDER: 0x20,
20
-
21
- // Incoming
22
- PONG: 0x81,
23
- SIGNAL: 0x90,
24
- TRADE: 0x91,
25
- FILL: 0x92,
26
- LOG: 0xA0,
27
- STATS: 0xA1,
28
- ERROR: 0xFF,
29
- };
30
-
31
- /**
32
- * Fast JSON parse with type hint
33
- * @param {string|Buffer} data
34
- * @returns {Object}
35
- */
36
- const fastParse = (data) => {
37
- const str = typeof data === 'string' ? data : data.toString('utf8');
38
- return JSON.parse(str);
39
- };
40
-
41
- /**
42
- * Handle binary trading signal (zero-copy)
43
- * @param {Buffer} data
44
- * @param {Function} emit - Emit function
45
- */
46
- function handleBinarySignal(data, emit) {
47
- // Binary format: [type:1][timestamp:8][side:1][price:8][qty:4]
48
- if (data.length >= 22) {
49
- const signal = {
50
- timestamp: data.readBigInt64LE(1),
51
- side: data.readUInt8(9),
52
- price: data.readDoubleLE(10),
53
- quantity: data.readUInt32LE(18),
54
- };
55
- emit('signal', signal);
56
- }
57
- }
58
-
59
- /**
60
- * Handle pong with latency calculation
61
- * @param {Buffer} data
62
- * @param {bigint} receiveTime
63
- * @param {number} lastPingTime
64
- * @param {Function} updateLatency
65
- */
66
- function handlePong(data, receiveTime, lastPingTime, updateLatency) {
67
- if (lastPingTime > 0) {
68
- // Use high-resolution timer
69
- const latency = Number(receiveTime - lastPingTime) / 1e6; // ns to ms
70
- updateLatency(latency);
71
- }
72
- }
73
-
74
- /**
75
- * Handle JSON message
76
- * @param {Object} message
77
- * @param {bigint} receiveTime
78
- * @param {Function} emit
79
- * @param {Function} updateLatency
80
- */
81
- function handleJsonMessage(message, receiveTime, emit, updateLatency) {
82
- // Calculate latency from server timestamp
83
- if (message.timestamp) {
84
- const latency = Date.now() - message.timestamp;
85
- if (latency >= 0 && latency < 5000) {
86
- updateLatency(latency);
87
- }
88
- }
89
-
90
- // Fast dispatch
91
- switch (message.type) {
92
- case 'signal':
93
- emit('signal', message.data);
94
- break;
95
- case 'trade':
96
- emit('trade', message.data);
97
- break;
98
- case 'fill':
99
- emit('fill', message.data);
100
- break;
101
- case 'log':
102
- emit('log', message.data);
103
- break;
104
- case 'stats':
105
- emit('stats', message.data);
106
- break;
107
- case 'error':
108
- emit('error', message.data);
109
- break;
110
- case 'pong':
111
- // Already handled in binary path
112
- break;
113
- default:
114
- emit('message', message);
115
- }
116
- }
117
-
118
- /**
119
- * Process incoming message
120
- * @param {Object} ctx - Service context
121
- * @param {Buffer|string} data - Raw message data
122
- * @param {Function} emit - Emit function
123
- * @param {Function} updateLatency - Latency update function
124
- */
125
- function processMessage(ctx, data, emit, updateLatency) {
126
- const receiveTime = process.hrtime.bigint();
127
- ctx.messagesReceived++;
128
- ctx.bytesReceived += data.length;
129
-
130
- try {
131
- // Try binary format first (faster)
132
- if (Buffer.isBuffer(data) && data.length > 0) {
133
- const msgType = data.readUInt8(0);
134
-
135
- // Fast path for pong
136
- if (msgType === MSG_TYPE.PONG) {
137
- handlePong(data, receiveTime, ctx.lastPingTime, updateLatency);
138
- return;
139
- }
140
-
141
- // Binary signal (fastest path)
142
- if (msgType === MSG_TYPE.SIGNAL) {
143
- handleBinarySignal(data, emit);
144
- return;
145
- }
146
- }
147
-
148
- // JSON fallback
149
- const message = fastParse(data);
150
- handleJsonMessage(message, receiveTime, emit, updateLatency);
151
-
152
- } catch (err) {
153
- log.warn('Message parse error', { error: err.message });
154
- }
155
- }
156
-
157
- /**
158
- * Build algo config payload
159
- * @param {Object} config
160
- * @returns {Object}
161
- */
162
- function buildAlgoPayload(config) {
163
- return {
164
- accountId: config.accountId,
165
- contractId: config.contractId,
166
- symbol: config.symbol,
167
- contracts: config.contracts,
168
- dailyTarget: config.dailyTarget,
169
- maxRisk: config.maxRisk,
170
- propfirm: config.propfirm,
171
- propfirmToken: config.propfirmToken,
172
- rithmicCredentials: config.rithmicCredentials || null,
173
- copyTrading: config.copyTrading || false,
174
- followerSymbol: config.followerSymbol,
175
- followerContracts: config.followerContracts,
176
- };
177
- }
178
-
179
- /**
180
- * Build copy trading config payload
181
- * @param {Object} config
182
- * @returns {Object}
183
- */
184
- function buildCopyTradingPayload(config) {
185
- return {
186
- // Lead
187
- leadAccountId: config.leadAccountId,
188
- leadContractId: config.leadContractId,
189
- leadSymbol: config.leadSymbol,
190
- leadContracts: config.leadContracts,
191
- leadPropfirm: config.leadPropfirm,
192
- leadToken: config.leadToken,
193
- leadRithmicCredentials: config.leadRithmicCredentials,
194
- // Follower
195
- followerAccountId: config.followerAccountId,
196
- followerContractId: config.followerContractId,
197
- followerSymbol: config.followerSymbol,
198
- followerContracts: config.followerContracts,
199
- followerPropfirm: config.followerPropfirm,
200
- followerToken: config.followerToken,
201
- followerRithmicCredentials: config.followerRithmicCredentials,
202
- // Targets
203
- dailyTarget: config.dailyTarget,
204
- maxRisk: config.maxRisk,
205
- };
206
- }
207
-
208
- module.exports = {
209
- MSG_TYPE,
210
- fastParse,
211
- handleBinarySignal,
212
- handlePong,
213
- handleJsonMessage,
214
- processMessage,
215
- buildAlgoPayload,
216
- buildCopyTradingPayload,
217
- };
@@ -1,136 +0,0 @@
1
- /**
2
- * @fileoverview HQX Server Latency Management
3
- * @module services/hqx-server-latency
4
- *
5
- * Handles latency tracking, adaptive heartbeat, and connection statistics.
6
- */
7
-
8
- /**
9
- * Latency manager mixin for HQXServerService
10
- * Call with .call(this) to bind to service instance
11
- */
12
-
13
- /**
14
- * Update latency statistics
15
- * @param {number} latency - Latency in ms
16
- */
17
- function updateLatency(latency) {
18
- this.latency = latency;
19
- this.minLatency = Math.min(this.minLatency, latency);
20
- this.maxLatency = Math.max(this.maxLatency, latency);
21
-
22
- // Rolling average (last 100 samples)
23
- this.latencySamples.push(latency);
24
- if (this.latencySamples.length > 100) {
25
- this.latencySamples.shift();
26
- }
27
- this.avgLatency = this.latencySamples.reduce((a, b) => a + b, 0) / this.latencySamples.length;
28
-
29
- // Adapt heartbeat based on latency
30
- adaptHeartbeat.call(this);
31
-
32
- this._emit('latency', {
33
- current: latency,
34
- min: this.minLatency,
35
- max: this.maxLatency,
36
- avg: this.avgLatency
37
- });
38
- }
39
-
40
- /**
41
- * Adapt heartbeat interval based on connection quality
42
- */
43
- function adaptHeartbeat() {
44
- // Good connection: slower heartbeat (less overhead)
45
- // Poor connection: faster heartbeat (detect issues quickly)
46
- if (this.avgLatency < 10) {
47
- this.adaptiveHeartbeat = 2000; // <10ms: 2s heartbeat
48
- } else if (this.avgLatency < 50) {
49
- this.adaptiveHeartbeat = 1000; // <50ms: 1s heartbeat
50
- } else if (this.avgLatency < 100) {
51
- this.adaptiveHeartbeat = 500; // <100ms: 500ms heartbeat
52
- } else {
53
- this.adaptiveHeartbeat = 250; // High latency: 250ms heartbeat
54
- }
55
- }
56
-
57
- /**
58
- * Start adaptive heartbeat
59
- * @param {Function} sendPing - Function to send ping
60
- */
61
- function startHeartbeat(sendPing) {
62
- stopHeartbeat.call(this);
63
-
64
- const heartbeat = () => {
65
- if (this.connected) {
66
- sendPing();
67
-
68
- // Schedule next with adaptive interval
69
- this.pingInterval = setTimeout(heartbeat, this.adaptiveHeartbeat);
70
- }
71
- };
72
-
73
- // First ping immediately
74
- sendPing();
75
- this.pingInterval = setTimeout(heartbeat, this.adaptiveHeartbeat);
76
- }
77
-
78
- /**
79
- * Stop heartbeat
80
- */
81
- function stopHeartbeat() {
82
- if (this.pingInterval) {
83
- clearTimeout(this.pingInterval);
84
- this.pingInterval = null;
85
- }
86
- }
87
-
88
- /**
89
- * Get latency statistics
90
- * @returns {Object}
91
- */
92
- function getLatencyStats() {
93
- return {
94
- current: this.latency,
95
- min: this.minLatency === Infinity ? 0 : this.minLatency,
96
- max: this.maxLatency,
97
- avg: this.avgLatency,
98
- samples: this.latencySamples.length,
99
- };
100
- }
101
-
102
- /**
103
- * Get connection statistics
104
- * @returns {Object}
105
- */
106
- function getConnectionStats() {
107
- return {
108
- connected: this.connected,
109
- messagesSent: this.messagesSent,
110
- messagesReceived: this.messagesReceived,
111
- bytesReceived: this.bytesReceived,
112
- heartbeatInterval: this.adaptiveHeartbeat,
113
- latency: getLatencyStats.call(this),
114
- };
115
- }
116
-
117
- /**
118
- * Reset latency stats
119
- */
120
- function resetLatencyStats() {
121
- this.latencySamples = [];
122
- this.minLatency = Infinity;
123
- this.maxLatency = 0;
124
- this.avgLatency = 0;
125
- this.latency = 0;
126
- }
127
-
128
- module.exports = {
129
- updateLatency,
130
- adaptHeartbeat,
131
- startHeartbeat,
132
- stopHeartbeat,
133
- getLatencyStats,
134
- getConnectionStats,
135
- resetLatencyStats,
136
- };