@tradejs/node 3.1.29-beta.289 → 3.1.29-beta.291
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 +109 -48
- package/dist/ai.mjs +1 -1
- package/dist/backtest.js +2504 -1883
- package/dist/backtest.mjs +3 -2
- package/dist/{chunk-KYGJBMKE.mjs → chunk-HRON2EAI.mjs} +432 -40
- package/dist/{chunk-UL5Z46JL.mjs → chunk-PYJWXAYR.mjs} +97 -30
- package/dist/chunk-UUNEWAT4.mjs +193 -0
- package/dist/{chunk-BO42QWAB.mjs → chunk-W6PPAADK.mjs} +1 -1
- package/dist/cli.js +837 -775
- package/dist/cli.mjs +4 -3
- package/dist/diagnostics.js +2532 -1911
- package/dist/diagnostics.mjs +4 -3
- package/dist/mcp.d.mts +4 -2
- package/dist/mcp.d.ts +4 -2
- package/dist/mcp.js +2614 -1971
- package/dist/mcp.mjs +27 -5
- package/dist/portfolio.d.mts +28 -0
- package/dist/portfolio.d.ts +28 -0
- package/dist/portfolio.js +210 -0
- package/dist/portfolio.mjs +9 -0
- package/dist/registry.js +2091 -1470
- package/dist/registry.mjs +3 -2
- package/dist/runtimeDashboard.js +2255 -1632
- package/dist/runtimeDashboard.mjs +4 -3
- package/dist/runtimeStrategies.js +2417 -1796
- package/dist/runtimeStrategies.mjs +4 -3
- package/dist/strategies.d.mts +3 -1
- package/dist/strategies.d.ts +3 -1
- package/dist/strategies.js +2106 -1485
- package/dist/strategies.mjs +3 -2
- package/package.json +10 -5
package/dist/cli.js
CHANGED
|
@@ -81,869 +81,881 @@ var import_candles = require("@tradejs/infra/timescale/candles");
|
|
|
81
81
|
var import_aiLanguages2 = require("@tradejs/core/aiLanguages");
|
|
82
82
|
var import_redis = require("@tradejs/infra/redis");
|
|
83
83
|
|
|
84
|
-
// src/
|
|
85
|
-
var
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
var
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
// src/strategyAdapters/ai.ts
|
|
85
|
+
var import_indicators2 = require("@tradejs/core/indicators");
|
|
86
|
+
|
|
87
|
+
// src/tradejsConfig.ts
|
|
88
|
+
var import_fs = __toESM(require("fs"));
|
|
89
|
+
var import_path = __toESM(require("path"));
|
|
90
|
+
var import_url = require("url");
|
|
91
|
+
var import_config = require("@tradejs/core/config");
|
|
92
|
+
var import_logger = require("@tradejs/infra/logger");
|
|
93
|
+
var CONFIG_FILE_NAMES = [
|
|
94
|
+
"tradejs.config.ts",
|
|
95
|
+
"tradejs.config.mts",
|
|
96
|
+
"tradejs.config.js",
|
|
97
|
+
"tradejs.config.mjs",
|
|
98
|
+
"tradejs.config.cjs"
|
|
99
|
+
];
|
|
100
|
+
var TS_MODULE_RE = /\.(cts|mts|ts)$/i;
|
|
101
|
+
var cachedByCwd = /* @__PURE__ */ new Map();
|
|
102
|
+
var announcedConfigFile = /* @__PURE__ */ new Set();
|
|
103
|
+
var tsNodeRegistered = false;
|
|
104
|
+
var tsconfigPathsRegisteredByCwd = /* @__PURE__ */ new Set();
|
|
105
|
+
var tsconfigPathMatchersByCwd = /* @__PURE__ */ new Map();
|
|
106
|
+
var getTradejsProjectCwd = (cwd) => {
|
|
107
|
+
const explicit = String(cwd ?? "").trim();
|
|
108
|
+
if (explicit) {
|
|
109
|
+
return import_path.default.resolve(explicit);
|
|
100
110
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
key,
|
|
105
|
-
trimSeriesDeep(nested)
|
|
106
|
-
])
|
|
107
|
-
);
|
|
111
|
+
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
112
|
+
if (fromEnv) {
|
|
113
|
+
return import_path.default.resolve(fromEnv);
|
|
108
114
|
}
|
|
109
|
-
return
|
|
115
|
+
return process.cwd();
|
|
110
116
|
};
|
|
111
|
-
var
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return compactSnapshot({ limit: MAX_AI_SERIES_POINTS });
|
|
117
|
+
var normalizeConfig = (rawConfig) => {
|
|
118
|
+
if (!rawConfig || typeof rawConfig !== "object") {
|
|
119
|
+
return {};
|
|
115
120
|
}
|
|
116
|
-
|
|
121
|
+
const config = rawConfig;
|
|
122
|
+
const strategies2 = Array.isArray(config.strategies) ? config.strategies.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
123
|
+
const indicators = Array.isArray(config.indicators) ? config.indicators.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
124
|
+
const connectors = Array.isArray(config.connectors) ? config.connectors.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
125
|
+
const hooks = (0, import_config.normalizeTradejsConfigHooks)(
|
|
126
|
+
config.hooks
|
|
127
|
+
);
|
|
128
|
+
const runtime = config.runtime && typeof config.runtime === "object" && !Array.isArray(config.runtime) ? config.runtime : void 0;
|
|
129
|
+
return {
|
|
130
|
+
strategies: strategies2,
|
|
131
|
+
indicators,
|
|
132
|
+
connectors,
|
|
133
|
+
...hooks ? { hooks } : {},
|
|
134
|
+
...runtime ? { runtime } : {}
|
|
135
|
+
};
|
|
117
136
|
};
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return null;
|
|
137
|
+
var getNodeCreateRequire = () => {
|
|
138
|
+
const builtinModule = process.getBuiltinModule?.("module");
|
|
139
|
+
if (typeof builtinModule?.createRequire === "function") {
|
|
140
|
+
return builtinModule.createRequire;
|
|
123
141
|
}
|
|
124
|
-
|
|
142
|
+
throw new TypeError("module.createRequire is not available");
|
|
125
143
|
};
|
|
126
|
-
var
|
|
127
|
-
|
|
128
|
-
|
|
144
|
+
var getRequireFn = (cwd = getTradejsProjectCwd()) => getNodeCreateRequire()(import_path.default.join(import_path.default.resolve(cwd), "__tradejs_loader__.js"));
|
|
145
|
+
var ensureTsNodeRegistered = async () => {
|
|
146
|
+
if (tsNodeRegistered) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const tsNodeModule = await import("ts-node");
|
|
150
|
+
const tsNode = tsNodeModule.default ?? tsNodeModule;
|
|
151
|
+
tsNode.register?.({
|
|
152
|
+
transpileOnly: true,
|
|
153
|
+
compilerOptions: {
|
|
154
|
+
module: "Node16",
|
|
155
|
+
moduleResolution: "node16"
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
tsNodeRegistered = true;
|
|
129
159
|
};
|
|
130
|
-
var
|
|
131
|
-
const
|
|
132
|
-
|
|
160
|
+
var ensureTsconfigPathsRegistered = async (cwd = getTradejsProjectCwd()) => {
|
|
161
|
+
const projectRoot = getTradejsProjectCwd(cwd);
|
|
162
|
+
if (tsconfigPathsRegisteredByCwd.has(projectRoot)) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const tsconfigPathsModule = await import("tsconfig-paths");
|
|
166
|
+
const loadConfig = tsconfigPathsModule.loadConfig;
|
|
167
|
+
const register = tsconfigPathsModule.register;
|
|
168
|
+
if (typeof loadConfig !== "function" || typeof register !== "function") {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const loadedConfig = loadConfig(projectRoot);
|
|
172
|
+
if (loadedConfig.resultType !== "success") {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
register({
|
|
176
|
+
baseUrl: loadedConfig.absoluteBaseUrl,
|
|
177
|
+
paths: loadedConfig.paths,
|
|
178
|
+
addMatchAll: false
|
|
179
|
+
});
|
|
180
|
+
tsconfigPathsRegisteredByCwd.add(projectRoot);
|
|
133
181
|
};
|
|
134
|
-
var
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
bps: null,
|
|
141
|
-
absBps: null,
|
|
142
|
-
bias: null,
|
|
143
|
-
severity: null
|
|
144
|
-
});
|
|
145
|
-
var buildSpreadContextFromSignal = (signal) => {
|
|
146
|
-
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
147
|
-
const relative = toRecord(baseContext?.relative);
|
|
148
|
-
const execution = toRecord(relative?.execution);
|
|
149
|
-
const spread = toFiniteNumber(execution?.venueSpread);
|
|
150
|
-
const zScore = toFiniteNumber(execution?.venueSpreadZScore);
|
|
151
|
-
if (spread == null) {
|
|
152
|
-
return buildMissingSpreadContext();
|
|
182
|
+
var resolveTsconfigPathModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
|
|
183
|
+
const projectRoot = getTradejsProjectCwd(cwd);
|
|
184
|
+
const cachedMatcher = tsconfigPathMatchersByCwd.get(projectRoot);
|
|
185
|
+
if (cachedMatcher) {
|
|
186
|
+
const resolved2 = cachedMatcher(moduleName);
|
|
187
|
+
return resolved2 || null;
|
|
153
188
|
}
|
|
154
|
-
const
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
189
|
+
const tsconfigPathsModule = await import("tsconfig-paths");
|
|
190
|
+
const loadConfig = tsconfigPathsModule.loadConfig;
|
|
191
|
+
const createMatchPath = tsconfigPathsModule.createMatchPath;
|
|
192
|
+
if (typeof loadConfig !== "function" || typeof createMatchPath !== "function") {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const loadedConfig = loadConfig(projectRoot);
|
|
196
|
+
if (loadedConfig.resultType !== "success") {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const matchPath = createMatchPath(
|
|
200
|
+
loadedConfig.absoluteBaseUrl,
|
|
201
|
+
loadedConfig.paths
|
|
202
|
+
);
|
|
203
|
+
const matcher = (requestedModule) => matchPath(requestedModule, void 0, import_fs.default.existsSync, [
|
|
204
|
+
".ts",
|
|
205
|
+
".tsx",
|
|
206
|
+
".mts",
|
|
207
|
+
".cts",
|
|
208
|
+
".js",
|
|
209
|
+
".jsx",
|
|
210
|
+
".mjs",
|
|
211
|
+
".cjs",
|
|
212
|
+
".json"
|
|
213
|
+
]) || "";
|
|
214
|
+
tsconfigPathMatchersByCwd.set(projectRoot, matcher);
|
|
215
|
+
const resolved = matcher(moduleName);
|
|
216
|
+
return resolved || null;
|
|
170
217
|
};
|
|
171
|
-
var
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const delta = toRecord(participation?.delta);
|
|
175
|
-
const source = String(delta?.source ?? "");
|
|
176
|
-
const isTrueDeltaSource = source === "kline_taker_volume" || source === "agg_trades" || source === "trades";
|
|
177
|
-
if (!delta || !isTrueDeltaSource) {
|
|
178
|
-
return {
|
|
179
|
-
source: source || null,
|
|
180
|
-
available: false,
|
|
181
|
-
buyPressurePct: null,
|
|
182
|
-
buyVolume: null,
|
|
183
|
-
sellVolume: null,
|
|
184
|
-
netDelta: null,
|
|
185
|
-
deltaPct: null,
|
|
186
|
-
signedVolumeZScore: null
|
|
187
|
-
};
|
|
218
|
+
var toImportSpecifier = (moduleName) => {
|
|
219
|
+
if (moduleName.startsWith("file://")) {
|
|
220
|
+
return moduleName;
|
|
188
221
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
buyVolume: toFiniteNumber(delta.buyVolume),
|
|
194
|
-
sellVolume: toFiniteNumber(delta.sellVolume),
|
|
195
|
-
netDelta: toFiniteNumber(delta.netDelta),
|
|
196
|
-
deltaPct: toFiniteNumber(delta.deltaPct),
|
|
197
|
-
signedVolumeZScore: toFiniteNumber(delta.signedVolumeZScore)
|
|
198
|
-
};
|
|
222
|
+
if (import_path.default.isAbsolute(moduleName)) {
|
|
223
|
+
return (0, import_url.pathToFileURL)(moduleName).href;
|
|
224
|
+
}
|
|
225
|
+
return moduleName;
|
|
199
226
|
};
|
|
200
|
-
var
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
if (!
|
|
205
|
-
return
|
|
206
|
-
source: null,
|
|
207
|
-
available: false,
|
|
208
|
-
interval: null,
|
|
209
|
-
stale: null,
|
|
210
|
-
trades: null,
|
|
211
|
-
buyPressurePct: null,
|
|
212
|
-
netBaseDelta: null,
|
|
213
|
-
netQuoteDelta: null
|
|
214
|
-
};
|
|
227
|
+
var isTsModulePath = (moduleName) => TS_MODULE_RE.test(moduleName.split("?")[0]);
|
|
228
|
+
var isRelativeModulePath = (moduleName) => moduleName.startsWith("./") || moduleName.startsWith("../");
|
|
229
|
+
var isBareModuleSpecifier = (moduleName) => {
|
|
230
|
+
const normalized = String(moduleName ?? "").trim();
|
|
231
|
+
if (!normalized) {
|
|
232
|
+
return false;
|
|
215
233
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
stale: typeof tradeFlow.stale === "boolean" ? tradeFlow.stale : null,
|
|
221
|
-
trades: toFiniteNumber(tradeFlow.trades),
|
|
222
|
-
buyPressurePct: toFiniteNumber(tradeFlow.buyPressurePct),
|
|
223
|
-
netBaseDelta: toFiniteNumber(tradeFlow.netBaseDelta),
|
|
224
|
-
netQuoteDelta: toFiniteNumber(tradeFlow.netQuoteDelta)
|
|
225
|
-
};
|
|
234
|
+
if (normalized.startsWith("file://") || import_path.default.isAbsolute(normalized) || isRelativeModulePath(normalized)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
226
238
|
};
|
|
227
|
-
var
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
universe: null,
|
|
236
|
-
interval: null,
|
|
237
|
-
stale: null,
|
|
238
|
-
symbolsCount: null,
|
|
239
|
-
advanceDeclineRatio: null,
|
|
240
|
-
pctAboveMa20: null,
|
|
241
|
-
pctAboveMa50: null,
|
|
242
|
-
equalWeightedReturn: null,
|
|
243
|
-
volumeWeightedReturn: null,
|
|
244
|
-
dispersion: null
|
|
245
|
-
};
|
|
239
|
+
var importConfigFile = async (configFilePath) => {
|
|
240
|
+
const ext = import_path.default.extname(configFilePath).toLowerCase();
|
|
241
|
+
const configFileUrl = `${toImportSpecifier(configFilePath)}?t=${Date.now()}`;
|
|
242
|
+
if (ext === ".ts" || ext === ".mts") {
|
|
243
|
+
const requireFn = getRequireFn(import_path.default.dirname(configFilePath));
|
|
244
|
+
await ensureTsNodeRegistered();
|
|
245
|
+
await ensureTsconfigPathsRegistered(import_path.default.dirname(configFilePath));
|
|
246
|
+
return requireFn(configFilePath);
|
|
246
247
|
}
|
|
247
|
-
return
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
interval: String(breadth.interval ?? ""),
|
|
252
|
-
stale: typeof breadth.stale === "boolean" ? breadth.stale : null,
|
|
253
|
-
symbolsCount: toFiniteNumber(breadth.symbolsCount),
|
|
254
|
-
advanceDeclineRatio: toFiniteNumber(breadth.advanceDeclineRatio),
|
|
255
|
-
pctAboveMa20: toFiniteNumber(breadth.pctAboveMa20),
|
|
256
|
-
pctAboveMa50: toFiniteNumber(breadth.pctAboveMa50),
|
|
257
|
-
equalWeightedReturn: toFiniteNumber(breadth.equalWeightedReturn),
|
|
258
|
-
volumeWeightedReturn: toFiniteNumber(breadth.volumeWeightedReturn),
|
|
259
|
-
dispersion: toFiniteNumber(breadth.dispersion)
|
|
260
|
-
};
|
|
248
|
+
return import(
|
|
249
|
+
/* webpackIgnore: true */
|
|
250
|
+
configFileUrl
|
|
251
|
+
);
|
|
261
252
|
};
|
|
262
|
-
var
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
interval: null,
|
|
274
|
-
stale: null,
|
|
275
|
-
symbolsCount: null,
|
|
276
|
-
advanceDeclineRatio: null,
|
|
277
|
-
pctAboveMa20: null,
|
|
278
|
-
pctAboveMa50: null,
|
|
279
|
-
equalWeightedReturn: null,
|
|
280
|
-
volumeWeightedReturn: null,
|
|
281
|
-
dispersion: null
|
|
282
|
-
};
|
|
253
|
+
var importTradejsModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
|
|
254
|
+
const normalized = String(moduleName ?? "").trim();
|
|
255
|
+
if (!normalized) {
|
|
256
|
+
return {};
|
|
257
|
+
}
|
|
258
|
+
let modulePath = normalized;
|
|
259
|
+
if (normalized.startsWith("file://")) {
|
|
260
|
+
try {
|
|
261
|
+
modulePath = (0, import_url.fileURLToPath)(normalized);
|
|
262
|
+
} catch {
|
|
263
|
+
modulePath = normalized;
|
|
283
264
|
}
|
|
284
|
-
return {
|
|
285
|
-
source: String(breadth.source ?? ""),
|
|
286
|
-
available: true,
|
|
287
|
-
universe: String(breadth.universe ?? ""),
|
|
288
|
-
interval: String(breadth.interval ?? ""),
|
|
289
|
-
stale: typeof breadth.stale === "boolean" ? breadth.stale : null,
|
|
290
|
-
symbolsCount: toFiniteNumber(breadth.symbolsCount),
|
|
291
|
-
advanceDeclineRatio: toFiniteNumber(breadth.advanceDeclineRatio),
|
|
292
|
-
pctAboveMa20: toFiniteNumber(breadth.pctAboveMa20),
|
|
293
|
-
pctAboveMa50: toFiniteNumber(breadth.pctAboveMa50),
|
|
294
|
-
equalWeightedReturn: toFiniteNumber(breadth.equalWeightedReturn),
|
|
295
|
-
volumeWeightedReturn: toFiniteNumber(breadth.volumeWeightedReturn),
|
|
296
|
-
dispersion: toFiniteNumber(breadth.dispersion)
|
|
297
|
-
};
|
|
298
|
-
};
|
|
299
|
-
return {
|
|
300
|
-
top5: build("top5"),
|
|
301
|
-
top10: build("top10"),
|
|
302
|
-
top30: build("top30"),
|
|
303
|
-
top50: build("top50"),
|
|
304
|
-
top100: build("top100")
|
|
305
|
-
};
|
|
306
|
-
};
|
|
307
|
-
var buildTargetVsBtcContextFromSignal = (signal) => {
|
|
308
|
-
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
309
|
-
const relative = toRecord(baseContext?.relative);
|
|
310
|
-
const targetVsBtc = toRecord(relative?.targetVsBtc);
|
|
311
|
-
if (!targetVsBtc) {
|
|
312
|
-
return {
|
|
313
|
-
source: null,
|
|
314
|
-
available: false,
|
|
315
|
-
ratioReturn1h: null,
|
|
316
|
-
ratioReturn4h: null,
|
|
317
|
-
ratioReturn24h: null,
|
|
318
|
-
alphaVsBtc1h: null,
|
|
319
|
-
alphaVsBtc4h: null,
|
|
320
|
-
alphaVsBtc24h: null,
|
|
321
|
-
betaToBtc20: null,
|
|
322
|
-
correlationToBtc20: null,
|
|
323
|
-
ratioTrend: null
|
|
324
|
-
};
|
|
325
265
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
266
|
+
const requireFn = getRequireFn(
|
|
267
|
+
import_path.default.isAbsolute(modulePath) ? import_path.default.dirname(modulePath) : cwd
|
|
268
|
+
);
|
|
269
|
+
if (isTsModulePath(modulePath)) {
|
|
270
|
+
await ensureTsNodeRegistered();
|
|
271
|
+
await ensureTsconfigPathsRegistered(cwd);
|
|
272
|
+
return requireFn(modulePath);
|
|
273
|
+
}
|
|
274
|
+
if (isBareModuleSpecifier(normalized)) {
|
|
275
|
+
await ensureTsconfigPathsRegistered(cwd);
|
|
276
|
+
try {
|
|
277
|
+
return requireFn(normalized);
|
|
278
|
+
} catch (error) {
|
|
279
|
+
const resolvedByTsconfig = await resolveTsconfigPathModule(
|
|
280
|
+
normalized,
|
|
281
|
+
cwd
|
|
282
|
+
);
|
|
283
|
+
if (resolvedByTsconfig && resolvedByTsconfig !== normalized) {
|
|
284
|
+
return requireFn(resolvedByTsconfig);
|
|
285
|
+
}
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
return await import(
|
|
291
|
+
/* webpackIgnore: true */
|
|
292
|
+
toImportSpecifier(normalized)
|
|
293
|
+
);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
if (isTsModulePath(modulePath)) {
|
|
296
|
+
await ensureTsNodeRegistered();
|
|
297
|
+
await ensureTsconfigPathsRegistered(cwd);
|
|
298
|
+
return requireFn(modulePath);
|
|
299
|
+
}
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
339
302
|
};
|
|
340
|
-
var
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
altDispersion24h: null
|
|
359
|
-
};
|
|
303
|
+
var resolveExportedConfig = (moduleExports) => {
|
|
304
|
+
const candidate = moduleExports && typeof moduleExports === "object" && "default" in moduleExports ? moduleExports.default : moduleExports;
|
|
305
|
+
return normalizeConfig(candidate);
|
|
306
|
+
};
|
|
307
|
+
var findConfigFilePath = (cwd) => {
|
|
308
|
+
let currentDir = import_path.default.resolve(cwd);
|
|
309
|
+
while (true) {
|
|
310
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
311
|
+
const fullPath = import_path.default.join(currentDir, fileName);
|
|
312
|
+
if (import_fs.default.existsSync(fullPath) && import_fs.default.statSync(fullPath).isFile()) {
|
|
313
|
+
return fullPath;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const parentDir = import_path.default.dirname(currentDir);
|
|
317
|
+
if (parentDir === currentDir) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
currentDir = parentDir;
|
|
360
321
|
}
|
|
361
|
-
return {
|
|
362
|
-
source: String(btcAltRegime.source ?? ""),
|
|
363
|
-
available: true,
|
|
364
|
-
universe: String(btcAltRegime.universe ?? ""),
|
|
365
|
-
interval: String(btcAltRegime.interval ?? ""),
|
|
366
|
-
stale: typeof btcAltRegime.stale === "boolean" ? btcAltRegime.stale : null,
|
|
367
|
-
regime: typeof btcAltRegime.regime === "string" ? btcAltRegime.regime : null,
|
|
368
|
-
btcReturn24h: toFiniteNumber(btcAltRegime.btcReturn24h),
|
|
369
|
-
altBasketReturn24h: toFiniteNumber(btcAltRegime.altBasketReturn24h),
|
|
370
|
-
btcVsAltReturn24h: toFiniteNumber(btcAltRegime.btcVsAltReturn24h),
|
|
371
|
-
btcTurnoverShare24h: toFiniteNumber(btcAltRegime.btcTurnoverShare24h),
|
|
372
|
-
btcTurnoverShareChange24h: toFiniteNumber(
|
|
373
|
-
btcAltRegime.btcTurnoverShareChange24h
|
|
374
|
-
),
|
|
375
|
-
altVolToBtcVol24h: toFiniteNumber(btcAltRegime.altVolToBtcVol24h),
|
|
376
|
-
altDispersion24h: toFiniteNumber(btcAltRegime.altDispersion24h)
|
|
377
|
-
};
|
|
378
322
|
};
|
|
379
|
-
var
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (!cmcGlobal) {
|
|
384
|
-
return {
|
|
385
|
-
source: null,
|
|
386
|
-
available: false,
|
|
387
|
-
interval: null,
|
|
388
|
-
asOfTs: null,
|
|
389
|
-
stale: null,
|
|
390
|
-
totalMarketCapUsd: null,
|
|
391
|
-
totalVolumeUsd: null,
|
|
392
|
-
totalVolumeReportedUsd: null,
|
|
393
|
-
altMarketCapUsd: null,
|
|
394
|
-
altVolumeUsd: null,
|
|
395
|
-
altVolumeReportedUsd: null,
|
|
396
|
-
btcDominancePct: null,
|
|
397
|
-
ethDominancePct: null,
|
|
398
|
-
btcDominanceChange24hPct: null,
|
|
399
|
-
ethDominanceChange24hPct: null,
|
|
400
|
-
altMarketCapChange24hPct: null,
|
|
401
|
-
altVolumeChange24hPct: null,
|
|
402
|
-
activeCryptocurrencies: null,
|
|
403
|
-
activeExchanges: null,
|
|
404
|
-
activeMarketPairs: null,
|
|
405
|
-
altLiquidityRegime: null
|
|
406
|
-
};
|
|
323
|
+
var resolvePluginModuleSpecifier = (moduleName, cwd = getTradejsProjectCwd()) => {
|
|
324
|
+
const normalized = String(moduleName ?? "").trim();
|
|
325
|
+
if (!normalized) {
|
|
326
|
+
return "";
|
|
407
327
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
btcDominanceChange24hPct: toFiniteNumber(
|
|
423
|
-
cmcGlobal.btcDominanceChange24hPct
|
|
424
|
-
),
|
|
425
|
-
ethDominanceChange24hPct: toFiniteNumber(
|
|
426
|
-
cmcGlobal.ethDominanceChange24hPct
|
|
427
|
-
),
|
|
428
|
-
altMarketCapChange24hPct: toFiniteNumber(
|
|
429
|
-
cmcGlobal.altMarketCapChange24hPct
|
|
430
|
-
),
|
|
431
|
-
altVolumeChange24hPct: toFiniteNumber(cmcGlobal.altVolumeChange24hPct),
|
|
432
|
-
activeCryptocurrencies: toFiniteNumber(cmcGlobal.activeCryptocurrencies),
|
|
433
|
-
activeExchanges: toFiniteNumber(cmcGlobal.activeExchanges),
|
|
434
|
-
activeMarketPairs: toFiniteNumber(cmcGlobal.activeMarketPairs),
|
|
435
|
-
altLiquidityRegime: typeof cmcGlobal.altLiquidityRegime === "string" ? cmcGlobal.altLiquidityRegime : null
|
|
436
|
-
};
|
|
328
|
+
if (normalized.startsWith("file://")) {
|
|
329
|
+
try {
|
|
330
|
+
return (0, import_url.fileURLToPath)(normalized);
|
|
331
|
+
} catch {
|
|
332
|
+
return normalized;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (import_path.default.isAbsolute(normalized)) {
|
|
336
|
+
return normalized;
|
|
337
|
+
}
|
|
338
|
+
if (isRelativeModulePath(normalized)) {
|
|
339
|
+
return import_path.default.resolve(cwd, normalized);
|
|
340
|
+
}
|
|
341
|
+
return normalized;
|
|
437
342
|
};
|
|
438
|
-
var
|
|
343
|
+
var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
|
|
344
|
+
const cached = cachedByCwd.get(cwd);
|
|
345
|
+
if (cached) {
|
|
346
|
+
return cached;
|
|
347
|
+
}
|
|
348
|
+
const configFilePath = findConfigFilePath(cwd);
|
|
349
|
+
if (!configFilePath) {
|
|
350
|
+
cachedByCwd.set(cwd, {});
|
|
351
|
+
return {};
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
const moduleExports = await importConfigFile(configFilePath);
|
|
355
|
+
const config = resolveExportedConfig(moduleExports);
|
|
356
|
+
cachedByCwd.set(cwd, config);
|
|
357
|
+
if (!announcedConfigFile.has(configFilePath)) {
|
|
358
|
+
announcedConfigFile.add(configFilePath);
|
|
359
|
+
import_logger.logger.log("debug", "Loaded TradeJS config: %s", configFilePath);
|
|
360
|
+
}
|
|
361
|
+
return config;
|
|
362
|
+
} catch (error) {
|
|
363
|
+
import_logger.logger.log(
|
|
364
|
+
"warn",
|
|
365
|
+
"Failed to load TradeJS config from %s: %s",
|
|
366
|
+
configFilePath,
|
|
367
|
+
String(error)
|
|
368
|
+
);
|
|
369
|
+
cachedByCwd.set(cwd, {});
|
|
370
|
+
return {};
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// src/strategyAdapters/ai.ts
|
|
375
|
+
var import_aiFeatures = require("@tradejs/core/aiFeatures");
|
|
376
|
+
|
|
377
|
+
// src/aiShared.ts
|
|
378
|
+
var MAX_AI_SERIES_POINTS = 5;
|
|
379
|
+
var COMPACT_INDICATORS_SNAPSHOT_SYMBOL = /* @__PURE__ */ Symbol.for(
|
|
380
|
+
"tradejs.indicators.compactSnapshot"
|
|
381
|
+
);
|
|
382
|
+
var COMPACT_INDICATORS_SNAPSHOT_KEY = "__tradejsCompactIndicatorsSnapshot";
|
|
383
|
+
var trimSeriesDeep = (value) => {
|
|
384
|
+
if (Array.isArray(value)) {
|
|
385
|
+
const trimmed = value.slice(-MAX_AI_SERIES_POINTS);
|
|
386
|
+
const isMatrix = trimmed.every((item) => Array.isArray(item));
|
|
387
|
+
if (isMatrix) {
|
|
388
|
+
return trimmed;
|
|
389
|
+
}
|
|
390
|
+
return trimmed.map(
|
|
391
|
+
(item) => item && typeof item === "object" ? trimSeriesDeep(item) : item
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
if (value && typeof value === "object") {
|
|
395
|
+
return Object.fromEntries(
|
|
396
|
+
Object.entries(value).map(([key, nested]) => [
|
|
397
|
+
key,
|
|
398
|
+
trimSeriesDeep(nested)
|
|
399
|
+
])
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
return value;
|
|
403
|
+
};
|
|
404
|
+
var buildCompactAiIndicatorsSnapshot = (value) => {
|
|
405
|
+
const compactSnapshot = value && typeof value === "object" ? value[COMPACT_INDICATORS_SNAPSHOT_SYMBOL] ?? value[COMPACT_INDICATORS_SNAPSHOT_KEY] : void 0;
|
|
406
|
+
if (typeof compactSnapshot === "function") {
|
|
407
|
+
return compactSnapshot({ limit: MAX_AI_SERIES_POINTS });
|
|
408
|
+
}
|
|
409
|
+
return trimSeriesDeep(value);
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// src/aiMarketContext.ts
|
|
413
|
+
var toRecord = (value) => {
|
|
414
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
return value;
|
|
418
|
+
};
|
|
419
|
+
var toFiniteNumber = (value) => {
|
|
420
|
+
const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : Number.NaN;
|
|
421
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
422
|
+
};
|
|
423
|
+
var roundTo = (value, decimals) => {
|
|
424
|
+
const factor = 10 ** decimals;
|
|
425
|
+
return Math.round(value * factor) / factor;
|
|
426
|
+
};
|
|
427
|
+
var buildMissingSpreadContext = () => ({
|
|
428
|
+
source: "payload.additionalIndicators.baseContext.relative.execution.venueSpread",
|
|
429
|
+
indicatorKey: "payload.additionalIndicators.baseContext.relative.execution.venueSpread",
|
|
430
|
+
available: false,
|
|
431
|
+
value: null,
|
|
432
|
+
zScore: null,
|
|
433
|
+
bps: null,
|
|
434
|
+
absBps: null,
|
|
435
|
+
bias: null,
|
|
436
|
+
severity: null
|
|
437
|
+
});
|
|
438
|
+
var buildSpreadContextFromSignal = (signal) => {
|
|
439
439
|
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
440
440
|
const relative = toRecord(baseContext?.relative);
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
interval: null,
|
|
447
|
-
asOfTs: null,
|
|
448
|
-
stale: null,
|
|
449
|
-
btcMarketCapUsd: null,
|
|
450
|
-
ethMarketCapUsd: null,
|
|
451
|
-
btcVolumeUsd: null,
|
|
452
|
-
ethVolumeUsd: null,
|
|
453
|
-
btcVolumeToMarketCap: null,
|
|
454
|
-
ethVolumeToMarketCap: null,
|
|
455
|
-
ethBtcMarketCapRatio: null,
|
|
456
|
-
ethBtcMarketCapRatioChange24hPct: null,
|
|
457
|
-
ethVsBtcVolumeRatio: null,
|
|
458
|
-
referenceLiquidityRegime: null
|
|
459
|
-
};
|
|
441
|
+
const execution = toRecord(relative?.execution);
|
|
442
|
+
const spread = toFiniteNumber(execution?.venueSpread);
|
|
443
|
+
const zScore = toFiniteNumber(execution?.venueSpreadZScore);
|
|
444
|
+
if (spread == null) {
|
|
445
|
+
return buildMissingSpreadContext();
|
|
460
446
|
}
|
|
447
|
+
const value = roundTo(spread, 8);
|
|
448
|
+
const bps = roundTo(value * 1e4, 2);
|
|
449
|
+
const absBps = Math.abs(bps);
|
|
450
|
+
const bias = absBps < 1 ? "flat" : bps > 0 ? "coinbase_premium" : "binance_premium";
|
|
451
|
+
const severity = absBps >= 20 ? "wide" : absBps >= 5 ? "elevated" : "normal";
|
|
461
452
|
return {
|
|
462
|
-
source:
|
|
453
|
+
source: "payload.additionalIndicators.baseContext.relative.execution.venueSpread",
|
|
454
|
+
indicatorKey: "payload.additionalIndicators.baseContext.relative.execution.venueSpread",
|
|
463
455
|
available: true,
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
ethVolumeUsd: toFiniteNumber(cmcReferenceAssets.ethVolumeUsd),
|
|
471
|
-
btcVolumeToMarketCap: toFiniteNumber(
|
|
472
|
-
cmcReferenceAssets.btcVolumeToMarketCap
|
|
473
|
-
),
|
|
474
|
-
ethVolumeToMarketCap: toFiniteNumber(
|
|
475
|
-
cmcReferenceAssets.ethVolumeToMarketCap
|
|
476
|
-
),
|
|
477
|
-
ethBtcMarketCapRatio: toFiniteNumber(
|
|
478
|
-
cmcReferenceAssets.ethBtcMarketCapRatio
|
|
479
|
-
),
|
|
480
|
-
ethBtcMarketCapRatioChange24hPct: toFiniteNumber(
|
|
481
|
-
cmcReferenceAssets.ethBtcMarketCapRatioChange24hPct
|
|
482
|
-
),
|
|
483
|
-
ethVsBtcVolumeRatio: toFiniteNumber(cmcReferenceAssets.ethVsBtcVolumeRatio),
|
|
484
|
-
referenceLiquidityRegime: typeof cmcReferenceAssets.referenceLiquidityRegime === "string" ? cmcReferenceAssets.referenceLiquidityRegime : null
|
|
456
|
+
value,
|
|
457
|
+
zScore,
|
|
458
|
+
bps,
|
|
459
|
+
absBps,
|
|
460
|
+
bias,
|
|
461
|
+
severity
|
|
485
462
|
};
|
|
486
463
|
};
|
|
487
|
-
var
|
|
464
|
+
var buildTrueDeltaContextFromSignal = (signal) => {
|
|
488
465
|
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
489
|
-
const
|
|
490
|
-
const
|
|
491
|
-
|
|
466
|
+
const participation = toRecord(baseContext?.participation);
|
|
467
|
+
const delta = toRecord(participation?.delta);
|
|
468
|
+
const source = String(delta?.source ?? "");
|
|
469
|
+
const isTrueDeltaSource = source === "kline_taker_volume" || source === "agg_trades" || source === "trades";
|
|
470
|
+
if (!delta || !isTrueDeltaSource) {
|
|
492
471
|
return {
|
|
493
|
-
source: null,
|
|
472
|
+
source: source || null,
|
|
494
473
|
available: false,
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
binanceVolumeUsd: null,
|
|
502
|
-
binanceVolumeShare: null,
|
|
503
|
-
topExchangeVolumeShare: null,
|
|
504
|
-
liquidityRegime: null
|
|
474
|
+
buyPressurePct: null,
|
|
475
|
+
buyVolume: null,
|
|
476
|
+
sellVolume: null,
|
|
477
|
+
netDelta: null,
|
|
478
|
+
deltaPct: null,
|
|
479
|
+
signedVolumeZScore: null
|
|
505
480
|
};
|
|
506
481
|
}
|
|
507
482
|
return {
|
|
508
|
-
source
|
|
483
|
+
source,
|
|
509
484
|
available: true,
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
cmcExchangeLiquidity.totalVolumeChange24hPct
|
|
517
|
-
),
|
|
518
|
-
binanceVolumeUsd: toFiniteNumber(cmcExchangeLiquidity.binanceVolumeUsd),
|
|
519
|
-
binanceVolumeShare: toFiniteNumber(cmcExchangeLiquidity.binanceVolumeShare),
|
|
520
|
-
topExchangeVolumeShare: toFiniteNumber(
|
|
521
|
-
cmcExchangeLiquidity.topExchangeVolumeShare
|
|
522
|
-
),
|
|
523
|
-
liquidityRegime: typeof cmcExchangeLiquidity.liquidityRegime === "string" ? cmcExchangeLiquidity.liquidityRegime : null
|
|
485
|
+
buyPressurePct: toFiniteNumber(delta.buyPressurePct),
|
|
486
|
+
buyVolume: toFiniteNumber(delta.buyVolume),
|
|
487
|
+
sellVolume: toFiniteNumber(delta.sellVolume),
|
|
488
|
+
netDelta: toFiniteNumber(delta.netDelta),
|
|
489
|
+
deltaPct: toFiniteNumber(delta.deltaPct),
|
|
490
|
+
signedVolumeZScore: toFiniteNumber(delta.signedVolumeZScore)
|
|
524
491
|
};
|
|
525
492
|
};
|
|
526
|
-
var
|
|
493
|
+
var buildTradeFlowContextFromSignal = (signal) => {
|
|
527
494
|
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
528
|
-
const
|
|
529
|
-
const
|
|
530
|
-
if (!
|
|
495
|
+
const participation = toRecord(baseContext?.participation);
|
|
496
|
+
const tradeFlow = toRecord(participation?.tradeFlow);
|
|
497
|
+
if (!tradeFlow) {
|
|
531
498
|
return {
|
|
532
499
|
source: null,
|
|
533
500
|
available: false,
|
|
534
501
|
interval: null,
|
|
535
|
-
asOfTs: null,
|
|
536
502
|
stale: null,
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
sentimentRegime: null
|
|
503
|
+
trades: null,
|
|
504
|
+
buyPressurePct: null,
|
|
505
|
+
netBaseDelta: null,
|
|
506
|
+
netQuoteDelta: null
|
|
542
507
|
};
|
|
543
508
|
}
|
|
544
509
|
return {
|
|
545
|
-
source: String(
|
|
510
|
+
source: String(tradeFlow.source ?? ""),
|
|
546
511
|
available: true,
|
|
547
|
-
interval:
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
classification: typeof cmcFearGreed.classification === "string" ? cmcFearGreed.classification : null,
|
|
554
|
-
sentimentRegime: typeof cmcFearGreed.sentimentRegime === "string" ? cmcFearGreed.sentimentRegime : null
|
|
512
|
+
interval: String(tradeFlow.interval ?? ""),
|
|
513
|
+
stale: typeof tradeFlow.stale === "boolean" ? tradeFlow.stale : null,
|
|
514
|
+
trades: toFiniteNumber(tradeFlow.trades),
|
|
515
|
+
buyPressurePct: toFiniteNumber(tradeFlow.buyPressurePct),
|
|
516
|
+
netBaseDelta: toFiniteNumber(tradeFlow.netBaseDelta),
|
|
517
|
+
netQuoteDelta: toFiniteNumber(tradeFlow.netQuoteDelta)
|
|
555
518
|
};
|
|
556
519
|
};
|
|
557
|
-
var
|
|
520
|
+
var buildMarketBreadthContextFromSignal = (signal) => {
|
|
558
521
|
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
559
522
|
const relative = toRecord(baseContext?.relative);
|
|
560
|
-
const
|
|
561
|
-
if (!
|
|
523
|
+
const breadth = toRecord(relative?.marketBreadth);
|
|
524
|
+
if (!breadth) {
|
|
562
525
|
return {
|
|
563
526
|
source: null,
|
|
564
527
|
available: false,
|
|
528
|
+
universe: null,
|
|
565
529
|
interval: null,
|
|
566
|
-
asOfTs: null,
|
|
567
530
|
stale: null,
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
cmc20TopConstituentWeightPct: null,
|
|
576
|
-
cmc20ToCmc100Ratio: null,
|
|
577
|
-
cmc20ToCmc100RatioChange24hPct: null,
|
|
578
|
-
indexRegime: null
|
|
531
|
+
symbolsCount: null,
|
|
532
|
+
advanceDeclineRatio: null,
|
|
533
|
+
pctAboveMa20: null,
|
|
534
|
+
pctAboveMa50: null,
|
|
535
|
+
equalWeightedReturn: null,
|
|
536
|
+
volumeWeightedReturn: null,
|
|
537
|
+
dispersion: null
|
|
579
538
|
};
|
|
580
539
|
}
|
|
581
540
|
return {
|
|
582
|
-
source: String(
|
|
541
|
+
source: String(breadth.source ?? ""),
|
|
583
542
|
available: true,
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
stale: typeof
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
),
|
|
593
|
-
|
|
594
|
-
cmc20Change24hPct: toFiniteNumber(cmcIndexes.cmc20Change24hPct),
|
|
595
|
-
cmc20TopConstituentSymbol: typeof cmcIndexes.cmc20TopConstituentSymbol === "string" ? cmcIndexes.cmc20TopConstituentSymbol : null,
|
|
596
|
-
cmc20TopConstituentWeightPct: toFiniteNumber(
|
|
597
|
-
cmcIndexes.cmc20TopConstituentWeightPct
|
|
598
|
-
),
|
|
599
|
-
cmc20ToCmc100Ratio: toFiniteNumber(cmcIndexes.cmc20ToCmc100Ratio),
|
|
600
|
-
cmc20ToCmc100RatioChange24hPct: toFiniteNumber(
|
|
601
|
-
cmcIndexes.cmc20ToCmc100RatioChange24hPct
|
|
602
|
-
),
|
|
603
|
-
indexRegime: typeof cmcIndexes.indexRegime === "string" ? cmcIndexes.indexRegime : null
|
|
543
|
+
universe: String(breadth.universe ?? ""),
|
|
544
|
+
interval: String(breadth.interval ?? ""),
|
|
545
|
+
stale: typeof breadth.stale === "boolean" ? breadth.stale : null,
|
|
546
|
+
symbolsCount: toFiniteNumber(breadth.symbolsCount),
|
|
547
|
+
advanceDeclineRatio: toFiniteNumber(breadth.advanceDeclineRatio),
|
|
548
|
+
pctAboveMa20: toFiniteNumber(breadth.pctAboveMa20),
|
|
549
|
+
pctAboveMa50: toFiniteNumber(breadth.pctAboveMa50),
|
|
550
|
+
equalWeightedReturn: toFiniteNumber(breadth.equalWeightedReturn),
|
|
551
|
+
volumeWeightedReturn: toFiniteNumber(breadth.volumeWeightedReturn),
|
|
552
|
+
dispersion: toFiniteNumber(breadth.dispersion)
|
|
604
553
|
};
|
|
605
554
|
};
|
|
606
|
-
var
|
|
555
|
+
var buildMarketBreadthsContextFromSignal = (signal) => {
|
|
607
556
|
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
608
557
|
const relative = toRecord(baseContext?.relative);
|
|
609
|
-
const
|
|
610
|
-
const
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
558
|
+
const breadths = toRecord(relative?.marketBreadths);
|
|
559
|
+
const build = (key) => {
|
|
560
|
+
const breadth = toRecord(breadths?.[key]);
|
|
561
|
+
if (!breadth) {
|
|
562
|
+
return {
|
|
563
|
+
source: null,
|
|
564
|
+
available: false,
|
|
565
|
+
universe: null,
|
|
566
|
+
interval: null,
|
|
567
|
+
stale: null,
|
|
568
|
+
symbolsCount: null,
|
|
569
|
+
advanceDeclineRatio: null,
|
|
570
|
+
pctAboveMa20: null,
|
|
571
|
+
pctAboveMa50: null,
|
|
572
|
+
equalWeightedReturn: null,
|
|
573
|
+
volumeWeightedReturn: null,
|
|
574
|
+
dispersion: null
|
|
575
|
+
};
|
|
576
|
+
}
|
|
614
577
|
return {
|
|
615
|
-
source:
|
|
616
|
-
available:
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
578
|
+
source: String(breadth.source ?? ""),
|
|
579
|
+
available: true,
|
|
580
|
+
universe: String(breadth.universe ?? ""),
|
|
581
|
+
interval: String(breadth.interval ?? ""),
|
|
582
|
+
stale: typeof breadth.stale === "boolean" ? breadth.stale : null,
|
|
583
|
+
symbolsCount: toFiniteNumber(breadth.symbolsCount),
|
|
584
|
+
advanceDeclineRatio: toFiniteNumber(breadth.advanceDeclineRatio),
|
|
585
|
+
pctAboveMa20: toFiniteNumber(breadth.pctAboveMa20),
|
|
586
|
+
pctAboveMa50: toFiniteNumber(breadth.pctAboveMa50),
|
|
587
|
+
equalWeightedReturn: toFiniteNumber(breadth.equalWeightedReturn),
|
|
588
|
+
volumeWeightedReturn: toFiniteNumber(breadth.volumeWeightedReturn),
|
|
589
|
+
dispersion: toFiniteNumber(breadth.dispersion)
|
|
621
590
|
};
|
|
622
|
-
}
|
|
591
|
+
};
|
|
623
592
|
return {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
primaryTradeFlow?.buyPressurePct
|
|
630
|
-
),
|
|
631
|
-
primaryTradeFlowStale: typeof primaryTradeFlow?.stale === "boolean" ? primaryTradeFlow.stale : null
|
|
593
|
+
top5: build("top5"),
|
|
594
|
+
top10: build("top10"),
|
|
595
|
+
top30: build("top30"),
|
|
596
|
+
top50: build("top50"),
|
|
597
|
+
top100: build("top100")
|
|
632
598
|
};
|
|
633
599
|
};
|
|
634
|
-
var
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}
|
|
638
|
-
participation: {
|
|
639
|
-
trueDelta: buildTrueDeltaContextFromSignal(signal),
|
|
640
|
-
tradeFlow: buildTradeFlowContextFromSignal(signal)
|
|
641
|
-
},
|
|
642
|
-
relative: {
|
|
643
|
-
marketBreadth: buildMarketBreadthContextFromSignal(signal),
|
|
644
|
-
marketBreadths: buildMarketBreadthsContextFromSignal(signal),
|
|
645
|
-
targetVsBtc: buildTargetVsBtcContextFromSignal(signal),
|
|
646
|
-
btcAltRegime: buildBtcAltRegimeContextFromSignal(signal),
|
|
647
|
-
cmcGlobal: buildCmcGlobalContextFromSignal(signal),
|
|
648
|
-
cmcReferenceAssets: buildCmcReferenceAssetsContextFromSignal(signal),
|
|
649
|
-
cmcExchangeLiquidity: buildCmcExchangeLiquidityContextFromSignal(signal),
|
|
650
|
-
cmcFearGreed: buildCmcFearGreedContextFromSignal(signal),
|
|
651
|
-
cmcIndexes: buildCmcIndexesContextFromSignal(signal),
|
|
652
|
-
referenceTradeFlow: buildReferenceTradeFlowContextFromSignal(signal)
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
|
|
656
|
-
// src/strategy/manifests.ts
|
|
657
|
-
var import_indicators = require("@tradejs/core/indicators");
|
|
658
|
-
|
|
659
|
-
// src/tradejsConfig.ts
|
|
660
|
-
var import_fs = __toESM(require("fs"));
|
|
661
|
-
var import_path = __toESM(require("path"));
|
|
662
|
-
var import_url = require("url");
|
|
663
|
-
var import_config = require("@tradejs/core/config");
|
|
664
|
-
var import_logger = require("@tradejs/infra/logger");
|
|
665
|
-
var CONFIG_FILE_NAMES = [
|
|
666
|
-
"tradejs.config.ts",
|
|
667
|
-
"tradejs.config.mts",
|
|
668
|
-
"tradejs.config.js",
|
|
669
|
-
"tradejs.config.mjs",
|
|
670
|
-
"tradejs.config.cjs"
|
|
671
|
-
];
|
|
672
|
-
var TS_MODULE_RE = /\.(cts|mts|ts)$/i;
|
|
673
|
-
var cachedByCwd = /* @__PURE__ */ new Map();
|
|
674
|
-
var announcedConfigFile = /* @__PURE__ */ new Set();
|
|
675
|
-
var tsNodeRegistered = false;
|
|
676
|
-
var tsconfigPathsRegisteredByCwd = /* @__PURE__ */ new Set();
|
|
677
|
-
var tsconfigPathMatchersByCwd = /* @__PURE__ */ new Map();
|
|
678
|
-
var getTradejsProjectCwd = (cwd) => {
|
|
679
|
-
const explicit = String(cwd ?? "").trim();
|
|
680
|
-
if (explicit) {
|
|
681
|
-
return import_path.default.resolve(explicit);
|
|
682
|
-
}
|
|
683
|
-
const fromEnv = String(process.env.PROJECT_CWD || "").trim();
|
|
684
|
-
if (fromEnv) {
|
|
685
|
-
return import_path.default.resolve(fromEnv);
|
|
686
|
-
}
|
|
687
|
-
return process.cwd();
|
|
688
|
-
};
|
|
689
|
-
var normalizeConfig = (rawConfig) => {
|
|
690
|
-
if (!rawConfig || typeof rawConfig !== "object") {
|
|
691
|
-
return {};
|
|
692
|
-
}
|
|
693
|
-
const config = rawConfig;
|
|
694
|
-
const strategies2 = Array.isArray(config.strategies) ? config.strategies.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
695
|
-
const indicators = Array.isArray(config.indicators) ? config.indicators.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
696
|
-
const connectors = Array.isArray(config.connectors) ? config.connectors.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
697
|
-
const hooks = (0, import_config.normalizeTradejsConfigHooks)(
|
|
698
|
-
config.hooks
|
|
699
|
-
);
|
|
700
|
-
const runtime = config.runtime && typeof config.runtime === "object" && !Array.isArray(config.runtime) ? config.runtime : void 0;
|
|
600
|
+
var buildTargetVsReference = (signal, asset) => {
|
|
601
|
+
const base = toRecord(signal.additionalIndicators?.baseContext);
|
|
602
|
+
const relative = toRecord(base?.relative);
|
|
603
|
+
const target = toRecord(relative?.[`targetVs${asset}`]);
|
|
701
604
|
return {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
605
|
+
source: target ? String(target.source ?? "") : null,
|
|
606
|
+
available: Boolean(target),
|
|
607
|
+
ratioReturn1h: toFiniteNumber(target?.ratioReturn1h),
|
|
608
|
+
ratioReturn4h: toFiniteNumber(target?.ratioReturn4h),
|
|
609
|
+
ratioReturn24h: toFiniteNumber(target?.ratioReturn24h),
|
|
610
|
+
alpha1h: toFiniteNumber(target?.[`alphaVs${asset}1h`]),
|
|
611
|
+
alpha4h: toFiniteNumber(target?.[`alphaVs${asset}4h`]),
|
|
612
|
+
alpha24h: toFiniteNumber(target?.[`alphaVs${asset}24h`]),
|
|
613
|
+
beta: toFiniteNumber(target?.[`betaTo${asset}20`]),
|
|
614
|
+
correlation: toFiniteNumber(target?.[`correlationTo${asset}20`]),
|
|
615
|
+
ratioTrend: typeof target?.ratioTrend === "string" ? target.ratioTrend : null
|
|
707
616
|
};
|
|
708
617
|
};
|
|
709
|
-
var
|
|
710
|
-
const
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
const tsNodeModule = await import("ts-node");
|
|
722
|
-
const tsNode = tsNodeModule.default ?? tsNodeModule;
|
|
723
|
-
tsNode.register?.({
|
|
724
|
-
transpileOnly: true,
|
|
725
|
-
compilerOptions: {
|
|
726
|
-
module: "Node16",
|
|
727
|
-
moduleResolution: "node16"
|
|
728
|
-
}
|
|
729
|
-
});
|
|
730
|
-
tsNodeRegistered = true;
|
|
731
|
-
};
|
|
732
|
-
var ensureTsconfigPathsRegistered = async (cwd = getTradejsProjectCwd()) => {
|
|
733
|
-
const projectRoot = getTradejsProjectCwd(cwd);
|
|
734
|
-
if (tsconfigPathsRegisteredByCwd.has(projectRoot)) {
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
const tsconfigPathsModule = await import("tsconfig-paths");
|
|
738
|
-
const loadConfig = tsconfigPathsModule.loadConfig;
|
|
739
|
-
const register = tsconfigPathsModule.register;
|
|
740
|
-
if (typeof loadConfig !== "function" || typeof register !== "function") {
|
|
741
|
-
return;
|
|
742
|
-
}
|
|
743
|
-
const loadedConfig = loadConfig(projectRoot);
|
|
744
|
-
if (loadedConfig.resultType !== "success") {
|
|
745
|
-
return;
|
|
746
|
-
}
|
|
747
|
-
register({
|
|
748
|
-
baseUrl: loadedConfig.absoluteBaseUrl,
|
|
749
|
-
paths: loadedConfig.paths,
|
|
750
|
-
addMatchAll: false
|
|
751
|
-
});
|
|
752
|
-
tsconfigPathsRegisteredByCwd.add(projectRoot);
|
|
753
|
-
};
|
|
754
|
-
var resolveTsconfigPathModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
|
|
755
|
-
const projectRoot = getTradejsProjectCwd(cwd);
|
|
756
|
-
const cachedMatcher = tsconfigPathMatchersByCwd.get(projectRoot);
|
|
757
|
-
if (cachedMatcher) {
|
|
758
|
-
const resolved2 = cachedMatcher(moduleName);
|
|
759
|
-
return resolved2 || null;
|
|
760
|
-
}
|
|
761
|
-
const tsconfigPathsModule = await import("tsconfig-paths");
|
|
762
|
-
const loadConfig = tsconfigPathsModule.loadConfig;
|
|
763
|
-
const createMatchPath = tsconfigPathsModule.createMatchPath;
|
|
764
|
-
if (typeof loadConfig !== "function" || typeof createMatchPath !== "function") {
|
|
765
|
-
return null;
|
|
766
|
-
}
|
|
767
|
-
const loadedConfig = loadConfig(projectRoot);
|
|
768
|
-
if (loadedConfig.resultType !== "success") {
|
|
769
|
-
return null;
|
|
770
|
-
}
|
|
771
|
-
const matchPath = createMatchPath(
|
|
772
|
-
loadedConfig.absoluteBaseUrl,
|
|
773
|
-
loadedConfig.paths
|
|
774
|
-
);
|
|
775
|
-
const matcher = (requestedModule) => matchPath(requestedModule, void 0, import_fs.default.existsSync, [
|
|
776
|
-
".ts",
|
|
777
|
-
".tsx",
|
|
778
|
-
".mts",
|
|
779
|
-
".cts",
|
|
780
|
-
".js",
|
|
781
|
-
".jsx",
|
|
782
|
-
".mjs",
|
|
783
|
-
".cjs",
|
|
784
|
-
".json"
|
|
785
|
-
]) || "";
|
|
786
|
-
tsconfigPathMatchersByCwd.set(projectRoot, matcher);
|
|
787
|
-
const resolved = matcher(moduleName);
|
|
788
|
-
return resolved || null;
|
|
789
|
-
};
|
|
790
|
-
var toImportSpecifier = (moduleName) => {
|
|
791
|
-
if (moduleName.startsWith("file://")) {
|
|
792
|
-
return moduleName;
|
|
793
|
-
}
|
|
794
|
-
if (import_path.default.isAbsolute(moduleName)) {
|
|
795
|
-
return (0, import_url.pathToFileURL)(moduleName).href;
|
|
796
|
-
}
|
|
797
|
-
return moduleName;
|
|
618
|
+
var buildTargetVsBtcContextFromSignal = (signal) => {
|
|
619
|
+
const { alpha1h, alpha4h, alpha24h, beta, correlation, ...shared } = buildTargetVsReference(signal, "Btc");
|
|
620
|
+
return {
|
|
621
|
+
...shared,
|
|
622
|
+
alphaVsBtc1h: alpha1h,
|
|
623
|
+
alphaVsBtc4h: alpha4h,
|
|
624
|
+
alphaVsBtc24h: alpha24h,
|
|
625
|
+
betaToBtc20: beta,
|
|
626
|
+
correlationToBtc20: correlation
|
|
627
|
+
};
|
|
798
628
|
};
|
|
799
|
-
var
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
}
|
|
809
|
-
return true;
|
|
629
|
+
var buildTargetVsEthContextFromSignal = (signal) => {
|
|
630
|
+
const { alpha1h, alpha4h, alpha24h, beta, correlation, ...shared } = buildTargetVsReference(signal, "Eth");
|
|
631
|
+
return {
|
|
632
|
+
...shared,
|
|
633
|
+
alphaVsEth1h: alpha1h,
|
|
634
|
+
alphaVsEth4h: alpha4h,
|
|
635
|
+
alphaVsEth24h: alpha24h,
|
|
636
|
+
betaToEth20: beta,
|
|
637
|
+
correlationToEth20: correlation
|
|
638
|
+
};
|
|
810
639
|
};
|
|
811
|
-
var
|
|
812
|
-
const
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
640
|
+
var buildBtcAltRegimeContextFromSignal = (signal) => {
|
|
641
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
642
|
+
const relative = toRecord(baseContext?.relative);
|
|
643
|
+
const btcAltRegime = toRecord(relative?.btcAltRegime);
|
|
644
|
+
if (!btcAltRegime) {
|
|
645
|
+
return {
|
|
646
|
+
source: null,
|
|
647
|
+
available: false,
|
|
648
|
+
universe: null,
|
|
649
|
+
interval: null,
|
|
650
|
+
stale: null,
|
|
651
|
+
regime: null,
|
|
652
|
+
btcReturn24h: null,
|
|
653
|
+
altBasketReturn24h: null,
|
|
654
|
+
btcVsAltReturn24h: null,
|
|
655
|
+
btcTurnoverShare24h: null,
|
|
656
|
+
btcTurnoverShareChange24h: null,
|
|
657
|
+
altVolToBtcVol24h: null,
|
|
658
|
+
altDispersion24h: null
|
|
659
|
+
};
|
|
819
660
|
}
|
|
820
|
-
return
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
661
|
+
return {
|
|
662
|
+
source: String(btcAltRegime.source ?? ""),
|
|
663
|
+
available: true,
|
|
664
|
+
universe: String(btcAltRegime.universe ?? ""),
|
|
665
|
+
interval: String(btcAltRegime.interval ?? ""),
|
|
666
|
+
stale: typeof btcAltRegime.stale === "boolean" ? btcAltRegime.stale : null,
|
|
667
|
+
regime: typeof btcAltRegime.regime === "string" ? btcAltRegime.regime : null,
|
|
668
|
+
btcReturn24h: toFiniteNumber(btcAltRegime.btcReturn24h),
|
|
669
|
+
altBasketReturn24h: toFiniteNumber(btcAltRegime.altBasketReturn24h),
|
|
670
|
+
btcVsAltReturn24h: toFiniteNumber(btcAltRegime.btcVsAltReturn24h),
|
|
671
|
+
btcTurnoverShare24h: toFiniteNumber(btcAltRegime.btcTurnoverShare24h),
|
|
672
|
+
btcTurnoverShareChange24h: toFiniteNumber(
|
|
673
|
+
btcAltRegime.btcTurnoverShareChange24h
|
|
674
|
+
),
|
|
675
|
+
altVolToBtcVol24h: toFiniteNumber(btcAltRegime.altVolToBtcVol24h),
|
|
676
|
+
altDispersion24h: toFiniteNumber(btcAltRegime.altDispersion24h)
|
|
677
|
+
};
|
|
824
678
|
};
|
|
825
|
-
var
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
cwd
|
|
854
|
-
);
|
|
855
|
-
if (resolvedByTsconfig && resolvedByTsconfig !== normalized) {
|
|
856
|
-
return requireFn(resolvedByTsconfig);
|
|
857
|
-
}
|
|
858
|
-
throw error;
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
try {
|
|
862
|
-
return await import(
|
|
863
|
-
/* webpackIgnore: true */
|
|
864
|
-
toImportSpecifier(normalized)
|
|
865
|
-
);
|
|
866
|
-
} catch (error) {
|
|
867
|
-
if (isTsModulePath(modulePath)) {
|
|
868
|
-
await ensureTsNodeRegistered();
|
|
869
|
-
await ensureTsconfigPathsRegistered(cwd);
|
|
870
|
-
return requireFn(modulePath);
|
|
871
|
-
}
|
|
872
|
-
throw error;
|
|
679
|
+
var buildCmcGlobalContextFromSignal = (signal) => {
|
|
680
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
681
|
+
const relative = toRecord(baseContext?.relative);
|
|
682
|
+
const cmcGlobal = toRecord(relative?.cmcGlobal);
|
|
683
|
+
if (!cmcGlobal) {
|
|
684
|
+
return {
|
|
685
|
+
source: null,
|
|
686
|
+
available: false,
|
|
687
|
+
interval: null,
|
|
688
|
+
asOfTs: null,
|
|
689
|
+
stale: null,
|
|
690
|
+
totalMarketCapUsd: null,
|
|
691
|
+
totalVolumeUsd: null,
|
|
692
|
+
totalVolumeReportedUsd: null,
|
|
693
|
+
altMarketCapUsd: null,
|
|
694
|
+
altVolumeUsd: null,
|
|
695
|
+
altVolumeReportedUsd: null,
|
|
696
|
+
btcDominancePct: null,
|
|
697
|
+
ethDominancePct: null,
|
|
698
|
+
btcDominanceChange24hPct: null,
|
|
699
|
+
ethDominanceChange24hPct: null,
|
|
700
|
+
altMarketCapChange24hPct: null,
|
|
701
|
+
altVolumeChange24hPct: null,
|
|
702
|
+
activeCryptocurrencies: null,
|
|
703
|
+
activeExchanges: null,
|
|
704
|
+
activeMarketPairs: null,
|
|
705
|
+
altLiquidityRegime: null
|
|
706
|
+
};
|
|
873
707
|
}
|
|
708
|
+
return {
|
|
709
|
+
source: String(cmcGlobal.source ?? ""),
|
|
710
|
+
available: true,
|
|
711
|
+
interval: typeof cmcGlobal.interval === "string" ? cmcGlobal.interval : null,
|
|
712
|
+
asOfTs: toFiniteNumber(cmcGlobal.asOfTs),
|
|
713
|
+
stale: typeof cmcGlobal.stale === "boolean" ? cmcGlobal.stale : null,
|
|
714
|
+
totalMarketCapUsd: toFiniteNumber(cmcGlobal.totalMarketCapUsd),
|
|
715
|
+
totalVolumeUsd: toFiniteNumber(cmcGlobal.totalVolumeUsd),
|
|
716
|
+
totalVolumeReportedUsd: toFiniteNumber(cmcGlobal.totalVolumeReportedUsd),
|
|
717
|
+
altMarketCapUsd: toFiniteNumber(cmcGlobal.altMarketCapUsd),
|
|
718
|
+
altVolumeUsd: toFiniteNumber(cmcGlobal.altVolumeUsd),
|
|
719
|
+
altVolumeReportedUsd: toFiniteNumber(cmcGlobal.altVolumeReportedUsd),
|
|
720
|
+
btcDominancePct: toFiniteNumber(cmcGlobal.btcDominancePct),
|
|
721
|
+
ethDominancePct: toFiniteNumber(cmcGlobal.ethDominancePct),
|
|
722
|
+
btcDominanceChange24hPct: toFiniteNumber(
|
|
723
|
+
cmcGlobal.btcDominanceChange24hPct
|
|
724
|
+
),
|
|
725
|
+
ethDominanceChange24hPct: toFiniteNumber(
|
|
726
|
+
cmcGlobal.ethDominanceChange24hPct
|
|
727
|
+
),
|
|
728
|
+
altMarketCapChange24hPct: toFiniteNumber(
|
|
729
|
+
cmcGlobal.altMarketCapChange24hPct
|
|
730
|
+
),
|
|
731
|
+
altVolumeChange24hPct: toFiniteNumber(cmcGlobal.altVolumeChange24hPct),
|
|
732
|
+
activeCryptocurrencies: toFiniteNumber(cmcGlobal.activeCryptocurrencies),
|
|
733
|
+
activeExchanges: toFiniteNumber(cmcGlobal.activeExchanges),
|
|
734
|
+
activeMarketPairs: toFiniteNumber(cmcGlobal.activeMarketPairs),
|
|
735
|
+
altLiquidityRegime: typeof cmcGlobal.altLiquidityRegime === "string" ? cmcGlobal.altLiquidityRegime : null
|
|
736
|
+
};
|
|
874
737
|
};
|
|
875
|
-
var
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
738
|
+
var buildCmcReferenceAssetsContextFromSignal = (signal) => {
|
|
739
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
740
|
+
const relative = toRecord(baseContext?.relative);
|
|
741
|
+
const cmcReferenceAssets = toRecord(relative?.cmcReferenceAssets);
|
|
742
|
+
if (!cmcReferenceAssets) {
|
|
743
|
+
return {
|
|
744
|
+
source: null,
|
|
745
|
+
available: false,
|
|
746
|
+
interval: null,
|
|
747
|
+
asOfTs: null,
|
|
748
|
+
stale: null,
|
|
749
|
+
btcMarketCapUsd: null,
|
|
750
|
+
ethMarketCapUsd: null,
|
|
751
|
+
btcVolumeUsd: null,
|
|
752
|
+
ethVolumeUsd: null,
|
|
753
|
+
btcVolumeToMarketCap: null,
|
|
754
|
+
ethVolumeToMarketCap: null,
|
|
755
|
+
ethBtcMarketCapRatio: null,
|
|
756
|
+
ethBtcMarketCapRatioChange24hPct: null,
|
|
757
|
+
ethVsBtcVolumeRatio: null,
|
|
758
|
+
referenceLiquidityRegime: null
|
|
759
|
+
};
|
|
893
760
|
}
|
|
761
|
+
return {
|
|
762
|
+
source: String(cmcReferenceAssets.source ?? ""),
|
|
763
|
+
available: true,
|
|
764
|
+
interval: typeof cmcReferenceAssets.interval === "string" ? cmcReferenceAssets.interval : null,
|
|
765
|
+
asOfTs: toFiniteNumber(cmcReferenceAssets.asOfTs),
|
|
766
|
+
stale: typeof cmcReferenceAssets.stale === "boolean" ? cmcReferenceAssets.stale : null,
|
|
767
|
+
btcMarketCapUsd: toFiniteNumber(cmcReferenceAssets.btcMarketCapUsd),
|
|
768
|
+
ethMarketCapUsd: toFiniteNumber(cmcReferenceAssets.ethMarketCapUsd),
|
|
769
|
+
btcVolumeUsd: toFiniteNumber(cmcReferenceAssets.btcVolumeUsd),
|
|
770
|
+
ethVolumeUsd: toFiniteNumber(cmcReferenceAssets.ethVolumeUsd),
|
|
771
|
+
btcVolumeToMarketCap: toFiniteNumber(
|
|
772
|
+
cmcReferenceAssets.btcVolumeToMarketCap
|
|
773
|
+
),
|
|
774
|
+
ethVolumeToMarketCap: toFiniteNumber(
|
|
775
|
+
cmcReferenceAssets.ethVolumeToMarketCap
|
|
776
|
+
),
|
|
777
|
+
ethBtcMarketCapRatio: toFiniteNumber(
|
|
778
|
+
cmcReferenceAssets.ethBtcMarketCapRatio
|
|
779
|
+
),
|
|
780
|
+
ethBtcMarketCapRatioChange24hPct: toFiniteNumber(
|
|
781
|
+
cmcReferenceAssets.ethBtcMarketCapRatioChange24hPct
|
|
782
|
+
),
|
|
783
|
+
ethVsBtcVolumeRatio: toFiniteNumber(cmcReferenceAssets.ethVsBtcVolumeRatio),
|
|
784
|
+
referenceLiquidityRegime: typeof cmcReferenceAssets.referenceLiquidityRegime === "string" ? cmcReferenceAssets.referenceLiquidityRegime : null
|
|
785
|
+
};
|
|
894
786
|
};
|
|
895
|
-
var
|
|
896
|
-
const
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
787
|
+
var buildCmcExchangeLiquidityContextFromSignal = (signal) => {
|
|
788
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
789
|
+
const relative = toRecord(baseContext?.relative);
|
|
790
|
+
const cmcExchangeLiquidity = toRecord(relative?.cmcExchangeLiquidity);
|
|
791
|
+
if (!cmcExchangeLiquidity) {
|
|
792
|
+
return {
|
|
793
|
+
source: null,
|
|
794
|
+
available: false,
|
|
795
|
+
interval: null,
|
|
796
|
+
asOfTs: null,
|
|
797
|
+
stale: null,
|
|
798
|
+
exchangesCount: null,
|
|
799
|
+
totalVolumeUsd: null,
|
|
800
|
+
totalVolumeChange24hPct: null,
|
|
801
|
+
binanceVolumeUsd: null,
|
|
802
|
+
binanceVolumeShare: null,
|
|
803
|
+
topExchangeVolumeShare: null,
|
|
804
|
+
liquidityRegime: null
|
|
805
|
+
};
|
|
912
806
|
}
|
|
913
|
-
return
|
|
807
|
+
return {
|
|
808
|
+
source: String(cmcExchangeLiquidity.source ?? ""),
|
|
809
|
+
available: true,
|
|
810
|
+
interval: typeof cmcExchangeLiquidity.interval === "string" ? cmcExchangeLiquidity.interval : null,
|
|
811
|
+
asOfTs: toFiniteNumber(cmcExchangeLiquidity.asOfTs),
|
|
812
|
+
stale: typeof cmcExchangeLiquidity.stale === "boolean" ? cmcExchangeLiquidity.stale : null,
|
|
813
|
+
exchangesCount: toFiniteNumber(cmcExchangeLiquidity.exchangesCount),
|
|
814
|
+
totalVolumeUsd: toFiniteNumber(cmcExchangeLiquidity.totalVolumeUsd),
|
|
815
|
+
totalVolumeChange24hPct: toFiniteNumber(
|
|
816
|
+
cmcExchangeLiquidity.totalVolumeChange24hPct
|
|
817
|
+
),
|
|
818
|
+
binanceVolumeUsd: toFiniteNumber(cmcExchangeLiquidity.binanceVolumeUsd),
|
|
819
|
+
binanceVolumeShare: toFiniteNumber(cmcExchangeLiquidity.binanceVolumeShare),
|
|
820
|
+
topExchangeVolumeShare: toFiniteNumber(
|
|
821
|
+
cmcExchangeLiquidity.topExchangeVolumeShare
|
|
822
|
+
),
|
|
823
|
+
liquidityRegime: typeof cmcExchangeLiquidity.liquidityRegime === "string" ? cmcExchangeLiquidity.liquidityRegime : null
|
|
824
|
+
};
|
|
914
825
|
};
|
|
915
|
-
var
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
826
|
+
var buildCmcFearGreedContextFromSignal = (signal) => {
|
|
827
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
828
|
+
const relative = toRecord(baseContext?.relative);
|
|
829
|
+
const cmcFearGreed = toRecord(relative?.cmcFearGreed);
|
|
830
|
+
if (!cmcFearGreed) {
|
|
831
|
+
return {
|
|
832
|
+
source: null,
|
|
833
|
+
available: false,
|
|
834
|
+
interval: null,
|
|
835
|
+
asOfTs: null,
|
|
836
|
+
stale: null,
|
|
837
|
+
value: null,
|
|
838
|
+
valueChange24h: null,
|
|
839
|
+
valueChange7d: null,
|
|
840
|
+
classification: null,
|
|
841
|
+
sentimentRegime: null
|
|
842
|
+
};
|
|
919
843
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
844
|
+
return {
|
|
845
|
+
source: String(cmcFearGreed.source ?? ""),
|
|
846
|
+
available: true,
|
|
847
|
+
interval: typeof cmcFearGreed.interval === "string" ? cmcFearGreed.interval : null,
|
|
848
|
+
asOfTs: toFiniteNumber(cmcFearGreed.asOfTs),
|
|
849
|
+
stale: typeof cmcFearGreed.stale === "boolean" ? cmcFearGreed.stale : null,
|
|
850
|
+
value: toFiniteNumber(cmcFearGreed.value),
|
|
851
|
+
valueChange24h: toFiniteNumber(cmcFearGreed.valueChange24h),
|
|
852
|
+
valueChange7d: toFiniteNumber(cmcFearGreed.valueChange7d),
|
|
853
|
+
classification: typeof cmcFearGreed.classification === "string" ? cmcFearGreed.classification : null,
|
|
854
|
+
sentimentRegime: typeof cmcFearGreed.sentimentRegime === "string" ? cmcFearGreed.sentimentRegime : null
|
|
855
|
+
};
|
|
856
|
+
};
|
|
857
|
+
var buildCmcIndexesContextFromSignal = (signal) => {
|
|
858
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
859
|
+
const relative = toRecord(baseContext?.relative);
|
|
860
|
+
const cmcIndexes = toRecord(relative?.cmcIndexes);
|
|
861
|
+
if (!cmcIndexes) {
|
|
862
|
+
return {
|
|
863
|
+
source: null,
|
|
864
|
+
available: false,
|
|
865
|
+
interval: null,
|
|
866
|
+
asOfTs: null,
|
|
867
|
+
stale: null,
|
|
868
|
+
cmc100Value: null,
|
|
869
|
+
cmc100Change24hPct: null,
|
|
870
|
+
cmc100TopConstituentSymbol: null,
|
|
871
|
+
cmc100TopConstituentWeightPct: null,
|
|
872
|
+
cmc20Value: null,
|
|
873
|
+
cmc20Change24hPct: null,
|
|
874
|
+
cmc20TopConstituentSymbol: null,
|
|
875
|
+
cmc20TopConstituentWeightPct: null,
|
|
876
|
+
cmc20ToCmc100Ratio: null,
|
|
877
|
+
cmc20ToCmc100RatioChange24hPct: null,
|
|
878
|
+
indexRegime: null
|
|
879
|
+
};
|
|
924
880
|
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
881
|
+
return {
|
|
882
|
+
source: String(cmcIndexes.source ?? ""),
|
|
883
|
+
available: true,
|
|
884
|
+
interval: typeof cmcIndexes.interval === "string" ? cmcIndexes.interval : null,
|
|
885
|
+
asOfTs: toFiniteNumber(cmcIndexes.asOfTs),
|
|
886
|
+
stale: typeof cmcIndexes.stale === "boolean" ? cmcIndexes.stale : null,
|
|
887
|
+
cmc100Value: toFiniteNumber(cmcIndexes.cmc100Value),
|
|
888
|
+
cmc100Change24hPct: toFiniteNumber(cmcIndexes.cmc100Change24hPct),
|
|
889
|
+
cmc100TopConstituentSymbol: typeof cmcIndexes.cmc100TopConstituentSymbol === "string" ? cmcIndexes.cmc100TopConstituentSymbol : null,
|
|
890
|
+
cmc100TopConstituentWeightPct: toFiniteNumber(
|
|
891
|
+
cmcIndexes.cmc100TopConstituentWeightPct
|
|
892
|
+
),
|
|
893
|
+
cmc20Value: toFiniteNumber(cmcIndexes.cmc20Value),
|
|
894
|
+
cmc20Change24hPct: toFiniteNumber(cmcIndexes.cmc20Change24hPct),
|
|
895
|
+
cmc20TopConstituentSymbol: typeof cmcIndexes.cmc20TopConstituentSymbol === "string" ? cmcIndexes.cmc20TopConstituentSymbol : null,
|
|
896
|
+
cmc20TopConstituentWeightPct: toFiniteNumber(
|
|
897
|
+
cmcIndexes.cmc20TopConstituentWeightPct
|
|
898
|
+
),
|
|
899
|
+
cmc20ToCmc100Ratio: toFiniteNumber(cmcIndexes.cmc20ToCmc100Ratio),
|
|
900
|
+
cmc20ToCmc100RatioChange24hPct: toFiniteNumber(
|
|
901
|
+
cmcIndexes.cmc20ToCmc100RatioChange24hPct
|
|
902
|
+
),
|
|
903
|
+
indexRegime: typeof cmcIndexes.indexRegime === "string" ? cmcIndexes.indexRegime : null
|
|
904
|
+
};
|
|
905
|
+
};
|
|
906
|
+
var buildReferenceTradeFlowContextFromSignal = (signal) => {
|
|
907
|
+
const baseContext = toRecord(signal.additionalIndicators?.baseContext);
|
|
908
|
+
const relative = toRecord(baseContext?.relative);
|
|
909
|
+
const refs = toRecord(relative?.referenceTradeFlow);
|
|
910
|
+
const primaryReferenceSymbol = typeof refs?.primaryReferenceSymbol === "string" ? refs.primaryReferenceSymbol : null;
|
|
911
|
+
const tradeFlowBySymbol = toRecord(refs?.tradeFlowBySymbol);
|
|
912
|
+
const primaryTradeFlow = primaryReferenceSymbol != null ? toRecord(tradeFlowBySymbol?.[primaryReferenceSymbol]) : null;
|
|
913
|
+
if (!refs) {
|
|
914
|
+
return {
|
|
915
|
+
source: null,
|
|
916
|
+
available: false,
|
|
917
|
+
primaryReferenceSymbol: null,
|
|
918
|
+
referenceSymbols: [],
|
|
919
|
+
primaryTradeFlowBuyPressurePct: null,
|
|
920
|
+
primaryTradeFlowStale: null
|
|
921
|
+
};
|
|
943
922
|
}
|
|
923
|
+
return {
|
|
924
|
+
source: String(refs.source ?? ""),
|
|
925
|
+
available: true,
|
|
926
|
+
primaryReferenceSymbol,
|
|
927
|
+
referenceSymbols: Array.isArray(refs.referenceSymbols) ? refs.referenceSymbols.map(String) : [],
|
|
928
|
+
primaryTradeFlowBuyPressurePct: toFiniteNumber(
|
|
929
|
+
primaryTradeFlow?.buyPressurePct
|
|
930
|
+
),
|
|
931
|
+
primaryTradeFlowStale: typeof primaryTradeFlow?.stale === "boolean" ? primaryTradeFlow.stale : null
|
|
932
|
+
};
|
|
944
933
|
};
|
|
934
|
+
var buildAiMarketContext = (signal) => ({
|
|
935
|
+
execution: {
|
|
936
|
+
binanceCoinbaseSpread: buildSpreadContextFromSignal(signal)
|
|
937
|
+
},
|
|
938
|
+
participation: {
|
|
939
|
+
trueDelta: buildTrueDeltaContextFromSignal(signal),
|
|
940
|
+
tradeFlow: buildTradeFlowContextFromSignal(signal)
|
|
941
|
+
},
|
|
942
|
+
relative: {
|
|
943
|
+
marketBreadth: buildMarketBreadthContextFromSignal(signal),
|
|
944
|
+
marketBreadths: buildMarketBreadthsContextFromSignal(signal),
|
|
945
|
+
targetVsBtc: buildTargetVsBtcContextFromSignal(signal),
|
|
946
|
+
targetVsEth: buildTargetVsEthContextFromSignal(signal),
|
|
947
|
+
btcAltRegime: buildBtcAltRegimeContextFromSignal(signal),
|
|
948
|
+
cmcGlobal: buildCmcGlobalContextFromSignal(signal),
|
|
949
|
+
cmcReferenceAssets: buildCmcReferenceAssetsContextFromSignal(signal),
|
|
950
|
+
cmcExchangeLiquidity: buildCmcExchangeLiquidityContextFromSignal(signal),
|
|
951
|
+
cmcFearGreed: buildCmcFearGreedContextFromSignal(signal),
|
|
952
|
+
cmcIndexes: buildCmcIndexesContextFromSignal(signal),
|
|
953
|
+
referenceTradeFlow: buildReferenceTradeFlowContextFromSignal(signal)
|
|
954
|
+
}
|
|
955
|
+
});
|
|
945
956
|
|
|
946
957
|
// src/strategy/manifests.ts
|
|
958
|
+
var import_indicators = require("@tradejs/core/indicators");
|
|
947
959
|
var SHARED_STRATEGY_REGISTRY_KEY = "__tradejsNodeSharedStrategyRegistryV1__";
|
|
948
960
|
var sharedRegistryScope = globalThis;
|
|
949
961
|
var sharedStrategyRegistry = sharedRegistryScope[SHARED_STRATEGY_REGISTRY_KEY] ?? (sharedRegistryScope[SHARED_STRATEGY_REGISTRY_KEY] = {
|
|
@@ -1211,12 +1223,61 @@ var buildBaseAiPayload = (signal) => {
|
|
|
1211
1223
|
};
|
|
1212
1224
|
};
|
|
1213
1225
|
var defaultAiAdapter = {};
|
|
1226
|
+
var tickerProfileFeatureIds = new Set(
|
|
1227
|
+
import_aiFeatures.TICKER_PROFILE_AI_FEATURES.map(({ id }) => id)
|
|
1228
|
+
);
|
|
1214
1229
|
var getStrategyAiAdapter = (strategy, profileId) => getStrategyProfileAiAdapter(getStrategyManifest(strategy), profileId) ?? defaultAiAdapter;
|
|
1215
1230
|
var getSignalAiAdapter = (signal) => getStrategyAiAdapter(signal.strategy, signal.policyProfileId);
|
|
1216
1231
|
var buildAiPayloadByStrategy = (signal) => {
|
|
1217
1232
|
const basePayload = buildBaseAiPayload(signal);
|
|
1218
1233
|
const adapter = getSignalAiAdapter(signal);
|
|
1219
|
-
|
|
1234
|
+
const payload = adapter.buildPayload?.({ signal, basePayload }) ?? basePayload;
|
|
1235
|
+
const custom = getStrategyManifest(signal.strategy)?.aiFeatures ?? [];
|
|
1236
|
+
const frozen = signal.aiFeatureReplay?.snapshot;
|
|
1237
|
+
if (frozen) (0, import_aiFeatures.validateAiFeatureSnapshot)(frozen);
|
|
1238
|
+
const tickerProfile = signal.additionalIndicators?.tickerProfile ?? signal.additionalIndicators?.baseContext?.tickerProfile;
|
|
1239
|
+
const hasProfile = Boolean(
|
|
1240
|
+
tickerProfile || frozen?.definitions.some(({ id }) => tickerProfileFeatureIds.has(id))
|
|
1241
|
+
);
|
|
1242
|
+
const indicatorFeatures = (0, import_indicators2.getRegisteredIndicatorEntries)(
|
|
1243
|
+
getTradejsProjectCwd()
|
|
1244
|
+
).flatMap((entry) => entry.indicator.enabled ? entry.aiFeatures ?? [] : []);
|
|
1245
|
+
const hasPortfolio = Boolean(
|
|
1246
|
+
signal.additionalIndicators?.portfolioContext || frozen?.definitions.some(
|
|
1247
|
+
({ id }) => import_aiFeatures.PORTFOLIO_AI_FEATURES.some((d) => d.id === id)
|
|
1248
|
+
)
|
|
1249
|
+
);
|
|
1250
|
+
const definitions = [
|
|
1251
|
+
...hasPortfolio ? import_aiFeatures.PORTFOLIO_AI_FEATURES : [],
|
|
1252
|
+
...hasProfile ? import_aiFeatures.TICKER_PROFILE_AI_FEATURES : [],
|
|
1253
|
+
...indicatorFeatures,
|
|
1254
|
+
...custom
|
|
1255
|
+
];
|
|
1256
|
+
if (!definitions.length && !signal.aiFeatureReplay?.snapshot) return payload;
|
|
1257
|
+
(0, import_aiFeatures.validateAiFeatureDefinitions)(definitions);
|
|
1258
|
+
if (signal.aiFeatureReplay && !frozen) {
|
|
1259
|
+
throw new Error(
|
|
1260
|
+
"Dataset has no frozen AI features; regenerate the decision-time export"
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
if (frozen && JSON.stringify(frozen.definitions) !== JSON.stringify(definitions)) {
|
|
1264
|
+
throw new Error(
|
|
1265
|
+
"AI feature definition changed; regenerate the decision-time export"
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
return {
|
|
1269
|
+
...payload,
|
|
1270
|
+
featureSnapshot: frozen ?? (0, import_aiFeatures.projectAiFeatures)(definitions, {
|
|
1271
|
+
signal: tickerProfile ? {
|
|
1272
|
+
...signal,
|
|
1273
|
+
additionalIndicators: {
|
|
1274
|
+
...signal.additionalIndicators,
|
|
1275
|
+
tickerProfile
|
|
1276
|
+
}
|
|
1277
|
+
} : signal,
|
|
1278
|
+
payload
|
|
1279
|
+
})
|
|
1280
|
+
};
|
|
1220
1281
|
};
|
|
1221
1282
|
var buildAiSystemPromptAddonByStrategy = (signal) => getSignalAiAdapter(signal).buildSystemPromptAddon?.({ signal }) ?? "";
|
|
1222
1283
|
var buildAiHumanPromptAddonByStrategy = (signal, payload) => getSignalAiAdapter(signal).buildHumanPromptAddon?.({
|
|
@@ -2396,8 +2457,9 @@ var formatMessage = (signal, analysis, _options = {}) => {
|
|
|
2396
2457
|
}
|
|
2397
2458
|
if (isConfigFromBacktest) {
|
|
2398
2459
|
lines.push("\u{1F7E2} Using config from backtest");
|
|
2399
|
-
}
|
|
2400
|
-
|
|
2460
|
+
}
|
|
2461
|
+
if (signal.riskDecision?.status === "warning") {
|
|
2462
|
+
lines.push("\u{1F7E1} Entry risk exceeds limit");
|
|
2401
2463
|
}
|
|
2402
2464
|
if (ml) {
|
|
2403
2465
|
lines.push(
|