hedgequantx 1.5.5 → 1.5.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 +1 -1
- package/src/app.js +11 -20
- package/src/menus/dashboard.js +13 -29
- package/src/pages/algo/copy-trading.js +24 -16
- package/src/pages/algo/ui.js +17 -13
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -259,35 +259,26 @@ const mainMenu = async () => {
|
|
|
259
259
|
console.log(chalk.cyan('║') + leftText + ' '.repeat(Math.max(0, leftPad)) + rightText + ' '.repeat(Math.max(0, rightPad)) + chalk.cyan('║'));
|
|
260
260
|
};
|
|
261
261
|
|
|
262
|
-
menuRow(chalk.cyan('[1] ProjectX'), chalk.cyan('[2] Rithmic'));
|
|
263
|
-
menuRow(chalk.cyan('[3] Tradovate'), chalk.red('[X] Exit'));
|
|
264
|
-
|
|
265
262
|
console.log(chalk.cyan('╚' + '═'.repeat(innerWidth) + '╝'));
|
|
266
263
|
console.log();
|
|
267
264
|
|
|
265
|
+
// Use list type - more stable stdin handling
|
|
268
266
|
const { action } = await inquirer.prompt([
|
|
269
267
|
{
|
|
270
|
-
type: '
|
|
268
|
+
type: 'list',
|
|
271
269
|
name: 'action',
|
|
272
|
-
message: chalk.cyan('
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
270
|
+
message: chalk.cyan('Select platform:'),
|
|
271
|
+
choices: [
|
|
272
|
+
{ name: chalk.cyan('[1] ProjectX'), value: 'projectx' },
|
|
273
|
+
{ name: chalk.cyan('[2] Rithmic'), value: 'rithmic' },
|
|
274
|
+
{ name: chalk.cyan('[3] Tradovate'), value: 'tradovate' },
|
|
275
|
+
{ name: chalk.red('[X] Exit'), value: 'exit' }
|
|
276
|
+
],
|
|
277
|
+
loop: false
|
|
278
278
|
}
|
|
279
279
|
]);
|
|
280
280
|
|
|
281
|
-
|
|
282
|
-
const actionMap = {
|
|
283
|
-
'1': 'projectx',
|
|
284
|
-
'2': 'rithmic',
|
|
285
|
-
'3': 'tradovate',
|
|
286
|
-
'x': 'exit',
|
|
287
|
-
'X': 'exit'
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
return actionMap[action] || 'exit';
|
|
281
|
+
return action;
|
|
291
282
|
};
|
|
292
283
|
|
|
293
284
|
/**
|
package/src/menus/dashboard.js
CHANGED
|
@@ -106,44 +106,28 @@ const dashboardMenu = async (service) => {
|
|
|
106
106
|
console.log(chalk.cyan('║') + ' ' + left + leftPad + ' ' + (right || '') + rightPad + chalk.cyan('║'));
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
menuRow(chalk.cyan('[1] View Accounts'), chalk.cyan('[2] View Stats'));
|
|
110
|
-
menuRow(chalk.cyan('[+] Add Prop-Account'), chalk.cyan('[A] Algo-Trading'));
|
|
111
|
-
menuRow(chalk.yellow('[U] Update HQX'), chalk.red('[X] Disconnect'));
|
|
112
|
-
|
|
113
109
|
console.log(chalk.cyan('╚' + '═'.repeat(W) + '╝'));
|
|
114
110
|
console.log();
|
|
115
111
|
|
|
116
|
-
//
|
|
117
|
-
prepareStdin();
|
|
118
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
119
|
-
|
|
112
|
+
// Use list type instead of input - more stable stdin handling
|
|
120
113
|
const { action } = await inquirer.prompt([
|
|
121
114
|
{
|
|
122
|
-
type: '
|
|
115
|
+
type: 'list',
|
|
123
116
|
name: 'action',
|
|
124
|
-
message: chalk.cyan('
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
117
|
+
message: chalk.cyan('Select action:'),
|
|
118
|
+
choices: [
|
|
119
|
+
{ name: chalk.cyan('[1] View Accounts'), value: 'accounts' },
|
|
120
|
+
{ name: chalk.cyan('[2] View Stats'), value: 'stats' },
|
|
121
|
+
{ name: chalk.cyan('[+] Add Prop-Account'), value: 'add_prop_account' },
|
|
122
|
+
{ name: chalk.magenta('[A] Algo-Trading'), value: 'algotrading' },
|
|
123
|
+
{ name: chalk.yellow('[U] Update HQX'), value: 'update' },
|
|
124
|
+
{ name: chalk.red('[X] Disconnect'), value: 'disconnect' }
|
|
125
|
+
],
|
|
126
|
+
loop: false
|
|
130
127
|
}
|
|
131
128
|
]);
|
|
132
129
|
|
|
133
|
-
|
|
134
|
-
const actionMap = {
|
|
135
|
-
'1': 'accounts',
|
|
136
|
-
'2': 'stats',
|
|
137
|
-
'+': 'add_prop_account',
|
|
138
|
-
'a': 'algotrading',
|
|
139
|
-
'A': 'algotrading',
|
|
140
|
-
'u': 'update',
|
|
141
|
-
'U': 'update',
|
|
142
|
-
'x': 'disconnect',
|
|
143
|
-
'X': 'disconnect'
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
return actionMap[action] || 'accounts';
|
|
130
|
+
return action;
|
|
147
131
|
};
|
|
148
132
|
|
|
149
133
|
/**
|
|
@@ -136,33 +136,41 @@ const copyTradingMenu = async () => {
|
|
|
136
136
|
console.log();
|
|
137
137
|
console.log(chalk.cyan(' Step 5: Configure Parameters'));
|
|
138
138
|
|
|
139
|
-
const {
|
|
140
|
-
type: '
|
|
141
|
-
name: '
|
|
139
|
+
const { leadContractsInput } = await inquirer.prompt([{
|
|
140
|
+
type: 'input',
|
|
141
|
+
name: 'leadContractsInput',
|
|
142
142
|
message: 'Lead contracts:',
|
|
143
|
-
default: 1
|
|
143
|
+
default: '1',
|
|
144
|
+
validate: v => !isNaN(parseInt(v)) && parseInt(v) > 0 ? true : 'Enter a positive number'
|
|
144
145
|
}]);
|
|
146
|
+
const leadContracts = parseInt(leadContractsInput) || 1;
|
|
145
147
|
|
|
146
|
-
const {
|
|
147
|
-
type: '
|
|
148
|
-
name: '
|
|
148
|
+
const { followerContractsInput } = await inquirer.prompt([{
|
|
149
|
+
type: 'input',
|
|
150
|
+
name: 'followerContractsInput',
|
|
149
151
|
message: 'Follower contracts:',
|
|
150
|
-
default: leadContracts
|
|
152
|
+
default: String(leadContracts),
|
|
153
|
+
validate: v => !isNaN(parseInt(v)) && parseInt(v) > 0 ? true : 'Enter a positive number'
|
|
151
154
|
}]);
|
|
155
|
+
const followerContracts = parseInt(followerContractsInput) || leadContracts;
|
|
152
156
|
|
|
153
|
-
const {
|
|
154
|
-
type: '
|
|
155
|
-
name: '
|
|
157
|
+
const { dailyTargetInput } = await inquirer.prompt([{
|
|
158
|
+
type: 'input',
|
|
159
|
+
name: 'dailyTargetInput',
|
|
156
160
|
message: 'Daily target ($):',
|
|
157
|
-
default: 400
|
|
161
|
+
default: '400',
|
|
162
|
+
validate: v => !isNaN(parseInt(v)) && parseInt(v) > 0 ? true : 'Enter a positive number'
|
|
158
163
|
}]);
|
|
164
|
+
const dailyTarget = parseInt(dailyTargetInput) || 400;
|
|
159
165
|
|
|
160
|
-
const {
|
|
161
|
-
type: '
|
|
162
|
-
name: '
|
|
166
|
+
const { maxRiskInput } = await inquirer.prompt([{
|
|
167
|
+
type: 'input',
|
|
168
|
+
name: 'maxRiskInput',
|
|
163
169
|
message: 'Max risk ($):',
|
|
164
|
-
default: 200
|
|
170
|
+
default: '200',
|
|
171
|
+
validate: v => !isNaN(parseInt(v)) && parseInt(v) > 0 ? true : 'Enter a positive number'
|
|
165
172
|
}]);
|
|
173
|
+
const maxRisk = parseInt(maxRiskInput) || 200;
|
|
166
174
|
|
|
167
175
|
// Step 6: Privacy
|
|
168
176
|
const { showNames } = await inquirer.prompt([{
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -146,11 +146,15 @@ class AlgoUI {
|
|
|
146
146
|
|
|
147
147
|
this._line(chalk.cyan(GT));
|
|
148
148
|
|
|
149
|
-
// Row 1: Account | Symbol
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
149
|
+
// Row 1: Account | Symbol (truncate long values)
|
|
150
|
+
const accName = (stats.accountName || 'N/A').substring(0, 35);
|
|
151
|
+
const symName = (stats.symbol || 'N/A').substring(0, 25);
|
|
152
|
+
const qtyStr = stats.contracts || '1/1';
|
|
153
|
+
|
|
154
|
+
const r1c1 = buildCell('Account', accName, chalk.cyan, colL);
|
|
155
|
+
const r1c2t = ` Symbol: ${chalk.yellow(symName)} Qty: ${chalk.cyan(qtyStr)}`;
|
|
156
|
+
const r1c2p = ` Symbol: ${symName} Qty: ${qtyStr}`;
|
|
157
|
+
row(r1c1.padded, r1c2t + pad(Math.max(0, colR - r1c2p.length)));
|
|
154
158
|
|
|
155
159
|
this._line(chalk.cyan(GM));
|
|
156
160
|
|
|
@@ -193,9 +197,9 @@ class AlgoUI {
|
|
|
193
197
|
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));
|
|
194
198
|
this._line(chalk.cyan(BOX.ML + BOX.H.repeat(W) + BOX.MR));
|
|
195
199
|
|
|
196
|
-
// Logs
|
|
197
|
-
// Take the last maxLogs entries
|
|
198
|
-
const visible = logs.slice(-maxLogs);
|
|
200
|
+
// Logs: newest at top, oldest at bottom
|
|
201
|
+
// Take the last maxLogs entries and reverse for display
|
|
202
|
+
const visible = logs.slice(-maxLogs).reverse();
|
|
199
203
|
|
|
200
204
|
if (visible.length === 0) {
|
|
201
205
|
this._line(chalk.cyan(BOX.V) + chalk.gray(fitToWidth(' Waiting for activity...', W)) + chalk.cyan(BOX.V));
|
|
@@ -203,17 +207,17 @@ class AlgoUI {
|
|
|
203
207
|
this._line(chalk.cyan(BOX.V) + ' '.repeat(W) + chalk.cyan(BOX.V));
|
|
204
208
|
}
|
|
205
209
|
} else {
|
|
206
|
-
//
|
|
207
|
-
for (let i = visible.length; i < maxLogs; i++) {
|
|
208
|
-
this._line(chalk.cyan(BOX.V) + ' '.repeat(W) + chalk.cyan(BOX.V));
|
|
209
|
-
}
|
|
210
|
-
// Then draw logs (oldest first, newest last/at bottom)
|
|
210
|
+
// Draw logs (newest first at top)
|
|
211
211
|
visible.forEach(log => {
|
|
212
212
|
const color = LOG_COLORS[log.type] || chalk.white;
|
|
213
213
|
const icon = LOG_ICONS[log.type] || LOG_ICONS.info;
|
|
214
214
|
const line = ` [${log.timestamp}] ${icon} ${log.message}`;
|
|
215
215
|
this._line(chalk.cyan(BOX.V) + color(fitToWidth(line, W)) + chalk.cyan(BOX.V));
|
|
216
216
|
});
|
|
217
|
+
// Pad remaining lines at bottom
|
|
218
|
+
for (let i = visible.length; i < maxLogs; i++) {
|
|
219
|
+
this._line(chalk.cyan(BOX.V) + ' '.repeat(W) + chalk.cyan(BOX.V));
|
|
220
|
+
}
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
// Bottom border
|