hedgequantx 2.9.34 → 2.9.36
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
|
@@ -39,7 +39,10 @@ const copyTradingMenu = async () => {
|
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// Filter active accounts: status === 0 (ProjectX) OR status === 'active' (Rithmic) OR no status
|
|
43
|
+
const activeAccounts = allAccounts.filter(acc =>
|
|
44
|
+
acc.status === 0 || acc.status === 'active' || acc.status === undefined || acc.status === null
|
|
45
|
+
);
|
|
43
46
|
|
|
44
47
|
if (activeAccounts.length < 2) {
|
|
45
48
|
spinner.fail(`Need at least 2 active accounts (found: ${activeAccounts.length})`);
|
|
@@ -46,7 +46,10 @@ const customStrategyMenu = async (service) => {
|
|
|
46
46
|
|
|
47
47
|
if (!allAccounts?.length) { spinner.fail('No accounts found'); await prompts.waitForEnter(); return; }
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
// Filter active accounts: status === 0 (ProjectX) OR status === 'active' (Rithmic) OR no status
|
|
50
|
+
const activeAccounts = allAccounts.filter(acc =>
|
|
51
|
+
acc.status === 0 || acc.status === 'active' || acc.status === undefined || acc.status === null
|
|
52
|
+
);
|
|
50
53
|
if (!activeAccounts.length) { spinner.fail('No active accounts'); await prompts.waitForEnter(); return; }
|
|
51
54
|
|
|
52
55
|
spinner.succeed(`Found ${activeAccounts.length} active account(s)`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One Account Mode -
|
|
2
|
+
* One Account Mode - Trading with Strategy Selection
|
|
3
3
|
* Supports multi-agent AI supervision
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -12,6 +12,7 @@ const { checkMarketHours } = require('../../services/rithmic/market');
|
|
|
12
12
|
const { executeAlgo } = require('./algo-executor');
|
|
13
13
|
const { getActiveAgentCount, getSupervisionConfig, getActiveAgents } = require('../ai-agents');
|
|
14
14
|
const { runPreflightCheck, formatPreflightResults, getPreflightSummary } = require('../../services/ai-supervision');
|
|
15
|
+
const { getAvailableStrategies } = require('../../lib/m');
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
|
|
@@ -40,7 +41,10 @@ const oneAccountMenu = async (service) => {
|
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
// Filter active accounts: status === 0 (ProjectX) OR status === 'active' (Rithmic) OR no status
|
|
45
|
+
const activeAccounts = allAccounts.filter(acc =>
|
|
46
|
+
acc.status === 0 || acc.status === 'active' || acc.status === undefined || acc.status === null
|
|
47
|
+
);
|
|
44
48
|
|
|
45
49
|
if (!activeAccounts.length) {
|
|
46
50
|
spinner.fail('No active accounts');
|
|
@@ -74,8 +78,12 @@ const oneAccountMenu = async (service) => {
|
|
|
74
78
|
const contract = await selectSymbol(accountService, selectedAccount);
|
|
75
79
|
if (!contract) return;
|
|
76
80
|
|
|
81
|
+
// Select strategy
|
|
82
|
+
const strategy = await selectStrategy();
|
|
83
|
+
if (!strategy) return;
|
|
84
|
+
|
|
77
85
|
// Configure algo
|
|
78
|
-
const config = await configureAlgo(selectedAccount, contract);
|
|
86
|
+
const config = await configureAlgo(selectedAccount, contract, strategy);
|
|
79
87
|
if (!config) return;
|
|
80
88
|
|
|
81
89
|
// Check for AI Supervision
|
|
@@ -126,6 +134,7 @@ const oneAccountMenu = async (service) => {
|
|
|
126
134
|
account: selectedAccount,
|
|
127
135
|
contract,
|
|
128
136
|
config,
|
|
137
|
+
strategy,
|
|
129
138
|
options: { supervisionConfig }
|
|
130
139
|
});
|
|
131
140
|
};
|
|
@@ -179,12 +188,42 @@ const selectSymbol = async (service, account) => {
|
|
|
179
188
|
return contract === 'back' || contract === null ? null : contract;
|
|
180
189
|
};
|
|
181
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Select trading strategy
|
|
193
|
+
*/
|
|
194
|
+
const selectStrategy = async () => {
|
|
195
|
+
console.log();
|
|
196
|
+
console.log(chalk.cyan(' Select Strategy'));
|
|
197
|
+
console.log();
|
|
198
|
+
|
|
199
|
+
const strategies = getAvailableStrategies();
|
|
200
|
+
|
|
201
|
+
const options = strategies.map(s => ({
|
|
202
|
+
label: `${s.name} (${s.backtest.winRate} WR, R:R ${s.params.riskReward})`,
|
|
203
|
+
value: s
|
|
204
|
+
}));
|
|
205
|
+
options.push({ label: chalk.gray('< Back'), value: 'back' });
|
|
206
|
+
|
|
207
|
+
// Show strategy details
|
|
208
|
+
for (const s of strategies) {
|
|
209
|
+
console.log(chalk.white(` ${s.name}`));
|
|
210
|
+
console.log(chalk.gray(` ${s.description}`));
|
|
211
|
+
console.log(chalk.gray(` Backtest: ${s.backtest.pnl} | ${s.backtest.winRate} WR | ${s.backtest.trades} trades`));
|
|
212
|
+
console.log(chalk.gray(` Stop: ${s.params.stopTicks} ticks | Target: ${s.params.targetTicks} ticks | R:R ${s.params.riskReward}`));
|
|
213
|
+
console.log();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const selected = await prompts.selectOption(chalk.yellow('Select Strategy:'), options);
|
|
217
|
+
return selected === 'back' || selected === null ? null : selected;
|
|
218
|
+
};
|
|
219
|
+
|
|
182
220
|
/**
|
|
183
221
|
* Configure algo
|
|
184
222
|
*/
|
|
185
|
-
const configureAlgo = async (account, contract) => {
|
|
223
|
+
const configureAlgo = async (account, contract, strategy) => {
|
|
186
224
|
console.log();
|
|
187
225
|
console.log(chalk.cyan(' Configure Algo Parameters'));
|
|
226
|
+
console.log(chalk.gray(` Strategy: ${strategy.name}`));
|
|
188
227
|
console.log();
|
|
189
228
|
|
|
190
229
|
const contracts = await prompts.numberInput('Number of contracts:', 1, 1, 10);
|
|
@@ -176,10 +176,13 @@ const fetchAllFrontMonths = (service) => {
|
|
|
176
176
|
|
|
177
177
|
/**
|
|
178
178
|
* Decode ProductCodes response
|
|
179
|
-
* @param {Buffer} buffer - Protobuf buffer
|
|
179
|
+
* @param {Buffer} buffer - Protobuf buffer (with 4-byte length prefix)
|
|
180
180
|
* @returns {Object} Decoded product data
|
|
181
181
|
*/
|
|
182
182
|
const decodeProductCodes = (buffer) => {
|
|
183
|
+
// Skip 4-byte length prefix
|
|
184
|
+
const data = buffer.length > 4 ? buffer.slice(4) : buffer;
|
|
185
|
+
|
|
183
186
|
const result = {};
|
|
184
187
|
let offset = 0;
|
|
185
188
|
|
|
@@ -200,18 +203,18 @@ const decodeProductCodes = (buffer) => {
|
|
|
200
203
|
return [buf.slice(newOff, newOff + len).toString('utf8'), newOff + len];
|
|
201
204
|
};
|
|
202
205
|
|
|
203
|
-
while (offset <
|
|
206
|
+
while (offset < data.length) {
|
|
204
207
|
try {
|
|
205
|
-
const [tag, tagOff] = readVarint(
|
|
208
|
+
const [tag, tagOff] = readVarint(data, offset);
|
|
206
209
|
const wireType = tag & 0x7;
|
|
207
210
|
const fieldNumber = tag >>> 3;
|
|
208
211
|
offset = tagOff;
|
|
209
212
|
|
|
210
213
|
if (wireType === 0) {
|
|
211
|
-
const [, newOff] = readVarint(
|
|
214
|
+
const [, newOff] = readVarint(data, offset);
|
|
212
215
|
offset = newOff;
|
|
213
216
|
} else if (wireType === 2) {
|
|
214
|
-
const [val, newOff] = readString(
|
|
217
|
+
const [val, newOff] = readString(data, offset);
|
|
215
218
|
offset = newOff;
|
|
216
219
|
if (fieldNumber === 110101) result.exchange = val;
|
|
217
220
|
if (fieldNumber === 100749) result.productCode = val;
|
|
@@ -459,44 +459,48 @@ function decodeProductCodes(buffer) {
|
|
|
459
459
|
|
|
460
460
|
/**
|
|
461
461
|
* Decode ResponseFrontMonthContract (template 114) - current tradeable contract
|
|
462
|
+
* Skips 4-byte length prefix if present
|
|
462
463
|
*/
|
|
463
464
|
function decodeFrontMonthContract(buffer) {
|
|
465
|
+
// Skip 4-byte length prefix
|
|
466
|
+
const data = buffer.length > 4 ? buffer.slice(4) : buffer;
|
|
467
|
+
|
|
464
468
|
const result = { rpCode: [] };
|
|
465
469
|
let offset = 0;
|
|
466
470
|
|
|
467
|
-
while (offset <
|
|
471
|
+
while (offset < data.length) {
|
|
468
472
|
try {
|
|
469
|
-
const [tag, tagOffset] = readVarint(
|
|
473
|
+
const [tag, tagOffset] = readVarint(data, offset);
|
|
470
474
|
const wireType = tag & 0x7;
|
|
471
475
|
const fieldNumber = tag >>> 3;
|
|
472
476
|
offset = tagOffset;
|
|
473
477
|
|
|
474
478
|
switch (fieldNumber) {
|
|
475
479
|
case SYMBOL_FIELDS.TEMPLATE_ID:
|
|
476
|
-
[result.templateId, offset] = readVarint(
|
|
480
|
+
[result.templateId, offset] = readVarint(data, offset);
|
|
477
481
|
break;
|
|
478
482
|
case SYMBOL_FIELDS.RP_CODE:
|
|
479
483
|
let rpCode;
|
|
480
|
-
[rpCode, offset] = readLengthDelimited(
|
|
484
|
+
[rpCode, offset] = readLengthDelimited(data, offset);
|
|
481
485
|
result.rpCode.push(rpCode);
|
|
482
486
|
break;
|
|
483
487
|
case SYMBOL_FIELDS.SYMBOL:
|
|
484
|
-
[result.symbol, offset] = readLengthDelimited(
|
|
488
|
+
[result.symbol, offset] = readLengthDelimited(data, offset);
|
|
485
489
|
break;
|
|
486
490
|
case SYMBOL_FIELDS.EXCHANGE:
|
|
487
|
-
[result.exchange, offset] = readLengthDelimited(
|
|
491
|
+
[result.exchange, offset] = readLengthDelimited(data, offset);
|
|
488
492
|
break;
|
|
489
493
|
case SYMBOL_FIELDS.TRADING_SYMBOL:
|
|
490
|
-
[result.tradingSymbol, offset] = readLengthDelimited(
|
|
494
|
+
[result.tradingSymbol, offset] = readLengthDelimited(data, offset);
|
|
491
495
|
break;
|
|
492
496
|
case SYMBOL_FIELDS.DESCRIPTION:
|
|
493
|
-
[result.description, offset] = readLengthDelimited(
|
|
497
|
+
[result.description, offset] = readLengthDelimited(data, offset);
|
|
494
498
|
break;
|
|
495
499
|
case SYMBOL_FIELDS.USER_MSG:
|
|
496
|
-
[result.userMsg, offset] = readLengthDelimited(
|
|
500
|
+
[result.userMsg, offset] = readLengthDelimited(data, offset);
|
|
497
501
|
break;
|
|
498
502
|
default:
|
|
499
|
-
offset = skipField(
|
|
503
|
+
offset = skipField(data, offset, wireType);
|
|
500
504
|
}
|
|
501
505
|
} catch (error) {
|
|
502
506
|
break;
|