hedgequantx 1.8.41 → 1.8.42

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.41",
3
+ "version": "1.8.42",
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": {
@@ -146,8 +146,9 @@ const configureAlgo = async (account, contract) => {
146
146
  */
147
147
  const launchAlgo = async (service, account, contract, config) => {
148
148
  const { contracts, dailyTarget, maxRisk, showName } = config;
149
- // NEVER show real name - only account ID or masked
150
- const accountName = showName ? account.accountId : 'HQX *****';
149
+ // Use real Rithmic account ID, not the hash
150
+ const realAccountId = account.rithmicAccountId || account.name || account.accountId;
151
+ const accountName = showName ? realAccountId : 'HQX *****';
151
152
  const symbolName = contract.name || contract.symbol;
152
153
 
153
154
  const ui = new AlgoUI({ subtitle: 'HQX Ultra-Scalping', mode: 'one-account' });
@@ -157,7 +158,8 @@ const launchAlgo = async (service, account, contract, config) => {
157
158
  target: dailyTarget, risk: maxRisk,
158
159
  propfirm: account.propfirm || 'Unknown',
159
160
  pnl: 0, trades: 0, wins: 0, losses: 0,
160
- latency: 0, connected: false
161
+ latency: 0, connected: false,
162
+ startTime: Date.now() // Track start time for duration
161
163
  };
162
164
 
163
165
  let running = true;
@@ -254,6 +256,17 @@ const launchAlgo = async (service, account, contract, config) => {
254
256
  if (stats.connected) { hqx.stopAlgo(); hqx.disconnect(); }
255
257
  ui.cleanup();
256
258
 
259
+ // Calculate duration
260
+ const durationMs = Date.now() - stats.startTime;
261
+ const hours = Math.floor(durationMs / 3600000);
262
+ const minutes = Math.floor((durationMs % 3600000) / 60000);
263
+ const seconds = Math.floor((durationMs % 60000) / 1000);
264
+ stats.duration = hours > 0
265
+ ? `${hours}h ${minutes}m ${seconds}s`
266
+ : minutes > 0
267
+ ? `${minutes}m ${seconds}s`
268
+ : `${seconds}s`;
269
+
257
270
  // Summary
258
271
  renderSessionSummary(stats, stopReason);
259
272
 
@@ -15,28 +15,36 @@ const BOX = {
15
15
  // Spinner characters
16
16
  const SPINNER = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F'];
17
17
 
18
- // Log type colors
18
+ // Log type colors - HF grade
19
19
  const LOG_COLORS = {
20
- info: chalk.cyan,
21
- success: chalk.green,
22
- signal: chalk.yellow.bold,
23
- trade: chalk.green.bold,
24
- loss: chalk.magenta.bold,
25
- error: chalk.red,
26
- warning: chalk.yellow
20
+ // Executions
21
+ fill_buy: chalk.green.bold,
22
+ fill_sell: chalk.red.bold,
23
+ fill_win: chalk.green.bold,
24
+ fill_loss: chalk.red.bold,
25
+ // Status
26
+ connected: chalk.green,
27
+ ready: chalk.cyan,
28
+ // Errors
29
+ error: chalk.red.bold,
30
+ reject: chalk.red,
31
+ // Info
32
+ info: chalk.gray,
33
+ system: chalk.blue
27
34
  };
28
35
 
29
- // Log type icons (fixed 10 chars for alignment)
36
+ // Log type icons - compact HF style
30
37
  const LOG_ICONS = {
31
- signal: '[SIGNAL] ',
32
- trade: '[TRADE] ',
33
- order: '[ORDER] ',
34
- position: '[POSITION]',
35
- error: '[ERROR] ',
36
- warning: '[WARNING] ',
37
- success: '[OK] ',
38
- analysis: '[ANALYSIS]',
39
- info: '[INFO] '
38
+ fill_buy: 'BUY ',
39
+ fill_sell: 'SELL ',
40
+ fill_win: 'WIN ',
41
+ fill_loss: 'LOSS ',
42
+ connected: 'CONN ',
43
+ ready: 'READY',
44
+ error: 'ERR ',
45
+ reject: 'REJ ',
46
+ info: 'INFO ',
47
+ system: 'SYS '
40
48
  };
41
49
 
42
50
  /**
@@ -265,37 +273,38 @@ class AlgoUI {
265
273
  _drawLogs() {
266
274
  const { W, logs, maxLogs } = this;
267
275
 
268
- // Activity header
276
+ // Activity header - HF style
269
277
  this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER.length;
270
278
  const spinner = SPINNER[this.spinnerFrame];
271
- const dateStr = new Date().toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });
272
- const left = ` Activity Log ${chalk.yellow(spinner)}`;
273
- const right = 'Press X to stop ';
274
- const mid = `- ${dateStr} -`;
275
- const space = W - stripAnsi(left).length - right.length;
276
- const midPad = Math.floor((space - mid.length) / 2);
277
-
278
- this._line(chalk.cyan(BOX.V) + chalk.white(left) + ' '.repeat(midPad) + chalk.cyan(mid) + ' '.repeat(space - midPad - mid.length) + chalk.yellow(right) + chalk.cyan(BOX.V));
279
+ const now = new Date();
280
+ const timeStr = now.toLocaleTimeString('en-US', { hour12: false });
281
+ const dateStr = now.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
282
+
283
+ const left = ` EXECUTION LOG ${chalk.yellow(spinner)}`;
284
+ const right = `${chalk.gray(dateStr)} ${chalk.white(timeStr)} ${chalk.yellow('[X] STOP')} `;
285
+ const leftPlain = stripAnsi(left);
286
+ const rightPlain = ` ${dateStr} ${timeStr} [X] STOP `;
287
+ const space = W - leftPlain.length - rightPlain.length;
288
+
289
+ this._line(chalk.cyan(BOX.V) + chalk.white.bold(left) + ' '.repeat(Math.max(0, space)) + right + chalk.cyan(BOX.V));
279
290
  this._line(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
280
291
 
281
- // Logs: newest at top, oldest at bottom
282
- // Take the last maxLogs entries and reverse for display
292
+ // Logs: newest at top
283
293
  const visible = logs.slice(-maxLogs).reverse();
284
294
 
285
295
  if (visible.length === 0) {
286
- this._line(chalk.cyan(BOX.V) + chalk.gray(fitToWidth(' Waiting for activity...', W)) + chalk.cyan(BOX.V));
296
+ this._line(chalk.cyan(BOX.V) + chalk.gray(fitToWidth(' Awaiting market signals...', W)) + chalk.cyan(BOX.V));
287
297
  for (let i = 0; i < maxLogs - 1; i++) {
288
298
  this._line(chalk.cyan(BOX.V) + ' '.repeat(W) + chalk.cyan(BOX.V));
289
299
  }
290
300
  } else {
291
- // Draw logs (newest first at top)
292
301
  visible.forEach(log => {
293
- const color = LOG_COLORS[log.type] || chalk.white;
294
- const icon = LOG_ICONS[log.type] || LOG_ICONS.info;
295
- const line = ` [${log.timestamp}] ${icon} ${log.message}`;
296
- this._line(chalk.cyan(BOX.V) + color(fitToWidth(line, W)) + chalk.cyan(BOX.V));
302
+ const color = LOG_COLORS[log.type] || chalk.gray;
303
+ const icon = LOG_ICONS[log.type] || '';
304
+ // HF style: TIME | TYPE | MESSAGE
305
+ const line = ` ${chalk.gray(log.timestamp)} ${color(icon)}${log.message}`;
306
+ this._line(chalk.cyan(BOX.V) + fitToWidth(line, W) + chalk.cyan(BOX.V));
297
307
  });
298
- // Pad remaining lines at bottom
299
308
  for (let i = visible.length; i < maxLogs; i++) {
300
309
  this._line(chalk.cyan(BOX.V) + ' '.repeat(W) + chalk.cyan(BOX.V));
301
310
  }