hedgequantx 1.8.5 → 1.8.7

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.8.5",
3
+ "version": "1.8.7",
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
@@ -170,7 +170,7 @@ const mainMenu = async () => {
170
170
 
171
171
  console.log(chalk.cyan('╚' + '═'.repeat(innerWidth) + '╝'));
172
172
 
173
- const input = await prompts.textInput('Select (1/2/3/X)');
173
+ const input = await prompts.textInput(chalk.cyan('Select (1/2/3/X)'));
174
174
 
175
175
  const actionMap = {
176
176
  '1': 'projectx',
@@ -91,7 +91,7 @@ const dashboardMenu = async (service) => {
91
91
  console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
92
92
 
93
93
  // Simple input - no duplicate menu
94
- const input = await prompts.textInput('Select (1/2/+/A/U/X)');
94
+ const input = await prompts.textInput(chalk.cyan('Select (1/2/+/A/U/X)'));
95
95
 
96
96
  const actionMap = {
97
97
  '1': 'accounts',
@@ -84,20 +84,15 @@ const copyTradingMenu = async () => {
84
84
  if (followerIdx === null || followerIdx === -1) return;
85
85
  const follower = allAccounts[followerIdx];
86
86
 
87
- // Step 3-4: Select Symbols
87
+ // Step 3: Select Trading Symbol
88
88
  console.log();
89
- console.log(chalk.cyan(' Step 3: Select Symbol for LEAD'));
90
- const leadSymbol = await selectSymbol(lead.service, 'Lead');
91
- if (!leadSymbol) return;
89
+ console.log(chalk.cyan(' Step 3: Select Trading Symbol'));
90
+ const symbol = await selectSymbol(lead.service, 'Trading');
91
+ if (!symbol) return;
92
92
 
93
+ // Step 4: Configure parameters
93
94
  console.log();
94
- console.log(chalk.cyan(' Step 4: Select Symbol for FOLLOWER'));
95
- const followerSymbol = await selectSymbol(follower.service, 'Follower');
96
- if (!followerSymbol) return;
97
-
98
- // Step 5: Configure parameters
99
- console.log();
100
- console.log(chalk.cyan(' Step 5: Configure Parameters'));
95
+ console.log(chalk.cyan(' Step 4: Configure Parameters'));
101
96
 
102
97
  const leadContracts = await prompts.numberInput('Lead contracts:', 1, 1, 10);
103
98
  if (leadContracts === null) return;
@@ -111,7 +106,7 @@ const copyTradingMenu = async () => {
111
106
  const maxRisk = await prompts.numberInput('Max risk ($):', 200, 1, 5000);
112
107
  if (maxRisk === null) return;
113
108
 
114
- // Step 6: Privacy
109
+ // Step 5: Privacy
115
110
  const showNames = await prompts.selectOption('Account names:', [
116
111
  { label: 'Hide account names', value: false },
117
112
  { label: 'Show account names', value: true }
@@ -121,8 +116,9 @@ const copyTradingMenu = async () => {
121
116
  // Confirm
122
117
  console.log();
123
118
  console.log(chalk.white(' Summary:'));
124
- console.log(chalk.gray(` Lead: ${lead.propfirm} -> ${leadSymbol.name} x${leadContracts}`));
125
- console.log(chalk.gray(` Follower: ${follower.propfirm} -> ${followerSymbol.name} x${followerContracts}`));
119
+ console.log(chalk.gray(` Symbol: ${symbol.name}`));
120
+ console.log(chalk.gray(` Lead: ${lead.propfirm} x${leadContracts}`));
121
+ console.log(chalk.gray(` Follower: ${follower.propfirm} x${followerContracts}`));
126
122
  console.log(chalk.gray(` Target: $${dailyTarget} | Risk: $${maxRisk}`));
127
123
  console.log();
128
124
 
@@ -131,32 +127,52 @@ const copyTradingMenu = async () => {
131
127
 
132
128
  // Launch
133
129
  await launchCopyTrading({
134
- lead: { ...lead, symbol: leadSymbol, contracts: leadContracts },
135
- follower: { ...follower, symbol: followerSymbol, contracts: followerContracts },
130
+ lead: { ...lead, symbol, contracts: leadContracts },
131
+ follower: { ...follower, symbol, contracts: followerContracts },
136
132
  dailyTarget, maxRisk, showNames
137
133
  });
138
134
  };
139
135
 
136
+ // Cached contracts from API
137
+ let cachedContracts = null;
138
+
140
139
  /**
141
- * Symbol selection helper
140
+ * Get contracts from ProjectX API (shared for all services)
141
+ */
142
+ const getContractsFromAPI = async () => {
143
+ if (cachedContracts) return cachedContracts;
144
+
145
+ // Find a ProjectX connection to get contracts from API
146
+ const allConns = connections.getAll();
147
+ const projectxConn = allConns.find(c => c.type === 'projectx');
148
+
149
+ if (projectxConn && typeof projectxConn.service.getContracts === 'function') {
150
+ const result = await projectxConn.service.getContracts();
151
+ if (result.success && result.contracts?.length > 0) {
152
+ cachedContracts = result.contracts;
153
+ return cachedContracts;
154
+ }
155
+ }
156
+
157
+ return null;
158
+ };
159
+
160
+ /**
161
+ * Symbol selection helper - uses API contracts for all services
142
162
  */
143
163
  const selectSymbol = async (service, label) => {
144
164
  try {
145
- let contracts = [];
165
+ // Always use contracts from ProjectX API for consistency
166
+ let contracts = await getContractsFromAPI();
146
167
 
147
- if (typeof service.getContracts === 'function') {
168
+ // Fallback to service's own contracts if no ProjectX available
169
+ if (!contracts && typeof service.getContracts === 'function') {
148
170
  const result = await service.getContracts();
149
171
  if (result.success && result.contracts?.length > 0) {
150
172
  contracts = result.contracts;
151
173
  }
152
174
  }
153
175
 
154
- if (contracts.length === 0 && typeof service.searchContracts === 'function') {
155
- const searchResult = await service.searchContracts('ES');
156
- if (Array.isArray(searchResult)) contracts = searchResult;
157
- else if (searchResult?.contracts) contracts = searchResult.contracts;
158
- }
159
-
160
176
  if (!contracts || contracts.length === 0) {
161
177
  console.log(chalk.red(' No contracts available'));
162
178
  return null;