@tradejs/cli 3.1.6 → 3.1.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/dist/cli.js +119 -67
- package/dist/scripts/signals.js +65 -20
- package/dist/scripts/signalsDaemon.js +65 -20
- 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,58 @@ var init_tickerEvaluator = __esm({
|
|
|
32262
32262
|
}
|
|
32263
32263
|
});
|
|
32264
32264
|
|
|
32265
|
+
// src/lib/signals/configuredScopes.ts
|
|
32266
|
+
var sorted, buildConfiguredSignalsScopes;
|
|
32267
|
+
var init_configuredScopes = __esm({
|
|
32268
|
+
"src/lib/signals/configuredScopes.ts"() {
|
|
32269
|
+
"use strict";
|
|
32270
|
+
sorted = (values) => values ? [...values].sort() : [];
|
|
32271
|
+
buildConfiguredSignalsScopes = ({
|
|
32272
|
+
connectorName,
|
|
32273
|
+
deployment,
|
|
32274
|
+
strategies
|
|
32275
|
+
}) => {
|
|
32276
|
+
const deploymentIdentity = JSON.stringify({
|
|
32277
|
+
id: deployment.id,
|
|
32278
|
+
enabled: deployment.enabled,
|
|
32279
|
+
connectorName: deployment.connectorName,
|
|
32280
|
+
provider: deployment.provider,
|
|
32281
|
+
accountId: deployment.accountId,
|
|
32282
|
+
tickers: sorted(deployment.tickers),
|
|
32283
|
+
assetClasses: sorted(deployment.assetClasses)
|
|
32284
|
+
});
|
|
32285
|
+
const groups = /* @__PURE__ */ new Map();
|
|
32286
|
+
for (const strategy of strategies) {
|
|
32287
|
+
const baseKey = [
|
|
32288
|
+
connectorName,
|
|
32289
|
+
strategy.universe,
|
|
32290
|
+
strategy.accountId ?? "default",
|
|
32291
|
+
strategy.interval
|
|
32292
|
+
].join(":");
|
|
32293
|
+
const group = groups.get(baseKey) ?? {
|
|
32294
|
+
scope: {
|
|
32295
|
+
connectorName,
|
|
32296
|
+
universe: strategy.universe,
|
|
32297
|
+
accountId: strategy.accountId,
|
|
32298
|
+
interval: strategy.interval
|
|
32299
|
+
},
|
|
32300
|
+
strategyIdentities: []
|
|
32301
|
+
};
|
|
32302
|
+
group.strategyIdentities.push(
|
|
32303
|
+
`${strategy.strategyName}@${strategy.releaseVersion}:${strategy.controlState}`
|
|
32304
|
+
);
|
|
32305
|
+
groups.set(baseKey, group);
|
|
32306
|
+
}
|
|
32307
|
+
return [...groups.entries()].map(([baseKey, group]) => ({
|
|
32308
|
+
key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
|
|
32309
|
+
":"
|
|
32310
|
+
),
|
|
32311
|
+
scope: group.scope
|
|
32312
|
+
}));
|
|
32313
|
+
};
|
|
32314
|
+
}
|
|
32315
|
+
});
|
|
32316
|
+
|
|
32265
32317
|
// src/lib/signals/runner.ts
|
|
32266
32318
|
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
32319
|
var init_runner = __esm({
|
|
@@ -32290,6 +32342,7 @@ var init_runner = __esm({
|
|
|
32290
32342
|
init_daemon();
|
|
32291
32343
|
init_klineFeed();
|
|
32292
32344
|
init_tickerEvaluator();
|
|
32345
|
+
init_configuredScopes();
|
|
32293
32346
|
SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
|
|
32294
32347
|
formatDuration3 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
|
|
32295
32348
|
resolvePositiveInteger2 = (value, fallback) => {
|
|
@@ -32797,22 +32850,13 @@ var init_runner = __esm({
|
|
|
32797
32850
|
const connectorName = await resolveSignalsConnectorName(
|
|
32798
32851
|
deployment.connectorName
|
|
32799
32852
|
);
|
|
32800
|
-
|
|
32801
|
-
|
|
32802
|
-
const key = [
|
|
32853
|
+
return new Map(
|
|
32854
|
+
buildConfiguredSignalsScopes({
|
|
32803
32855
|
connectorName,
|
|
32804
|
-
|
|
32805
|
-
|
|
32806
|
-
|
|
32807
|
-
|
|
32808
|
-
scopes.set(key, {
|
|
32809
|
-
connectorName,
|
|
32810
|
-
universe: strategy.universe,
|
|
32811
|
-
accountId: strategy.accountId,
|
|
32812
|
-
interval: strategy.interval
|
|
32813
|
-
});
|
|
32814
|
-
}
|
|
32815
|
-
return scopes;
|
|
32856
|
+
deployment,
|
|
32857
|
+
strategies: configuredStrategies
|
|
32858
|
+
}).map(({ key, scope }) => [key, scope])
|
|
32859
|
+
);
|
|
32816
32860
|
};
|
|
32817
32861
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
32818
32862
|
if (config2.updateOnly || config2.showTickersList) {
|
|
@@ -32853,12 +32897,13 @@ var init_runner = __esm({
|
|
|
32853
32897
|
if (!config2.deploymentId) {
|
|
32854
32898
|
throw new Error("Runtime deployment id is required");
|
|
32855
32899
|
}
|
|
32856
|
-
const
|
|
32900
|
+
const deploymentId = config2.deploymentId;
|
|
32901
|
+
const initialDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
|
|
32857
32902
|
config2.userName,
|
|
32858
|
-
|
|
32903
|
+
deploymentId
|
|
32859
32904
|
);
|
|
32860
|
-
if (!
|
|
32861
|
-
throw new Error(`Runtime deployment not found: ${
|
|
32905
|
+
if (!initialDeployment) {
|
|
32906
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
32862
32907
|
}
|
|
32863
32908
|
const sessions = /* @__PURE__ */ new Map();
|
|
32864
32909
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
@@ -32877,7 +32922,14 @@ var init_runner = __esm({
|
|
|
32877
32922
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
32878
32923
|
signal: abortController.signal,
|
|
32879
32924
|
runCycle: async () => {
|
|
32880
|
-
const
|
|
32925
|
+
const currentDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
|
|
32926
|
+
config2.userName,
|
|
32927
|
+
deploymentId
|
|
32928
|
+
);
|
|
32929
|
+
if (!currentDeployment) {
|
|
32930
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
32931
|
+
}
|
|
32932
|
+
const scopes = await loadConfiguredSignalsScopes(currentDeployment);
|
|
32881
32933
|
for (const [key, staleSession] of sessions) {
|
|
32882
32934
|
if (scopes.has(key)) continue;
|
|
32883
32935
|
await staleSession.klineFeed?.close();
|
|
@@ -36599,8 +36651,8 @@ var init_outputReport = __esm({
|
|
|
36599
36651
|
grouped.set(record.strategy, existing);
|
|
36600
36652
|
}
|
|
36601
36653
|
const formatSet = (values) => {
|
|
36602
|
-
const
|
|
36603
|
-
return
|
|
36654
|
+
const sorted2 = [...values].sort();
|
|
36655
|
+
return sorted2.length <= 3 ? sorted2.join(", ") : `${sorted2.slice(0, 3).join(", ")} \u2026 (+${sorted2.length - 3})`;
|
|
36604
36656
|
};
|
|
36605
36657
|
return grouped.size ? createMarkdownTable2(
|
|
36606
36658
|
[
|
package/dist/scripts/signals.js
CHANGED
|
@@ -4994,6 +4994,52 @@ 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 buildConfiguredSignalsScopes = ({
|
|
5000
|
+
connectorName,
|
|
5001
|
+
deployment,
|
|
5002
|
+
strategies
|
|
5003
|
+
}) => {
|
|
5004
|
+
const deploymentIdentity = JSON.stringify({
|
|
5005
|
+
id: deployment.id,
|
|
5006
|
+
enabled: deployment.enabled,
|
|
5007
|
+
connectorName: deployment.connectorName,
|
|
5008
|
+
provider: deployment.provider,
|
|
5009
|
+
accountId: deployment.accountId,
|
|
5010
|
+
tickers: sorted(deployment.tickers),
|
|
5011
|
+
assetClasses: sorted(deployment.assetClasses)
|
|
5012
|
+
});
|
|
5013
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5014
|
+
for (const strategy of strategies) {
|
|
5015
|
+
const baseKey = [
|
|
5016
|
+
connectorName,
|
|
5017
|
+
strategy.universe,
|
|
5018
|
+
strategy.accountId ?? "default",
|
|
5019
|
+
strategy.interval
|
|
5020
|
+
].join(":");
|
|
5021
|
+
const group = groups.get(baseKey) ?? {
|
|
5022
|
+
scope: {
|
|
5023
|
+
connectorName,
|
|
5024
|
+
universe: strategy.universe,
|
|
5025
|
+
accountId: strategy.accountId,
|
|
5026
|
+
interval: strategy.interval
|
|
5027
|
+
},
|
|
5028
|
+
strategyIdentities: []
|
|
5029
|
+
};
|
|
5030
|
+
group.strategyIdentities.push(
|
|
5031
|
+
`${strategy.strategyName}@${strategy.releaseVersion}:${strategy.controlState}`
|
|
5032
|
+
);
|
|
5033
|
+
groups.set(baseKey, group);
|
|
5034
|
+
}
|
|
5035
|
+
return [...groups.entries()].map(([baseKey, group]) => ({
|
|
5036
|
+
key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
|
|
5037
|
+
":"
|
|
5038
|
+
),
|
|
5039
|
+
scope: group.scope
|
|
5040
|
+
}));
|
|
5041
|
+
};
|
|
5042
|
+
|
|
4997
5043
|
// src/lib/signals/runner.ts
|
|
4998
5044
|
var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
|
|
4999
5045
|
var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
|
|
@@ -5502,22 +5548,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5502
5548
|
const connectorName = await resolveSignalsConnectorName(
|
|
5503
5549
|
deployment.connectorName
|
|
5504
5550
|
);
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
const key = [
|
|
5508
|
-
connectorName,
|
|
5509
|
-
strategy.universe,
|
|
5510
|
-
strategy.accountId ?? "default",
|
|
5511
|
-
strategy.interval
|
|
5512
|
-
].join(":");
|
|
5513
|
-
scopes.set(key, {
|
|
5551
|
+
return new Map(
|
|
5552
|
+
buildConfiguredSignalsScopes({
|
|
5514
5553
|
connectorName,
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
}
|
|
5520
|
-
return scopes;
|
|
5554
|
+
deployment,
|
|
5555
|
+
strategies: configuredStrategies
|
|
5556
|
+
}).map(({ key, scope }) => [key, scope])
|
|
5557
|
+
);
|
|
5521
5558
|
};
|
|
5522
5559
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
5523
5560
|
if (config2.updateOnly || config2.showTickersList) {
|
|
@@ -5558,12 +5595,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5558
5595
|
if (!config2.deploymentId) {
|
|
5559
5596
|
throw new Error("Runtime deployment id is required");
|
|
5560
5597
|
}
|
|
5561
|
-
const
|
|
5598
|
+
const deploymentId = config2.deploymentId;
|
|
5599
|
+
const initialDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5562
5600
|
config2.userName,
|
|
5563
|
-
|
|
5601
|
+
deploymentId
|
|
5564
5602
|
);
|
|
5565
|
-
if (!
|
|
5566
|
-
throw new Error(`Runtime deployment not found: ${
|
|
5603
|
+
if (!initialDeployment) {
|
|
5604
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5567
5605
|
}
|
|
5568
5606
|
const sessions = /* @__PURE__ */ new Map();
|
|
5569
5607
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
@@ -5582,7 +5620,14 @@ var createSignalsRunner = (config2) => {
|
|
|
5582
5620
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
5583
5621
|
signal: abortController.signal,
|
|
5584
5622
|
runCycle: async () => {
|
|
5585
|
-
const
|
|
5623
|
+
const currentDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5624
|
+
config2.userName,
|
|
5625
|
+
deploymentId
|
|
5626
|
+
);
|
|
5627
|
+
if (!currentDeployment) {
|
|
5628
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5629
|
+
}
|
|
5630
|
+
const scopes = await loadConfiguredSignalsScopes(currentDeployment);
|
|
5586
5631
|
for (const [key, staleSession] of sessions) {
|
|
5587
5632
|
if (scopes.has(key)) continue;
|
|
5588
5633
|
await staleSession.klineFeed?.close();
|
|
@@ -4992,6 +4992,52 @@ 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 buildConfiguredSignalsScopes = ({
|
|
4998
|
+
connectorName,
|
|
4999
|
+
deployment,
|
|
5000
|
+
strategies
|
|
5001
|
+
}) => {
|
|
5002
|
+
const deploymentIdentity = JSON.stringify({
|
|
5003
|
+
id: deployment.id,
|
|
5004
|
+
enabled: deployment.enabled,
|
|
5005
|
+
connectorName: deployment.connectorName,
|
|
5006
|
+
provider: deployment.provider,
|
|
5007
|
+
accountId: deployment.accountId,
|
|
5008
|
+
tickers: sorted(deployment.tickers),
|
|
5009
|
+
assetClasses: sorted(deployment.assetClasses)
|
|
5010
|
+
});
|
|
5011
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5012
|
+
for (const strategy of strategies) {
|
|
5013
|
+
const baseKey = [
|
|
5014
|
+
connectorName,
|
|
5015
|
+
strategy.universe,
|
|
5016
|
+
strategy.accountId ?? "default",
|
|
5017
|
+
strategy.interval
|
|
5018
|
+
].join(":");
|
|
5019
|
+
const group = groups.get(baseKey) ?? {
|
|
5020
|
+
scope: {
|
|
5021
|
+
connectorName,
|
|
5022
|
+
universe: strategy.universe,
|
|
5023
|
+
accountId: strategy.accountId,
|
|
5024
|
+
interval: strategy.interval
|
|
5025
|
+
},
|
|
5026
|
+
strategyIdentities: []
|
|
5027
|
+
};
|
|
5028
|
+
group.strategyIdentities.push(
|
|
5029
|
+
`${strategy.strategyName}@${strategy.releaseVersion}:${strategy.controlState}`
|
|
5030
|
+
);
|
|
5031
|
+
groups.set(baseKey, group);
|
|
5032
|
+
}
|
|
5033
|
+
return [...groups.entries()].map(([baseKey, group]) => ({
|
|
5034
|
+
key: [baseKey, deploymentIdentity, ...group.strategyIdentities.sort()].join(
|
|
5035
|
+
":"
|
|
5036
|
+
),
|
|
5037
|
+
scope: group.scope
|
|
5038
|
+
}));
|
|
5039
|
+
};
|
|
5040
|
+
|
|
4995
5041
|
// src/lib/signals/runner.ts
|
|
4996
5042
|
var SLOW_SIGNALS_WARNING_MS = 10 * 6e4;
|
|
4997
5043
|
var formatDuration2 = (durationMs) => `${(durationMs / 1e3).toFixed(1)}s`;
|
|
@@ -5500,22 +5546,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5500
5546
|
const connectorName = await resolveSignalsConnectorName(
|
|
5501
5547
|
deployment.connectorName
|
|
5502
5548
|
);
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
const key = [
|
|
5506
|
-
connectorName,
|
|
5507
|
-
strategy.universe,
|
|
5508
|
-
strategy.accountId ?? "default",
|
|
5509
|
-
strategy.interval
|
|
5510
|
-
].join(":");
|
|
5511
|
-
scopes.set(key, {
|
|
5549
|
+
return new Map(
|
|
5550
|
+
buildConfiguredSignalsScopes({
|
|
5512
5551
|
connectorName,
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
}
|
|
5518
|
-
return scopes;
|
|
5552
|
+
deployment,
|
|
5553
|
+
strategies: configuredStrategies
|
|
5554
|
+
}).map(({ key, scope }) => [key, scope])
|
|
5555
|
+
);
|
|
5519
5556
|
};
|
|
5520
5557
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
5521
5558
|
if (config2.updateOnly || config2.showTickersList) {
|
|
@@ -5556,12 +5593,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5556
5593
|
if (!config2.deploymentId) {
|
|
5557
5594
|
throw new Error("Runtime deployment id is required");
|
|
5558
5595
|
}
|
|
5559
|
-
const
|
|
5596
|
+
const deploymentId = config2.deploymentId;
|
|
5597
|
+
const initialDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5560
5598
|
config2.userName,
|
|
5561
|
-
|
|
5599
|
+
deploymentId
|
|
5562
5600
|
);
|
|
5563
|
-
if (!
|
|
5564
|
-
throw new Error(`Runtime deployment not found: ${
|
|
5601
|
+
if (!initialDeployment) {
|
|
5602
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5565
5603
|
}
|
|
5566
5604
|
const sessions = /* @__PURE__ */ new Map();
|
|
5567
5605
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
@@ -5580,7 +5618,14 @@ var createSignalsRunner = (config2) => {
|
|
|
5580
5618
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
5581
5619
|
signal: abortController.signal,
|
|
5582
5620
|
runCycle: async () => {
|
|
5583
|
-
const
|
|
5621
|
+
const currentDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(
|
|
5622
|
+
config2.userName,
|
|
5623
|
+
deploymentId
|
|
5624
|
+
);
|
|
5625
|
+
if (!currentDeployment) {
|
|
5626
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
5627
|
+
}
|
|
5628
|
+
const scopes = await loadConfiguredSignalsScopes(currentDeployment);
|
|
5584
5629
|
for (const [key, staleSession] of sessions) {
|
|
5585
5630
|
if (scopes.has(key)) continue;
|
|
5586
5631
|
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.7",
|
|
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.7",
|
|
36
|
+
"@tradejs/core": "^3.1.7",
|
|
37
|
+
"@tradejs/indicators": "^3.1.7",
|
|
38
|
+
"@tradejs/infra": "^3.1.7",
|
|
39
|
+
"@tradejs/node": "^3.1.7",
|
|
40
40
|
"@tradejs/strategy-kit": "^3.0.0",
|
|
41
|
-
"@tradejs/types": "^3.1.
|
|
41
|
+
"@tradejs/types": "^3.1.7",
|
|
42
42
|
"args": "^5.0.3",
|
|
43
43
|
"bcryptjs": "^2.4.3",
|
|
44
44
|
"chalk": "4.1.2",
|