@tradejs/cli 3.1.6 → 3.1.8-beta.204
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/dist/cli.js +119 -68
- package/dist/scripts/signals.js +65 -21
- package/dist/scripts/signalsDaemon.js +65 -21
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -6611,13 +6611,13 @@ var init_aiTrainCharts = __esm({
|
|
|
6611
6611
|
if (!evaluations.length) {
|
|
6612
6612
|
return [];
|
|
6613
6613
|
}
|
|
6614
|
-
const
|
|
6614
|
+
const sorted2 = [...evaluations].sort(
|
|
6615
6615
|
(left, right) => (left.timestamp ?? 0) - (right.timestamp ?? 0) || left.symbol.localeCompare(right.symbol) || left.signalId.localeCompare(right.signalId)
|
|
6616
6616
|
);
|
|
6617
6617
|
let amount = 100;
|
|
6618
|
-
const firstTimestamp =
|
|
6618
|
+
const firstTimestamp = sorted2[0]?.timestamp ?? Date.now();
|
|
6619
6619
|
const orderLog = [[firstTimestamp, amount]];
|
|
6620
|
-
for (const evaluation of
|
|
6620
|
+
for (const evaluation of sorted2) {
|
|
6621
6621
|
amount += evaluation.profit;
|
|
6622
6622
|
orderLog.push([
|
|
6623
6623
|
evaluation.timestamp ?? firstTimestamp,
|
|
@@ -16388,12 +16388,12 @@ var init_executionCalibration = __esm({
|
|
|
16388
16388
|
if (!values.length) {
|
|
16389
16389
|
return null;
|
|
16390
16390
|
}
|
|
16391
|
-
const
|
|
16392
|
-
const index = (
|
|
16391
|
+
const sorted2 = [...values].sort((left, right) => left - right);
|
|
16392
|
+
const index = (sorted2.length - 1) * probability;
|
|
16393
16393
|
const lowerIndex = Math.floor(index);
|
|
16394
16394
|
const upperIndex = Math.ceil(index);
|
|
16395
|
-
const lower =
|
|
16396
|
-
const upper =
|
|
16395
|
+
const lower = sorted2[lowerIndex];
|
|
16396
|
+
const upper = sorted2[upperIndex];
|
|
16397
16397
|
if (lower == null || upper == null) {
|
|
16398
16398
|
return null;
|
|
16399
16399
|
}
|
|
@@ -17905,9 +17905,9 @@ var init_hyperliquidWhaleSelection = __esm({
|
|
|
17905
17905
|
};
|
|
17906
17906
|
median = (values) => {
|
|
17907
17907
|
if (!values.length) return 0;
|
|
17908
|
-
const
|
|
17909
|
-
const middle = Math.floor(
|
|
17910
|
-
return
|
|
17908
|
+
const sorted2 = [...values].sort((left, right) => left - right);
|
|
17909
|
+
const middle = Math.floor(sorted2.length / 2);
|
|
17910
|
+
return sorted2.length % 2 ? sorted2[middle] : (sorted2[middle - 1] + sorted2[middle]) / 2;
|
|
17911
17911
|
};
|
|
17912
17912
|
evaluateHyperliquidWhaleStructure = (params) => {
|
|
17913
17913
|
const fills = params.fills.filter((fill) => {
|
|
@@ -18387,14 +18387,14 @@ var init_mlInspect = __esm({
|
|
|
18387
18387
|
}
|
|
18388
18388
|
return sample;
|
|
18389
18389
|
};
|
|
18390
|
-
quantileSorted = (
|
|
18391
|
-
if (!
|
|
18392
|
-
if (
|
|
18393
|
-
const pos = (
|
|
18390
|
+
quantileSorted = (sorted2, q) => {
|
|
18391
|
+
if (!sorted2.length) return 0;
|
|
18392
|
+
if (sorted2.length === 1) return sorted2[0];
|
|
18393
|
+
const pos = (sorted2.length - 1) * q;
|
|
18394
18394
|
const base = Math.floor(pos);
|
|
18395
18395
|
const rest = pos - base;
|
|
18396
|
-
const left =
|
|
18397
|
-
const right =
|
|
18396
|
+
const left = sorted2[base];
|
|
18397
|
+
const right = sorted2[Math.min(base + 1, sorted2.length - 1)];
|
|
18398
18398
|
return left + (right - left) * rest;
|
|
18399
18399
|
};
|
|
18400
18400
|
mean2 = (values) => {
|
|
@@ -18469,12 +18469,12 @@ var init_mlInspect = __esm({
|
|
|
18469
18469
|
if (values.length < minFieldValues) {
|
|
18470
18470
|
continue;
|
|
18471
18471
|
}
|
|
18472
|
-
const
|
|
18473
|
-
const q1 = quantileSorted(
|
|
18474
|
-
const median2 = quantileSorted(
|
|
18475
|
-
const q3 = quantileSorted(
|
|
18476
|
-
const p95 = quantileSorted(
|
|
18477
|
-
const p99 = quantileSorted(
|
|
18472
|
+
const sorted2 = [...values].sort((a, b) => a - b);
|
|
18473
|
+
const q1 = quantileSorted(sorted2, 0.25);
|
|
18474
|
+
const median2 = quantileSorted(sorted2, 0.5);
|
|
18475
|
+
const q3 = quantileSorted(sorted2, 0.75);
|
|
18476
|
+
const p95 = quantileSorted(sorted2, 0.95);
|
|
18477
|
+
const p99 = quantileSorted(sorted2, 0.99);
|
|
18478
18478
|
const valuesMean = mean2(values);
|
|
18479
18479
|
const valuesStd = std(values, valuesMean);
|
|
18480
18480
|
const iqr = q3 - q1;
|
|
@@ -18490,8 +18490,8 @@ var init_mlInspect = __esm({
|
|
|
18490
18490
|
nonFiniteRate: nonFinite / Math.max(present, 1),
|
|
18491
18491
|
zeroRate: zeros / Math.max(values.length, 1),
|
|
18492
18492
|
uniqueCount,
|
|
18493
|
-
min:
|
|
18494
|
-
max:
|
|
18493
|
+
min: sorted2[0],
|
|
18494
|
+
max: sorted2[sorted2.length - 1],
|
|
18495
18495
|
mean: valuesMean,
|
|
18496
18496
|
std: valuesStd,
|
|
18497
18497
|
median: median2,
|
|
@@ -21339,14 +21339,14 @@ var init_metrics = __esm({
|
|
|
21339
21339
|
"SHORT"
|
|
21340
21340
|
];
|
|
21341
21341
|
selectCohort = (trades, cohort) => cohort === "ALL" ? trades : trades.filter((trade) => trade.direction === cohort);
|
|
21342
|
-
quantile2 = (
|
|
21343
|
-
if (!
|
|
21344
|
-
const position = (
|
|
21342
|
+
quantile2 = (sorted2, probability) => {
|
|
21343
|
+
if (!sorted2.length) return null;
|
|
21344
|
+
const position = (sorted2.length - 1) * probability;
|
|
21345
21345
|
const lower = Math.floor(position);
|
|
21346
21346
|
const upper = Math.ceil(position);
|
|
21347
|
-
if (lower === upper) return
|
|
21347
|
+
if (lower === upper) return sorted2[lower];
|
|
21348
21348
|
const weight = position - lower;
|
|
21349
|
-
return
|
|
21349
|
+
return sorted2[lower] * (1 - weight) + sorted2[upper] * weight;
|
|
21350
21350
|
};
|
|
21351
21351
|
compareChronologicalTrades = (left, right) => left.exitTimestamp - right.exitTimestamp || (left.signalId < right.signalId ? -1 : left.signalId > right.signalId ? 1 : 0);
|
|
21352
21352
|
orderCoreResearchTrades = (trades) => {
|
|
@@ -21358,7 +21358,7 @@ var init_metrics = __esm({
|
|
|
21358
21358
|
return trades;
|
|
21359
21359
|
};
|
|
21360
21360
|
summarizeCoreResearchTrades = (trades, periodDays) => {
|
|
21361
|
-
const
|
|
21361
|
+
const sorted2 = orderCoreResearchTrades(trades);
|
|
21362
21362
|
let pnl = 0;
|
|
21363
21363
|
let grossProfit = 0;
|
|
21364
21364
|
let grossLoss = 0;
|
|
@@ -21370,7 +21370,7 @@ var init_metrics = __esm({
|
|
|
21370
21370
|
let realizedMaxDrawdown = 0;
|
|
21371
21371
|
let consecutiveLosses = 0;
|
|
21372
21372
|
let maximumConsecutiveLosses = 0;
|
|
21373
|
-
for (const trade of
|
|
21373
|
+
for (const trade of sorted2) {
|
|
21374
21374
|
pnl += trade.netProfit;
|
|
21375
21375
|
if (trade.netProfit > 0) {
|
|
21376
21376
|
wins += 1;
|
|
@@ -21392,9 +21392,9 @@ var init_metrics = __esm({
|
|
|
21392
21392
|
peak = Math.max(peak, equity);
|
|
21393
21393
|
realizedMaxDrawdown = Math.max(realizedMaxDrawdown, peak - equity);
|
|
21394
21394
|
}
|
|
21395
|
-
const count =
|
|
21396
|
-
const pnlDistribution =
|
|
21397
|
-
const holdingHours =
|
|
21395
|
+
const count = sorted2.length;
|
|
21396
|
+
const pnlDistribution = sorted2.map((trade) => trade.netProfit).sort((left, right) => left - right);
|
|
21397
|
+
const holdingHours = sorted2.map((trade) => (trade.exitTimestamp - trade.entryTimestamp) / 36e5).sort((left, right) => left - right);
|
|
21398
21398
|
const averageWin = wins > 0 ? grossProfit / wins : null;
|
|
21399
21399
|
const strictLosses = losses - breakeven;
|
|
21400
21400
|
const averageLoss = strictLosses > 0 ? grossLoss / strictLosses : null;
|
|
@@ -21567,13 +21567,13 @@ var init_statistics = __esm({
|
|
|
21567
21567
|
return (state >>> 0) / 4294967296;
|
|
21568
21568
|
};
|
|
21569
21569
|
};
|
|
21570
|
-
percentile = (
|
|
21571
|
-
if (!
|
|
21570
|
+
percentile = (sorted2, probability) => {
|
|
21571
|
+
if (!sorted2.length) return Number.NaN;
|
|
21572
21572
|
const index = Math.min(
|
|
21573
|
-
|
|
21574
|
-
Math.max(0, Math.floor(probability *
|
|
21573
|
+
sorted2.length - 1,
|
|
21574
|
+
Math.max(0, Math.floor(probability * sorted2.length))
|
|
21575
21575
|
);
|
|
21576
|
-
return
|
|
21576
|
+
return sorted2[index];
|
|
21577
21577
|
};
|
|
21578
21578
|
calendarClusterBootstrap = (params) => {
|
|
21579
21579
|
const clusterMs = params.clusterDays * DAY_MS11;
|
|
@@ -21787,8 +21787,8 @@ var init_statistics = __esm({
|
|
|
21787
21787
|
const outScores = performanceByVariant.map(
|
|
21788
21788
|
(performance) => outSample.reduce((sum3, index) => sum3 + performance[index], 0)
|
|
21789
21789
|
);
|
|
21790
|
-
const
|
|
21791
|
-
const rankAscending =
|
|
21790
|
+
const sorted2 = [...outScores].sort((left, right) => left - right);
|
|
21791
|
+
const rankAscending = sorted2.indexOf(outScores[selected]);
|
|
21792
21792
|
const omega = (rankAscending + 1) / (outScores.length + 1);
|
|
21793
21793
|
if (Math.log(omega / (1 - omega)) < 0) belowMedian += 1;
|
|
21794
21794
|
}
|
|
@@ -26584,12 +26584,12 @@ var init_monitoringProfile = __esm({
|
|
|
26584
26584
|
return left;
|
|
26585
26585
|
};
|
|
26586
26586
|
percentile2 = (values, probability) => {
|
|
26587
|
-
const
|
|
26588
|
-
const position = (
|
|
26587
|
+
const sorted2 = [...values].sort((left, right) => left - right);
|
|
26588
|
+
const position = (sorted2.length - 1) * probability;
|
|
26589
26589
|
const lower = Math.floor(position);
|
|
26590
26590
|
const upper = Math.ceil(position);
|
|
26591
|
-
if (lower === upper) return
|
|
26592
|
-
return
|
|
26591
|
+
if (lower === upper) return sorted2[lower];
|
|
26592
|
+
return sorted2[lower] * (upper - position) + sorted2[upper] * (position - lower);
|
|
26593
26593
|
};
|
|
26594
26594
|
buildStrategyMonitoringProfile = ({
|
|
26595
26595
|
trades,
|
|
@@ -32262,6 +32262,57 @@ var init_tickerEvaluator = __esm({
|
|
|
32262
32262
|
}
|
|
32263
32263
|
});
|
|
32264
32264
|
|
|
32265
|
+
// src/lib/signals/configuredScopes.ts
|
|
32266
|
+
var sorted, formatConfiguredStrategyIdentity, buildConfiguredSignalsScopes;
|
|
32267
|
+
var init_configuredScopes = __esm({
|
|
32268
|
+
"src/lib/signals/configuredScopes.ts"() {
|
|
32269
|
+
"use strict";
|
|
32270
|
+
sorted = (values) => values ? [...values].sort() : [];
|
|
32271
|
+
formatConfiguredStrategyIdentity = (strategy) => `${strategy.strategyName}@v${strategy.releaseVersion}[${strategy.controlState}]`;
|
|
32272
|
+
buildConfiguredSignalsScopes = ({
|
|
32273
|
+
connectorName,
|
|
32274
|
+
deployment,
|
|
32275
|
+
strategies
|
|
32276
|
+
}) => {
|
|
32277
|
+
const deploymentIdentity = JSON.stringify({
|
|
32278
|
+
id: deployment.id,
|
|
32279
|
+
enabled: deployment.enabled,
|
|
32280
|
+
connectorName: deployment.connectorName,
|
|
32281
|
+
provider: deployment.provider,
|
|
32282
|
+
accountId: deployment.accountId,
|
|
32283
|
+
tickers: sorted(deployment.tickers),
|
|
32284
|
+
assetClasses: sorted(deployment.assetClasses)
|
|
32285
|
+
});
|
|
32286
|
+
const groups = /* @__PURE__ */ new Map();
|
|
32287
|
+
for (const strategy of strategies) {
|
|
32288
|
+
const baseKey = [
|
|
32289
|
+
connectorName,
|
|
32290
|
+
strategy.universe,
|
|
32291
|
+
strategy.accountId ?? "default",
|
|
32292
|
+
strategy.interval
|
|
32293
|
+
].join(":");
|
|
32294
|
+
const group = groups.get(baseKey) ?? {
|
|
32295
|
+
scope: {
|
|
32296
|
+
connectorName,
|
|
32297
|
+
universe: strategy.universe,
|
|
32298
|
+
accountId: strategy.accountId,
|
|
32299
|
+
interval: strategy.interval
|
|
32300
|
+
},
|
|
32301
|
+
strategyIdentities: []
|
|
32302
|
+
};
|
|
32303
|
+
group.strategyIdentities.push(formatConfiguredStrategyIdentity(strategy));
|
|
32304
|
+
groups.set(baseKey, group);
|
|
32305
|
+
}
|
|
32306
|
+
return [...groups.entries()].map(([baseKey, group]) => ({
|
|
32307
|
+
key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
|
|
32308
|
+
":"
|
|
32309
|
+
),
|
|
32310
|
+
scope: group.scope
|
|
32311
|
+
}));
|
|
32312
|
+
};
|
|
32313
|
+
}
|
|
32314
|
+
});
|
|
32315
|
+
|
|
32265
32316
|
// src/lib/signals/runner.ts
|
|
32266
32317
|
var import_progress11, import_chalk45, import_connectors16, import_cli12, import_async5, import_strategies13, import_constants16, import_time8, import_logger10, import_runtimeDeployments3, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
|
|
32267
32318
|
var init_runner = __esm({
|
|
@@ -32290,6 +32341,7 @@ var init_runner = __esm({
|
|
|
32290
32341
|
init_daemon();
|
|
32291
32342
|
init_klineFeed();
|
|
32292
32343
|
init_tickerEvaluator();
|
|
32344
|
+
init_configuredScopes();
|
|
32293
32345
|
SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
|
|
32294
32346
|
formatDuration3 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
|
|
32295
32347
|
resolvePositiveInteger2 = (value, fallback) => {
|
|
@@ -32611,7 +32663,7 @@ var init_runner = __esm({
|
|
|
32611
32663
|
);
|
|
32612
32664
|
import_logger10.logger.info(
|
|
32613
32665
|
import_chalk45.default.yellow(
|
|
32614
|
-
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(
|
|
32666
|
+
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
|
|
32615
32667
|
)
|
|
32616
32668
|
);
|
|
32617
32669
|
afterSignalsHookContext = {
|
|
@@ -32797,22 +32849,13 @@ var init_runner = __esm({
|
|
|
32797
32849
|
const connectorName = await resolveSignalsConnectorName(
|
|
32798
32850
|
deployment.connectorName
|
|
32799
32851
|
);
|
|
32800
|
-
|
|
32801
|
-
|
|
32802
|
-
const key = [
|
|
32803
|
-
connectorName,
|
|
32804
|
-
strategy.universe,
|
|
32805
|
-
strategy.accountId ?? "default",
|
|
32806
|
-
strategy.interval
|
|
32807
|
-
].join(":");
|
|
32808
|
-
scopes.set(key, {
|
|
32852
|
+
return new Map(
|
|
32853
|
+
buildConfiguredSignalsScopes({
|
|
32809
32854
|
connectorName,
|
|
32810
|
-
|
|
32811
|
-
|
|
32812
|
-
|
|
32813
|
-
|
|
32814
|
-
}
|
|
32815
|
-
return scopes;
|
|
32855
|
+
deployment,
|
|
32856
|
+
strategies: configuredStrategies
|
|
32857
|
+
}).map(({ key, scope }) => [key, scope])
|
|
32858
|
+
);
|
|
32816
32859
|
};
|
|
32817
32860
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
32818
32861
|
if (config2.updateOnly || config2.showTickersList) {
|
|
@@ -32853,12 +32896,13 @@ var init_runner = __esm({
|
|
|
32853
32896
|
if (!config2.deploymentId) {
|
|
32854
32897
|
throw new Error("Runtime deployment id is required");
|
|
32855
32898
|
}
|
|
32856
|
-
const
|
|
32899
|
+
const deploymentId = config2.deploymentId;
|
|
32900
|
+
const initialDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
|
|
32857
32901
|
config2.userName,
|
|
32858
|
-
|
|
32902
|
+
deploymentId
|
|
32859
32903
|
);
|
|
32860
|
-
if (!
|
|
32861
|
-
throw new Error(`Runtime deployment not found: ${
|
|
32904
|
+
if (!initialDeployment) {
|
|
32905
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
32862
32906
|
}
|
|
32863
32907
|
const sessions = /* @__PURE__ */ new Map();
|
|
32864
32908
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
@@ -32877,7 +32921,14 @@ var init_runner = __esm({
|
|
|
32877
32921
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
32878
32922
|
signal: abortController.signal,
|
|
32879
32923
|
runCycle: async () => {
|
|
32880
|
-
const
|
|
32924
|
+
const currentDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
|
|
32925
|
+
config2.userName,
|
|
32926
|
+
deploymentId
|
|
32927
|
+
);
|
|
32928
|
+
if (!currentDeployment) {
|
|
32929
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
32930
|
+
}
|
|
32931
|
+
const scopes = await loadConfiguredSignalsScopes(currentDeployment);
|
|
32881
32932
|
for (const [key, staleSession] of sessions) {
|
|
32882
32933
|
if (scopes.has(key)) continue;
|
|
32883
32934
|
await staleSession.klineFeed?.close();
|
|
@@ -36599,8 +36650,8 @@ var init_outputReport = __esm({
|
|
|
36599
36650
|
grouped.set(record.strategy, existing);
|
|
36600
36651
|
}
|
|
36601
36652
|
const formatSet = (values) => {
|
|
36602
|
-
const
|
|
36603
|
-
return
|
|
36653
|
+
const sorted2 = [...values].sort();
|
|
36654
|
+
return sorted2.length <= 3 ? sorted2.join(", ") : `${sorted2.slice(0, 3).join(", ")} \u2026 (+${sorted2.length - 3})`;
|
|
36604
36655
|
};
|
|
36605
36656
|
return grouped.size ? createMarkdownTable2(
|
|
36606
36657
|
[
|
package/dist/scripts/signals.js
CHANGED
|
@@ -4994,6 +4994,51 @@ var createSignalsTickerEvaluator = ({
|
|
|
4994
4994
|
return strategySignals;
|
|
4995
4995
|
};
|
|
4996
4996
|
|
|
4997
|
+
// src/lib/signals/configuredScopes.ts
|
|
4998
|
+
var sorted = (values) => values ? [...values].sort() : [];
|
|
4999
|
+
var formatConfiguredStrategyIdentity = (strategy) => `${strategy.strategyName}@v${strategy.releaseVersion}[${strategy.controlState}]`;
|
|
5000
|
+
var buildConfiguredSignalsScopes = ({
|
|
5001
|
+
connectorName,
|
|
5002
|
+
deployment,
|
|
5003
|
+
strategies
|
|
5004
|
+
}) => {
|
|
5005
|
+
const deploymentIdentity = JSON.stringify({
|
|
5006
|
+
id: deployment.id,
|
|
5007
|
+
enabled: deployment.enabled,
|
|
5008
|
+
connectorName: deployment.connectorName,
|
|
5009
|
+
provider: deployment.provider,
|
|
5010
|
+
accountId: deployment.accountId,
|
|
5011
|
+
tickers: sorted(deployment.tickers),
|
|
5012
|
+
assetClasses: sorted(deployment.assetClasses)
|
|
5013
|
+
});
|
|
5014
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5015
|
+
for (const strategy of strategies) {
|
|
5016
|
+
const baseKey = [
|
|
5017
|
+
connectorName,
|
|
5018
|
+
strategy.universe,
|
|
5019
|
+
strategy.accountId ?? "default",
|
|
5020
|
+
strategy.interval
|
|
5021
|
+
].join(":");
|
|
5022
|
+
const group = groups.get(baseKey) ?? {
|
|
5023
|
+
scope: {
|
|
5024
|
+
connectorName,
|
|
5025
|
+
universe: strategy.universe,
|
|
5026
|
+
accountId: strategy.accountId,
|
|
5027
|
+
interval: strategy.interval
|
|
5028
|
+
},
|
|
5029
|
+
strategyIdentities: []
|
|
5030
|
+
};
|
|
5031
|
+
group.strategyIdentities.push(formatConfiguredStrategyIdentity(strategy));
|
|
5032
|
+
groups.set(baseKey, group);
|
|
5033
|
+
}
|
|
5034
|
+
return [...groups.entries()].map(([baseKey, group]) => ({
|
|
5035
|
+
key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
|
|
5036
|
+
":"
|
|
5037
|
+
),
|
|
5038
|
+
scope: group.scope
|
|
5039
|
+
}));
|
|
5040
|
+
};
|
|
5041
|
+
|
|
4997
5042
|
// src/lib/signals/runner.ts
|
|
4998
5043
|
var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
|
|
4999
5044
|
var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
|
|
@@ -5316,7 +5361,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5316
5361
|
);
|
|
5317
5362
|
import_logger4.logger.info(
|
|
5318
5363
|
import_chalk7.default.yellow(
|
|
5319
|
-
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(
|
|
5364
|
+
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
|
|
5320
5365
|
)
|
|
5321
5366
|
);
|
|
5322
5367
|
afterSignalsHookContext = {
|
|
@@ -5502,22 +5547,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5502
5547
|
const connectorName = await resolveSignalsConnectorName(
|
|
5503
5548
|
deployment.connectorName
|
|
5504
5549
|
);
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
const key = [
|
|
5508
|
-
connectorName,
|
|
5509
|
-
strategy.universe,
|
|
5510
|
-
strategy.accountId ?? "default",
|
|
5511
|
-
strategy.interval
|
|
5512
|
-
].join(":");
|
|
5513
|
-
scopes.set(key, {
|
|
5550
|
+
return new Map(
|
|
5551
|
+
buildConfiguredSignalsScopes({
|
|
5514
5552
|
connectorName,
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
}
|
|
5520
|
-
return scopes;
|
|
5553
|
+
deployment,
|
|
5554
|
+
strategies: configuredStrategies
|
|
5555
|
+
}).map(({ key, scope }) => [key, scope])
|
|
5556
|
+
);
|
|
5521
5557
|
};
|
|
5522
5558
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
5523
5559
|
if (config2.updateOnly || config2.showTickersList) {
|
|
@@ -5558,12 +5594,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5558
5594
|
if (!config2.deploymentId) {
|
|
5559
5595
|
throw new Error("Runtime deployment id is required");
|
|
5560
5596
|
}
|
|
5561
|
-
const
|
|
5597
|
+
const deploymentId = config2.deploymentId;
|
|
5598
|
+
const initialDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5562
5599
|
config2.userName,
|
|
5563
|
-
|
|
5600
|
+
deploymentId
|
|
5564
5601
|
);
|
|
5565
|
-
if (!
|
|
5566
|
-
throw new Error(`Runtime deployment not found: ${
|
|
5602
|
+
if (!initialDeployment) {
|
|
5603
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5567
5604
|
}
|
|
5568
5605
|
const sessions = /* @__PURE__ */ new Map();
|
|
5569
5606
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
@@ -5582,7 +5619,14 @@ var createSignalsRunner = (config2) => {
|
|
|
5582
5619
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
5583
5620
|
signal: abortController.signal,
|
|
5584
5621
|
runCycle: async () => {
|
|
5585
|
-
const
|
|
5622
|
+
const currentDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5623
|
+
config2.userName,
|
|
5624
|
+
deploymentId
|
|
5625
|
+
);
|
|
5626
|
+
if (!currentDeployment) {
|
|
5627
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5628
|
+
}
|
|
5629
|
+
const scopes = await loadConfiguredSignalsScopes(currentDeployment);
|
|
5586
5630
|
for (const [key, staleSession] of sessions) {
|
|
5587
5631
|
if (scopes.has(key)) continue;
|
|
5588
5632
|
await staleSession.klineFeed?.close();
|
|
@@ -4992,6 +4992,51 @@ var createSignalsTickerEvaluator = ({
|
|
|
4992
4992
|
return strategySignals;
|
|
4993
4993
|
};
|
|
4994
4994
|
|
|
4995
|
+
// src/lib/signals/configuredScopes.ts
|
|
4996
|
+
var sorted = (values) => values ? [...values].sort() : [];
|
|
4997
|
+
var formatConfiguredStrategyIdentity = (strategy) => `${strategy.strategyName}@v${strategy.releaseVersion}[${strategy.controlState}]`;
|
|
4998
|
+
var buildConfiguredSignalsScopes = ({
|
|
4999
|
+
connectorName,
|
|
5000
|
+
deployment,
|
|
5001
|
+
strategies
|
|
5002
|
+
}) => {
|
|
5003
|
+
const deploymentIdentity = JSON.stringify({
|
|
5004
|
+
id: deployment.id,
|
|
5005
|
+
enabled: deployment.enabled,
|
|
5006
|
+
connectorName: deployment.connectorName,
|
|
5007
|
+
provider: deployment.provider,
|
|
5008
|
+
accountId: deployment.accountId,
|
|
5009
|
+
tickers: sorted(deployment.tickers),
|
|
5010
|
+
assetClasses: sorted(deployment.assetClasses)
|
|
5011
|
+
});
|
|
5012
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5013
|
+
for (const strategy of strategies) {
|
|
5014
|
+
const baseKey = [
|
|
5015
|
+
connectorName,
|
|
5016
|
+
strategy.universe,
|
|
5017
|
+
strategy.accountId ?? "default",
|
|
5018
|
+
strategy.interval
|
|
5019
|
+
].join(":");
|
|
5020
|
+
const group = groups.get(baseKey) ?? {
|
|
5021
|
+
scope: {
|
|
5022
|
+
connectorName,
|
|
5023
|
+
universe: strategy.universe,
|
|
5024
|
+
accountId: strategy.accountId,
|
|
5025
|
+
interval: strategy.interval
|
|
5026
|
+
},
|
|
5027
|
+
strategyIdentities: []
|
|
5028
|
+
};
|
|
5029
|
+
group.strategyIdentities.push(formatConfiguredStrategyIdentity(strategy));
|
|
5030
|
+
groups.set(baseKey, group);
|
|
5031
|
+
}
|
|
5032
|
+
return [...groups.entries()].map(([baseKey, group]) => ({
|
|
5033
|
+
key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
|
|
5034
|
+
":"
|
|
5035
|
+
),
|
|
5036
|
+
scope: group.scope
|
|
5037
|
+
}));
|
|
5038
|
+
};
|
|
5039
|
+
|
|
4995
5040
|
// src/lib/signals/runner.ts
|
|
4996
5041
|
var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
|
|
4997
5042
|
var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
|
|
@@ -5314,7 +5359,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5314
5359
|
);
|
|
5315
5360
|
import_logger4.logger.info(
|
|
5316
5361
|
import_chalk7.default.yellow(
|
|
5317
|
-
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(
|
|
5362
|
+
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
|
|
5318
5363
|
)
|
|
5319
5364
|
);
|
|
5320
5365
|
afterSignalsHookContext = {
|
|
@@ -5500,22 +5545,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5500
5545
|
const connectorName = await resolveSignalsConnectorName(
|
|
5501
5546
|
deployment.connectorName
|
|
5502
5547
|
);
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
const key = [
|
|
5506
|
-
connectorName,
|
|
5507
|
-
strategy.universe,
|
|
5508
|
-
strategy.accountId ?? "default",
|
|
5509
|
-
strategy.interval
|
|
5510
|
-
].join(":");
|
|
5511
|
-
scopes.set(key, {
|
|
5548
|
+
return new Map(
|
|
5549
|
+
buildConfiguredSignalsScopes({
|
|
5512
5550
|
connectorName,
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
}
|
|
5518
|
-
return scopes;
|
|
5551
|
+
deployment,
|
|
5552
|
+
strategies: configuredStrategies
|
|
5553
|
+
}).map(({ key, scope }) => [key, scope])
|
|
5554
|
+
);
|
|
5519
5555
|
};
|
|
5520
5556
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
5521
5557
|
if (config2.updateOnly || config2.showTickersList) {
|
|
@@ -5556,12 +5592,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5556
5592
|
if (!config2.deploymentId) {
|
|
5557
5593
|
throw new Error("Runtime deployment id is required");
|
|
5558
5594
|
}
|
|
5559
|
-
const
|
|
5595
|
+
const deploymentId = config2.deploymentId;
|
|
5596
|
+
const initialDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5560
5597
|
config2.userName,
|
|
5561
|
-
|
|
5598
|
+
deploymentId
|
|
5562
5599
|
);
|
|
5563
|
-
if (!
|
|
5564
|
-
throw new Error(`Runtime deployment not found: ${
|
|
5600
|
+
if (!initialDeployment) {
|
|
5601
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5565
5602
|
}
|
|
5566
5603
|
const sessions = /* @__PURE__ */ new Map();
|
|
5567
5604
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
@@ -5580,7 +5617,14 @@ var createSignalsRunner = (config2) => {
|
|
|
5580
5617
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
5581
5618
|
signal: abortController.signal,
|
|
5582
5619
|
runCycle: async () => {
|
|
5583
|
-
const
|
|
5620
|
+
const currentDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5621
|
+
config2.userName,
|
|
5622
|
+
deploymentId
|
|
5623
|
+
);
|
|
5624
|
+
if (!currentDeployment) {
|
|
5625
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5626
|
+
}
|
|
5627
|
+
const scopes = await loadConfiguredSignalsScopes(currentDeployment);
|
|
5584
5628
|
for (const [key, staleSession] of sessions) {
|
|
5585
5629
|
if (scopes.has(key)) continue;
|
|
5586
5630
|
await staleSession.klineFeed?.close();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.8-beta.204",
|
|
4
4
|
"description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"tradejs": "dist/cli.js"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@tradejs/connectors": "^3.1.
|
|
36
|
-
"@tradejs/core": "^3.1.
|
|
37
|
-
"@tradejs/indicators": "^3.1.
|
|
38
|
-
"@tradejs/infra": "^3.1.
|
|
39
|
-
"@tradejs/node": "^3.1.
|
|
35
|
+
"@tradejs/connectors": "^3.1.8-beta.204",
|
|
36
|
+
"@tradejs/core": "^3.1.8-beta.204",
|
|
37
|
+
"@tradejs/indicators": "^3.1.8-beta.204",
|
|
38
|
+
"@tradejs/infra": "^3.1.8-beta.204",
|
|
39
|
+
"@tradejs/node": "^3.1.8-beta.204",
|
|
40
40
|
"@tradejs/strategy-kit": "^3.0.0",
|
|
41
|
-
"@tradejs/types": "^3.1.
|
|
41
|
+
"@tradejs/types": "^3.1.8-beta.204",
|
|
42
42
|
"args": "^5.0.3",
|
|
43
43
|
"bcryptjs": "^2.4.3",
|
|
44
44
|
"chalk": "4.1.2",
|