hedgequantx 2.9.60 → 2.9.61
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/package.json
CHANGED
|
@@ -216,9 +216,9 @@ const decodeProductCodes = (buffer) => {
|
|
|
216
216
|
} else if (wireType === 2) {
|
|
217
217
|
const [val, newOff] = readString(data, offset);
|
|
218
218
|
offset = newOff;
|
|
219
|
-
// Field IDs from
|
|
219
|
+
// Field IDs from Rithmic API
|
|
220
220
|
if (fieldNumber === 110101) result.exchange = val; // exchange
|
|
221
|
-
if (fieldNumber ===
|
|
221
|
+
if (fieldNumber === 100749) result.productCode = val; // product_code (ES, MES, MNQ, etc.)
|
|
222
222
|
if (fieldNumber === 110103) result.productName = val; // product_name
|
|
223
223
|
} else {
|
|
224
224
|
break;
|
|
@@ -30,8 +30,9 @@ const PNL_FIELDS = {
|
|
|
30
30
|
const SYMBOL_FIELDS = {
|
|
31
31
|
TEMPLATE_ID: 154467,
|
|
32
32
|
RP_CODE: 132766,
|
|
33
|
+
RP_CODE_2: 132764, // Another rp_code field
|
|
33
34
|
EXCHANGE: 110101,
|
|
34
|
-
PRODUCT_CODE:
|
|
35
|
+
PRODUCT_CODE: 100749, // Base symbol (ES, NQ, MNQ) - actual field ID from Rithmic
|
|
35
36
|
PRODUCT_NAME: 110103, // Product name
|
|
36
37
|
SYMBOL: 110100, // Full contract symbol (ESH26)
|
|
37
38
|
TRADING_SYMBOL: 157095, // Trading symbol
|
|
@@ -262,43 +263,45 @@ function decodeInstrumentPnL(buffer) {
|
|
|
262
263
|
|
|
263
264
|
/**
|
|
264
265
|
* Decode ResponseProductCodes (template 112) - list of available symbols
|
|
265
|
-
* @param {Buffer} buffer - Raw protobuf buffer
|
|
266
|
+
* @param {Buffer} buffer - Raw protobuf buffer (with 4-byte length prefix)
|
|
266
267
|
* @returns {Object} Decoded product codes
|
|
267
268
|
*/
|
|
268
269
|
function decodeProductCodes(buffer) {
|
|
270
|
+
// Skip 4-byte length prefix
|
|
271
|
+
const data = buffer.length > 4 ? buffer.slice(4) : buffer;
|
|
269
272
|
const result = { rpCode: [] };
|
|
270
273
|
let offset = 0;
|
|
271
274
|
|
|
272
|
-
while (offset <
|
|
275
|
+
while (offset < data.length) {
|
|
273
276
|
try {
|
|
274
|
-
const [tag, tagOffset] = readVarint(
|
|
277
|
+
const [tag, tagOffset] = readVarint(data, offset);
|
|
275
278
|
const wireType = tag & 0x7;
|
|
276
279
|
const fieldNumber = tag >>> 3;
|
|
277
280
|
offset = tagOffset;
|
|
278
281
|
|
|
279
282
|
switch (fieldNumber) {
|
|
280
283
|
case SYMBOL_FIELDS.TEMPLATE_ID:
|
|
281
|
-
[result.templateId, offset] = readVarint(
|
|
284
|
+
[result.templateId, offset] = readVarint(data, offset);
|
|
282
285
|
break;
|
|
283
286
|
case SYMBOL_FIELDS.RP_CODE:
|
|
284
287
|
let rpCode;
|
|
285
|
-
[rpCode, offset] = readLengthDelimited(
|
|
288
|
+
[rpCode, offset] = readLengthDelimited(data, offset);
|
|
286
289
|
result.rpCode.push(rpCode);
|
|
287
290
|
break;
|
|
288
291
|
case SYMBOL_FIELDS.EXCHANGE:
|
|
289
|
-
[result.exchange, offset] = readLengthDelimited(
|
|
292
|
+
[result.exchange, offset] = readLengthDelimited(data, offset);
|
|
290
293
|
break;
|
|
291
294
|
case SYMBOL_FIELDS.PRODUCT_CODE:
|
|
292
|
-
[result.productCode, offset] = readLengthDelimited(
|
|
295
|
+
[result.productCode, offset] = readLengthDelimited(data, offset);
|
|
293
296
|
break;
|
|
294
297
|
case SYMBOL_FIELDS.PRODUCT_NAME:
|
|
295
|
-
[result.productName, offset] = readLengthDelimited(
|
|
298
|
+
[result.productName, offset] = readLengthDelimited(data, offset);
|
|
296
299
|
break;
|
|
297
300
|
case SYMBOL_FIELDS.USER_MSG:
|
|
298
|
-
[result.userMsg, offset] = readLengthDelimited(
|
|
301
|
+
[result.userMsg, offset] = readLengthDelimited(data, offset);
|
|
299
302
|
break;
|
|
300
303
|
default:
|
|
301
|
-
offset = skipField(
|
|
304
|
+
offset = skipField(data, offset, wireType);
|
|
302
305
|
}
|
|
303
306
|
} catch (error) {
|
|
304
307
|
break;
|
package/src/services/session.js
CHANGED
|
@@ -112,27 +112,36 @@ const connections = {
|
|
|
112
112
|
},
|
|
113
113
|
|
|
114
114
|
saveToStorage() {
|
|
115
|
-
|
|
115
|
+
// Load existing sessions to preserve AI agents
|
|
116
|
+
const existingSessions = storage.load();
|
|
117
|
+
const aiSessions = existingSessions.filter(s => s.type === 'ai');
|
|
118
|
+
|
|
119
|
+
// Build Rithmic sessions
|
|
120
|
+
const rithmicSessions = this.services.map(conn => ({
|
|
116
121
|
type: conn.type,
|
|
117
122
|
propfirm: conn.propfirm,
|
|
118
123
|
propfirmKey: conn.service.propfirmKey || conn.propfirmKey,
|
|
119
124
|
credentials: conn.service.credentials,
|
|
120
125
|
}));
|
|
121
126
|
|
|
122
|
-
|
|
127
|
+
// Merge: AI sessions + Rithmic sessions
|
|
128
|
+
storage.save([...aiSessions, ...rithmicSessions]);
|
|
123
129
|
},
|
|
124
130
|
|
|
125
131
|
async restoreFromStorage() {
|
|
126
132
|
loadServices();
|
|
127
133
|
const sessions = storage.load();
|
|
128
134
|
|
|
129
|
-
|
|
135
|
+
// Filter only Rithmic sessions (AI sessions are managed by ai-agents.js)
|
|
136
|
+
const rithmicSessions = sessions.filter(s => s.type === 'rithmic');
|
|
137
|
+
|
|
138
|
+
if (!rithmicSessions.length) {
|
|
130
139
|
return false;
|
|
131
140
|
}
|
|
132
141
|
|
|
133
|
-
log.info('Restoring sessions', { count:
|
|
142
|
+
log.info('Restoring sessions', { count: rithmicSessions.length });
|
|
134
143
|
|
|
135
|
-
for (const session of
|
|
144
|
+
for (const session of rithmicSessions) {
|
|
136
145
|
try {
|
|
137
146
|
await this._restoreSession(session);
|
|
138
147
|
} catch (err) {
|