hedgequantx 1.2.99 → 1.2.101

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.99",
3
+ "version": "1.2.101",
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/app.js CHANGED
@@ -579,7 +579,8 @@ const mainMenu = async () => {
579
579
  */
580
580
  const dashboardMenu = async (service) => {
581
581
  const user = service.user;
582
- const W = 60; // Fixed width for dashboard box
582
+ const boxWidth = getLogoWidth();
583
+ const W = boxWidth - 2; // Same width as logo (inner width)
583
584
 
584
585
  // Helper to center text
585
586
  const centerLine = (text, width) => {
package/src/pages/algo.js CHANGED
@@ -159,25 +159,47 @@ const selectSymbolMenu = async (service, account) => {
159
159
 
160
160
  let availableSymbols = [];
161
161
 
162
- // Search for common symbols to get available contracts
163
- const commonSearches = ['NQ', 'ES', 'YM', 'RTY', 'CL', 'GC', 'SI', '6E', 'ZB', 'NG'];
162
+ // Search for common symbols to get available contracts (including micros)
163
+ const commonSearches = [
164
+ 'NQ', 'MNQ', // NASDAQ
165
+ 'ES', 'MES', // S&P 500
166
+ 'YM', 'MYM', // Dow Jones
167
+ 'RTY', 'M2K', // Russell 2000
168
+ 'CL', 'MCL', 'QM', // Crude Oil
169
+ 'GC', 'MGC', // Gold
170
+ 'SI', 'SIL', // Silver
171
+ '6E', 'M6E', // Euro FX
172
+ '6B', '6J', '6A', '6C', // Other currencies
173
+ 'ZB', 'ZN', 'ZF', 'ZT', // Treasuries
174
+ 'NG', 'QG', // Natural Gas
175
+ 'HG', 'PL' // Copper, Platinum
176
+ ];
164
177
 
165
178
  try {
166
179
  for (const search of commonSearches) {
167
180
  const result = await service.searchContracts(search, false);
168
181
  if (result.success && result.contracts && result.contracts.length > 0) {
169
182
  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);
183
+ // Only add contracts that have valid data
184
+ if (contract.id || contract.contractId || contract.name) {
185
+ const contractId = contract.id || contract.contractId;
186
+ const existing = availableSymbols.find(s => s.id === contractId);
173
187
  if (!existing) {
188
+ // Extract symbol from name if not provided (e.g., "NQH6" from "CON.F.US.ENQ.H26")
189
+ let symbolCode = contract.symbol || search;
190
+ if (contract.name && contract.name.includes(' ')) {
191
+ // Try to extract from name like "E-mini NASDAQ-100 Mar 2026"
192
+ symbolCode = search;
193
+ }
194
+
174
195
  availableSymbols.push({
175
- id: contract.id || contract.contractId,
176
- name: contract.name || contract.symbol,
177
- symbol: contract.symbol || search,
196
+ id: contractId,
197
+ name: contract.name || contract.symbol || search,
198
+ symbol: symbolCode,
178
199
  tickSize: contract.tickSize,
179
200
  tickValue: contract.tickValue,
180
- exchange: contract.exchange || 'CME'
201
+ exchange: contract.exchange || 'CME',
202
+ activeContract: contract.activeContract || false
181
203
  });
182
204
  }
183
205
  }
@@ -241,8 +263,11 @@ const selectSymbolMenu = async (service, account) => {
241
263
  'ZW': 'Wheat'
242
264
  };
243
265
 
244
- // Format symbols for display
245
- const symbolChoices = availableSymbols.map(symbol => {
266
+ // Format symbols for display - deduplicate by base symbol + month
267
+ const seenSymbols = new Set();
268
+ const symbolChoices = [];
269
+
270
+ for (const symbol of availableSymbols) {
246
271
  const symbolCode = symbol.symbol || symbol.id || '';
247
272
 
248
273
  // Extract base symbol (e.g., NQ from NQH6) and month code
@@ -258,15 +283,20 @@ const selectSymbolMenu = async (service, account) => {
258
283
  monthYear = (monthCodes[monthCode] || monthCode) + year;
259
284
  }
260
285
 
286
+ // Create unique key to deduplicate
287
+ const uniqueKey = `${baseSymbol}-${monthYear}`;
288
+ if (seenSymbols.has(uniqueKey)) continue;
289
+ seenSymbols.add(uniqueKey);
290
+
261
291
  // Get descriptive name from mapping
262
292
  const description = symbolDescriptions[baseSymbol] || symbol.name || baseSymbol;
263
293
 
264
294
  // Format: "NQ Mar26 E-mini NASDAQ-100"
265
- return {
295
+ symbolChoices.push({
266
296
  name: chalk.yellow(baseSymbol.padEnd(5)) + chalk.cyan(monthYear.padEnd(7)) + chalk.white(description),
267
297
  value: symbol
268
- };
269
- });
298
+ });
299
+ }
270
300
 
271
301
  symbolChoices.push(new inquirer.Separator());
272
302
  symbolChoices.push({ name: chalk.yellow('< Back'), value: 'back' });
@@ -506,9 +536,10 @@ const launchAlgo = async (service, account, contract, numContracts, dailyTarget,
506
536
  // Use ANSI escape codes to avoid flickering
507
537
  let firstDraw = true;
508
538
  const displayUI = () => {
509
- // First time: clear screen, after: just move cursor to top
539
+ // First time: clear screen and hide cursor, after: just move cursor to top
510
540
  if (firstDraw) {
511
541
  console.clear();
542
+ process.stdout.write('\x1B[?25l'); // Hide cursor
512
543
  firstDraw = false;
513
544
  } else {
514
545
  // Move cursor to top-left without clearing (avoids flicker)
@@ -871,6 +902,9 @@ const launchAlgo = async (service, account, contract, numContracts, dailyTarget,
871
902
  // Clear spinner interval
872
903
  clearInterval(spinnerInterval);
873
904
 
905
+ // Show cursor again
906
+ process.stdout.write('\x1B[?25h');
907
+
874
908
  // Stop algo
875
909
  console.log();
876
910
  if (!stopReason) {