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,403 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HQX Server Service - Ultra Low Latency WebSocket for Scalping
|
|
3
|
-
* Optimized for sub-ms message handling with TCP_NODELAY and binary format
|
|
4
|
-
* @module services/hqx-server
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const WebSocket = require('ws');
|
|
8
|
-
const crypto = require('crypto');
|
|
9
|
-
const os = require('os');
|
|
10
|
-
const { request } = require('../utils/http');
|
|
11
|
-
const { HQX_SERVER, TIMEOUTS, SECURITY } = require('../config/settings');
|
|
12
|
-
const { logger } = require('../utils/logger');
|
|
13
|
-
const latencyMgr = require('./hqx-server-latency');
|
|
14
|
-
const eventMgr = require('./hqx-server-events');
|
|
15
|
-
const handlers = require('./hqx-server-handlers');
|
|
16
|
-
|
|
17
|
-
const log = logger.scope('HQX');
|
|
18
|
-
|
|
19
|
-
// Re-export MSG_TYPE from handlers
|
|
20
|
-
const { MSG_TYPE } = handlers;
|
|
21
|
-
|
|
22
|
-
/** Pre-allocated ping buffer */
|
|
23
|
-
const PING_BUFFER = Buffer.alloc(9);
|
|
24
|
-
PING_BUFFER.writeUInt8(MSG_TYPE.PING, 0);
|
|
25
|
-
|
|
26
|
-
/** Fast JSON stringify */
|
|
27
|
-
const fastStringify = (obj) => {
|
|
28
|
-
if (obj === null) return 'null';
|
|
29
|
-
if (typeof obj !== 'object') return JSON.stringify(obj);
|
|
30
|
-
return JSON.stringify(obj);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/** HQX Server Service - Ultra Low Latency */
|
|
34
|
-
class HQXServerService {
|
|
35
|
-
constructor() {
|
|
36
|
-
// Connection
|
|
37
|
-
this.ws = null;
|
|
38
|
-
this.connected = false;
|
|
39
|
-
this.reconnecting = false;
|
|
40
|
-
this.reconnectAttempts = 0;
|
|
41
|
-
|
|
42
|
-
// Auth
|
|
43
|
-
this.token = null;
|
|
44
|
-
this.refreshToken = null;
|
|
45
|
-
this.apiKey = null;
|
|
46
|
-
this.sessionId = null;
|
|
47
|
-
|
|
48
|
-
// Performance
|
|
49
|
-
this.latency = 0;
|
|
50
|
-
this.minLatency = Infinity;
|
|
51
|
-
this.maxLatency = 0;
|
|
52
|
-
this.avgLatency = 0;
|
|
53
|
-
this.latencySamples = [];
|
|
54
|
-
this.lastPingTime = 0;
|
|
55
|
-
this.pingInterval = null;
|
|
56
|
-
this.adaptiveHeartbeat = 1000; // Start at 1s, adapt based on connection
|
|
57
|
-
|
|
58
|
-
// Message handling
|
|
59
|
-
this.listeners = new Map();
|
|
60
|
-
this.messageQueue = [];
|
|
61
|
-
this.sendBuffer = Buffer.alloc(4096); // Pre-allocated send buffer
|
|
62
|
-
|
|
63
|
-
// Device
|
|
64
|
-
this._deviceId = null;
|
|
65
|
-
|
|
66
|
-
// Stats
|
|
67
|
-
this.messagesSent = 0;
|
|
68
|
-
this.messagesReceived = 0;
|
|
69
|
-
this.bytesReceived = 0;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/** Get cached device fingerprint */
|
|
73
|
-
_getDeviceId() {
|
|
74
|
-
if (this._deviceId) return this._deviceId;
|
|
75
|
-
|
|
76
|
-
const data = `${os.hostname()}-${os.platform()}-${os.arch()}-${os.cpus()[0]?.model || 'cpu'}`;
|
|
77
|
-
this._deviceId = crypto.createHash('sha256').update(data).digest('hex').slice(0, 32);
|
|
78
|
-
return this._deviceId;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Authenticate with HQX Server */
|
|
82
|
-
async authenticate(userId, propfirm = 'unknown') {
|
|
83
|
-
const start = process.hrtime.bigint();
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const deviceId = this._getDeviceId();
|
|
87
|
-
const url = `http://${HQX_SERVER.host}:${HQX_SERVER.port}/${HQX_SERVER.VERSION}/auth/token`;
|
|
88
|
-
|
|
89
|
-
const response = await request(url, {
|
|
90
|
-
method: 'POST',
|
|
91
|
-
body: {
|
|
92
|
-
userId: userId || deviceId,
|
|
93
|
-
deviceId,
|
|
94
|
-
propfirm,
|
|
95
|
-
timestamp: Date.now(),
|
|
96
|
-
},
|
|
97
|
-
timeout: 5000, // Fast timeout for auth
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (response.statusCode === 200 && response.data?.success) {
|
|
101
|
-
const { token, refreshToken, apiKey, sessionId } = response.data.data;
|
|
102
|
-
this.token = token;
|
|
103
|
-
this.refreshToken = refreshToken;
|
|
104
|
-
this.apiKey = apiKey;
|
|
105
|
-
this.sessionId = sessionId;
|
|
106
|
-
|
|
107
|
-
const elapsed = Number(process.hrtime.bigint() - start) / 1e6;
|
|
108
|
-
log.info('Authenticated', { sessionId, latency: `${elapsed.toFixed(1)}ms` });
|
|
109
|
-
|
|
110
|
-
return { success: true, sessionId, apiKey };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return { success: false, error: response.data?.error || 'Authentication failed' };
|
|
114
|
-
} catch (err) {
|
|
115
|
-
log.error('Auth error', { error: err.message });
|
|
116
|
-
return { success: false, error: err.message };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Connect with ultra-low latency settings */
|
|
121
|
-
async connect() {
|
|
122
|
-
if (!this.token) {
|
|
123
|
-
return { success: false, error: 'Not authenticated' };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return new Promise((resolve) => {
|
|
127
|
-
const wsUrl = `${HQX_SERVER.wsUrl}?token=${this.token}&session=${this.sessionId}`;
|
|
128
|
-
|
|
129
|
-
log.debug('Connecting', { url: HQX_SERVER.wsUrl });
|
|
130
|
-
|
|
131
|
-
this.ws = new WebSocket(wsUrl, {
|
|
132
|
-
headers: {
|
|
133
|
-
'X-Device-Id': this._getDeviceId(),
|
|
134
|
-
'X-API-Key': this.apiKey,
|
|
135
|
-
},
|
|
136
|
-
// Performance options
|
|
137
|
-
perMessageDeflate: false, // Disable compression for speed
|
|
138
|
-
maxPayload: 64 * 1024, // 64KB max payload
|
|
139
|
-
handshakeTimeout: 5000, // Fast handshake
|
|
140
|
-
// TCP optimizations applied after open
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Binary mode for speed
|
|
144
|
-
this.ws.binaryType = 'nodebuffer';
|
|
145
|
-
|
|
146
|
-
const connectTimeout = setTimeout(() => {
|
|
147
|
-
if (!this.connected) {
|
|
148
|
-
this.ws?.terminate();
|
|
149
|
-
resolve({ success: false, error: 'Connection timeout' });
|
|
150
|
-
}
|
|
151
|
-
}, 5000);
|
|
152
|
-
|
|
153
|
-
this.ws.on('open', () => {
|
|
154
|
-
clearTimeout(connectTimeout);
|
|
155
|
-
this.connected = true;
|
|
156
|
-
this.reconnectAttempts = 0;
|
|
157
|
-
|
|
158
|
-
// Apply TCP_NODELAY for lowest latency
|
|
159
|
-
this._optimizeSocket();
|
|
160
|
-
|
|
161
|
-
// Start adaptive heartbeat
|
|
162
|
-
this._startHeartbeat();
|
|
163
|
-
|
|
164
|
-
// Flush queued messages
|
|
165
|
-
this._flushQueue();
|
|
166
|
-
|
|
167
|
-
this._emit('connected', { sessionId: this.sessionId });
|
|
168
|
-
log.info('Connected with TCP_NODELAY');
|
|
169
|
-
|
|
170
|
-
resolve({ success: true });
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
this.ws.on('message', (data) => {
|
|
174
|
-
this._handleMessage(data);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
this.ws.on('close', (code, reason) => {
|
|
178
|
-
clearTimeout(connectTimeout);
|
|
179
|
-
this.connected = false;
|
|
180
|
-
this._stopHeartbeat();
|
|
181
|
-
|
|
182
|
-
log.info('Disconnected', { code });
|
|
183
|
-
this._emit('disconnected', { code, reason: reason?.toString() });
|
|
184
|
-
|
|
185
|
-
if (!this.reconnecting) {
|
|
186
|
-
this._attemptReconnect();
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
this.ws.on('error', (err) => {
|
|
191
|
-
log.error('WebSocket error', { error: err.message });
|
|
192
|
-
this._emit('error', { message: err.message });
|
|
193
|
-
|
|
194
|
-
if (!this.connected) {
|
|
195
|
-
clearTimeout(connectTimeout);
|
|
196
|
-
resolve({ success: false, error: err.message });
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** Apply TCP socket optimizations */
|
|
203
|
-
_optimizeSocket() {
|
|
204
|
-
try {
|
|
205
|
-
const socket = this.ws._socket;
|
|
206
|
-
if (socket) {
|
|
207
|
-
// Disable Nagle's algorithm - critical for low latency
|
|
208
|
-
socket.setNoDelay(true);
|
|
209
|
-
|
|
210
|
-
// Keep connection alive
|
|
211
|
-
socket.setKeepAlive(true, 10000);
|
|
212
|
-
|
|
213
|
-
// Increase buffer sizes for throughput
|
|
214
|
-
if (socket.setRecvBufferSize) socket.setRecvBufferSize(65536);
|
|
215
|
-
if (socket.setSendBufferSize) socket.setSendBufferSize(65536);
|
|
216
|
-
|
|
217
|
-
log.debug('Socket optimized: TCP_NODELAY enabled');
|
|
218
|
-
}
|
|
219
|
-
} catch (err) {
|
|
220
|
-
log.warn('Socket optimization failed', { error: err.message });
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** Ultra-fast message handler */
|
|
225
|
-
_handleMessage(data) {
|
|
226
|
-
handlers.processMessage(
|
|
227
|
-
this,
|
|
228
|
-
data,
|
|
229
|
-
(event, payload) => this._emit(event, payload),
|
|
230
|
-
(latency) => this._updateLatency(latency)
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/** Update latency statistics */
|
|
235
|
-
_updateLatency(latency) {
|
|
236
|
-
latencyMgr.updateLatency.call(this, latency);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/** Send message with minimal overhead */
|
|
240
|
-
send(type, data) {
|
|
241
|
-
const message = {
|
|
242
|
-
type,
|
|
243
|
-
data,
|
|
244
|
-
ts: Date.now(), // Short key for speed
|
|
245
|
-
sid: this.sessionId,
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
if (this.connected && this.ws?.readyState === WebSocket.OPEN) {
|
|
249
|
-
this._sendRaw(fastStringify(message));
|
|
250
|
-
this.messagesSent++;
|
|
251
|
-
} else {
|
|
252
|
-
this.messageQueue.push(message);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/** Send raw data */
|
|
257
|
-
_sendRaw(data) {
|
|
258
|
-
try {
|
|
259
|
-
this.ws.send(data);
|
|
260
|
-
} catch (err) {
|
|
261
|
-
log.warn('Send error', { error: err.message });
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/** Send binary ping for lowest latency measurement */
|
|
266
|
-
_sendBinaryPing() {
|
|
267
|
-
if (!this.connected || this.ws?.readyState !== WebSocket.OPEN) return;
|
|
268
|
-
|
|
269
|
-
this.lastPingTime = process.hrtime.bigint();
|
|
270
|
-
|
|
271
|
-
// Write timestamp to pre-allocated buffer
|
|
272
|
-
PING_BUFFER.writeBigInt64LE(this.lastPingTime, 1);
|
|
273
|
-
|
|
274
|
-
try {
|
|
275
|
-
this.ws.send(PING_BUFFER);
|
|
276
|
-
} catch {
|
|
277
|
-
// Ignore ping errors
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/** Flush message queue */
|
|
282
|
-
_flushQueue() {
|
|
283
|
-
while (this.messageQueue.length > 0 && this.ws?.readyState === WebSocket.OPEN) {
|
|
284
|
-
const message = this.messageQueue.shift();
|
|
285
|
-
this._sendRaw(fastStringify(message));
|
|
286
|
-
this.messagesSent++;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/** Start algo trading session */
|
|
291
|
-
startAlgo(config) {
|
|
292
|
-
log.info('Starting algo', { symbol: config.symbol, contracts: config.contracts });
|
|
293
|
-
this.send('start_algo', handlers.buildAlgoPayload(config));
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/** Stop algo trading */
|
|
297
|
-
stopAlgo() {
|
|
298
|
-
log.info('Stopping algo');
|
|
299
|
-
this.send('stop_algo', {});
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/** Start copy trading */
|
|
303
|
-
startCopyTrading(config) {
|
|
304
|
-
log.info('Starting copy trading');
|
|
305
|
-
this.send('start_copy_trading', handlers.buildCopyTradingPayload(config));
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/** Register event listener */
|
|
309
|
-
on(event, callback) {
|
|
310
|
-
eventMgr.on(this.listeners, event, callback);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/** Remove event listener */
|
|
314
|
-
off(event, callback) {
|
|
315
|
-
eventMgr.off(this.listeners, event, callback);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/** Emit event */
|
|
319
|
-
_emit(event, data) {
|
|
320
|
-
eventMgr.emit(this.listeners, event, data);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/** Start adaptive heartbeat */
|
|
324
|
-
_startHeartbeat() {
|
|
325
|
-
latencyMgr.startHeartbeat.call(this, () => this._sendBinaryPing());
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/** Stop heartbeat */
|
|
329
|
-
_stopHeartbeat() {
|
|
330
|
-
latencyMgr.stopHeartbeat.call(this);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/** Attempt reconnection with exponential backoff */
|
|
334
|
-
_attemptReconnect() {
|
|
335
|
-
if (this.reconnectAttempts >= SECURITY.MAX_RECONNECT_ATTEMPTS) {
|
|
336
|
-
log.error('Max reconnect attempts reached');
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
this.reconnecting = true;
|
|
341
|
-
this.reconnectAttempts++;
|
|
342
|
-
|
|
343
|
-
// Fast initial reconnect, then backoff
|
|
344
|
-
const delay = Math.min(
|
|
345
|
-
100 * Math.pow(2, this.reconnectAttempts - 1), // Start at 100ms
|
|
346
|
-
10000 // Max 10s
|
|
347
|
-
);
|
|
348
|
-
|
|
349
|
-
log.info('Reconnecting', { attempt: this.reconnectAttempts, delay });
|
|
350
|
-
|
|
351
|
-
setTimeout(async () => {
|
|
352
|
-
try {
|
|
353
|
-
await this.connect();
|
|
354
|
-
} catch (err) {
|
|
355
|
-
log.error('Reconnect failed', { error: err.message });
|
|
356
|
-
}
|
|
357
|
-
this.reconnecting = false;
|
|
358
|
-
}, delay);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/** Get latency statistics */
|
|
362
|
-
getLatencyStats() {
|
|
363
|
-
return latencyMgr.getLatencyStats.call(this);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/** Get connection statistics */
|
|
367
|
-
getStats() {
|
|
368
|
-
return latencyMgr.getConnectionStats.call(this);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/** Get current latency */
|
|
372
|
-
getLatency() {
|
|
373
|
-
return this.latency;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
/** Disconnect and cleanup */
|
|
377
|
-
disconnect() {
|
|
378
|
-
log.info('Disconnecting');
|
|
379
|
-
|
|
380
|
-
this._stopHeartbeat();
|
|
381
|
-
|
|
382
|
-
if (this.ws) {
|
|
383
|
-
this.ws.close(1000, 'Client disconnect');
|
|
384
|
-
this.ws = null;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
this.connected = false;
|
|
388
|
-
this.token = null;
|
|
389
|
-
this.sessionId = null;
|
|
390
|
-
this.messageQueue = [];
|
|
391
|
-
eventMgr.clearAll(this.listeners);
|
|
392
|
-
|
|
393
|
-
// Reset stats
|
|
394
|
-
latencyMgr.resetLatencyStats.call(this);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/** Check if connected */
|
|
398
|
-
isConnected() {
|
|
399
|
-
return this.connected && this.ws?.readyState === WebSocket.OPEN;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
module.exports = { HQXServerService, HQX_SERVER, MSG_TYPE };
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Position Manager Constants
|
|
3
|
-
* Momentum thresholds and weights for position management
|
|
4
|
-
*
|
|
5
|
-
* Data source: Calibrated from backtesting and live trading analysis
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// =============================================================================
|
|
9
|
-
// MOMENTUM THRESHOLDS (from analysis)
|
|
10
|
-
// =============================================================================
|
|
11
|
-
const MOMENTUM = {
|
|
12
|
-
STRONG_FAVORABLE: 0.5, // momentum > 0.5 + profit → HOLD
|
|
13
|
-
WEAK_THRESHOLD: 0.2, // momentum < 0.2 + profit → EXIT with profit
|
|
14
|
-
ADVERSE_THRESHOLD: -0.3, // momentum < -0.3 → EXIT immediately
|
|
15
|
-
VPIN_DANGER: 0.7, // VPIN > 0.7 → informed traders = EXIT
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// Momentum weights
|
|
19
|
-
const WEIGHTS = {
|
|
20
|
-
OFI: 0.50, // Order Flow Imbalance - 50%
|
|
21
|
-
KALMAN: 0.25, // Kalman Velocity - 25%
|
|
22
|
-
ZSCORE: 0.25, // Z-Score progression - 25%
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
module.exports = {
|
|
26
|
-
MOMENTUM,
|
|
27
|
-
WEIGHTS,
|
|
28
|
-
};
|