hedgequantx 1.2.113 → 1.2.114

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/pages/algo.js +40 -45
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "1.2.113",
3
+ "version": "1.2.114",
4
4
  "description": "Prop Futures Algo Trading CLI - Connect to Topstep, Alpha Futures, and other prop firms",
5
5
  "main": "src/app.js",
6
6
  "bin": {
package/src/pages/algo.js CHANGED
@@ -178,29 +178,31 @@ const selectSymbolMenu = async (service, account) => {
178
178
  const result = await service.searchContracts(search, false);
179
179
  if (result.success && result.contracts && result.contracts.length > 0) {
180
180
  for (const contract of result.contracts) {
181
- // Only add contracts that have valid data
182
- if (contract.id || contract.contractId || contract.name) {
183
- const contractId = contract.id || contract.contractId;
184
- const existing = availableSymbols.find(s => s.id === contractId);
185
- if (!existing) {
186
- // Extract symbol from name if not provided (e.g., "NQH6" from "CON.F.US.ENQ.H26")
187
- let symbolCode = contract.symbol || search;
188
- if (contract.name && contract.name.includes(' ')) {
189
- // Try to extract from name like "E-mini NASDAQ-100 Mar 2026"
190
- symbolCode = search;
191
- }
192
-
193
- availableSymbols.push({
194
- id: contractId,
195
- name: contract.name || contract.symbol || search,
196
- symbol: symbolCode,
197
- tickSize: contract.tickSize,
198
- tickValue: contract.tickValue,
199
- exchange: contract.exchange || 'CME',
200
- activeContract: contract.activeContract || false
201
- });
202
- }
203
- }
181
+ // ProjectX API returns:
182
+ // id: "CON.F.US.ENQ.H26" (contract ID)
183
+ // name: "NQH6" (short symbol with month/year)
184
+ // description: "E-mini NASDAQ-100: March 2026"
185
+
186
+ const contractId = contract.id || contract.contractId;
187
+ if (!contractId) continue;
188
+
189
+ const existing = availableSymbols.find(s => s.id === contractId);
190
+ if (existing) continue;
191
+
192
+ // Use 'name' field which contains the symbol code like "NQH6", "ESH6", "MNQH6"
193
+ const symbolCode = contract.name || contract.symbol || '';
194
+ if (!symbolCode) continue;
195
+
196
+ availableSymbols.push({
197
+ id: contractId,
198
+ name: symbolCode,
199
+ symbol: symbolCode,
200
+ description: contract.description || '',
201
+ tickSize: contract.tickSize,
202
+ tickValue: contract.tickValue,
203
+ exchange: contract.exchange || 'CME',
204
+ activeContract: contract.activeContract || false
205
+ });
204
206
  }
205
207
  }
206
208
  }
@@ -208,22 +210,6 @@ const selectSymbolMenu = async (service, account) => {
208
210
  // Fallback to static list
209
211
  }
210
212
 
211
- // Add micro contracts if not found from API
212
- const microContracts = [
213
- { symbol: 'MNQ', name: 'Micro E-mini NASDAQ-100' },
214
- { symbol: 'MES', name: 'Micro E-mini S&P 500' },
215
- { symbol: 'MYM', name: 'Micro E-mini Dow Jones' },
216
- { symbol: 'M2K', name: 'Micro E-mini Russell 2000' },
217
- { symbol: 'MCL', name: 'Micro Crude Oil' },
218
- { symbol: 'MGC', name: 'Micro Gold' }
219
- ];
220
-
221
- // Get current month code for front month
222
- const now = new Date();
223
- const monthCodes = ['F', 'G', 'H', 'J', 'K', 'M', 'N', 'Q', 'U', 'V', 'X', 'Z'];
224
- const currentMonthCode = monthCodes[now.getMonth()];
225
- const yearCode = (now.getFullYear() % 100).toString();
226
-
227
213
  for (const micro of microContracts) {
228
214
  const hasMicro = availableSymbols.some(s =>
229
215
  (s.symbol && s.symbol.toUpperCase().startsWith(micro.symbol)) ||
@@ -299,9 +285,10 @@ const selectSymbolMenu = async (service, account) => {
299
285
  const symbolChoices = [];
300
286
 
301
287
  for (const symbol of availableSymbols) {
302
- const symbolCode = symbol.symbol || symbol.id || '';
288
+ const symbolCode = symbol.symbol || symbol.name || symbol.id || '';
303
289
 
304
290
  // Extract base symbol (e.g., NQ from NQH6) and month code
291
+ // Handles: NQH6, MNQH6, ESH26, MESH26, etc.
305
292
  const baseMatch = symbolCode.match(/^([A-Z0-9]{1,4})([FGHJKMNQUVXZ])(\d{1,2})$/i);
306
293
  let baseSymbol = symbolCode;
307
294
  let monthYear = '';
@@ -319,13 +306,21 @@ const selectSymbolMenu = async (service, account) => {
319
306
  if (seenSymbols.has(uniqueKey)) continue;
320
307
  seenSymbols.add(uniqueKey);
321
308
 
322
- // Get descriptive name from mapping
323
- const description = symbolDescriptions[baseSymbol] || symbol.name || baseSymbol;
309
+ // Get description: prefer API description, then our mapping, then symbol name
310
+ // API description format: "E-mini NASDAQ-100: March 2026"
311
+ let description = '';
312
+ if (symbol.description) {
313
+ // Extract just the instrument name (before the colon)
314
+ description = symbol.description.split(':')[0].trim();
315
+ }
316
+ if (!description) {
317
+ description = symbolDescriptions[baseSymbol] || baseSymbol;
318
+ }
324
319
 
325
- // Format: "NQ.Mar26 E-mini NASDAQ-100"
326
- const symbolDisplay = monthYear ? `${baseSymbol}.${monthYear}` : baseSymbol;
320
+ // Format: "NQH6 E-mini NASDAQ-100"
321
+ // Show full symbol code so user knows exactly what they're trading
327
322
  symbolChoices.push({
328
- name: chalk.yellow(symbolDisplay.padEnd(12)) + chalk.white(description),
323
+ name: chalk.yellow(symbolCode.padEnd(12)) + chalk.white(description),
329
324
  value: symbol
330
325
  });
331
326
  }