hedgequantx 1.3.3 → 1.3.4

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.3",
3
+ "version": "1.3.4",
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": {
@@ -7,6 +7,10 @@
7
7
 
8
8
  const https = require('https');
9
9
  const { PROPFIRMS } = require('../../config');
10
+
11
+ // Debug mode - set HQX_DEBUG=1 to enable
12
+ const DEBUG = process.env.HQX_DEBUG === '1';
13
+ const debug = (...args) => DEBUG && console.log('[ProjectX]', ...args);
10
14
  const {
11
15
  validateUsername,
12
16
  validatePassword,
@@ -149,53 +153,35 @@ class ProjectXService {
149
153
 
150
154
  /**
151
155
  * Get trading accounts - ONLY returns values from API
152
- * P&L comes from: today's trades + open positions (both from API)
156
+ * For banner display: returns basic account info quickly
157
+ * Use getAccountPnL() for detailed P&L data
153
158
  */
154
159
  async getTradingAccounts() {
155
160
  try {
156
161
  const response = await this._request(this.propfirm.userApi, '/TradingAccount', 'GET');
162
+ debug('getTradingAccounts response:', JSON.stringify(response.data, null, 2));
163
+
157
164
  if (response.statusCode !== 200) {
158
165
  return { success: false, accounts: [], error: 'Failed to get accounts' };
159
166
  }
160
167
 
161
168
  const accounts = Array.isArray(response.data) ? response.data : [];
162
- const enrichedAccounts = [];
163
-
164
- for (const account of accounts) {
165
- // Start with RAW API data only
166
- const enriched = {
167
- accountId: account.accountId,
168
- accountName: account.accountName,
169
- balance: account.balance, // From API
170
- status: account.status, // From API
171
- type: account.type, // From API
172
- platform: 'ProjectX',
173
- propfirm: this.propfirm.name,
174
- // P&L fields - will be populated from API calls
175
- todayPnL: null,
176
- openPnL: null,
177
- profitAndLoss: null,
178
- startingBalance: null,
179
- };
180
-
181
- // Only fetch P&L for active accounts
182
- if (account.status === 0) {
183
- // Get today's realized P&L from trades API
184
- const todayPnL = await this._getTodayRealizedPnL(account.accountId);
185
- enriched.todayPnL = todayPnL;
186
-
187
- // Get unrealized P&L from open positions API
188
- const openPnL = await this._getOpenPositionsPnL(account.accountId);
189
- enriched.openPnL = openPnL;
190
-
191
- // Total P&L = realized + unrealized (both from API)
192
- if (todayPnL !== null || openPnL !== null) {
193
- enriched.profitAndLoss = (todayPnL || 0) + (openPnL || 0);
194
- }
195
- }
196
-
197
- enrichedAccounts.push(enriched);
198
- }
169
+
170
+ // Return RAW API data only - no additional calls for speed
171
+ const enrichedAccounts = accounts.map(account => ({
172
+ accountId: account.accountId,
173
+ accountName: account.accountName,
174
+ balance: account.balance, // From API
175
+ status: account.status, // From API
176
+ type: account.type, // From API
177
+ platform: 'ProjectX',
178
+ propfirm: this.propfirm.name,
179
+ // P&L not available from /TradingAccount endpoint
180
+ todayPnL: null,
181
+ openPnL: null,
182
+ profitAndLoss: null,
183
+ startingBalance: null,
184
+ }));
199
185
 
200
186
  return { success: true, accounts: enrichedAccounts };
201
187
  } catch (error) {
@@ -203,6 +189,28 @@ class ProjectXService {
203
189
  }
204
190
  }
205
191
 
192
+ /**
193
+ * Get detailed P&L for a specific account
194
+ * Call this separately when P&L details are needed (e.g., stats page)
195
+ */
196
+ async getAccountPnL(accountId) {
197
+ const todayPnL = await this._getTodayRealizedPnL(accountId);
198
+ const openPnL = await this._getOpenPositionsPnL(accountId);
199
+
200
+ let totalPnL = null;
201
+ if (todayPnL !== null || openPnL !== null) {
202
+ totalPnL = (todayPnL || 0) + (openPnL || 0);
203
+ }
204
+
205
+ debug(`Account ${accountId} P&L:`, { todayPnL, openPnL, totalPnL });
206
+
207
+ return {
208
+ todayPnL,
209
+ openPnL,
210
+ profitAndLoss: totalPnL
211
+ };
212
+ }
213
+
206
214
  /**
207
215
  * Get today's realized P&L from Trade API
208
216
  * Returns null if API fails (not 0)
@@ -227,15 +235,20 @@ class ProjectXService {
227
235
  ? response.data
228
236
  : (response.data.trades || []);
229
237
 
238
+ debug(`_getTodayRealizedPnL: ${trades.length} trades found`);
239
+
230
240
  // Sum P&L from API response only
231
241
  let totalPnL = 0;
232
242
  for (const trade of trades) {
233
243
  if (trade.profitAndLoss !== undefined && trade.profitAndLoss !== null) {
234
244
  totalPnL += trade.profitAndLoss;
245
+ debug(` Trade P&L: ${trade.profitAndLoss}`);
235
246
  }
236
247
  }
248
+ debug(` Total realized P&L: ${totalPnL}`);
237
249
  return totalPnL;
238
250
  }
251
+ debug('_getTodayRealizedPnL: API failed or no data');
239
252
  return null; // API failed - return null, not 0
240
253
  } catch (e) {
241
254
  return null;
@@ -256,16 +269,21 @@ class ProjectXService {
256
269
 
257
270
  if (response.statusCode === 200 && response.data) {
258
271
  const positions = response.data.positions || response.data || [];
272
+ debug(`_getOpenPositionsPnL: ${positions.length} positions found`);
273
+
259
274
  if (Array.isArray(positions)) {
260
275
  let totalPnL = 0;
261
276
  for (const pos of positions) {
262
277
  if (pos.profitAndLoss !== undefined && pos.profitAndLoss !== null) {
263
278
  totalPnL += pos.profitAndLoss;
279
+ debug(` Position ${pos.symbolId || 'unknown'} P&L: ${pos.profitAndLoss}`);
264
280
  }
265
281
  }
282
+ debug(` Total open P&L: ${totalPnL}`);
266
283
  return totalPnL;
267
284
  }
268
285
  }
286
+ debug('_getOpenPositionsPnL: API failed or no data');
269
287
  return null;
270
288
  } catch (e) {
271
289
  return null;
@@ -7,6 +7,10 @@
7
7
 
8
8
  const { REQ } = require('./constants');
9
9
 
10
+ // Debug mode - set HQX_DEBUG=1 to enable
11
+ const DEBUG = process.env.HQX_DEBUG === '1';
12
+ const debug = (...args) => DEBUG && console.log('[Rithmic]', ...args);
13
+
10
14
  /**
11
15
  * Hash account ID to numeric (for compatibility)
12
16
  */
package/src/ui/index.js CHANGED
@@ -29,15 +29,8 @@ 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
32
33
  try {
33
- // Remove any raw mode that might be left from previous operations
34
- if (process.stdin.isTTY && process.stdin.isRaw) {
35
- process.stdin.setRawMode(false);
36
- }
37
- // Remove any lingering keypress listeners
38
- process.stdin.removeAllListeners('keypress');
39
- process.stdin.removeAllListeners('data');
40
- // Resume stdin so inquirer can take control
41
34
  if (process.stdin.isPaused()) {
42
35
  process.stdin.resume();
43
36
  }