hedgequantx 1.2.86 → 1.2.88

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": "1.2.86",
3
+ "version": "1.2.88",
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": {
@@ -49,20 +49,45 @@ const ORDER_SIDE = {
49
49
  1: { text: 'Sell', color: 'red' }
50
50
  };
51
51
 
52
- // Popular Futures Symbols
52
+ // Popular Futures Symbols - Complete list
53
53
  const FUTURES_SYMBOLS = [
54
- { name: 'NQ - E-mini NASDAQ-100', value: 'NQ', searchText: 'NQ' },
55
- { name: 'MNQ - Micro E-mini NASDAQ-100', value: 'MNQ', searchText: 'MNQ' },
56
- { name: 'ES - E-mini S&P 500', value: 'ES', searchText: 'ES' },
57
- { name: 'MES - Micro E-mini S&P 500', value: 'MES', searchText: 'MES' },
58
- { name: 'YM - E-mini Dow Jones', value: 'YM', searchText: 'YM' },
59
- { name: 'MYM - Micro E-mini Dow Jones', value: 'MYM', searchText: 'MYM' },
60
- { name: 'RTY - E-mini Russell 2000', value: 'RTY', searchText: 'RTY' },
61
- { name: 'M2K - Micro E-mini Russell 2000', value: 'M2K', searchText: 'M2K' },
62
- { name: 'CL - Crude Oil', value: 'CL', searchText: 'CL' },
63
- { name: 'MCL - Micro Crude Oil', value: 'MCL', searchText: 'MCL' },
64
- { name: 'GC - Gold', value: 'GC', searchText: 'GC' },
65
- { name: 'MGC - Micro Gold', value: 'MGC', searchText: 'MGC' }
54
+ // Index Futures
55
+ { name: 'NQ - E-mini NASDAQ-100', value: 'NQ', searchText: 'NQ', category: 'index' },
56
+ { name: 'MNQ - Micro E-mini NASDAQ-100', value: 'MNQ', searchText: 'MNQ', category: 'index' },
57
+ { name: 'ES - E-mini S&P 500', value: 'ES', searchText: 'ES', category: 'index' },
58
+ { name: 'MES - Micro E-mini S&P 500', value: 'MES', searchText: 'MES', category: 'index' },
59
+ { name: 'YM - E-mini Dow Jones', value: 'YM', searchText: 'YM', category: 'index' },
60
+ { name: 'MYM - Micro E-mini Dow Jones', value: 'MYM', searchText: 'MYM', category: 'index' },
61
+ { name: 'RTY - E-mini Russell 2000', value: 'RTY', searchText: 'RTY', category: 'index' },
62
+ { name: 'M2K - Micro E-mini Russell 2000', value: 'M2K', searchText: 'M2K', category: 'index' },
63
+ // Energy
64
+ { name: 'CL - Crude Oil WTI', value: 'CL', searchText: 'CL', category: 'energy' },
65
+ { name: 'MCL - Micro Crude Oil', value: 'MCL', searchText: 'MCL', category: 'energy' },
66
+ { name: 'NG - Natural Gas', value: 'NG', searchText: 'NG', category: 'energy' },
67
+ { name: 'QG - E-mini Natural Gas', value: 'QG', searchText: 'QG', category: 'energy' },
68
+ // Metals
69
+ { name: 'GC - Gold', value: 'GC', searchText: 'GC', category: 'metals' },
70
+ { name: 'MGC - Micro Gold', value: 'MGC', searchText: 'MGC', category: 'metals' },
71
+ { name: 'SI - Silver', value: 'SI', searchText: 'SI', category: 'metals' },
72
+ { name: 'SIL - Micro Silver', value: 'SIL', searchText: 'SIL', category: 'metals' },
73
+ { name: 'HG - Copper', value: 'HG', searchText: 'HG', category: 'metals' },
74
+ { name: 'PL - Platinum', value: 'PL', searchText: 'PL', category: 'metals' },
75
+ // Currencies
76
+ { name: '6E - Euro FX', value: '6E', searchText: '6E', category: 'currency' },
77
+ { name: 'M6E - Micro Euro FX', value: 'M6E', searchText: 'M6E', category: 'currency' },
78
+ { name: '6B - British Pound', value: '6B', searchText: '6B', category: 'currency' },
79
+ { name: '6J - Japanese Yen', value: '6J', searchText: '6J', category: 'currency' },
80
+ { name: '6A - Australian Dollar', value: '6A', searchText: '6A', category: 'currency' },
81
+ { name: '6C - Canadian Dollar', value: '6C', searchText: '6C', category: 'currency' },
82
+ // Bonds
83
+ { name: 'ZB - 30-Year T-Bond', value: 'ZB', searchText: 'ZB', category: 'bonds' },
84
+ { name: 'ZN - 10-Year T-Note', value: 'ZN', searchText: 'ZN', category: 'bonds' },
85
+ { name: 'ZF - 5-Year T-Note', value: 'ZF', searchText: 'ZF', category: 'bonds' },
86
+ { name: 'ZT - 2-Year T-Note', value: 'ZT', searchText: 'ZT', category: 'bonds' },
87
+ // Agriculture
88
+ { name: 'ZC - Corn', value: 'ZC', searchText: 'ZC', category: 'agriculture' },
89
+ { name: 'ZS - Soybeans', value: 'ZS', searchText: 'ZS', category: 'agriculture' },
90
+ { name: 'ZW - Wheat', value: 'ZW', searchText: 'ZW', category: 'agriculture' }
66
91
  ];
67
92
 
68
93
  module.exports = {
package/src/pages/algo.js CHANGED
@@ -146,6 +146,7 @@ const oneAccountMenu = async (service) => {
146
146
  const selectSymbolMenu = async (service, account) => {
147
147
  const device = getDevice();
148
148
  const accountName = account.accountName || account.name || 'Account #' + account.accountId;
149
+ const propfirm = account.propfirm || 'projectx';
149
150
 
150
151
  console.log();
151
152
  console.log(chalk.gray(getSeparator()));
@@ -153,12 +154,69 @@ const selectSymbolMenu = async (service, account) => {
153
154
  console.log(chalk.gray(getSeparator()));
154
155
  console.log();
155
156
 
156
- // Format symbols with aligned columns: "NQ - E-mini NASDAQ-100"
157
- const symbolChoices = FUTURES_SYMBOLS.map(symbol => {
158
- const code = symbol.value.padEnd(4);
159
- const desc = symbol.name.split(' - ')[1] || '';
157
+ // Fetch available symbols from API
158
+ const spinner = ora('Loading available symbols...').start();
159
+
160
+ let availableSymbols = [];
161
+
162
+ // Search for common symbols to get available contracts
163
+ const commonSearches = ['NQ', 'ES', 'YM', 'RTY', 'CL', 'GC', 'SI', '6E', 'ZB', 'NG'];
164
+
165
+ try {
166
+ for (const search of commonSearches) {
167
+ const result = await service.searchContracts(search, false);
168
+ if (result.success && result.contracts && result.contracts.length > 0) {
169
+ for (const contract of result.contracts) {
170
+ // Only add active/front-month contracts
171
+ if (contract.activeContract || contract.name) {
172
+ const existing = availableSymbols.find(s => s.id === contract.id);
173
+ if (!existing) {
174
+ availableSymbols.push({
175
+ id: contract.id || contract.contractId,
176
+ name: contract.name || contract.symbol,
177
+ symbol: contract.symbol || search,
178
+ tickSize: contract.tickSize,
179
+ tickValue: contract.tickValue,
180
+ exchange: contract.exchange || 'CME'
181
+ });
182
+ }
183
+ }
184
+ }
185
+ }
186
+ }
187
+ } catch (e) {
188
+ // Fallback to static list
189
+ }
190
+
191
+ // If no symbols found from API, use static list
192
+ if (availableSymbols.length === 0) {
193
+ spinner.warn('Using default symbol list');
194
+ availableSymbols = FUTURES_SYMBOLS.map(s => ({
195
+ id: s.value,
196
+ name: s.name,
197
+ symbol: s.value,
198
+ searchText: s.searchText
199
+ }));
200
+ } else {
201
+ spinner.succeed(`Found ${availableSymbols.length} available contracts`);
202
+ }
203
+
204
+ console.log();
205
+
206
+ // Format symbols for display
207
+ const symbolChoices = availableSymbols.map(symbol => {
208
+ // Extract short code and description
209
+ const name = symbol.name || symbol.symbol || symbol.id;
210
+ // Parse name like "E-mini NASDAQ-100 Mar26" or "NQH6"
211
+ let displayName = name;
212
+ let code = symbol.symbol || '';
213
+
214
+ // Try to extract month/year from name
215
+ const monthMatch = name.match(/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)(\d{2})/i);
216
+ const monthYear = monthMatch ? `${monthMatch[1]}${monthMatch[2]}` : '';
217
+
160
218
  return {
161
- name: chalk.yellow(code) + chalk.gray(' - ') + chalk.white(desc),
219
+ name: chalk.yellow(code.padEnd(5)) + chalk.cyan((monthYear || '').padEnd(7)) + chalk.white(displayName),
162
220
  value: symbol
163
221
  };
164
222
  });
@@ -172,7 +230,7 @@ const selectSymbolMenu = async (service, account) => {
172
230
  name: 'selectedSymbol',
173
231
  message: chalk.white.bold('Select Symbol:'),
174
232
  choices: symbolChoices,
175
- pageSize: 15,
233
+ pageSize: 20,
176
234
  loop: false
177
235
  }
178
236
  ]);
@@ -181,24 +239,32 @@ const selectSymbolMenu = async (service, account) => {
181
239
  return;
182
240
  }
183
241
 
184
- // Search contract via Gateway API
185
- const spinner = ora(`Searching for ${selectedSymbol.value} contract...`).start();
186
- const contractResult = await service.searchContracts(selectedSymbol.searchText, false);
242
+ // Use the selected contract directly (already fetched from API)
243
+ let contract = selectedSymbol;
187
244
 
188
- let contract = null;
189
- if (contractResult.success && contractResult.contracts && contractResult.contracts.length > 0) {
190
- contract = contractResult.contracts.find(c => c.activeContract) || contractResult.contracts[0];
191
- spinner.succeed(`Found: ${contract.name || selectedSymbol.value}`);
192
- if (contract.tickSize && contract.tickValue) {
193
- console.log(chalk.gray(` Tick Size: ${contract.tickSize} | Tick Value: $${contract.tickValue}`));
245
+ console.log();
246
+ console.log(chalk.green(` [OK] Selected: ${contract.name || contract.symbol}`));
247
+ if (contract.tickSize && contract.tickValue) {
248
+ console.log(chalk.gray(` Tick Size: ${contract.tickSize} | Tick Value: $${contract.tickValue}`));
249
+ }
250
+
251
+ // If contract doesn't have full details, search again
252
+ if (!contract.id || !contract.tickSize) {
253
+ const searchSpinner = ora(`Getting contract details...`).start();
254
+ const contractResult = await service.searchContracts(contract.symbol || contract.searchText, false);
255
+
256
+ if (contractResult.success && contractResult.contracts && contractResult.contracts.length > 0) {
257
+ const found = contractResult.contracts.find(c => c.activeContract) || contractResult.contracts[0];
258
+ contract = { ...contract, ...found };
259
+ searchSpinner.succeed(`Contract: ${contract.name || contract.symbol}`);
260
+ } else {
261
+ searchSpinner.warn('Using basic contract info');
262
+ contract = {
263
+ id: contract.symbol || contract.id,
264
+ name: contract.name || contract.symbol,
265
+ symbol: contract.symbol || contract.id
266
+ };
194
267
  }
195
- } else {
196
- spinner.warn(`Using ${selectedSymbol.value} (contract details unavailable)`);
197
- contract = {
198
- id: selectedSymbol.value,
199
- name: selectedSymbol.name,
200
- symbol: selectedSymbol.value
201
- };
202
268
  }
203
269
 
204
270
  console.log();
@@ -342,11 +408,15 @@ const launchAlgo = async (service, account, contract, numContracts, dailyTarget,
342
408
 
343
409
  const getIcon = (type) => {
344
410
  switch(type) {
345
- case 'signal': return '[*]';
346
- case 'trade': return '[>]';
347
- case 'error': return '[X]';
411
+ case 'signal': return '[SIGNAL]';
412
+ case 'trade': return '[TRADE]';
413
+ case 'order': return '[ORDER]';
414
+ case 'position': return '[POSITION]';
415
+ case 'error': return '[ERROR]';
416
+ case 'warning': return '[WARNING]';
348
417
  case 'success': return '[OK]';
349
- default: return '[.]';
418
+ case 'analysis': return '[ANALYSIS]';
419
+ default: return '[INFO]';
350
420
  }
351
421
  };
352
422