hedgequantx 1.3.7 → 1.3.9

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.3.7",
3
+ "version": "1.3.9",
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": {
@@ -113,6 +113,10 @@ const dashboardMenu = async (service) => {
113
113
  console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
114
114
  console.log();
115
115
 
116
+ // Small delay to ensure stdin is ready
117
+ await new Promise(resolve => setTimeout(resolve, 50));
118
+ prepareStdin();
119
+
116
120
  const { action } = await inquirer.prompt([
117
121
  {
118
122
  type: 'input',
@@ -19,15 +19,16 @@ const { AlgoUI, checkMarketStatus } = require('./ui');
19
19
  const oneAccountMenu = async (service) => {
20
20
  const spinner = ora('Fetching active accounts...').start();
21
21
 
22
- const result = await service.getTradingAccounts();
22
+ // Get ALL accounts from ALL connections
23
+ const allAccounts = await connections.getAllAccounts();
23
24
 
24
- if (!result.success || !result.accounts?.length) {
25
+ if (!allAccounts?.length) {
25
26
  spinner.fail('No accounts found');
26
27
  await inquirer.prompt([{ type: 'input', name: 'c', message: 'Press Enter...' }]);
27
28
  return;
28
29
  }
29
30
 
30
- const activeAccounts = result.accounts.filter(acc => acc.status === 0);
31
+ const activeAccounts = allAccounts.filter(acc => acc.status === 0);
31
32
 
32
33
  if (!activeAccounts.length) {
33
34
  spinner.fail('No active accounts');
@@ -37,14 +38,16 @@ const oneAccountMenu = async (service) => {
37
38
 
38
39
  spinner.succeed(`Found ${activeAccounts.length} active account(s)`);
39
40
 
40
- // Select account
41
+ // Select account - show propfirm for clarity
41
42
  const { selectedAccount } = await inquirer.prompt([{
42
43
  type: 'list',
43
44
  name: 'selectedAccount',
44
45
  message: 'Select Account:',
45
46
  choices: [
46
47
  ...activeAccounts.map(acc => ({
47
- name: chalk.cyan(`${acc.accountName || acc.accountId} - $${acc.balance.toLocaleString()}`),
48
+ name: chalk.cyan(`${acc.accountName || acc.accountId}`) +
49
+ chalk.gray(` (${acc.propfirm || 'Unknown'})`) +
50
+ chalk.white(` - $${(acc.balance || 0).toLocaleString()}`),
48
51
  value: acc
49
52
  })),
50
53
  new inquirer.Separator(),
@@ -54,16 +57,19 @@ const oneAccountMenu = async (service) => {
54
57
 
55
58
  if (selectedAccount === 'back') return;
56
59
 
60
+ // Find the service for this account
61
+ const accountService = connections.getServiceForAccount(selectedAccount.accountId) || service;
62
+
57
63
  // Select symbol
58
- const contract = await selectSymbol(service, selectedAccount);
64
+ const contract = await selectSymbol(accountService, selectedAccount);
59
65
  if (!contract) return;
60
66
 
61
67
  // Configure algo
62
68
  const config = await configureAlgo(selectedAccount, contract);
63
69
  if (!config) return;
64
70
 
65
- // Launch
66
- await launchAlgo(service, selectedAccount, contract, config);
71
+ // Launch with the correct service for this account
72
+ await launchAlgo(accountService, selectedAccount, contract, config);
67
73
  };
68
74
 
69
75
  /**
@@ -261,6 +261,30 @@ const connections = {
261
261
  return allAccounts;
262
262
  },
263
263
 
264
+ /**
265
+ * Gets the service for a specific account
266
+ * @param {string|number} accountId - Account ID to find
267
+ * @returns {Object|null} Service instance or null
268
+ */
269
+ getServiceForAccount(accountId) {
270
+ for (const conn of this.services) {
271
+ try {
272
+ // Check if this service has this account
273
+ if (conn.service && conn.service.accounts) {
274
+ const found = conn.service.accounts.find(acc =>
275
+ acc.accountId == accountId ||
276
+ acc.rithmicAccountId == accountId ||
277
+ acc.accountName == accountId
278
+ );
279
+ if (found) return conn.service;
280
+ }
281
+ } catch (e) {
282
+ // Skip
283
+ }
284
+ }
285
+ return null;
286
+ },
287
+
264
288
  /**
265
289
  * Checks if any connection is active
266
290
  * @returns {boolean} True if connected
package/src/ui/index.js CHANGED
@@ -29,11 +29,32 @@ const { createBoxMenu } = require('./menu');
29
29
  * This fixes input leaking to bash after session restore or algo trading
30
30
  */
31
31
  const prepareStdin = () => {
32
- // Minimal intervention - just ensure stdin is flowing
33
32
  try {
33
+ // Ensure stdin is flowing
34
34
  if (process.stdin.isPaused()) {
35
35
  process.stdin.resume();
36
36
  }
37
+
38
+ // Reset stdin to proper state for inquirer
39
+ if (process.stdin.isTTY) {
40
+ // Disable raw mode if it was left on
41
+ if (process.stdin.isRaw) {
42
+ process.stdin.setRawMode(false);
43
+ }
44
+ }
45
+
46
+ // Clear any buffered input by removing old listeners temporarily
47
+ const oldListeners = process.stdin.listeners('data');
48
+ process.stdin.removeAllListeners('data');
49
+
50
+ // Restore listeners after a tick
51
+ setImmediate(() => {
52
+ oldListeners.forEach(listener => {
53
+ if (!process.stdin.listeners('data').includes(listener)) {
54
+ process.stdin.on('data', listener);
55
+ }
56
+ });
57
+ });
37
58
  } catch (e) {
38
59
  // Ignore errors
39
60
  }