@tradejs/node 3.1.11 → 3.1.12-beta.218
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/ai.js +0 -1
- package/dist/ai.mjs +1 -1
- package/dist/backtest.js +99 -82
- package/dist/backtest.mjs +2 -2
- package/dist/{chunk-B6X2HEGL.mjs → chunk-6PIVDS4M.mjs} +6 -6
- package/dist/{chunk-C3KRBNUR.mjs → chunk-IKRSNRP6.mjs} +58 -31
- package/dist/chunk-NQO2MFP6.mjs +552 -0
- package/dist/cli.js +108 -91
- package/dist/cli.mjs +1 -1
- package/dist/registry.js +86 -65
- package/dist/registry.mjs +2 -2
- package/dist/runtimeDashboard.js +420 -216
- package/dist/runtimeDashboard.mjs +9 -9
- package/dist/runtimeStrategies.d.mts +66 -6
- package/dist/runtimeStrategies.d.ts +66 -6
- package/dist/runtimeStrategies.js +450 -218
- package/dist/runtimeStrategies.mjs +11 -3
- package/dist/strategies.js +97 -76
- package/dist/strategies.mjs +2 -2
- package/package.json +14 -8
- package/dist/chunk-7BAL7EN3.mjs +0 -345
package/dist/chunk-7BAL7EN3.mjs
DELETED
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getStrategyCreator,
|
|
3
|
-
getStrategyPluginSource
|
|
4
|
-
} from "./chunk-C3KRBNUR.mjs";
|
|
5
|
-
import {
|
|
6
|
-
loadTradejsConfig
|
|
7
|
-
} from "./chunk-LZDXRXIU.mjs";
|
|
8
|
-
|
|
9
|
-
// src/runtimeStrategies.ts
|
|
10
|
-
import { readFile } from "fs/promises";
|
|
11
|
-
import path from "path";
|
|
12
|
-
import { getRuntimeControls } from "@tradejs/infra/runtimeControls";
|
|
13
|
-
import { resolveTradingAccount } from "@tradejs/infra/tradingAccounts";
|
|
14
|
-
var INTERVALS = /* @__PURE__ */ new Set([
|
|
15
|
-
"1",
|
|
16
|
-
"3",
|
|
17
|
-
"5",
|
|
18
|
-
"15",
|
|
19
|
-
"30",
|
|
20
|
-
"60",
|
|
21
|
-
"120",
|
|
22
|
-
"240",
|
|
23
|
-
"360",
|
|
24
|
-
"720",
|
|
25
|
-
"D",
|
|
26
|
-
"W",
|
|
27
|
-
"M"
|
|
28
|
-
]);
|
|
29
|
-
var RUNTIME_KEYS = /* @__PURE__ */ new Set(["deployments"]);
|
|
30
|
-
var DEPLOYMENT_KEYS = /* @__PURE__ */ new Set([
|
|
31
|
-
"label",
|
|
32
|
-
"connectorName",
|
|
33
|
-
"provider",
|
|
34
|
-
"accountId",
|
|
35
|
-
"enabled",
|
|
36
|
-
"strategies",
|
|
37
|
-
"assetClasses",
|
|
38
|
-
"tickers"
|
|
39
|
-
]);
|
|
40
|
-
var STRATEGY_KEYS = /* @__PURE__ */ new Set(["version", "enabled", "selection", "config"]);
|
|
41
|
-
var SELECTION_KEYS = /* @__PURE__ */ new Set(["tickers"]);
|
|
42
|
-
var FORBIDDEN_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
43
|
-
"ACCOUNT_ID",
|
|
44
|
-
"DEPLOYMENT_ID",
|
|
45
|
-
"CONNECTOR_NAME",
|
|
46
|
-
"ENABLE"
|
|
47
|
-
]);
|
|
48
|
-
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
49
|
-
var readPackageManifest = async (projectRoot) => {
|
|
50
|
-
const candidates = [
|
|
51
|
-
process.env.TRADEJS_RUNTIME_PACKAGE_MANIFEST,
|
|
52
|
-
path.join(projectRoot, "runtime-package-manifest.json"),
|
|
53
|
-
"/app/runtime-package-manifest.json"
|
|
54
|
-
].filter((candidate) => Boolean(candidate));
|
|
55
|
-
for (const candidate of candidates) {
|
|
56
|
-
try {
|
|
57
|
-
return JSON.parse(
|
|
58
|
-
await readFile(candidate, "utf8")
|
|
59
|
-
);
|
|
60
|
-
} catch {
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return { packages: {} };
|
|
64
|
-
};
|
|
65
|
-
var resolveInstalledPackageVersion = async (projectRoot, packageName, manifest) => {
|
|
66
|
-
if (!packageName || packageName === "runtime") return null;
|
|
67
|
-
const manifestVersion = manifest.packages?.[packageName];
|
|
68
|
-
if (manifestVersion) return manifestVersion;
|
|
69
|
-
try {
|
|
70
|
-
const packageJsonPath = path.join(
|
|
71
|
-
projectRoot,
|
|
72
|
-
"node_modules",
|
|
73
|
-
...packageName.split("/"),
|
|
74
|
-
"package.json"
|
|
75
|
-
);
|
|
76
|
-
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
77
|
-
return packageJson.version ?? null;
|
|
78
|
-
} catch {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
var resolveStrategyPackageName = async ({
|
|
83
|
-
pluginSource,
|
|
84
|
-
projectRoot
|
|
85
|
-
}) => {
|
|
86
|
-
if (!pluginSource) return null;
|
|
87
|
-
if (!pluginSource.startsWith(".") && !path.isAbsolute(pluginSource)) {
|
|
88
|
-
return pluginSource;
|
|
89
|
-
}
|
|
90
|
-
try {
|
|
91
|
-
const packageJson = JSON.parse(
|
|
92
|
-
await readFile(path.join(projectRoot, "package.json"), "utf8")
|
|
93
|
-
);
|
|
94
|
-
return typeof packageJson.name === "string" && packageJson.name.trim() ? packageJson.name : null;
|
|
95
|
-
} catch {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
var verifyStringArray = (value) => value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
100
|
-
var verifyStrategySelection = (value) => value === void 0 || isRecord(value) && Object.keys(value).length === 1 && Object.keys(value).every((key) => SELECTION_KEYS.has(key)) && Array.isArray(value.tickers) && value.tickers.length > 0 && value.tickers.every(
|
|
101
|
-
(ticker) => typeof ticker === "string" && ticker.trim().length > 0
|
|
102
|
-
);
|
|
103
|
-
var cloneSelection = (selection) => selection ? { tickers: [...selection.tickers] } : void 0;
|
|
104
|
-
var resolveStrategySelection = ({
|
|
105
|
-
deployment,
|
|
106
|
-
strategy
|
|
107
|
-
}) => cloneSelection(
|
|
108
|
-
strategy.selection ?? (deployment.tickers ? { tickers: deployment.tickers } : void 0)
|
|
109
|
-
);
|
|
110
|
-
var verifyDeploymentDeclaration = (deploymentId, value) => {
|
|
111
|
-
if (!deploymentId.trim() || !isRecord(value) || Object.keys(value).some((key) => !DEPLOYMENT_KEYS.has(key)) || typeof value.connectorName !== "string" || !value.connectorName.trim() || typeof value.accountId !== "string" || !value.accountId.trim() || value.label !== void 0 && typeof value.label !== "string" || value.provider !== void 0 && typeof value.provider !== "string" || value.enabled !== void 0 && typeof value.enabled !== "boolean" || !verifyStringArray(value.assetClasses) || !verifyStringArray(value.tickers) || !isRecord(value.strategies) || !Object.keys(value.strategies).length) {
|
|
112
|
-
throw new Error(`Invalid runtime deployment declaration: ${deploymentId}`);
|
|
113
|
-
}
|
|
114
|
-
for (const [strategyName, strategyValue] of Object.entries(
|
|
115
|
-
value.strategies
|
|
116
|
-
)) {
|
|
117
|
-
if (!strategyName.trim() || !isRecord(strategyValue) || Object.keys(strategyValue).some((key) => !STRATEGY_KEYS.has(key)) || !Number.isSafeInteger(strategyValue.version) || Number(strategyValue.version) <= 0 || typeof strategyValue.enabled !== "boolean" || !verifyStrategySelection(strategyValue.selection) || !isRecord(strategyValue.config) || Object.keys(strategyValue.config).some(
|
|
118
|
-
(key) => FORBIDDEN_CONFIG_KEYS.has(key)
|
|
119
|
-
) || !INTERVALS.has(String(strategyValue.config.INTERVAL)) || !["crypto", "tradfi"].includes(String(strategyValue.config.UNIVERSE))) {
|
|
120
|
-
throw new Error(
|
|
121
|
-
`Invalid runtime strategy declaration: ${deploymentId}/${strategyName}`
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return value;
|
|
126
|
-
};
|
|
127
|
-
var verifyRuntimeDeclaration = (value) => {
|
|
128
|
-
if (!isRecord(value) || Object.keys(value).some((key) => !RUNTIME_KEYS.has(key)) || !isRecord(value.deployments) || !Object.keys(value.deployments).length) {
|
|
129
|
-
throw new Error("Invalid runtime declaration");
|
|
130
|
-
}
|
|
131
|
-
for (const [deploymentId, deployment] of Object.entries(value.deployments)) {
|
|
132
|
-
verifyDeploymentDeclaration(deploymentId, deployment);
|
|
133
|
-
}
|
|
134
|
-
return value;
|
|
135
|
-
};
|
|
136
|
-
var toRuntimeDeployment = ({
|
|
137
|
-
id,
|
|
138
|
-
declaration,
|
|
139
|
-
controls
|
|
140
|
-
}) => {
|
|
141
|
-
const deploymentEnabled = declaration.enabled ?? true;
|
|
142
|
-
return {
|
|
143
|
-
id,
|
|
144
|
-
label: declaration.label?.trim() || id,
|
|
145
|
-
connectorName: declaration.connectorName.trim(),
|
|
146
|
-
provider: (declaration.provider || declaration.connectorName).trim().toLowerCase(),
|
|
147
|
-
accountId: declaration.accountId.trim(),
|
|
148
|
-
enabled: deploymentEnabled,
|
|
149
|
-
strategies: Object.entries(declaration.strategies).map(
|
|
150
|
-
([strategyName, strategy]) => {
|
|
151
|
-
const selection = resolveStrategySelection({
|
|
152
|
-
deployment: declaration,
|
|
153
|
-
strategy
|
|
154
|
-
});
|
|
155
|
-
return {
|
|
156
|
-
strategyName,
|
|
157
|
-
version: strategy.version,
|
|
158
|
-
enabled: strategy.enabled,
|
|
159
|
-
controlState: deploymentEnabled && strategy.enabled && !controls.deployments[id]?.[strategyName]?.entriesPaused ? "active" : "entries_paused",
|
|
160
|
-
...selection ? { selection } : {}
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
),
|
|
164
|
-
...declaration.assetClasses ? { assetClasses: declaration.assetClasses } : {},
|
|
165
|
-
...declaration.tickers ? { tickers: declaration.tickers } : {}
|
|
166
|
-
};
|
|
167
|
-
};
|
|
168
|
-
var loadRuntimeDeclaration = async (projectRoot) => {
|
|
169
|
-
const projectConfig = await loadTradejsConfig(projectRoot);
|
|
170
|
-
if (!projectConfig.runtime) {
|
|
171
|
-
throw new Error("Runtime declaration is required in tradejs.config.ts");
|
|
172
|
-
}
|
|
173
|
-
return verifyRuntimeDeclaration(projectConfig.runtime);
|
|
174
|
-
};
|
|
175
|
-
var listRuntimeDeployments = async ({
|
|
176
|
-
userName,
|
|
177
|
-
projectRoot
|
|
178
|
-
}) => {
|
|
179
|
-
const [runtime, controls] = await Promise.all([
|
|
180
|
-
loadRuntimeDeclaration(projectRoot),
|
|
181
|
-
getRuntimeControls(userName)
|
|
182
|
-
]);
|
|
183
|
-
return Object.entries(runtime.deployments).map(
|
|
184
|
-
([id, declaration]) => toRuntimeDeployment({ id, declaration, controls })
|
|
185
|
-
).sort((left, right) => left.label.localeCompare(right.label));
|
|
186
|
-
};
|
|
187
|
-
var getRuntimeDeployment = async ({
|
|
188
|
-
userName,
|
|
189
|
-
projectRoot,
|
|
190
|
-
deploymentId
|
|
191
|
-
}) => {
|
|
192
|
-
const deployments = await listRuntimeDeployments({ userName, projectRoot });
|
|
193
|
-
return deployments.find((deployment) => deployment.id === deploymentId) ?? null;
|
|
194
|
-
};
|
|
195
|
-
var resolveAccountId = async ({
|
|
196
|
-
userName,
|
|
197
|
-
deployment,
|
|
198
|
-
universe
|
|
199
|
-
}) => {
|
|
200
|
-
const account = await resolveTradingAccount({
|
|
201
|
-
userName,
|
|
202
|
-
accountId: deployment.accountId,
|
|
203
|
-
provider: deployment.provider,
|
|
204
|
-
universe
|
|
205
|
-
});
|
|
206
|
-
if (!account) {
|
|
207
|
-
throw new Error(`Trading account not found: ${deployment.accountId}`);
|
|
208
|
-
}
|
|
209
|
-
return account.id;
|
|
210
|
-
};
|
|
211
|
-
var loadResolvedRuntimeStrategies = async ({
|
|
212
|
-
userName,
|
|
213
|
-
projectRoot,
|
|
214
|
-
deploymentId,
|
|
215
|
-
universe,
|
|
216
|
-
accountId,
|
|
217
|
-
interval
|
|
218
|
-
}) => {
|
|
219
|
-
const [runtime, controls, packageManifest] = await Promise.all([
|
|
220
|
-
loadRuntimeDeclaration(projectRoot),
|
|
221
|
-
getRuntimeControls(userName),
|
|
222
|
-
readPackageManifest(projectRoot)
|
|
223
|
-
]);
|
|
224
|
-
const declaration = runtime.deployments[deploymentId];
|
|
225
|
-
if (!declaration) {
|
|
226
|
-
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
227
|
-
}
|
|
228
|
-
const deployment = toRuntimeDeployment({
|
|
229
|
-
id: deploymentId,
|
|
230
|
-
declaration,
|
|
231
|
-
controls
|
|
232
|
-
});
|
|
233
|
-
const strategies = await Promise.all(
|
|
234
|
-
Object.entries(declaration.strategies).map(
|
|
235
|
-
async ([strategyName, strategyDeclaration]) => {
|
|
236
|
-
const strategyCreator = await getStrategyCreator(
|
|
237
|
-
strategyName,
|
|
238
|
-
projectRoot
|
|
239
|
-
);
|
|
240
|
-
if (!strategyCreator) {
|
|
241
|
-
throw new Error(`Unknown strategy: ${strategyName}`);
|
|
242
|
-
}
|
|
243
|
-
const pluginSource = await getStrategyPluginSource(strategyName, projectRoot) ?? null;
|
|
244
|
-
const strategyPackage = await resolveStrategyPackageName({
|
|
245
|
-
pluginSource,
|
|
246
|
-
projectRoot
|
|
247
|
-
});
|
|
248
|
-
const [strategyPackageVersion, runtimePackageVersion] = await Promise.all([
|
|
249
|
-
resolveInstalledPackageVersion(
|
|
250
|
-
projectRoot,
|
|
251
|
-
strategyPackage,
|
|
252
|
-
packageManifest
|
|
253
|
-
),
|
|
254
|
-
resolveInstalledPackageVersion(
|
|
255
|
-
projectRoot,
|
|
256
|
-
"@tradejs/node",
|
|
257
|
-
packageManifest
|
|
258
|
-
)
|
|
259
|
-
]);
|
|
260
|
-
if (!strategyPackage || !strategyPackageVersion) {
|
|
261
|
-
throw new Error(
|
|
262
|
-
`Installed strategy package not found: ${strategyName}`
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
if (!runtimePackageVersion) {
|
|
266
|
-
throw new Error("Installed @tradejs/node package version not found");
|
|
267
|
-
}
|
|
268
|
-
const strategyView = deployment.strategies.find(
|
|
269
|
-
(candidate) => candidate.strategyName === strategyName
|
|
270
|
-
);
|
|
271
|
-
const selection = resolveStrategySelection({
|
|
272
|
-
deployment: declaration,
|
|
273
|
-
strategy: strategyDeclaration
|
|
274
|
-
});
|
|
275
|
-
const strategyConfig = strategyDeclaration.config;
|
|
276
|
-
const strategyUniverse = strategyConfig.UNIVERSE;
|
|
277
|
-
const resolvedAccountId = await resolveAccountId({
|
|
278
|
-
userName,
|
|
279
|
-
deployment,
|
|
280
|
-
universe: strategyUniverse
|
|
281
|
-
});
|
|
282
|
-
return {
|
|
283
|
-
strategyName,
|
|
284
|
-
version: strategyDeclaration.version,
|
|
285
|
-
enabled: strategyDeclaration.enabled,
|
|
286
|
-
controlState: strategyView?.controlState ?? "entries_paused",
|
|
287
|
-
interval: String(strategyConfig.INTERVAL),
|
|
288
|
-
universe: strategyUniverse,
|
|
289
|
-
accountId: resolvedAccountId,
|
|
290
|
-
strategyPackage,
|
|
291
|
-
strategyPackageVersion,
|
|
292
|
-
runtimePackageVersion,
|
|
293
|
-
strategyCreator,
|
|
294
|
-
sourceStrategyConfig: strategyConfig,
|
|
295
|
-
strategyConfig,
|
|
296
|
-
...selection ? { selection } : {}
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
)
|
|
300
|
-
);
|
|
301
|
-
const filtered = strategies.filter(
|
|
302
|
-
(candidate) => (!universe || candidate.universe === universe) && (!interval || String(candidate.interval) === String(interval)) && (!accountId || candidate.accountId === accountId)
|
|
303
|
-
);
|
|
304
|
-
const identities = /* @__PURE__ */ new Set();
|
|
305
|
-
for (const candidate of filtered) {
|
|
306
|
-
const identity = `${candidate.strategyName}:${candidate.accountId ?? "default"}`;
|
|
307
|
-
if (identities.has(identity)) {
|
|
308
|
-
throw new Error(`Runtime strategy conflict: ${identity}`);
|
|
309
|
-
}
|
|
310
|
-
identities.add(identity);
|
|
311
|
-
}
|
|
312
|
-
return filtered;
|
|
313
|
-
};
|
|
314
|
-
var getRuntimeStrategyPackageMetadata = async ({
|
|
315
|
-
strategyName,
|
|
316
|
-
projectRoot
|
|
317
|
-
}) => {
|
|
318
|
-
const packageManifest = await readPackageManifest(projectRoot);
|
|
319
|
-
const pluginSource = await getStrategyPluginSource(strategyName, projectRoot) ?? null;
|
|
320
|
-
const strategyPackage = await resolveStrategyPackageName({
|
|
321
|
-
pluginSource,
|
|
322
|
-
projectRoot
|
|
323
|
-
});
|
|
324
|
-
return {
|
|
325
|
-
strategyPackage,
|
|
326
|
-
strategyPackageVersion: await resolveInstalledPackageVersion(
|
|
327
|
-
projectRoot,
|
|
328
|
-
strategyPackage,
|
|
329
|
-
packageManifest
|
|
330
|
-
),
|
|
331
|
-
runtimePackageVersion: await resolveInstalledPackageVersion(
|
|
332
|
-
projectRoot,
|
|
333
|
-
"@tradejs/node",
|
|
334
|
-
packageManifest
|
|
335
|
-
)
|
|
336
|
-
};
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
export {
|
|
340
|
-
verifyRuntimeDeclaration,
|
|
341
|
-
listRuntimeDeployments,
|
|
342
|
-
getRuntimeDeployment,
|
|
343
|
-
loadResolvedRuntimeStrategies,
|
|
344
|
-
getRuntimeStrategyPackageMetadata
|
|
345
|
-
};
|