hedgequantx 2.9.147 → 2.9.149
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/algo-executor.js +5 -8
- package/src/pages/algo/copy-executor.js +6 -2
- package/src/pages/algo/multi-symbol-executor.js +6 -2
- package/src/pages/algo/one-account.js +32 -29
- package/src/services/rithmic-broker/client.js +7 -1
- package/src/services/rithmic-broker/daemon.js +16 -2
package/package.json
CHANGED
|
@@ -326,14 +326,11 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
|
|
|
326
326
|
marketFeed.on('disconnected', () => { stats.connected = false; ui.addLog('error', 'Market disconnected'); });
|
|
327
327
|
|
|
328
328
|
try {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (service.disconnectTicker) {
|
|
335
|
-
await service.disconnectTicker();
|
|
336
|
-
}
|
|
329
|
+
// Try sync (RithmicService) then async (BrokerClient)
|
|
330
|
+
let rithmicCredentials = service.getRithmicCredentials?.();
|
|
331
|
+
if (!rithmicCredentials && service.getRithmicCredentialsAsync) rithmicCredentials = await service.getRithmicCredentialsAsync();
|
|
332
|
+
if (!rithmicCredentials) throw new Error('Rithmic credentials not available - try "hqx login"');
|
|
333
|
+
if (service.disconnectTicker) await service.disconnectTicker(); // Avoid TICKER conflict
|
|
337
334
|
await marketFeed.connect(rithmicCredentials);
|
|
338
335
|
await marketFeed.subscribe(symbolCode, contract.exchange || 'CME');
|
|
339
336
|
|
|
@@ -188,9 +188,13 @@ const launchCopyTrading = async (config) => {
|
|
|
188
188
|
|
|
189
189
|
// Connect to market data (Rithmic TICKER_PLANT)
|
|
190
190
|
try {
|
|
191
|
-
|
|
191
|
+
// Try sync first (RithmicService), then async (RithmicBrokerClient)
|
|
192
|
+
let rithmicCredentials = leadService.getRithmicCredentials?.();
|
|
193
|
+
if (!rithmicCredentials && leadService.getRithmicCredentialsAsync) {
|
|
194
|
+
rithmicCredentials = await leadService.getRithmicCredentialsAsync();
|
|
195
|
+
}
|
|
192
196
|
if (!rithmicCredentials) {
|
|
193
|
-
throw new Error('Rithmic credentials not available');
|
|
197
|
+
throw new Error('Rithmic credentials not available - try "hqx login"');
|
|
194
198
|
}
|
|
195
199
|
await marketFeed.connect(rithmicCredentials);
|
|
196
200
|
await marketFeed.subscribe(symbolName, contract.exchange || 'CME');
|
|
@@ -267,8 +267,12 @@ const executeMultiSymbol = async ({ service, account, contracts, config, strateg
|
|
|
267
267
|
|
|
268
268
|
// Connect and subscribe to all symbols
|
|
269
269
|
try {
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
// Try sync first (RithmicService), then async (RithmicBrokerClient)
|
|
271
|
+
let rithmicCredentials = service.getRithmicCredentials?.();
|
|
272
|
+
if (!rithmicCredentials && service.getRithmicCredentialsAsync) {
|
|
273
|
+
rithmicCredentials = await service.getRithmicCredentialsAsync();
|
|
274
|
+
}
|
|
275
|
+
if (!rithmicCredentials) throw new Error('Rithmic credentials not available - try "hqx login"');
|
|
272
276
|
|
|
273
277
|
if (service.disconnectTicker) await service.disconnectTicker();
|
|
274
278
|
await marketFeed.connect(rithmicCredentials);
|
|
@@ -302,6 +302,9 @@ const oneAccountMenu = async (service) => {
|
|
|
302
302
|
const selectMultipleSymbols = async (service, account) => {
|
|
303
303
|
const spinner = ora({ text: 'Loading symbols...', color: 'yellow' }).start();
|
|
304
304
|
|
|
305
|
+
// Debug: log service type
|
|
306
|
+
const serviceType = service.constructor?.name || 'Unknown';
|
|
307
|
+
|
|
305
308
|
// Ensure we have a logged-in service
|
|
306
309
|
if (!service.loginInfo && service.credentials) {
|
|
307
310
|
spinner.text = 'Reconnecting to broker...';
|
|
@@ -312,19 +315,24 @@ const selectMultipleSymbols = async (service, account) => {
|
|
|
312
315
|
}
|
|
313
316
|
}
|
|
314
317
|
|
|
315
|
-
|
|
318
|
+
let contractsResult;
|
|
319
|
+
try {
|
|
320
|
+
contractsResult = await service.getContracts();
|
|
321
|
+
} catch (err) {
|
|
322
|
+
spinner.fail(`getContracts exception: ${err.message}`);
|
|
323
|
+
console.log(chalk.gray(` Service: ${serviceType} | Tip: Try "hqx login"`));
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
316
326
|
if (!contractsResult.success || !contractsResult.contracts?.length) {
|
|
317
327
|
spinner.fail(`Failed to load contracts: ${contractsResult.error || 'No contracts'}`);
|
|
328
|
+
console.log(chalk.gray(` Service: ${serviceType} | Tip: Try "hqx login"`));
|
|
318
329
|
return null;
|
|
319
330
|
}
|
|
320
331
|
|
|
321
332
|
const contracts = sortContracts(contractsResult.contracts);
|
|
322
333
|
spinner.succeed(`Found ${contracts.length} contracts`);
|
|
323
|
-
|
|
324
|
-
console.log();
|
|
325
|
-
console.log(chalk.cyan(' Select up to 5 symbols (one at a time)'));
|
|
326
|
-
console.log(chalk.gray(' Select "Done" when finished'));
|
|
327
|
-
console.log();
|
|
334
|
+
console.log(chalk.cyan('\n Select up to 5 symbols (one at a time)'));
|
|
335
|
+
console.log(chalk.gray(' Select "Done" when finished\n'));
|
|
328
336
|
|
|
329
337
|
const selectedContracts = [];
|
|
330
338
|
const maxSymbols = 5;
|
|
@@ -356,30 +364,17 @@ const selectMultipleSymbols = async (service, account) => {
|
|
|
356
364
|
: `Select Symbol ${selectedContracts.length + 1}/${maxSymbols} (${remaining} remaining):`;
|
|
357
365
|
|
|
358
366
|
const selection = await prompts.selectOption(chalk.yellow(promptText), options);
|
|
359
|
-
|
|
360
|
-
if (selection === '
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
if (selection === 'done') {
|
|
364
|
-
break;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
+
if (selection === 'back' || selection === null) return null;
|
|
368
|
+
if (selection === 'done') break;
|
|
367
369
|
selectedContracts.push(selection);
|
|
368
370
|
console.log(chalk.green(` ✓ Added: ${selection.symbol}`));
|
|
369
371
|
}
|
|
370
|
-
|
|
371
|
-
if (selectedContracts.length === 0) {
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
372
|
+
if (selectedContracts.length === 0) return null;
|
|
374
373
|
|
|
375
374
|
// Display summary
|
|
375
|
+
console.log(chalk.cyan(`\n Selected ${selectedContracts.length} symbol(s):`));
|
|
376
|
+
for (const c of selectedContracts) console.log(chalk.white(` - ${c.symbol} (${c.baseSymbol || c.name})`));
|
|
376
377
|
console.log();
|
|
377
|
-
console.log(chalk.cyan(` Selected ${selectedContracts.length} symbol(s):`));
|
|
378
|
-
for (const c of selectedContracts) {
|
|
379
|
-
console.log(chalk.white(` - ${c.symbol} (${c.baseSymbol || c.name})`));
|
|
380
|
-
}
|
|
381
|
-
console.log();
|
|
382
|
-
|
|
383
378
|
return selectedContracts;
|
|
384
379
|
};
|
|
385
380
|
|
|
@@ -389,6 +384,9 @@ const selectMultipleSymbols = async (service, account) => {
|
|
|
389
384
|
const selectSymbol = async (service, account) => {
|
|
390
385
|
const spinner = ora({ text: 'Loading symbols...', color: 'yellow' }).start();
|
|
391
386
|
|
|
387
|
+
// Debug: log service type
|
|
388
|
+
const serviceType = service.constructor?.name || 'Unknown';
|
|
389
|
+
|
|
392
390
|
// Ensure we have a logged-in service (for direct RithmicService, not BrokerClient)
|
|
393
391
|
if (!service.loginInfo && service.credentials && typeof service.login === 'function') {
|
|
394
392
|
spinner.text = 'Reconnecting to broker...';
|
|
@@ -399,12 +397,17 @@ const selectSymbol = async (service, account) => {
|
|
|
399
397
|
}
|
|
400
398
|
}
|
|
401
399
|
|
|
402
|
-
|
|
403
|
-
|
|
400
|
+
let contractsResult;
|
|
401
|
+
try {
|
|
402
|
+
contractsResult = await service.getContracts();
|
|
403
|
+
} catch (err) {
|
|
404
|
+
spinner.fail(`getContracts exception: ${err.message}`);
|
|
405
|
+
console.log(chalk.gray(` Service: ${serviceType} | Tip: Try "hqx login"`));
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
404
408
|
if (!contractsResult.success || !contractsResult.contracts?.length) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
console.log(chalk.gray(' Tip: Try reconnecting with "hqx login"'));
|
|
409
|
+
spinner.fail(`Failed to load contracts: ${contractsResult.error || 'No contracts available'}`);
|
|
410
|
+
console.log(chalk.gray(` Service: ${serviceType} | Tip: Try "hqx login"`));
|
|
408
411
|
return null;
|
|
409
412
|
}
|
|
410
413
|
|
|
@@ -211,7 +211,13 @@ class RithmicBrokerClient extends EventEmitter {
|
|
|
211
211
|
*/
|
|
212
212
|
async getContracts() {
|
|
213
213
|
const result = await this._request('getContracts', { propfirmKey: this.propfirmKey });
|
|
214
|
-
if (result.error)
|
|
214
|
+
if (result.error) {
|
|
215
|
+
// Debug: show exactly what error came from daemon
|
|
216
|
+
if (process.env.HQX_DEBUG === '1') {
|
|
217
|
+
console.log('[BrokerClient] getContracts error:', result.error, 'propfirmKey:', this.propfirmKey);
|
|
218
|
+
}
|
|
219
|
+
return { success: false, contracts: [], error: result.error };
|
|
220
|
+
}
|
|
215
221
|
return result.payload || { success: true, contracts: [] };
|
|
216
222
|
}
|
|
217
223
|
|
|
@@ -299,13 +299,27 @@ class RithmicBrokerDaemon {
|
|
|
299
299
|
|
|
300
300
|
async _handleGetContracts(payload, requestId) {
|
|
301
301
|
const conn = this.connections.get(payload.propfirmKey);
|
|
302
|
-
if (!conn?.service)
|
|
302
|
+
if (!conn?.service) {
|
|
303
|
+
log('WARN', 'getContracts: Not connected', { propfirm: payload.propfirmKey, hasConn: !!conn });
|
|
304
|
+
return { error: 'Not connected to broker', requestId };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Log service state for debugging
|
|
308
|
+
const hasCredentials = !!conn.service.credentials;
|
|
309
|
+
const hasTickerConn = !!conn.service.tickerConn;
|
|
310
|
+
log('DEBUG', 'getContracts request', { propfirm: payload.propfirmKey, hasCredentials, hasTickerConn });
|
|
303
311
|
|
|
304
312
|
try {
|
|
305
313
|
const result = await conn.service.getContracts();
|
|
314
|
+
log('DEBUG', 'getContracts result', {
|
|
315
|
+
propfirm: payload.propfirmKey,
|
|
316
|
+
success: result.success,
|
|
317
|
+
count: result.contracts?.length || 0,
|
|
318
|
+
error: result.error
|
|
319
|
+
});
|
|
306
320
|
return { type: 'contracts', payload: result, requestId };
|
|
307
321
|
} catch (err) {
|
|
308
|
-
log('ERROR', 'getContracts
|
|
322
|
+
log('ERROR', 'getContracts exception', { propfirm: payload.propfirmKey, error: err.message, stack: err.stack?.split('\n')[1] });
|
|
309
323
|
return { type: 'contracts', payload: { success: false, error: err.message, contracts: [] }, requestId };
|
|
310
324
|
}
|
|
311
325
|
}
|