hedgequantx 1.5.5 → 1.5.6
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/pages/algo/copy-trading.js +24 -16
- package/src/pages/algo/ui.js +17 -13
package/package.json
CHANGED
|
@@ -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
|