hedgequantx 2.9.60 → 2.9.62

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.9.60",
3
+ "version": "2.9.62",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -255,7 +255,7 @@ const copyTradingMenu = async () => {
255
255
  if (enableAI) {
256
256
  // Run pre-flight check - ALL agents must pass
257
257
  console.log();
258
- console.log(chalk.yellow(' Running AI pre-flight check...'));
258
+ console.log(chalk.yellow(' Running AI pre-algo check...'));
259
259
  console.log();
260
260
 
261
261
  const agents = getActiveAgents();
@@ -96,7 +96,7 @@ const customStrategyMenu = async (service) => {
96
96
  if (aiSupervision) {
97
97
  // Run pre-flight check - agent must pass
98
98
  console.log();
99
- console.log(chalk.yellow(' Running AI pre-flight check...'));
99
+ console.log(chalk.yellow(' Running AI pre-algo check...'));
100
100
  console.log();
101
101
 
102
102
  const agents = getActiveAgents();
@@ -181,7 +181,7 @@ const oneAccountMenu = async (service) => {
181
181
  if (enableAI) {
182
182
  // Run pre-flight check - ALL agents must pass
183
183
  console.log();
184
- console.log(chalk.yellow(' Running AI pre-flight check...'));
184
+ console.log(chalk.yellow(' Running AI pre-algo check...'));
185
185
  console.log();
186
186
 
187
187
  const agents = getActiveAgents();
@@ -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 response_product_codes.proto
219
+ // Field IDs from Rithmic API
220
220
  if (fieldNumber === 110101) result.exchange = val; // exchange
221
- if (fieldNumber === 110102) result.productCode = val; // product_code (ES, MES, MNQ, etc.)
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: 110102, // Base symbol (ES, NQ, MNQ)
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 < buffer.length) {
275
+ while (offset < data.length) {
273
276
  try {
274
- const [tag, tagOffset] = readVarint(buffer, offset);
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(buffer, offset);
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(buffer, offset);
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(buffer, offset);
292
+ [result.exchange, offset] = readLengthDelimited(data, offset);
290
293
  break;
291
294
  case SYMBOL_FIELDS.PRODUCT_CODE:
292
- [result.productCode, offset] = readLengthDelimited(buffer, offset);
295
+ [result.productCode, offset] = readLengthDelimited(data, offset);
293
296
  break;
294
297
  case SYMBOL_FIELDS.PRODUCT_NAME:
295
- [result.productName, offset] = readLengthDelimited(buffer, offset);
298
+ [result.productName, offset] = readLengthDelimited(data, offset);
296
299
  break;
297
300
  case SYMBOL_FIELDS.USER_MSG:
298
- [result.userMsg, offset] = readLengthDelimited(buffer, offset);
301
+ [result.userMsg, offset] = readLengthDelimited(data, offset);
299
302
  break;
300
303
  default:
301
- offset = skipField(buffer, offset, wireType);
304
+ offset = skipField(data, offset, wireType);
302
305
  }
303
306
  } catch (error) {
304
307
  break;
@@ -112,27 +112,36 @@ const connections = {
112
112
  },
113
113
 
114
114
  saveToStorage() {
115
- const sessions = this.services.map(conn => ({
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
- storage.save(sessions);
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
- if (!sessions.length) {
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: sessions.length });
142
+ log.info('Restoring sessions', { count: rithmicSessions.length });
134
143
 
135
- for (const session of sessions) {
144
+ for (const session of rithmicSessions) {
136
145
  try {
137
146
  await this._restoreSession(session);
138
147
  } catch (err) {