@tradejs/core 1.0.5 → 1.0.8
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/backtest.d.mts +1 -1
- package/dist/backtest.d.ts +1 -1
- package/dist/backtest.js +5 -5
- package/dist/backtest.mjs +5 -5
- package/dist/{chunk-4F73AYK6.mjs → chunk-622V7IAT.mjs} +253 -12
- package/dist/{chunk-NQ7D3T4E.mjs → chunk-AJK4NS7Y.mjs} +2 -2
- package/dist/{chunk-JG2QPVAV.mjs → chunk-JLORHLL6.mjs} +12 -1
- package/dist/{chunk-PXLXXXLA.mjs → chunk-PQETJ42A.mjs} +6 -2
- package/dist/config.d.mts +49 -2
- package/dist/config.d.ts +49 -2
- package/dist/config.js +40 -3
- package/dist/config.mjs +37 -2
- package/dist/constants.d.mts +6 -2
- package/dist/constants.d.ts +6 -2
- package/dist/constants.js +16 -1
- package/dist/constants.mjs +9 -1
- package/dist/indicators.d.mts +11 -2
- package/dist/indicators.d.ts +11 -2
- package/dist/indicators.js +252 -10
- package/dist/indicators.mjs +5 -3
- package/dist/strategies.d.mts +2 -0
- package/dist/strategies.d.ts +2 -0
- package/dist/strategies.js +72 -27
- package/dist/strategies.mjs +54 -21
- package/dist/{time-DEyFa2vI.d.mts → time-BMkFD4Kd.d.mts} +2 -1
- package/dist/{time-DEyFa2vI.d.ts → time-BMkFD4Kd.d.ts} +2 -1
- package/dist/time.d.mts +1 -1
- package/dist/time.d.ts +1 -1
- package/dist/time.js +9 -0
- package/dist/time.mjs +4 -2
- package/package.json +4 -5
package/dist/backtest.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StrategyConfigGrid, TestSuite, StrategyConfig, PositionLogData, TestStat, TestThresholdsKey, ThresholdLevel, TestWorkerResult } from '@tradejs/types';
|
|
2
|
-
export { c as compactOrderLog, g as getTimeline } from './time-
|
|
2
|
+
export { c as compactOrderLog, g as getTimeline } from './time-BMkFD4Kd.mjs';
|
|
3
3
|
|
|
4
4
|
type GenericConfig = StrategyConfig;
|
|
5
5
|
declare const generateParamGrid: <T extends StrategyConfig>(paramOptions: StrategyConfigGrid) => T[];
|
package/dist/backtest.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StrategyConfigGrid, TestSuite, StrategyConfig, PositionLogData, TestStat, TestThresholdsKey, ThresholdLevel, TestWorkerResult } from '@tradejs/types';
|
|
2
|
-
export { c as compactOrderLog, g as getTimeline } from './time-
|
|
2
|
+
export { c as compactOrderLog, g as getTimeline } from './time-BMkFD4Kd.js';
|
|
3
3
|
|
|
4
4
|
type GenericConfig = StrategyConfig;
|
|
5
5
|
declare const generateParamGrid: <T extends StrategyConfig>(paramOptions: StrategyConfigGrid) => T[];
|
package/dist/backtest.js
CHANGED
|
@@ -50,7 +50,7 @@ module.exports = __toCommonJS(backtest_exports);
|
|
|
50
50
|
var import_lodash = __toESM(require("lodash"));
|
|
51
51
|
|
|
52
52
|
// src/constants/index.ts
|
|
53
|
-
var
|
|
53
|
+
var BACKTEST_DEFAULT_DAYS = 160;
|
|
54
54
|
var TestThresholdsConfig = {
|
|
55
55
|
// Период и частота — используем как требования к качеству теста, в скоринг не влияют
|
|
56
56
|
periodDays: {
|
|
@@ -189,7 +189,7 @@ var getTimestamp = (days = 0) => {
|
|
|
189
189
|
}
|
|
190
190
|
return (0, import_date_fns2.getUnixTime)(/* @__PURE__ */ new Date()) * 1e3;
|
|
191
191
|
};
|
|
192
|
-
var getTimeline = (start = getTimestamp(
|
|
192
|
+
var getTimeline = (start = getTimestamp(BACKTEST_DEFAULT_DAYS), end = getTimestamp(), step = TIMELINE_STEP) => {
|
|
193
193
|
const res = new Array();
|
|
194
194
|
for (let ind = start; ind <= end; ind += step) {
|
|
195
195
|
res.push(ind);
|
|
@@ -223,9 +223,9 @@ var compactOrderLog = (timeline, orderLog) => {
|
|
|
223
223
|
};
|
|
224
224
|
|
|
225
225
|
// src/utils/uuid.ts
|
|
226
|
-
var
|
|
226
|
+
var import_node_crypto = require("crypto");
|
|
227
227
|
var uuid = (len = 12) => {
|
|
228
|
-
const uuid2 = (0,
|
|
228
|
+
const uuid2 = (0, import_node_crypto.randomUUID)();
|
|
229
229
|
return uuid2.slice(-len);
|
|
230
230
|
};
|
|
231
231
|
|
|
@@ -275,7 +275,7 @@ var mergeConfigs = (configs) => {
|
|
|
275
275
|
return result;
|
|
276
276
|
};
|
|
277
277
|
var createTestSuite = (userName, tickers, strategyName, backtestConfig, connectorName) => {
|
|
278
|
-
const start = getTimestamp(
|
|
278
|
+
const start = getTimestamp(BACKTEST_DEFAULT_DAYS);
|
|
279
279
|
const end = getTimestamp();
|
|
280
280
|
const testSuiteId = uuid(6);
|
|
281
281
|
const paramGrid = generateParamGrid(backtestConfig);
|
package/dist/backtest.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
uuid
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AJK4NS7Y.mjs";
|
|
4
4
|
import {
|
|
5
5
|
absReturns,
|
|
6
6
|
equityPoints,
|
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
compactOrderLog,
|
|
14
14
|
getTimeline,
|
|
15
15
|
getTimestamp
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-PQETJ42A.mjs";
|
|
17
17
|
import {
|
|
18
|
-
|
|
18
|
+
BACKTEST_DEFAULT_DAYS,
|
|
19
19
|
TestThresholdsConfig
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-JLORHLL6.mjs";
|
|
21
21
|
|
|
22
22
|
// src/utils/grid.ts
|
|
23
23
|
import _ from "lodash";
|
|
@@ -66,7 +66,7 @@ var mergeConfigs = (configs) => {
|
|
|
66
66
|
return result;
|
|
67
67
|
};
|
|
68
68
|
var createTestSuite = (userName, tickers, strategyName, backtestConfig, connectorName) => {
|
|
69
|
-
const start = getTimestamp(
|
|
69
|
+
const start = getTimestamp(BACKTEST_DEFAULT_DAYS);
|
|
70
70
|
const end = getTimestamp();
|
|
71
71
|
const testSuiteId = uuid(6);
|
|
72
72
|
const paramGrid = generateParamGrid(backtestConfig);
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
} from "./chunk-AYC2QVKI.mjs";
|
|
4
4
|
import {
|
|
5
5
|
toMs
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PQETJ42A.mjs";
|
|
7
7
|
import {
|
|
8
8
|
CORRELATION_WINDOW,
|
|
9
9
|
ML_BASE_CANDLES_WINDOW,
|
|
10
10
|
TRENDLINE_DEFAULTS
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-JLORHLL6.mjs";
|
|
12
12
|
import {
|
|
13
13
|
cloneArrayValues
|
|
14
14
|
} from "./chunk-M7QGVZ3J.mjs";
|
|
@@ -211,6 +211,235 @@ var coinalyzePointsToRows = (points, interval, source) => points.map((point) =>
|
|
|
211
211
|
source
|
|
212
212
|
}));
|
|
213
213
|
|
|
214
|
+
// src/utils/derivativesContext.ts
|
|
215
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
216
|
+
var DEFAULT_STALE_AFTER_MS = {
|
|
217
|
+
"15m": 45 * 60 * 1e3,
|
|
218
|
+
"1h": 3 * HOUR_MS
|
|
219
|
+
};
|
|
220
|
+
var DERIVATIVES_INTERVALS = ["15m", "1h"];
|
|
221
|
+
var toFiniteNumberOrNull = (value) => {
|
|
222
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
223
|
+
if (typeof value === "string" && value.trim()) {
|
|
224
|
+
const parsed = Number(value);
|
|
225
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
};
|
|
229
|
+
var toTimestampMs = (value) => {
|
|
230
|
+
if (value instanceof Date) {
|
|
231
|
+
const time = value.getTime();
|
|
232
|
+
return Number.isFinite(time) ? time : null;
|
|
233
|
+
}
|
|
234
|
+
const num = toFiniteNumberOrNull(value);
|
|
235
|
+
if (num == null) return null;
|
|
236
|
+
return num > 1e10 ? Math.floor(num) : Math.floor(num * 1e3);
|
|
237
|
+
};
|
|
238
|
+
var roundNullable = (value, digits = 6) => {
|
|
239
|
+
if (value == null || !Number.isFinite(value)) return null;
|
|
240
|
+
const multiplier = 10 ** digits;
|
|
241
|
+
return Math.round(value * multiplier) / multiplier;
|
|
242
|
+
};
|
|
243
|
+
var pctChange = (current, previous) => {
|
|
244
|
+
if (current == null || previous == null || !Number.isFinite(current) || !Number.isFinite(previous) || previous === 0) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
return (current - previous) / Math.abs(previous) * 100;
|
|
248
|
+
};
|
|
249
|
+
var normalizeRows = (rows, timestamp) => (rows ?? []).map((row) => ({
|
|
250
|
+
...row,
|
|
251
|
+
tsMs: toTimestampMs(row.ts),
|
|
252
|
+
openInterest: toFiniteNumberOrNull(row.openInterest),
|
|
253
|
+
fundingRate: toFiniteNumberOrNull(row.fundingRate),
|
|
254
|
+
liqLong: toFiniteNumberOrNull(row.liqLong),
|
|
255
|
+
liqShort: toFiniteNumberOrNull(row.liqShort),
|
|
256
|
+
liqTotal: toFiniteNumberOrNull(row.liqTotal)
|
|
257
|
+
})).filter((row) => {
|
|
258
|
+
return row.tsMs != null && row.tsMs <= timestamp;
|
|
259
|
+
}).sort((a, b) => a.tsMs - b.tsMs);
|
|
260
|
+
var findRowAtOrBefore = (rows, targetTs) => {
|
|
261
|
+
for (let i = rows.length - 1; i >= 0; i -= 1) {
|
|
262
|
+
if (rows[i].tsMs <= targetTs) {
|
|
263
|
+
return rows[i];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
};
|
|
268
|
+
var calculateZScore = (values, current) => {
|
|
269
|
+
const finite = values.filter(
|
|
270
|
+
(value) => typeof value === "number" && Number.isFinite(value)
|
|
271
|
+
);
|
|
272
|
+
if (current == null || finite.length < 3) return null;
|
|
273
|
+
const mean = finite.reduce((sum, value) => sum + value, 0) / finite.length;
|
|
274
|
+
const variance = finite.reduce((sum, value) => sum + (value - mean) ** 2, 0) / finite.length;
|
|
275
|
+
const std = Math.sqrt(variance);
|
|
276
|
+
if (!Number.isFinite(std) || std === 0) return 0;
|
|
277
|
+
return (current - mean) / std;
|
|
278
|
+
};
|
|
279
|
+
var calculateAverage = (values) => {
|
|
280
|
+
const finite = values.filter(
|
|
281
|
+
(value) => typeof value === "number" && Number.isFinite(value)
|
|
282
|
+
);
|
|
283
|
+
if (!finite.length) return null;
|
|
284
|
+
return finite.reduce((sum, value) => sum + value, 0) / finite.length;
|
|
285
|
+
};
|
|
286
|
+
var buildIntervalContext = (params) => {
|
|
287
|
+
const { interval, rows, timestamp, staleAfterMs } = params;
|
|
288
|
+
const normalizedRows = normalizeRows(rows, timestamp);
|
|
289
|
+
const latest = normalizedRows[normalizedRows.length - 1];
|
|
290
|
+
if (!latest) return null;
|
|
291
|
+
const openInterest = latest.openInterest;
|
|
292
|
+
const row1h = findRowAtOrBefore(normalizedRows, latest.tsMs - HOUR_MS);
|
|
293
|
+
const row4h = findRowAtOrBefore(normalizedRows, latest.tsMs - 4 * HOUR_MS);
|
|
294
|
+
const row24h = findRowAtOrBefore(normalizedRows, latest.tsMs - 24 * HOUR_MS);
|
|
295
|
+
const liqLong = latest.liqLong;
|
|
296
|
+
const liqShort = latest.liqShort;
|
|
297
|
+
const liqTotal = latest.liqTotal ?? (liqLong ?? 0) + (liqShort ?? 0);
|
|
298
|
+
const previousLiquidations = normalizedRows.slice(0, -1).map((row) => row.liqTotal ?? (row.liqLong ?? 0) + (row.liqShort ?? 0));
|
|
299
|
+
const avgPreviousLiquidations = calculateAverage(previousLiquidations);
|
|
300
|
+
const liqSpikeRatio = liqTotal != null && avgPreviousLiquidations != null && avgPreviousLiquidations > 0 ? liqTotal / avgPreviousLiquidations : null;
|
|
301
|
+
const liqImbalance = liqTotal != null && liqTotal > 0 ? ((liqShort ?? 0) - (liqLong ?? 0)) / liqTotal : null;
|
|
302
|
+
return {
|
|
303
|
+
interval,
|
|
304
|
+
asOfTs: latest.tsMs,
|
|
305
|
+
stale: timestamp - latest.tsMs > staleAfterMs,
|
|
306
|
+
points: normalizedRows.length,
|
|
307
|
+
openInterest: roundNullable(openInterest),
|
|
308
|
+
oiChangePct1h: roundNullable(
|
|
309
|
+
pctChange(openInterest, row1h?.openInterest ?? null),
|
|
310
|
+
4
|
|
311
|
+
),
|
|
312
|
+
oiChangePct4h: roundNullable(
|
|
313
|
+
pctChange(openInterest, row4h?.openInterest ?? null),
|
|
314
|
+
4
|
|
315
|
+
),
|
|
316
|
+
oiChangePct24h: roundNullable(
|
|
317
|
+
pctChange(openInterest, row24h?.openInterest ?? null),
|
|
318
|
+
4
|
|
319
|
+
),
|
|
320
|
+
fundingRate: roundNullable(latest.fundingRate, 8),
|
|
321
|
+
fundingZScore: roundNullable(
|
|
322
|
+
calculateZScore(
|
|
323
|
+
normalizedRows.map((row) => row.fundingRate),
|
|
324
|
+
latest.fundingRate
|
|
325
|
+
),
|
|
326
|
+
4
|
|
327
|
+
),
|
|
328
|
+
liqLong: roundNullable(liqLong),
|
|
329
|
+
liqShort: roundNullable(liqShort),
|
|
330
|
+
liqTotal: roundNullable(liqTotal),
|
|
331
|
+
liqImbalance: roundNullable(liqImbalance, 4),
|
|
332
|
+
liqSpikeRatio: roundNullable(liqSpikeRatio, 4)
|
|
333
|
+
};
|
|
334
|
+
};
|
|
335
|
+
var getPrimaryContext = (intervals) => intervals["15m"] ?? intervals["1h"] ?? null;
|
|
336
|
+
var isCrowdedLong = (context) => context.fundingRate != null && context.fundingRate >= 5e-4 || context.fundingZScore != null && context.fundingZScore >= 1.5;
|
|
337
|
+
var isCrowdedShort = (context) => context.fundingRate != null && context.fundingRate <= -5e-4 || context.fundingZScore != null && context.fundingZScore <= -1.5;
|
|
338
|
+
var hasLiquidationSpike = (context) => context.liqSpikeRatio != null && context.liqSpikeRatio >= 2;
|
|
339
|
+
var detectPressure = (context) => {
|
|
340
|
+
if (!context) return "neutral";
|
|
341
|
+
if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance <= -0.35) {
|
|
342
|
+
return "long_flush";
|
|
343
|
+
}
|
|
344
|
+
if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance >= 0.35) {
|
|
345
|
+
return "short_flush";
|
|
346
|
+
}
|
|
347
|
+
if (isCrowdedLong(context)) return "crowded_long";
|
|
348
|
+
if (isCrowdedShort(context)) return "crowded_short";
|
|
349
|
+
return "neutral";
|
|
350
|
+
};
|
|
351
|
+
var collectRiskFlags = (contexts) => {
|
|
352
|
+
const flags = /* @__PURE__ */ new Set();
|
|
353
|
+
if (!contexts.length) {
|
|
354
|
+
flags.add("missing_derivatives");
|
|
355
|
+
return [...flags];
|
|
356
|
+
}
|
|
357
|
+
if (contexts.some((context) => context.stale)) {
|
|
358
|
+
flags.add("stale_derivatives");
|
|
359
|
+
}
|
|
360
|
+
for (const context of contexts) {
|
|
361
|
+
if (isCrowdedLong(context)) flags.add("crowded_long");
|
|
362
|
+
if (isCrowdedShort(context)) flags.add("crowded_short");
|
|
363
|
+
if (context.oiChangePct1h != null && context.oiChangePct1h < -1) {
|
|
364
|
+
flags.add("oi_falling");
|
|
365
|
+
}
|
|
366
|
+
if (context.oiChangePct1h != null && Math.abs(context.oiChangePct1h) < 0.15) {
|
|
367
|
+
flags.add("oi_not_confirming");
|
|
368
|
+
}
|
|
369
|
+
if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance <= -0.35) {
|
|
370
|
+
flags.add("long_liquidation_spike");
|
|
371
|
+
}
|
|
372
|
+
if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance >= 0.35) {
|
|
373
|
+
flags.add("short_liquidation_spike");
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return [...flags];
|
|
377
|
+
};
|
|
378
|
+
var resolveDirectionAligned = (params) => {
|
|
379
|
+
const { direction, primary, pressure, riskFlags } = params;
|
|
380
|
+
if (!primary || primary.stale || riskFlags.includes("missing_derivatives")) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
if (direction === "LONG") {
|
|
384
|
+
if (pressure === "crowded_long" || riskFlags.includes("oi_falling")) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
if (pressure === "short_flush" || primary.oiChangePct1h != null && primary.oiChangePct1h > 0.25 && !riskFlags.includes("crowded_long")) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
if (pressure === "crowded_short" || riskFlags.includes("oi_falling")) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
if (pressure === "long_flush" || primary.oiChangePct1h != null && primary.oiChangePct1h > 0.25 && !riskFlags.includes("crowded_short")) {
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
return null;
|
|
399
|
+
};
|
|
400
|
+
var buildDerivativesContext = (params) => {
|
|
401
|
+
const {
|
|
402
|
+
symbol,
|
|
403
|
+
direction,
|
|
404
|
+
timestamp,
|
|
405
|
+
rowsByInterval,
|
|
406
|
+
intervals = DERIVATIVES_INTERVALS,
|
|
407
|
+
staleAfterMsByInterval = {}
|
|
408
|
+
} = params;
|
|
409
|
+
const intervalContexts = {};
|
|
410
|
+
for (const interval of intervals) {
|
|
411
|
+
const context = buildIntervalContext({
|
|
412
|
+
interval,
|
|
413
|
+
rows: rowsByInterval[interval],
|
|
414
|
+
timestamp,
|
|
415
|
+
staleAfterMs: staleAfterMsByInterval[interval] ?? DEFAULT_STALE_AFTER_MS[interval]
|
|
416
|
+
});
|
|
417
|
+
if (context) {
|
|
418
|
+
intervalContexts[interval] = context;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
const contexts = Object.values(intervalContexts);
|
|
422
|
+
const primary = getPrimaryContext(intervalContexts);
|
|
423
|
+
const pressure = detectPressure(primary);
|
|
424
|
+
const riskFlags = collectRiskFlags(contexts);
|
|
425
|
+
return {
|
|
426
|
+
source: "coinalyze",
|
|
427
|
+
symbol,
|
|
428
|
+
timestamp,
|
|
429
|
+
intervals: intervalContexts,
|
|
430
|
+
summary: {
|
|
431
|
+
pressure,
|
|
432
|
+
directionAligned: resolveDirectionAligned({
|
|
433
|
+
direction,
|
|
434
|
+
primary,
|
|
435
|
+
pressure,
|
|
436
|
+
riskFlags
|
|
437
|
+
}),
|
|
438
|
+
riskFlags
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
};
|
|
442
|
+
|
|
214
443
|
// src/utils/indicators.ts
|
|
215
444
|
import { SMA, ATR, BollingerBands, OBV, MACD } from "technicalindicators";
|
|
216
445
|
|
|
@@ -406,6 +635,17 @@ var DEFAULT_INDICATOR_PERIODS = {
|
|
|
406
635
|
levelLookback: 20,
|
|
407
636
|
levelDelay: 2
|
|
408
637
|
};
|
|
638
|
+
var resolveIndicatorPeriods = (periods = {}) => {
|
|
639
|
+
const resolved = {
|
|
640
|
+
...DEFAULT_INDICATOR_PERIODS
|
|
641
|
+
};
|
|
642
|
+
for (const [key, value] of Object.entries(periods)) {
|
|
643
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
644
|
+
resolved[key] = value;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return resolved;
|
|
648
|
+
};
|
|
409
649
|
var ONE_HOUR_MS = 36e5;
|
|
410
650
|
var ONE_DAY_MS = 864e5;
|
|
411
651
|
var toMlCandle = (candle) => ({
|
|
@@ -488,10 +728,7 @@ var createIndicators = (data, btcData = [], options = {}) => {
|
|
|
488
728
|
options.pluginRegistryScope
|
|
489
729
|
);
|
|
490
730
|
const includeMlPayload = options.includeMlPayload !== false;
|
|
491
|
-
const indicatorPeriods =
|
|
492
|
-
...DEFAULT_INDICATOR_PERIODS,
|
|
493
|
-
...options.periods || {}
|
|
494
|
-
};
|
|
731
|
+
const indicatorPeriods = resolveIndicatorPeriods(options.periods);
|
|
495
732
|
const closes = [];
|
|
496
733
|
const highs = [];
|
|
497
734
|
const lows = [];
|
|
@@ -820,10 +1057,7 @@ var createIndicators = (data, btcData = [], options = {}) => {
|
|
|
820
1057
|
};
|
|
821
1058
|
var buildMlTimeframeIndicators = (candles, periods = {}) => {
|
|
822
1059
|
const result = {};
|
|
823
|
-
const indicatorPeriods =
|
|
824
|
-
...DEFAULT_INDICATOR_PERIODS,
|
|
825
|
-
...periods
|
|
826
|
-
};
|
|
1060
|
+
const indicatorPeriods = resolveIndicatorPeriods(periods);
|
|
827
1061
|
for (const timeframe of INDICATOR_TIMEFRAMES) {
|
|
828
1062
|
const tfCandles = resampleCandles(candles, timeframe.minutes);
|
|
829
1063
|
if (tfCandles.length === 0) continue;
|
|
@@ -1522,8 +1756,14 @@ var createTrendlineEngine = (initialCandles, options) => {
|
|
|
1522
1756
|
return result;
|
|
1523
1757
|
};
|
|
1524
1758
|
const nextMany = (candles) => {
|
|
1525
|
-
|
|
1526
|
-
|
|
1759
|
+
for (const candle of candles) {
|
|
1760
|
+
appendCandle(candle);
|
|
1761
|
+
}
|
|
1762
|
+
let result = buildResult();
|
|
1763
|
+
if (opts.capture && result.length === 0 && rawExtremaPoints.length) {
|
|
1764
|
+
rebuildCandidatesLikeBatch();
|
|
1765
|
+
result = buildResult();
|
|
1766
|
+
}
|
|
1527
1767
|
return result;
|
|
1528
1768
|
};
|
|
1529
1769
|
const getLines = () => buildResult();
|
|
@@ -1548,6 +1788,7 @@ export {
|
|
|
1548
1788
|
toArrayData,
|
|
1549
1789
|
mergeCoinalyzeMetrics,
|
|
1550
1790
|
coinalyzePointsToRows,
|
|
1791
|
+
buildDerivativesContext,
|
|
1551
1792
|
registerIndicatorEntries,
|
|
1552
1793
|
getRegisteredIndicatorEntries,
|
|
1553
1794
|
getPluginIndicatorCatalog,
|
|
@@ -4,7 +4,9 @@ var CORRELATION_WINDOW = 50;
|
|
|
4
4
|
var SPREAD_WINDOW = 50;
|
|
5
5
|
var PRELOAD_DAYS = 200;
|
|
6
6
|
var SIGNALS_PRELOAD_DAYS = 60;
|
|
7
|
-
var
|
|
7
|
+
var SIGNALS_CLI_PRELOAD_DAYS = 10;
|
|
8
|
+
var BACKTEST_DEFAULT_DAYS = 160;
|
|
9
|
+
var BACKTEST_PRELOAD_DAYS = 60;
|
|
8
10
|
var DASHBOARD_PRELOAD_DAYS = 160;
|
|
9
11
|
var BOT_PRELOAD_DAYS = 160;
|
|
10
12
|
var PRELOAD_FALLBACK_DAYS = 160;
|
|
@@ -12,6 +14,7 @@ var TTL_1H = 3600;
|
|
|
12
14
|
var TTL_3H = 10800;
|
|
13
15
|
var TTL_12H = 43300;
|
|
14
16
|
var TTL_1D = 86400;
|
|
17
|
+
var TTL_3D = 259200;
|
|
15
18
|
var TTL_1M = 26e5;
|
|
16
19
|
var TTL_3M = 78e5;
|
|
17
20
|
var TESTS_TOP_LIMIT = 50;
|
|
@@ -20,6 +23,10 @@ var TESTS_ORDERS_MIN_LIMIT = 3;
|
|
|
20
23
|
var MARKET_CATEGORY = "linear";
|
|
21
24
|
var ML_CANDLE_FEATURE_WINDOW = 50;
|
|
22
25
|
var ML_BASE_CANDLES_WINDOW = 50;
|
|
26
|
+
var DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS = [
|
|
27
|
+
"BTCUSDT",
|
|
28
|
+
"ETHUSDT"
|
|
29
|
+
];
|
|
23
30
|
var TRENDLINE_DEFAULTS = {
|
|
24
31
|
maxLines: 20,
|
|
25
32
|
range: 15,
|
|
@@ -169,6 +176,8 @@ export {
|
|
|
169
176
|
SPREAD_WINDOW,
|
|
170
177
|
PRELOAD_DAYS,
|
|
171
178
|
SIGNALS_PRELOAD_DAYS,
|
|
179
|
+
SIGNALS_CLI_PRELOAD_DAYS,
|
|
180
|
+
BACKTEST_DEFAULT_DAYS,
|
|
172
181
|
BACKTEST_PRELOAD_DAYS,
|
|
173
182
|
DASHBOARD_PRELOAD_DAYS,
|
|
174
183
|
BOT_PRELOAD_DAYS,
|
|
@@ -177,6 +186,7 @@ export {
|
|
|
177
186
|
TTL_3H,
|
|
178
187
|
TTL_12H,
|
|
179
188
|
TTL_1D,
|
|
189
|
+
TTL_3D,
|
|
180
190
|
TTL_1M,
|
|
181
191
|
TTL_3M,
|
|
182
192
|
TESTS_TOP_LIMIT,
|
|
@@ -185,6 +195,7 @@ export {
|
|
|
185
195
|
MARKET_CATEGORY,
|
|
186
196
|
ML_CANDLE_FEATURE_WINDOW,
|
|
187
197
|
ML_BASE_CANDLES_WINDOW,
|
|
198
|
+
DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS,
|
|
188
199
|
TRENDLINE_DEFAULTS,
|
|
189
200
|
TestThresholdsConfig
|
|
190
201
|
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
BACKTEST_DEFAULT_DAYS,
|
|
2
3
|
BACKTEST_PRELOAD_DAYS
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JLORHLL6.mjs";
|
|
4
5
|
|
|
5
6
|
// src/utils/timestamp.ts
|
|
6
7
|
import { format } from "date-fns";
|
|
7
8
|
import { getUnixTime, subDays } from "date-fns";
|
|
8
9
|
var TIMELINE_STEP = 864e5;
|
|
10
|
+
var DAY_MS = 864e5;
|
|
9
11
|
var toMs = (ts) => ts < 1e12 ? ts * 1e3 : ts;
|
|
10
12
|
var getTimestamp = (days = 0) => {
|
|
11
13
|
if (days > 0) {
|
|
@@ -23,7 +25,8 @@ var getDataTimestamp = (data) => {
|
|
|
23
25
|
var formatUnix = (dt) => {
|
|
24
26
|
return format(new Date(dt), "d MMM u HH:mm:ss");
|
|
25
27
|
};
|
|
26
|
-
var
|
|
28
|
+
var getBacktestPreloadStart = (start, preloadDays = BACKTEST_PRELOAD_DAYS) => Math.max(0, Math.trunc(start - preloadDays * DAY_MS));
|
|
29
|
+
var getTimeline = (start = getTimestamp(BACKTEST_DEFAULT_DAYS), end = getTimestamp(), step = TIMELINE_STEP) => {
|
|
27
30
|
const res = new Array();
|
|
28
31
|
for (let ind = start; ind <= end; ind += step) {
|
|
29
32
|
res.push(ind);
|
|
@@ -62,6 +65,7 @@ export {
|
|
|
62
65
|
getItemTimestamp,
|
|
63
66
|
getDataTimestamp,
|
|
64
67
|
formatUnix,
|
|
68
|
+
getBacktestPreloadStart,
|
|
65
69
|
getTimeline,
|
|
66
70
|
compactOrderLog
|
|
67
71
|
};
|
package/dist/config.d.mts
CHANGED
|
@@ -1,14 +1,61 @@
|
|
|
1
|
-
import { ConnectorPluginDefinition, IndicatorPluginDefinition, StrategyPluginDefinition } from '@tradejs/types';
|
|
1
|
+
import { Connector, Interval, StrategyConfig, Signal, StrategyManifest, StrategyHookBarContext, StrategyDecision, StrategyHookAfterDecisionContext, ConnectorPluginDefinition, IndicatorPluginDefinition, StrategyPluginDefinition } from '@tradejs/types';
|
|
2
2
|
|
|
3
3
|
type PluginModuleSpecifier = string;
|
|
4
|
+
type StrategyManifestHooks = NonNullable<StrategyManifest['hooks']>;
|
|
5
|
+
type HookOrHooks<THook> = THook | THook[];
|
|
6
|
+
type TradejsConfigAfterCoreDecisionHook = (params: StrategyHookAfterDecisionContext) => Promise<StrategyDecision | void> | StrategyDecision | void;
|
|
7
|
+
type TradejsConfigAfterBarDecisionHook = (params: StrategyHookAfterDecisionContext) => Promise<StrategyDecision | void> | StrategyDecision | void;
|
|
8
|
+
type TradejsConfigOnBarHook = (params: StrategyHookBarContext) => Promise<StrategyDecision | void> | StrategyDecision | void;
|
|
9
|
+
interface TradejsConfigSignalsRuntimeStrategy {
|
|
10
|
+
strategyName: string;
|
|
11
|
+
strategyConfig: StrategyConfig;
|
|
12
|
+
}
|
|
13
|
+
interface TradejsConfigSignalsHookContext {
|
|
14
|
+
connector: Connector;
|
|
15
|
+
connectorName: string;
|
|
16
|
+
userName: string;
|
|
17
|
+
interval: Interval;
|
|
18
|
+
tickers: string[];
|
|
19
|
+
runtimeStrategies: TradejsConfigSignalsRuntimeStrategy[];
|
|
20
|
+
}
|
|
21
|
+
interface TradejsConfigBeforeSignalsHookResult {
|
|
22
|
+
abort?: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}
|
|
25
|
+
interface TradejsConfigAfterSignalsHookContext extends TradejsConfigSignalsHookContext {
|
|
26
|
+
signals: Signal[];
|
|
27
|
+
status: 'completed' | 'failed';
|
|
28
|
+
durationMs: number;
|
|
29
|
+
}
|
|
30
|
+
type TradejsConfigBeforeSignalsHook = (params: TradejsConfigSignalsHookContext) => Promise<TradejsConfigBeforeSignalsHookResult | void> | TradejsConfigBeforeSignalsHookResult | void;
|
|
31
|
+
type TradejsConfigAfterSignalsHook = (params: TradejsConfigAfterSignalsHookContext) => Promise<void> | void;
|
|
32
|
+
interface TradejsConfigHooks {
|
|
33
|
+
beforeSignals?: HookOrHooks<TradejsConfigBeforeSignalsHook>;
|
|
34
|
+
afterSignals?: HookOrHooks<TradejsConfigAfterSignalsHook>;
|
|
35
|
+
onInit?: HookOrHooks<NonNullable<StrategyManifestHooks['onInit']>>;
|
|
36
|
+
onBar?: HookOrHooks<TradejsConfigOnBarHook>;
|
|
37
|
+
afterCoreDecision?: HookOrHooks<TradejsConfigAfterCoreDecisionHook>;
|
|
38
|
+
afterBarDecision?: HookOrHooks<TradejsConfigAfterBarDecisionHook>;
|
|
39
|
+
onSkip?: HookOrHooks<NonNullable<StrategyManifestHooks['onSkip']>>;
|
|
40
|
+
beforeClosePosition?: HookOrHooks<NonNullable<StrategyManifestHooks['beforeClosePosition']>>;
|
|
41
|
+
afterEnrichMl?: HookOrHooks<NonNullable<StrategyManifestHooks['afterEnrichMl']>>;
|
|
42
|
+
afterEnrichAi?: HookOrHooks<NonNullable<StrategyManifestHooks['afterEnrichAi']>>;
|
|
43
|
+
beforeEntryGate?: HookOrHooks<NonNullable<StrategyManifestHooks['beforeEntryGate']>>;
|
|
44
|
+
beforePlaceOrder?: HookOrHooks<NonNullable<StrategyManifestHooks['beforePlaceOrder']>>;
|
|
45
|
+
afterPlaceOrder?: HookOrHooks<NonNullable<StrategyManifestHooks['afterPlaceOrder']>>;
|
|
46
|
+
onRuntimeError?: HookOrHooks<NonNullable<StrategyManifestHooks['onRuntimeError']>>;
|
|
47
|
+
}
|
|
4
48
|
interface TradejsConfig {
|
|
5
49
|
strategies?: PluginModuleSpecifier[];
|
|
6
50
|
indicators?: PluginModuleSpecifier[];
|
|
7
51
|
connectors?: PluginModuleSpecifier[];
|
|
52
|
+
hooks?: TradejsConfigHooks;
|
|
8
53
|
}
|
|
54
|
+
declare const mergeTradejsConfigHooks: (...groups: Array<TradejsConfigHooks | undefined>) => TradejsConfigHooks | undefined;
|
|
55
|
+
declare const normalizeTradejsConfigHooks: (hooks?: TradejsConfigHooks) => TradejsConfigHooks | undefined;
|
|
9
56
|
declare function defineConfig(...configs: TradejsConfig[]): TradejsConfig;
|
|
10
57
|
declare const defineStrategyPlugin: <T extends StrategyPluginDefinition>(plugin: T) => T;
|
|
11
58
|
declare const defineIndicatorPlugin: <T extends IndicatorPluginDefinition>(plugin: T) => T;
|
|
12
59
|
declare const defineConnectorPlugin: <T extends ConnectorPluginDefinition>(plugin: T) => T;
|
|
13
60
|
|
|
14
|
-
export { type PluginModuleSpecifier, type TradejsConfig, defineConfig, defineConnectorPlugin, defineIndicatorPlugin, defineStrategyPlugin };
|
|
61
|
+
export { type PluginModuleSpecifier, type TradejsConfig, type TradejsConfigAfterBarDecisionHook, type TradejsConfigAfterCoreDecisionHook, type TradejsConfigAfterSignalsHook, type TradejsConfigAfterSignalsHookContext, type TradejsConfigBeforeSignalsHook, type TradejsConfigBeforeSignalsHookResult, type TradejsConfigHooks, type TradejsConfigOnBarHook, type TradejsConfigSignalsHookContext, type TradejsConfigSignalsRuntimeStrategy, defineConfig, defineConnectorPlugin, defineIndicatorPlugin, defineStrategyPlugin, mergeTradejsConfigHooks, normalizeTradejsConfigHooks };
|
package/dist/config.d.ts
CHANGED
|
@@ -1,14 +1,61 @@
|
|
|
1
|
-
import { ConnectorPluginDefinition, IndicatorPluginDefinition, StrategyPluginDefinition } from '@tradejs/types';
|
|
1
|
+
import { Connector, Interval, StrategyConfig, Signal, StrategyManifest, StrategyHookBarContext, StrategyDecision, StrategyHookAfterDecisionContext, ConnectorPluginDefinition, IndicatorPluginDefinition, StrategyPluginDefinition } from '@tradejs/types';
|
|
2
2
|
|
|
3
3
|
type PluginModuleSpecifier = string;
|
|
4
|
+
type StrategyManifestHooks = NonNullable<StrategyManifest['hooks']>;
|
|
5
|
+
type HookOrHooks<THook> = THook | THook[];
|
|
6
|
+
type TradejsConfigAfterCoreDecisionHook = (params: StrategyHookAfterDecisionContext) => Promise<StrategyDecision | void> | StrategyDecision | void;
|
|
7
|
+
type TradejsConfigAfterBarDecisionHook = (params: StrategyHookAfterDecisionContext) => Promise<StrategyDecision | void> | StrategyDecision | void;
|
|
8
|
+
type TradejsConfigOnBarHook = (params: StrategyHookBarContext) => Promise<StrategyDecision | void> | StrategyDecision | void;
|
|
9
|
+
interface TradejsConfigSignalsRuntimeStrategy {
|
|
10
|
+
strategyName: string;
|
|
11
|
+
strategyConfig: StrategyConfig;
|
|
12
|
+
}
|
|
13
|
+
interface TradejsConfigSignalsHookContext {
|
|
14
|
+
connector: Connector;
|
|
15
|
+
connectorName: string;
|
|
16
|
+
userName: string;
|
|
17
|
+
interval: Interval;
|
|
18
|
+
tickers: string[];
|
|
19
|
+
runtimeStrategies: TradejsConfigSignalsRuntimeStrategy[];
|
|
20
|
+
}
|
|
21
|
+
interface TradejsConfigBeforeSignalsHookResult {
|
|
22
|
+
abort?: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}
|
|
25
|
+
interface TradejsConfigAfterSignalsHookContext extends TradejsConfigSignalsHookContext {
|
|
26
|
+
signals: Signal[];
|
|
27
|
+
status: 'completed' | 'failed';
|
|
28
|
+
durationMs: number;
|
|
29
|
+
}
|
|
30
|
+
type TradejsConfigBeforeSignalsHook = (params: TradejsConfigSignalsHookContext) => Promise<TradejsConfigBeforeSignalsHookResult | void> | TradejsConfigBeforeSignalsHookResult | void;
|
|
31
|
+
type TradejsConfigAfterSignalsHook = (params: TradejsConfigAfterSignalsHookContext) => Promise<void> | void;
|
|
32
|
+
interface TradejsConfigHooks {
|
|
33
|
+
beforeSignals?: HookOrHooks<TradejsConfigBeforeSignalsHook>;
|
|
34
|
+
afterSignals?: HookOrHooks<TradejsConfigAfterSignalsHook>;
|
|
35
|
+
onInit?: HookOrHooks<NonNullable<StrategyManifestHooks['onInit']>>;
|
|
36
|
+
onBar?: HookOrHooks<TradejsConfigOnBarHook>;
|
|
37
|
+
afterCoreDecision?: HookOrHooks<TradejsConfigAfterCoreDecisionHook>;
|
|
38
|
+
afterBarDecision?: HookOrHooks<TradejsConfigAfterBarDecisionHook>;
|
|
39
|
+
onSkip?: HookOrHooks<NonNullable<StrategyManifestHooks['onSkip']>>;
|
|
40
|
+
beforeClosePosition?: HookOrHooks<NonNullable<StrategyManifestHooks['beforeClosePosition']>>;
|
|
41
|
+
afterEnrichMl?: HookOrHooks<NonNullable<StrategyManifestHooks['afterEnrichMl']>>;
|
|
42
|
+
afterEnrichAi?: HookOrHooks<NonNullable<StrategyManifestHooks['afterEnrichAi']>>;
|
|
43
|
+
beforeEntryGate?: HookOrHooks<NonNullable<StrategyManifestHooks['beforeEntryGate']>>;
|
|
44
|
+
beforePlaceOrder?: HookOrHooks<NonNullable<StrategyManifestHooks['beforePlaceOrder']>>;
|
|
45
|
+
afterPlaceOrder?: HookOrHooks<NonNullable<StrategyManifestHooks['afterPlaceOrder']>>;
|
|
46
|
+
onRuntimeError?: HookOrHooks<NonNullable<StrategyManifestHooks['onRuntimeError']>>;
|
|
47
|
+
}
|
|
4
48
|
interface TradejsConfig {
|
|
5
49
|
strategies?: PluginModuleSpecifier[];
|
|
6
50
|
indicators?: PluginModuleSpecifier[];
|
|
7
51
|
connectors?: PluginModuleSpecifier[];
|
|
52
|
+
hooks?: TradejsConfigHooks;
|
|
8
53
|
}
|
|
54
|
+
declare const mergeTradejsConfigHooks: (...groups: Array<TradejsConfigHooks | undefined>) => TradejsConfigHooks | undefined;
|
|
55
|
+
declare const normalizeTradejsConfigHooks: (hooks?: TradejsConfigHooks) => TradejsConfigHooks | undefined;
|
|
9
56
|
declare function defineConfig(...configs: TradejsConfig[]): TradejsConfig;
|
|
10
57
|
declare const defineStrategyPlugin: <T extends StrategyPluginDefinition>(plugin: T) => T;
|
|
11
58
|
declare const defineIndicatorPlugin: <T extends IndicatorPluginDefinition>(plugin: T) => T;
|
|
12
59
|
declare const defineConnectorPlugin: <T extends ConnectorPluginDefinition>(plugin: T) => T;
|
|
13
60
|
|
|
14
|
-
export { type PluginModuleSpecifier, type TradejsConfig, defineConfig, defineConnectorPlugin, defineIndicatorPlugin, defineStrategyPlugin };
|
|
61
|
+
export { type PluginModuleSpecifier, type TradejsConfig, type TradejsConfigAfterBarDecisionHook, type TradejsConfigAfterCoreDecisionHook, type TradejsConfigAfterSignalsHook, type TradejsConfigAfterSignalsHookContext, type TradejsConfigBeforeSignalsHook, type TradejsConfigBeforeSignalsHookResult, type TradejsConfigHooks, type TradejsConfigOnBarHook, type TradejsConfigSignalsHookContext, type TradejsConfigSignalsRuntimeStrategy, defineConfig, defineConnectorPlugin, defineIndicatorPlugin, defineStrategyPlugin, mergeTradejsConfigHooks, normalizeTradejsConfigHooks };
|