hedgequantx 1.1.1 → 1.2.32

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.
@@ -0,0 +1,538 @@
1
+ /**
2
+ * Algo Trading Page
3
+ */
4
+
5
+ const chalk = require('chalk');
6
+ const ora = require('ora');
7
+ const inquirer = require('inquirer');
8
+ const readline = require('readline');
9
+
10
+ const { connections } = require('../services');
11
+ const { HQXServerService } = require('../services/hqx-server');
12
+ const { FUTURES_SYMBOLS } = require('../config');
13
+ const { getDevice, getSeparator } = require('../ui');
14
+
15
+ /**
16
+ * Algo Trading Menu
17
+ */
18
+ const algoTradingMenu = async (service) => {
19
+ const device = getDevice();
20
+ console.log();
21
+ console.log(chalk.gray(getSeparator()));
22
+ console.log(chalk.magenta.bold(' Algo-Trading'));
23
+ console.log(chalk.gray(getSeparator()));
24
+ console.log();
25
+
26
+ const { action } = await inquirer.prompt([
27
+ {
28
+ type: 'list',
29
+ name: 'action',
30
+ message: chalk.white.bold('Select Mode:'),
31
+ choices: [
32
+ { name: chalk.cyan('One Account'), value: 'one_account' },
33
+ { name: chalk.gray('Copy Trading (Coming Soon)'), value: 'copy_trading', disabled: 'Coming Soon' },
34
+ new inquirer.Separator(),
35
+ { name: chalk.yellow('< Back'), value: 'back' }
36
+ ],
37
+ pageSize: 10,
38
+ loop: false
39
+ }
40
+ ]);
41
+
42
+ switch (action) {
43
+ case 'one_account':
44
+ await oneAccountMenu(service);
45
+ break;
46
+ case 'copy_trading':
47
+ // Disabled - Coming Soon
48
+ break;
49
+ case 'back':
50
+ return 'back';
51
+ }
52
+
53
+ return action;
54
+ };
55
+
56
+ /**
57
+ * One Account Menu - Select active account
58
+ */
59
+ const oneAccountMenu = async (service) => {
60
+ const spinner = ora('Fetching active accounts...').start();
61
+
62
+ const result = await service.getTradingAccounts();
63
+
64
+ if (!result.success || !result.accounts || result.accounts.length === 0) {
65
+ spinner.fail('No accounts found');
66
+ console.log(chalk.yellow(' You need at least one trading account.'));
67
+ console.log();
68
+ await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
69
+ return;
70
+ }
71
+
72
+ // Filter only active accounts (status === 0)
73
+ const activeAccounts = result.accounts.filter(acc => acc.status === 0);
74
+
75
+ if (activeAccounts.length === 0) {
76
+ spinner.fail('No active accounts found');
77
+ console.log(chalk.yellow(' You need at least one active trading account (status: Active).'));
78
+ console.log();
79
+ await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
80
+ return;
81
+ }
82
+
83
+ spinner.succeed(`Found ${activeAccounts.length} active account(s)`);
84
+ console.log();
85
+
86
+ const accountChoices = activeAccounts.map(account => ({
87
+ name: chalk.cyan(`${account.accountName || account.name || 'Account #' + account.accountId} - Balance: $${account.balance.toLocaleString()}`),
88
+ value: account
89
+ }));
90
+
91
+ accountChoices.push(new inquirer.Separator());
92
+ accountChoices.push({ name: chalk.yellow('< Back'), value: 'back' });
93
+
94
+ const { selectedAccount } = await inquirer.prompt([
95
+ {
96
+ type: 'list',
97
+ name: 'selectedAccount',
98
+ message: chalk.white.bold('Select Account:'),
99
+ choices: accountChoices,
100
+ pageSize: 15,
101
+ loop: false
102
+ }
103
+ ]);
104
+
105
+ if (selectedAccount === 'back') {
106
+ return;
107
+ }
108
+
109
+ // Check market status
110
+ console.log();
111
+ const marketSpinner = ora('Checking market status...').start();
112
+
113
+ const marketHours = service.checkMarketHours();
114
+ const marketStatus = await service.getMarketStatus(selectedAccount.accountId);
115
+
116
+ if (!marketHours.isOpen) {
117
+ marketSpinner.fail('Market is CLOSED');
118
+ console.log();
119
+ console.log(chalk.red.bold(' [X] ' + marketHours.message));
120
+ console.log();
121
+ console.log(chalk.gray(' Futures markets (CME) trading hours:'));
122
+ console.log(chalk.gray(' Sunday 5:00 PM CT - Friday 4:00 PM CT'));
123
+ console.log(chalk.gray(' Daily maintenance: 4:00 PM - 5:00 PM CT'));
124
+ console.log();
125
+ await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
126
+ return;
127
+ }
128
+
129
+ if (marketStatus.success && !marketStatus.isOpen) {
130
+ marketSpinner.fail('Cannot trade on this account');
131
+ console.log();
132
+ console.log(chalk.red.bold(' [X] ' + marketStatus.message));
133
+ console.log();
134
+ await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
135
+ return;
136
+ }
137
+
138
+ marketSpinner.succeed('Market is OPEN - Ready to trade!');
139
+
140
+ await selectSymbolMenu(service, selectedAccount);
141
+ };
142
+
143
+ /**
144
+ * Symbol Selection Menu
145
+ */
146
+ const selectSymbolMenu = async (service, account) => {
147
+ const device = getDevice();
148
+ const accountName = account.accountName || account.name || 'Account #' + account.accountId;
149
+
150
+ console.log();
151
+ console.log(chalk.gray(getSeparator()));
152
+ console.log(chalk.cyan.bold(` Account: ${accountName}`));
153
+ console.log(chalk.gray(getSeparator()));
154
+ console.log();
155
+
156
+ const symbolChoices = FUTURES_SYMBOLS.map(symbol => ({
157
+ name: chalk.cyan(device.isMobile ? symbol.value : symbol.name),
158
+ value: symbol
159
+ }));
160
+
161
+ symbolChoices.push(new inquirer.Separator());
162
+ symbolChoices.push({ name: chalk.yellow('< Back'), value: 'back' });
163
+
164
+ const { selectedSymbol } = await inquirer.prompt([
165
+ {
166
+ type: 'list',
167
+ name: 'selectedSymbol',
168
+ message: chalk.white.bold('Select Symbol:'),
169
+ choices: symbolChoices,
170
+ pageSize: 15,
171
+ loop: false
172
+ }
173
+ ]);
174
+
175
+ if (selectedSymbol === 'back') {
176
+ return;
177
+ }
178
+
179
+ // Search contract via Gateway API
180
+ const spinner = ora(`Searching for ${selectedSymbol.value} contract...`).start();
181
+ const contractResult = await service.searchContracts(selectedSymbol.searchText, false);
182
+
183
+ let contract = null;
184
+ if (contractResult.success && contractResult.contracts && contractResult.contracts.length > 0) {
185
+ contract = contractResult.contracts.find(c => c.activeContract) || contractResult.contracts[0];
186
+ spinner.succeed(`Found: ${contract.name || selectedSymbol.value}`);
187
+ if (contract.tickSize && contract.tickValue) {
188
+ console.log(chalk.gray(` Tick Size: ${contract.tickSize} | Tick Value: $${contract.tickValue}`));
189
+ }
190
+ } else {
191
+ spinner.warn(`Using ${selectedSymbol.value} (contract details unavailable)`);
192
+ contract = {
193
+ id: selectedSymbol.value,
194
+ name: selectedSymbol.name,
195
+ symbol: selectedSymbol.value
196
+ };
197
+ }
198
+
199
+ console.log();
200
+
201
+ // Number of contracts
202
+ const { contracts } = await inquirer.prompt([
203
+ {
204
+ type: 'input',
205
+ name: 'contracts',
206
+ message: chalk.white.bold('Number of Contracts:'),
207
+ default: '1',
208
+ validate: (input) => {
209
+ const num = parseInt(input);
210
+ if (isNaN(num) || num <= 0 || num > 100) {
211
+ return 'Please enter a valid number between 1 and 100';
212
+ }
213
+ return true;
214
+ },
215
+ filter: (input) => parseInt(input)
216
+ }
217
+ ]);
218
+
219
+ // Confirmation
220
+ console.log();
221
+ console.log(chalk.gray(getSeparator()));
222
+ console.log(chalk.white.bold(' Algo Configuration:'));
223
+ console.log(chalk.gray(getSeparator()));
224
+ console.log(chalk.white(` Account: ${chalk.cyan(accountName)}`));
225
+ console.log(chalk.white(` Symbol: ${chalk.cyan(contract.name || selectedSymbol.value)}`));
226
+ console.log(chalk.white(` Contracts: ${chalk.cyan(contracts)}`));
227
+ console.log(chalk.gray(getSeparator()));
228
+ console.log();
229
+
230
+ const { launch } = await inquirer.prompt([
231
+ {
232
+ type: 'list',
233
+ name: 'launch',
234
+ message: chalk.white.bold('Ready to launch?'),
235
+ choices: [
236
+ { name: chalk.green.bold('[>] Launch Algo'), value: 'launch' },
237
+ { name: chalk.yellow('< Back'), value: 'back' }
238
+ ],
239
+ loop: false
240
+ }
241
+ ]);
242
+
243
+ if (launch === 'back') {
244
+ return;
245
+ }
246
+
247
+ await launchAlgo(service, account, contract, contracts);
248
+ };
249
+
250
+ /**
251
+ * Launch Algo with HQX Server Connection
252
+ */
253
+ const launchAlgo = async (service, account, contract, numContracts) => {
254
+ const accountName = account.accountName || account.name || 'Account #' + account.accountId;
255
+ const symbolName = contract.name || contract.symbol || contract.id;
256
+ const symbol = contract.symbol || contract.id;
257
+
258
+ console.log();
259
+ console.log(chalk.green.bold(' [>] Launching HQX Algo...'));
260
+ console.log();
261
+
262
+ // Initialize HQX Server connection
263
+ const hqxServer = new HQXServerService();
264
+ let hqxConnected = false;
265
+ let algoRunning = false;
266
+
267
+ // Activity logs
268
+ const logs = [];
269
+ const MAX_LOGS = 12;
270
+
271
+ // Stats
272
+ let stats = {
273
+ trades: 0,
274
+ wins: 0,
275
+ losses: 0,
276
+ pnl: 0,
277
+ signals: 0,
278
+ winRate: '0.0'
279
+ };
280
+
281
+ const addLog = (type, message) => {
282
+ const timestamp = new Date().toLocaleTimeString();
283
+ logs.push({ timestamp, type, message });
284
+ if (logs.length > MAX_LOGS) logs.shift();
285
+ };
286
+
287
+ const clearScreen = () => {
288
+ console.clear();
289
+ };
290
+
291
+ const displayUI = () => {
292
+ clearScreen();
293
+ console.log();
294
+ console.log(chalk.gray(getSeparator()));
295
+ console.log(chalk.cyan.bold(' HQX Ultra-Scalping Algo'));
296
+ console.log(chalk.gray(getSeparator()));
297
+ console.log(chalk.white(` Status: ${algoRunning ? chalk.green('RUNNING') : chalk.yellow('CONNECTING...')}`));
298
+ console.log(chalk.white(` Account: ${chalk.cyan(accountName)}`));
299
+ console.log(chalk.white(` Symbol: ${chalk.cyan(symbolName)}`));
300
+ console.log(chalk.white(` Contracts: ${chalk.cyan(numContracts)}`));
301
+ console.log(chalk.white(` Mode: ${hqxConnected ? chalk.green('LIVE') : chalk.yellow('OFFLINE')}`));
302
+ console.log(chalk.gray(getSeparator()));
303
+
304
+ // Stats bar
305
+ console.log();
306
+ console.log(chalk.white(' Stats: ') +
307
+ chalk.gray('Trades: ') + chalk.cyan(stats.trades) +
308
+ chalk.gray(' | Wins: ') + chalk.green(stats.wins) +
309
+ chalk.gray(' | Losses: ') + chalk.red(stats.losses) +
310
+ chalk.gray(' | Win Rate: ') + chalk.yellow(stats.winRate + '%') +
311
+ chalk.gray(' | P&L: ') + (stats.pnl >= 0 ? chalk.green('$' + stats.pnl.toFixed(2)) : chalk.red('-$' + Math.abs(stats.pnl).toFixed(2)))
312
+ );
313
+ console.log();
314
+
315
+ // Activity logs
316
+ console.log(chalk.gray(getSeparator()));
317
+ console.log(chalk.white.bold(' Activity Log'));
318
+ console.log(chalk.gray(getSeparator()));
319
+
320
+ const typeColors = {
321
+ info: chalk.cyan,
322
+ success: chalk.green,
323
+ signal: chalk.yellow.bold,
324
+ trade: chalk.green.bold,
325
+ error: chalk.red,
326
+ warning: chalk.yellow
327
+ };
328
+
329
+ if (logs.length === 0) {
330
+ console.log(chalk.gray(' Waiting for activity...'));
331
+ } else {
332
+ logs.forEach(log => {
333
+ const color = typeColors[log.type] || chalk.white;
334
+ const icon = log.type === 'signal' ? '[*]' :
335
+ log.type === 'trade' ? '[>]' :
336
+ log.type === 'error' ? '[X]' :
337
+ log.type === 'success' ? '[OK]' : '[.]';
338
+ console.log(chalk.gray(` [${log.timestamp}]`) + ' ' + color(`${icon} ${log.message}`));
339
+ });
340
+ }
341
+
342
+ console.log(chalk.gray(getSeparator()));
343
+ console.log();
344
+ console.log(chalk.yellow(' Press X to stop algo...'));
345
+ console.log();
346
+ };
347
+
348
+ // Connect to HQX Server
349
+ const spinner = ora('Authenticating with HQX Server...').start();
350
+
351
+ try {
352
+ // Authenticate
353
+ const authResult = await hqxServer.authenticate(account.accountId.toString(), account.propfirm || 'projectx');
354
+
355
+ if (!authResult.success) {
356
+ spinner.fail('Authentication failed: ' + (authResult.error || 'Unknown error'));
357
+ addLog('error', 'Authentication failed');
358
+
359
+ // Fallback to offline mode
360
+ console.log(chalk.yellow(' Running in offline demo mode...'));
361
+ console.log();
362
+ await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
363
+ return;
364
+ }
365
+
366
+ spinner.text = 'Connecting to WebSocket...';
367
+
368
+ // Connect WebSocket
369
+ const connectResult = await hqxServer.connect();
370
+
371
+ if (connectResult.success) {
372
+ spinner.succeed('Connected to HQX Server');
373
+ hqxConnected = true;
374
+ } else {
375
+ throw new Error('WebSocket connection failed');
376
+ }
377
+
378
+ } catch (error) {
379
+ spinner.warn('HQX Server unavailable - Running in offline mode');
380
+ hqxConnected = false;
381
+ }
382
+
383
+ // Setup event handlers
384
+ hqxServer.on('log', (data) => {
385
+ addLog(data.type || 'info', data.message);
386
+ displayUI();
387
+ });
388
+
389
+ hqxServer.on('signal', (data) => {
390
+ stats.signals++;
391
+ const side = data.side === 'long' ? 'BUY' : 'SELL';
392
+ addLog('signal', `${side} Signal @ ${data.entry?.toFixed(2) || 'N/A'} | SL: ${data.stop?.toFixed(2) || 'N/A'} | TP: ${data.target?.toFixed(2) || 'N/A'}`);
393
+ displayUI();
394
+
395
+ // Execute order via PropFirm API if connected
396
+ if (hqxConnected && service) {
397
+ executeSignal(service, account, contract, numContracts, data);
398
+ }
399
+ });
400
+
401
+ hqxServer.on('trade', (data) => {
402
+ stats.trades++;
403
+ stats.pnl += data.pnl || 0;
404
+ if (data.pnl > 0) {
405
+ stats.wins++;
406
+ addLog('trade', `Closed +$${data.pnl.toFixed(2)} (${data.reason || 'take_profit'})`);
407
+ } else {
408
+ stats.losses++;
409
+ addLog('trade', `Closed -$${Math.abs(data.pnl).toFixed(2)} (${data.reason || 'stop_loss'})`);
410
+ }
411
+ stats.winRate = stats.trades > 0 ? ((stats.wins / stats.trades) * 100).toFixed(1) : '0.0';
412
+ displayUI();
413
+ });
414
+
415
+ hqxServer.on('stats', (data) => {
416
+ stats = { ...stats, ...data };
417
+ displayUI();
418
+ });
419
+
420
+ hqxServer.on('error', (data) => {
421
+ addLog('error', data.message || 'Unknown error');
422
+ displayUI();
423
+ });
424
+
425
+ hqxServer.on('disconnected', () => {
426
+ hqxConnected = false;
427
+ addLog('warning', 'Disconnected from HQX Server');
428
+ displayUI();
429
+ });
430
+
431
+ // Start algo
432
+ if (hqxConnected) {
433
+ addLog('info', 'Starting HQX Ultra-Scalping...');
434
+ hqxServer.startAlgo({
435
+ accountId: account.accountId,
436
+ contractId: contract.id || contract.contractId,
437
+ symbol: symbol,
438
+ contracts: numContracts,
439
+ dailyTarget: 500, // Default daily target
440
+ maxRisk: 200, // Default max risk
441
+ propfirm: account.propfirm || 'projectx',
442
+ propfirmToken: service.getToken ? service.getToken() : null
443
+ });
444
+ algoRunning = true;
445
+ } else {
446
+ addLog('warning', 'Running in offline demo mode');
447
+ addLog('info', 'No real trades will be executed');
448
+ algoRunning = true;
449
+ }
450
+
451
+ displayUI();
452
+
453
+ // Wait for X key to stop
454
+ await waitForStopKey();
455
+
456
+ // Stop algo
457
+ addLog('warning', 'Stopping algo...');
458
+ displayUI();
459
+
460
+ if (hqxConnected) {
461
+ hqxServer.stopAlgo();
462
+ }
463
+
464
+ hqxServer.disconnect();
465
+ algoRunning = false;
466
+
467
+ console.log();
468
+ console.log(chalk.green(' [OK] Algo stopped successfully'));
469
+ console.log();
470
+
471
+ // Final stats
472
+ console.log(chalk.gray(getSeparator()));
473
+ console.log(chalk.white.bold(' Session Summary'));
474
+ console.log(chalk.gray(getSeparator()));
475
+ console.log(chalk.white(` Total Trades: ${chalk.cyan(stats.trades)}`));
476
+ console.log(chalk.white(` Wins: ${chalk.green(stats.wins)}`));
477
+ console.log(chalk.white(` Losses: ${chalk.red(stats.losses)}`));
478
+ console.log(chalk.white(` Win Rate: ${chalk.yellow(stats.winRate + '%')}`));
479
+ console.log(chalk.white(` Total P&L: ${stats.pnl >= 0 ? chalk.green('+$' + stats.pnl.toFixed(2)) : chalk.red('-$' + Math.abs(stats.pnl).toFixed(2))}`));
480
+ console.log(chalk.gray(getSeparator()));
481
+ console.log();
482
+
483
+ await inquirer.prompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
484
+ };
485
+
486
+ /**
487
+ * Execute signal via PropFirm API
488
+ */
489
+ const executeSignal = async (service, account, contract, numContracts, signal) => {
490
+ try {
491
+ const orderData = {
492
+ accountId: account.accountId,
493
+ contractId: contract.id || contract.contractId,
494
+ type: 2, // Market order
495
+ side: signal.side === 'long' ? 0 : 1, // 0=Buy, 1=Sell
496
+ size: numContracts
497
+ };
498
+
499
+ // Place order via ProjectX Gateway API
500
+ const result = await service.placeOrder(orderData);
501
+
502
+ if (result.success) {
503
+ console.log(chalk.green(` [OK] Order executed: ${signal.side.toUpperCase()} ${numContracts} contracts`));
504
+ } else {
505
+ console.log(chalk.red(` [X] Order failed: ${result.error || 'Unknown error'}`));
506
+ }
507
+ } catch (error) {
508
+ console.log(chalk.red(` [X] Order error: ${error.message}`));
509
+ }
510
+ };
511
+
512
+ /**
513
+ * Wait for X key to stop
514
+ */
515
+ const waitForStopKey = () => {
516
+ return new Promise((resolve) => {
517
+ // Enable raw mode to capture keypresses
518
+ if (process.stdin.isTTY) {
519
+ readline.emitKeypressEvents(process.stdin);
520
+ process.stdin.setRawMode(true);
521
+
522
+ const onKeypress = (str, key) => {
523
+ if (key && (key.name === 'x' || key.name === 'X' || (key.ctrl && key.name === 'c'))) {
524
+ process.stdin.setRawMode(false);
525
+ process.stdin.removeListener('keypress', onKeypress);
526
+ resolve();
527
+ }
528
+ };
529
+
530
+ process.stdin.on('keypress', onKeypress);
531
+ } else {
532
+ // Fallback: wait 30 seconds in non-TTY mode
533
+ setTimeout(resolve, 30000);
534
+ }
535
+ });
536
+ };
537
+
538
+ module.exports = { algoTradingMenu };
@@ -1,9 +1,20 @@
1
1
  /**
2
- * Pages Module Exports
2
+ * @fileoverview Pages module exports
3
+ * @module pages
3
4
  */
4
5
 
5
6
  const { showStats } = require('./stats');
7
+ const { showAccounts } = require('./accounts');
8
+ const { showPositions } = require('./positions');
9
+ const { showOrders } = require('./orders');
10
+ const { showUserInfo } = require('./user');
11
+ const { algoTradingMenu } = require('./algo');
6
12
 
7
13
  module.exports = {
8
- showStats
14
+ showStats,
15
+ showAccounts,
16
+ showPositions,
17
+ showOrders,
18
+ showUserInfo,
19
+ algoTradingMenu
9
20
  };
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @fileoverview Orders page
3
+ * @module pages/orders
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const ora = require('ora');
8
+ const inquirer = require('inquirer');
9
+
10
+ const { connections } = require('../services');
11
+ const { ORDER_STATUS, ORDER_TYPE, ORDER_SIDE } = require('../config');
12
+ const { getLogoWidth, drawBoxHeader, drawBoxFooter, drawBoxRow, drawBoxSeparator, visibleLength, padText } = require('../ui');
13
+
14
+ /**
15
+ * Shows all orders from all connections
16
+ * @param {Object} service - Current service
17
+ */
18
+ const showOrders = async (service) => {
19
+ const spinner = ora('Fetching orders...').start();
20
+ const boxWidth = getLogoWidth();
21
+
22
+ // Get all accounts first
23
+ let allAccounts = [];
24
+
25
+ if (connections.count() > 0) {
26
+ for (const conn of connections.getAll()) {
27
+ try {
28
+ const result = await conn.service.getTradingAccounts();
29
+ if (result.success && result.accounts) {
30
+ result.accounts.forEach(account => {
31
+ allAccounts.push({
32
+ ...account,
33
+ propfirm: conn.propfirm || conn.type,
34
+ service: conn.service
35
+ });
36
+ });
37
+ }
38
+ } catch (e) { /* ignore */ }
39
+ }
40
+ } else if (service) {
41
+ const result = await service.getTradingAccounts();
42
+ if (result.success && result.accounts) {
43
+ allAccounts = result.accounts.map(a => ({ ...a, service, propfirm: service.propfirm.name }));
44
+ }
45
+ }
46
+
47
+ // Get orders for each account
48
+ let allOrders = [];
49
+
50
+ for (const account of allAccounts) {
51
+ try {
52
+ const result = await account.service.getOrders(account.accountId);
53
+ if (result.success && result.orders && result.orders.length > 0) {
54
+ result.orders.forEach(order => {
55
+ allOrders.push({
56
+ ...order,
57
+ accountName: account.accountName || account.name,
58
+ propfirm: account.propfirm
59
+ });
60
+ });
61
+ }
62
+ } catch (e) { /* ignore */ }
63
+ }
64
+
65
+ spinner.succeed(`Found ${allOrders.length} order(s)`);
66
+ console.log();
67
+
68
+ drawBoxHeader('ORDERS', boxWidth);
69
+
70
+ if (allOrders.length === 0) {
71
+ drawBoxRow(chalk.gray(' No orders found'), boxWidth);
72
+ } else {
73
+ // Header row
74
+ const header = ' ' +
75
+ 'Symbol'.padEnd(12) +
76
+ 'Side'.padEnd(6) +
77
+ 'Type'.padEnd(8) +
78
+ 'Qty'.padEnd(6) +
79
+ 'Price'.padEnd(10) +
80
+ 'Status'.padEnd(12) +
81
+ 'Account';
82
+ drawBoxRow(chalk.white.bold(header), boxWidth);
83
+ drawBoxSeparator(boxWidth);
84
+
85
+ // Order rows
86
+ for (const order of allOrders) {
87
+ const symbol = (order.contractId || order.symbol || 'Unknown').substring(0, 11);
88
+ const sideInfo = ORDER_SIDE[order.side] || { text: '?', color: 'white' };
89
+ const type = ORDER_TYPE[order.type] || 'Unknown';
90
+ const qty = order.size || order.quantity || 0;
91
+ const price = order.limitPrice || order.price || 0;
92
+ const statusInfo = ORDER_STATUS[order.status] || { text: 'Unknown', color: 'gray', icon: '[?]' };
93
+ const account = (order.accountName || 'Unknown').substring(0, 12);
94
+
95
+ const row = ' ' +
96
+ chalk.white(symbol.padEnd(12)) +
97
+ chalk[sideInfo.color](sideInfo.text.substring(0, 4).padEnd(6)) +
98
+ chalk.white(type.substring(0, 7).padEnd(8)) +
99
+ chalk.white(qty.toString().padEnd(6)) +
100
+ chalk.white((price > 0 ? price.toFixed(2) : 'MKT').padEnd(10)) +
101
+ chalk[statusInfo.color]((statusInfo.icon + ' ' + statusInfo.text).substring(0, 11).padEnd(12)) +
102
+ chalk.gray(account);
103
+
104
+ drawBoxRow(row, boxWidth);
105
+ }
106
+ }
107
+
108
+ drawBoxFooter(boxWidth);
109
+ console.log();
110
+
111
+ await inquirer.prompt([{ type: 'input', name: 'c', message: 'Press Enter to continue...' }]);
112
+ };
113
+
114
+ module.exports = { showOrders };