hedgequantx 2.3.15 → 2.3.17

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/dist/lib/api.jsc CHANGED
Binary file
package/dist/lib/api2.jsc CHANGED
Binary file
package/dist/lib/core.jsc CHANGED
Binary file
Binary file
package/dist/lib/data.jsc CHANGED
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/lib/n/r1.jsc CHANGED
Binary file
package/dist/lib/n/r2.jsc CHANGED
Binary file
package/dist/lib/n/r3.jsc CHANGED
Binary file
package/dist/lib/n/r4.jsc CHANGED
Binary file
package/dist/lib/n/r5.jsc CHANGED
Binary file
package/dist/lib/n/r6.jsc CHANGED
Binary file
package/dist/lib/n/r7.jsc CHANGED
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.3.15",
3
+ "version": "2.3.17",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -11,6 +11,8 @@ const { AlgoUI, renderSessionSummary } = require('./ui');
11
11
  const { prompts } = require('../../utils');
12
12
  const { checkMarketHours } = require('../../services/projectx/market');
13
13
 
14
+
15
+
14
16
  /**
15
17
  * One Account Menu
16
18
  */
@@ -154,28 +156,49 @@ const configureAlgo = async (account, contract) => {
154
156
 
155
157
  /**
156
158
  * Launch algo trading
159
+ * 100% API data - no simulation, no mock data, no local calculations
157
160
  */
158
161
  const launchAlgo = async (service, account, contract, config) => {
159
162
  const { contracts, dailyTarget, maxRisk, showName } = config;
160
- // Use real account ID from API
161
- const realAccountId = account.rithmicAccountId || account.accountName || account.accountId;
162
- const accountName = showName ? realAccountId : 'HQX *****';
163
- // Use RAW API field 'name' for symbol (e.g., "MESH6")
163
+
164
+ // Use RAW API fields
165
+ const accountName = showName
166
+ ? (account.accountName || account.rithmicAccountId || account.accountId)
167
+ : 'HQX *****';
164
168
  const symbolName = contract.name;
169
+ const connectionType = account.platform || 'ProjectX';
165
170
 
166
171
  const ui = new AlgoUI({ subtitle: 'HQX Algo Trading', mode: 'one-account' });
167
172
 
168
173
  const stats = {
169
- accountName, symbol: symbolName, contracts,
170
- target: dailyTarget, risk: maxRisk,
174
+ accountName,
175
+ symbol: symbolName,
176
+ qty: contracts,
177
+ target: dailyTarget,
178
+ risk: maxRisk,
171
179
  propfirm: account.propfirm || 'Unknown',
172
- platform: account.platform || 'ProjectX',
173
- pnl: 0, trades: 0, wins: 0, losses: 0,
174
- latency: 0, connected: false,
175
- startTime: Date.now() // Track start time for duration
180
+ platform: connectionType,
181
+ pnl: 0,
182
+ trades: 0,
183
+ wins: 0,
184
+ losses: 0,
185
+ latency: 0,
186
+ connected: true,
187
+ startTime: Date.now()
176
188
  };
177
189
 
178
- // Measure API latency (CLI <-> API)
190
+ let running = true;
191
+ let stopReason = null;
192
+ let lastPnL = 0;
193
+
194
+ // Log startup info from API
195
+ ui.addLog('info', `Connection: ${connectionType}`);
196
+ ui.addLog('info', `Account: ${accountName}`);
197
+ ui.addLog('info', `Symbol: ${symbolName} | Qty: ${contracts}`);
198
+ ui.addLog('info', `Target: $${dailyTarget} | Max Risk: $${maxRisk}`);
199
+ ui.addLog('info', 'Monitoring positions from API...');
200
+
201
+ // Measure API latency (real network round-trip)
179
202
  const measureLatency = async () => {
180
203
  try {
181
204
  const start = Date.now();
@@ -186,45 +209,64 @@ const launchAlgo = async (service, account, contract, config) => {
186
209
  }
187
210
  };
188
211
 
189
- let running = true;
190
- let stopReason = null;
191
-
192
- // Local algo - no external server needed
193
- ui.addLog('info', `Starting algo on ${stats.platform}...`);
194
- ui.addLog('info', `Symbol: ${symbolName} | Qty: ${contracts}`);
195
- ui.addLog('info', `Target: $${dailyTarget} | Risk: $${maxRisk}`);
196
- stats.connected = true;
197
-
198
- // Poll P&L from API every 2 seconds
199
- const pollPnL = async () => {
212
+ // Poll data from API - 100% real data
213
+ const pollAPI = async () => {
200
214
  try {
201
- // Get positions to check P&L
215
+ // Get positions from API
202
216
  const posResult = await service.getPositions(account.accountId);
217
+
203
218
  if (posResult.success && posResult.positions) {
204
- // Find position for our symbol
205
- const pos = posResult.positions.find(p =>
206
- (p.contractId || p.symbol || '').includes(contract.name || contract.symbol)
207
- );
208
- if (pos && pos.profitAndLoss !== undefined) {
209
- const prevPnL = stats.pnl;
210
- stats.pnl = pos.profitAndLoss;
219
+ // Find position for selected contract
220
+ const position = posResult.positions.find(p => {
221
+ const posSymbol = p.contractId || p.symbol || '';
222
+ return posSymbol.includes(contract.name) || posSymbol.includes(contract.id);
223
+ });
224
+
225
+ if (position) {
226
+ // P&L directly from API - no calculation
227
+ const apiPnL = position.profitAndLoss || 0;
211
228
 
212
- // Detect trade completion
213
- if (Math.abs(stats.pnl - prevPnL) > 0.01 && prevPnL !== 0) {
214
- const tradePnL = stats.pnl - prevPnL;
229
+ // Detect trade completion (P&L changed)
230
+ if (lastPnL !== 0 && Math.abs(apiPnL - lastPnL) > 0.01) {
231
+ const tradePnL = apiPnL - lastPnL;
215
232
  stats.trades++;
216
- if (tradePnL >= 0) {
233
+
234
+ if (tradePnL > 0) {
217
235
  stats.wins++;
218
- ui.addLog('trade', `Trade closed: +$${tradePnL.toFixed(2)}`);
236
+ ui.addLog('trade', `+$${tradePnL.toFixed(2)} (from API)`);
219
237
  } else {
220
238
  stats.losses++;
221
- ui.addLog('loss', `Trade closed: -$${Math.abs(tradePnL).toFixed(2)}`);
239
+ ui.addLog('loss', `-$${Math.abs(tradePnL).toFixed(2)} (from API)`);
222
240
  }
223
241
  }
242
+
243
+ lastPnL = apiPnL;
244
+ stats.pnl = apiPnL;
245
+
246
+ // Log position info from API
247
+ if (position.quantity && position.quantity !== 0) {
248
+ const side = position.quantity > 0 ? 'LONG' : 'SHORT';
249
+ const qty = Math.abs(position.quantity);
250
+ ui.addLog('info', `Position: ${side} ${qty}x | P&L: $${apiPnL.toFixed(2)}`);
251
+ }
252
+ } else {
253
+ // No position - flat
254
+ if (stats.pnl !== 0) {
255
+ ui.addLog('info', 'Position closed - Flat');
256
+ }
224
257
  }
225
258
  }
226
259
 
227
- // Check target/risk limits
260
+ // Get account balance from API
261
+ const accountResult = await service.getTradingAccounts();
262
+ if (accountResult.success && accountResult.accounts) {
263
+ const acc = accountResult.accounts.find(a => a.accountId === account.accountId);
264
+ if (acc && acc.profitAndLoss !== undefined) {
265
+ stats.pnl = acc.profitAndLoss;
266
+ }
267
+ }
268
+
269
+ // Check target/risk limits (using API P&L)
228
270
  if (stats.pnl >= dailyTarget) {
229
271
  stopReason = 'target';
230
272
  running = false;
@@ -232,10 +274,11 @@ const launchAlgo = async (service, account, contract, config) => {
232
274
  } else if (stats.pnl <= -maxRisk) {
233
275
  stopReason = 'risk';
234
276
  running = false;
235
- ui.addLog('error', `MAX RISK HIT! -$${Math.abs(stats.pnl).toFixed(2)}`);
277
+ ui.addLog('error', `MAX RISK! -$${Math.abs(stats.pnl).toFixed(2)}`);
236
278
  }
279
+
237
280
  } catch (e) {
238
- // Silent fail - will retry
281
+ ui.addLog('error', `API Error: ${e.message}`);
239
282
  }
240
283
  };
241
284
 
@@ -245,9 +288,9 @@ const launchAlgo = async (service, account, contract, config) => {
245
288
  measureLatency(); // Initial measurement
246
289
  const latencyInterval = setInterval(() => { if (running) measureLatency(); }, 5000);
247
290
 
248
- // Poll P&L from API every 2 seconds
249
- pollPnL(); // Initial poll
250
- const pnlInterval = setInterval(() => { if (running) pollPnL(); }, 2000);
291
+ // Poll data from API every 2 seconds
292
+ pollAPI(); // Initial poll
293
+ const apiInterval = setInterval(() => { if (running) pollAPI(); }, 2000);
251
294
 
252
295
  // Keyboard
253
296
  const setupKeyHandler = () => {
@@ -276,7 +319,7 @@ const launchAlgo = async (service, account, contract, config) => {
276
319
 
277
320
  clearInterval(refreshInterval);
278
321
  clearInterval(latencyInterval);
279
- clearInterval(pnlInterval);
322
+ clearInterval(apiInterval);
280
323
  if (cleanupKeys) cleanupKeys();
281
324
  ui.cleanup();
282
325
 
@@ -275,14 +275,18 @@ class AlgoUI {
275
275
  const dateStr = now.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
276
276
 
277
277
  const leftText = ` EXECUTION LOG ${spinner}`;
278
- const rightText = `${dateStr} ${timeStr} [X] STOP `;
279
- const totalLen = leftText.length + rightText.length;
280
- const space = W - totalLen;
278
+ const rightText = `[X] STOP `;
279
+
280
+ const totalFixed = leftText.length + rightText.length;
281
+ const centerSpace = W - totalFixed;
282
+ const centerPadLeft = Math.floor((centerSpace - dateStr.length) / 2);
283
+ const centerPadRight = centerSpace - dateStr.length - centerPadLeft;
281
284
 
282
285
  const left = ` EXECUTION LOG ${chalk.yellow(spinner)}`;
283
- const right = `${chalk.gray(dateStr)} ${chalk.white(timeStr)} ${chalk.yellow('[X] STOP')} `;
286
+ const center = ' '.repeat(Math.max(0, centerPadLeft)) + chalk.white(dateStr) + ' '.repeat(Math.max(0, centerPadRight));
287
+ const right = chalk.yellow('[X] STOP') + ' ';
284
288
 
285
- this._line(chalk.cyan(BOX.V) + chalk.white.bold(left) + ' '.repeat(Math.max(0, space)) + right + chalk.cyan(BOX.V));
289
+ this._line(chalk.cyan(BOX.V) + chalk.white.bold(left) + center + right + chalk.cyan(BOX.V));
286
290
  this._line(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
287
291
 
288
292
  // Logs: newest at top