@tradejs/core 1.0.6 → 1.0.9

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/config.mjs CHANGED
@@ -3,11 +3,44 @@ var normalizePlugins = (values) => Array.isArray(values) ? values.map((value) =>
3
3
  var mergePluginSpecifiers = (...groups) => [
4
4
  ...new Set(groups.flatMap((group) => normalizePlugins(group)))
5
5
  ];
6
+ var normalizeHookList = (value) => {
7
+ if (Array.isArray(value)) {
8
+ return value.filter((item) => typeof item === "function");
9
+ }
10
+ return typeof value === "function" ? [value] : [];
11
+ };
12
+ var mergeHookLists = (...groups) => [...new Set(groups.flatMap((group) => normalizeHookList(group)))];
13
+ var setMergedHook = (key, groups, target) => {
14
+ const merged = mergeHookLists(...groups.map((group) => group?.[key]));
15
+ if (merged.length > 0) {
16
+ target[key] = merged;
17
+ }
18
+ };
19
+ var mergeTradejsConfigHooks = (...groups) => {
20
+ const hooks = {};
21
+ setMergedHook("beforeSignals", groups, hooks);
22
+ setMergedHook("afterSignals", groups, hooks);
23
+ setMergedHook("onInit", groups, hooks);
24
+ setMergedHook("onBar", groups, hooks);
25
+ setMergedHook("afterCoreDecision", groups, hooks);
26
+ setMergedHook("afterBarDecision", groups, hooks);
27
+ setMergedHook("onSkip", groups, hooks);
28
+ setMergedHook("beforeClosePosition", groups, hooks);
29
+ setMergedHook("afterEnrichMl", groups, hooks);
30
+ setMergedHook("afterEnrichAi", groups, hooks);
31
+ setMergedHook("beforeEntryGate", groups, hooks);
32
+ setMergedHook("beforePlaceOrder", groups, hooks);
33
+ setMergedHook("afterPlaceOrder", groups, hooks);
34
+ setMergedHook("onRuntimeError", groups, hooks);
35
+ return Object.keys(hooks).length > 0 ? hooks : void 0;
36
+ };
37
+ var normalizeTradejsConfigHooks = (hooks) => mergeTradejsConfigHooks(hooks);
6
38
  function defineConfig(...configs) {
7
39
  return {
8
40
  strategies: mergePluginSpecifiers(...configs.map((cfg) => cfg.strategies)),
9
41
  indicators: mergePluginSpecifiers(...configs.map((cfg) => cfg.indicators)),
10
- connectors: mergePluginSpecifiers(...configs.map((cfg) => cfg.connectors))
42
+ connectors: mergePluginSpecifiers(...configs.map((cfg) => cfg.connectors)),
43
+ hooks: mergeTradejsConfigHooks(...configs.map((cfg) => cfg.hooks))
11
44
  };
12
45
  }
13
46
  var defineStrategyPlugin = (plugin) => plugin;
@@ -17,5 +50,7 @@ export {
17
50
  defineConfig,
18
51
  defineConnectorPlugin,
19
52
  defineIndicatorPlugin,
20
- defineStrategyPlugin
53
+ defineStrategyPlugin,
54
+ mergeTradejsConfigHooks,
55
+ normalizeTradejsConfigHooks
21
56
  };
@@ -6,7 +6,8 @@ declare const SPREAD_WINDOW = 50;
6
6
  declare const PRELOAD_DAYS = 200;
7
7
  declare const SIGNALS_PRELOAD_DAYS = 60;
8
8
  declare const SIGNALS_CLI_PRELOAD_DAYS = 10;
9
- declare const BACKTEST_PRELOAD_DAYS = 160;
9
+ declare const BACKTEST_DEFAULT_DAYS = 160;
10
+ declare const BACKTEST_PRELOAD_DAYS = 60;
10
11
  declare const DASHBOARD_PRELOAD_DAYS = 160;
11
12
  declare const BOT_PRELOAD_DAYS = 160;
12
13
  declare const PRELOAD_FALLBACK_DAYS = 160;
@@ -14,6 +15,8 @@ declare const TTL_1H = 3600;
14
15
  declare const TTL_3H = 10800;
15
16
  declare const TTL_12H = 43300;
16
17
  declare const TTL_1D = 86400;
18
+ declare const TTL_3D = 259200;
19
+ declare const TTL_10D = 864000;
17
20
  declare const TTL_1M = 2600000;
18
21
  declare const TTL_3M = 7800000;
19
22
  declare const TESTS_TOP_LIMIT = 50;
@@ -22,6 +25,7 @@ declare const TESTS_ORDERS_MIN_LIMIT = 3;
22
25
  declare const MARKET_CATEGORY = "linear";
23
26
  declare const ML_CANDLE_FEATURE_WINDOW = 50;
24
27
  declare const ML_BASE_CANDLES_WINDOW = 50;
28
+ declare const DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS: readonly ["BTCUSDT", "ETHUSDT"];
25
29
  declare const TRENDLINE_DEFAULTS: {
26
30
  maxLines: number;
27
31
  range: number;
@@ -39,4 +43,4 @@ declare const TRENDLINE_DEFAULTS: {
39
43
  };
40
44
  declare const TestThresholdsConfig: TestThresholds;
41
45
 
42
- export { BACKTEST_PRELOAD_DAYS, BOT_PRELOAD_DAYS, CORRELATION_WINDOW, DASHBOARD_PRELOAD_DAYS, FEE_PERCENT, MARKET_CATEGORY, ML_BASE_CANDLES_WINDOW, ML_CANDLE_FEATURE_WINDOW, PRELOAD_DAYS, PRELOAD_FALLBACK_DAYS, SIGNALS_CLI_PRELOAD_DAYS, SIGNALS_PRELOAD_DAYS, SPREAD_WINDOW, TESTS_LIMIT, TESTS_ORDERS_MIN_LIMIT, TESTS_TOP_LIMIT, TRENDLINE_DEFAULTS, TTL_12H, TTL_1D, TTL_1H, TTL_1M, TTL_3H, TTL_3M, TestThresholdsConfig };
46
+ export { BACKTEST_DEFAULT_DAYS, BACKTEST_PRELOAD_DAYS, BOT_PRELOAD_DAYS, CORRELATION_WINDOW, DASHBOARD_PRELOAD_DAYS, DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS, FEE_PERCENT, MARKET_CATEGORY, ML_BASE_CANDLES_WINDOW, ML_CANDLE_FEATURE_WINDOW, PRELOAD_DAYS, PRELOAD_FALLBACK_DAYS, SIGNALS_CLI_PRELOAD_DAYS, SIGNALS_PRELOAD_DAYS, SPREAD_WINDOW, TESTS_LIMIT, TESTS_ORDERS_MIN_LIMIT, TESTS_TOP_LIMIT, TRENDLINE_DEFAULTS, TTL_10D, TTL_12H, TTL_1D, TTL_1H, TTL_1M, TTL_3D, TTL_3H, TTL_3M, TestThresholdsConfig };
@@ -6,7 +6,8 @@ declare const SPREAD_WINDOW = 50;
6
6
  declare const PRELOAD_DAYS = 200;
7
7
  declare const SIGNALS_PRELOAD_DAYS = 60;
8
8
  declare const SIGNALS_CLI_PRELOAD_DAYS = 10;
9
- declare const BACKTEST_PRELOAD_DAYS = 160;
9
+ declare const BACKTEST_DEFAULT_DAYS = 160;
10
+ declare const BACKTEST_PRELOAD_DAYS = 60;
10
11
  declare const DASHBOARD_PRELOAD_DAYS = 160;
11
12
  declare const BOT_PRELOAD_DAYS = 160;
12
13
  declare const PRELOAD_FALLBACK_DAYS = 160;
@@ -14,6 +15,8 @@ declare const TTL_1H = 3600;
14
15
  declare const TTL_3H = 10800;
15
16
  declare const TTL_12H = 43300;
16
17
  declare const TTL_1D = 86400;
18
+ declare const TTL_3D = 259200;
19
+ declare const TTL_10D = 864000;
17
20
  declare const TTL_1M = 2600000;
18
21
  declare const TTL_3M = 7800000;
19
22
  declare const TESTS_TOP_LIMIT = 50;
@@ -22,6 +25,7 @@ declare const TESTS_ORDERS_MIN_LIMIT = 3;
22
25
  declare const MARKET_CATEGORY = "linear";
23
26
  declare const ML_CANDLE_FEATURE_WINDOW = 50;
24
27
  declare const ML_BASE_CANDLES_WINDOW = 50;
28
+ declare const DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS: readonly ["BTCUSDT", "ETHUSDT"];
25
29
  declare const TRENDLINE_DEFAULTS: {
26
30
  maxLines: number;
27
31
  range: number;
@@ -39,4 +43,4 @@ declare const TRENDLINE_DEFAULTS: {
39
43
  };
40
44
  declare const TestThresholdsConfig: TestThresholds;
41
45
 
42
- export { BACKTEST_PRELOAD_DAYS, BOT_PRELOAD_DAYS, CORRELATION_WINDOW, DASHBOARD_PRELOAD_DAYS, FEE_PERCENT, MARKET_CATEGORY, ML_BASE_CANDLES_WINDOW, ML_CANDLE_FEATURE_WINDOW, PRELOAD_DAYS, PRELOAD_FALLBACK_DAYS, SIGNALS_CLI_PRELOAD_DAYS, SIGNALS_PRELOAD_DAYS, SPREAD_WINDOW, TESTS_LIMIT, TESTS_ORDERS_MIN_LIMIT, TESTS_TOP_LIMIT, TRENDLINE_DEFAULTS, TTL_12H, TTL_1D, TTL_1H, TTL_1M, TTL_3H, TTL_3M, TestThresholdsConfig };
46
+ export { BACKTEST_DEFAULT_DAYS, BACKTEST_PRELOAD_DAYS, BOT_PRELOAD_DAYS, CORRELATION_WINDOW, DASHBOARD_PRELOAD_DAYS, DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS, FEE_PERCENT, MARKET_CATEGORY, ML_BASE_CANDLES_WINDOW, ML_CANDLE_FEATURE_WINDOW, PRELOAD_DAYS, PRELOAD_FALLBACK_DAYS, SIGNALS_CLI_PRELOAD_DAYS, SIGNALS_PRELOAD_DAYS, SPREAD_WINDOW, TESTS_LIMIT, TESTS_ORDERS_MIN_LIMIT, TESTS_TOP_LIMIT, TRENDLINE_DEFAULTS, TTL_10D, TTL_12H, TTL_1D, TTL_1H, TTL_1M, TTL_3D, TTL_3H, TTL_3M, TestThresholdsConfig };
package/dist/constants.js CHANGED
@@ -20,10 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/constants.ts
21
21
  var constants_exports = {};
22
22
  __export(constants_exports, {
23
+ BACKTEST_DEFAULT_DAYS: () => BACKTEST_DEFAULT_DAYS,
23
24
  BACKTEST_PRELOAD_DAYS: () => BACKTEST_PRELOAD_DAYS,
24
25
  BOT_PRELOAD_DAYS: () => BOT_PRELOAD_DAYS,
25
26
  CORRELATION_WINDOW: () => CORRELATION_WINDOW,
26
27
  DASHBOARD_PRELOAD_DAYS: () => DASHBOARD_PRELOAD_DAYS,
28
+ DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS: () => DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS,
27
29
  FEE_PERCENT: () => FEE_PERCENT,
28
30
  MARKET_CATEGORY: () => MARKET_CATEGORY,
29
31
  ML_BASE_CANDLES_WINDOW: () => ML_BASE_CANDLES_WINDOW,
@@ -37,10 +39,12 @@ __export(constants_exports, {
37
39
  TESTS_ORDERS_MIN_LIMIT: () => TESTS_ORDERS_MIN_LIMIT,
38
40
  TESTS_TOP_LIMIT: () => TESTS_TOP_LIMIT,
39
41
  TRENDLINE_DEFAULTS: () => TRENDLINE_DEFAULTS,
42
+ TTL_10D: () => TTL_10D,
40
43
  TTL_12H: () => TTL_12H,
41
44
  TTL_1D: () => TTL_1D,
42
45
  TTL_1H: () => TTL_1H,
43
46
  TTL_1M: () => TTL_1M,
47
+ TTL_3D: () => TTL_3D,
44
48
  TTL_3H: () => TTL_3H,
45
49
  TTL_3M: () => TTL_3M,
46
50
  TestThresholdsConfig: () => TestThresholdsConfig
@@ -54,7 +58,8 @@ var SPREAD_WINDOW = 50;
54
58
  var PRELOAD_DAYS = 200;
55
59
  var SIGNALS_PRELOAD_DAYS = 60;
56
60
  var SIGNALS_CLI_PRELOAD_DAYS = 10;
57
- var BACKTEST_PRELOAD_DAYS = 160;
61
+ var BACKTEST_DEFAULT_DAYS = 160;
62
+ var BACKTEST_PRELOAD_DAYS = 60;
58
63
  var DASHBOARD_PRELOAD_DAYS = 160;
59
64
  var BOT_PRELOAD_DAYS = 160;
60
65
  var PRELOAD_FALLBACK_DAYS = 160;
@@ -62,6 +67,8 @@ var TTL_1H = 3600;
62
67
  var TTL_3H = 10800;
63
68
  var TTL_12H = 43300;
64
69
  var TTL_1D = 86400;
70
+ var TTL_3D = 259200;
71
+ var TTL_10D = 864e3;
65
72
  var TTL_1M = 26e5;
66
73
  var TTL_3M = 78e5;
67
74
  var TESTS_TOP_LIMIT = 50;
@@ -70,6 +77,10 @@ var TESTS_ORDERS_MIN_LIMIT = 3;
70
77
  var MARKET_CATEGORY = "linear";
71
78
  var ML_CANDLE_FEATURE_WINDOW = 50;
72
79
  var ML_BASE_CANDLES_WINDOW = 50;
80
+ var DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS = [
81
+ "BTCUSDT",
82
+ "ETHUSDT"
83
+ ];
73
84
  var TRENDLINE_DEFAULTS = {
74
85
  maxLines: 20,
75
86
  range: 15,
@@ -214,10 +225,12 @@ var TestThresholdsConfig = {
214
225
  };
215
226
  // Annotate the CommonJS export names for ESM import in node:
216
227
  0 && (module.exports = {
228
+ BACKTEST_DEFAULT_DAYS,
217
229
  BACKTEST_PRELOAD_DAYS,
218
230
  BOT_PRELOAD_DAYS,
219
231
  CORRELATION_WINDOW,
220
232
  DASHBOARD_PRELOAD_DAYS,
233
+ DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS,
221
234
  FEE_PERCENT,
222
235
  MARKET_CATEGORY,
223
236
  ML_BASE_CANDLES_WINDOW,
@@ -231,10 +244,12 @@ var TestThresholdsConfig = {
231
244
  TESTS_ORDERS_MIN_LIMIT,
232
245
  TESTS_TOP_LIMIT,
233
246
  TRENDLINE_DEFAULTS,
247
+ TTL_10D,
234
248
  TTL_12H,
235
249
  TTL_1D,
236
250
  TTL_1H,
237
251
  TTL_1M,
252
+ TTL_3D,
238
253
  TTL_3H,
239
254
  TTL_3M,
240
255
  TestThresholdsConfig
@@ -1,8 +1,10 @@
1
1
  import {
2
+ BACKTEST_DEFAULT_DAYS,
2
3
  BACKTEST_PRELOAD_DAYS,
3
4
  BOT_PRELOAD_DAYS,
4
5
  CORRELATION_WINDOW,
5
6
  DASHBOARD_PRELOAD_DAYS,
7
+ DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS,
6
8
  FEE_PERCENT,
7
9
  MARKET_CATEGORY,
8
10
  ML_BASE_CANDLES_WINDOW,
@@ -16,19 +18,23 @@ import {
16
18
  TESTS_ORDERS_MIN_LIMIT,
17
19
  TESTS_TOP_LIMIT,
18
20
  TRENDLINE_DEFAULTS,
21
+ TTL_10D,
19
22
  TTL_12H,
20
23
  TTL_1D,
21
24
  TTL_1H,
22
25
  TTL_1M,
26
+ TTL_3D,
23
27
  TTL_3H,
24
28
  TTL_3M,
25
29
  TestThresholdsConfig
26
- } from "./chunk-KQQUP2YF.mjs";
30
+ } from "./chunk-2ORZC66W.mjs";
27
31
  export {
32
+ BACKTEST_DEFAULT_DAYS,
28
33
  BACKTEST_PRELOAD_DAYS,
29
34
  BOT_PRELOAD_DAYS,
30
35
  CORRELATION_WINDOW,
31
36
  DASHBOARD_PRELOAD_DAYS,
37
+ DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS,
32
38
  FEE_PERCENT,
33
39
  MARKET_CATEGORY,
34
40
  ML_BASE_CANDLES_WINDOW,
@@ -42,10 +48,12 @@ export {
42
48
  TESTS_ORDERS_MIN_LIMIT,
43
49
  TESTS_TOP_LIMIT,
44
50
  TRENDLINE_DEFAULTS,
51
+ TTL_10D,
45
52
  TTL_12H,
46
53
  TTL_1D,
47
54
  TTL_1H,
48
55
  TTL_1M,
56
+ TTL_3D,
49
57
  TTL_3H,
50
58
  TTL_3M,
51
59
  TestThresholdsConfig
@@ -1,4 +1,4 @@
1
- import { KlineChartItem, DerivativesInterval, DerivativesRow, IndicatorPluginRenderer, Indicator, IndicatorPluginEntry, SpreadRow, TrendLine, TrendLineOptions } from '@tradejs/types';
1
+ import { KlineChartItem, DerivativesInterval, DerivativesRow, Direction, DerivativesContext, IndicatorPluginRenderer, Indicator, IndicatorPluginEntry, SpreadRow, TrendLine, TrendLineOptions } from '@tradejs/types';
2
2
  export { I as IndicatorPeriods, a as applyIndicatorsToHistory, b as buildMlCandleIndicators, c as buildMlTimeframeIndicators, d as createIndicators } from './indicators-B-GGjP5F.mjs';
3
3
  import { KLineData } from 'klinecharts';
4
4
 
@@ -50,6 +50,15 @@ declare const mergeCoinalyzeMetrics: (params: {
50
50
  }) => CoinalyzePoint[];
51
51
  declare const coinalyzePointsToRows: (points: CoinalyzePoint[], interval: DerivativesInterval, source: string) => DerivativesRow[];
52
52
 
53
+ declare const buildDerivativesContext: (params: {
54
+ symbol: string;
55
+ direction: Direction;
56
+ timestamp: number;
57
+ rowsByInterval: Partial<Record<DerivativesInterval, DerivativesRow[]>>;
58
+ intervals?: DerivativesInterval[];
59
+ staleAfterMsByInterval?: Partial<Record<DerivativesInterval, number>>;
60
+ }) => DerivativesContext;
61
+
53
62
  declare const registerIndicatorEntries: (entries: readonly IndicatorPluginEntry[], source: string, scope?: string) => void;
54
63
  declare const getRegisteredIndicatorEntries: (scope?: string) => IndicatorPluginEntry[];
55
64
  declare const getPluginIndicatorCatalog: (scope?: string) => Indicator[];
@@ -119,4 +128,4 @@ type TrendlineEngine = {
119
128
  };
120
129
  declare const createTrendlineEngine: (initialCandles: KLineData[], options: TrendLineOptions) => TrendlineEngine;
121
130
 
122
- export { type CoinalyzePoint, type IndicatorRendererDescriptor, type PricePoint, type TrendlineEngine, alignSortedCandlesByTimestamp, alignSpreadRows, buildReturnsFromCandles, calculateCoinBtcCorrelation, calculatePearsonCorrelation, coinalyzePointsToRows, coinbaseProductFromSymbol, createSpreadSmoother, createTrendlineEngine, detectRawSupportResistance, getPluginIndicatorCatalog, getPluginIndicatorRenderers, getRegisteredIndicatorEntries, getSupportResistanceLevels, intervalToMs, mergeCoinalyzeMetrics, normalizeCoinalyzeSymbols, normalizeDerivativesIntervals, registerIndicatorEntries, resetIndicatorRegistryCache, rollingMeanStd, smoothSpreadSeries, toArrayData, toCoinalyzeTimestampMs, toFiniteNumber };
131
+ export { type CoinalyzePoint, type IndicatorRendererDescriptor, type PricePoint, type TrendlineEngine, alignSortedCandlesByTimestamp, alignSpreadRows, buildDerivativesContext, buildReturnsFromCandles, calculateCoinBtcCorrelation, calculatePearsonCorrelation, coinalyzePointsToRows, coinbaseProductFromSymbol, createSpreadSmoother, createTrendlineEngine, detectRawSupportResistance, getPluginIndicatorCatalog, getPluginIndicatorRenderers, getRegisteredIndicatorEntries, getSupportResistanceLevels, intervalToMs, mergeCoinalyzeMetrics, normalizeCoinalyzeSymbols, normalizeDerivativesIntervals, registerIndicatorEntries, resetIndicatorRegistryCache, rollingMeanStd, smoothSpreadSeries, toArrayData, toCoinalyzeTimestampMs, toFiniteNumber };
@@ -1,4 +1,4 @@
1
- import { KlineChartItem, DerivativesInterval, DerivativesRow, IndicatorPluginRenderer, Indicator, IndicatorPluginEntry, SpreadRow, TrendLine, TrendLineOptions } from '@tradejs/types';
1
+ import { KlineChartItem, DerivativesInterval, DerivativesRow, Direction, DerivativesContext, IndicatorPluginRenderer, Indicator, IndicatorPluginEntry, SpreadRow, TrendLine, TrendLineOptions } from '@tradejs/types';
2
2
  export { I as IndicatorPeriods, a as applyIndicatorsToHistory, b as buildMlCandleIndicators, c as buildMlTimeframeIndicators, d as createIndicators } from './indicators-B-GGjP5F.js';
3
3
  import { KLineData } from 'klinecharts';
4
4
 
@@ -50,6 +50,15 @@ declare const mergeCoinalyzeMetrics: (params: {
50
50
  }) => CoinalyzePoint[];
51
51
  declare const coinalyzePointsToRows: (points: CoinalyzePoint[], interval: DerivativesInterval, source: string) => DerivativesRow[];
52
52
 
53
+ declare const buildDerivativesContext: (params: {
54
+ symbol: string;
55
+ direction: Direction;
56
+ timestamp: number;
57
+ rowsByInterval: Partial<Record<DerivativesInterval, DerivativesRow[]>>;
58
+ intervals?: DerivativesInterval[];
59
+ staleAfterMsByInterval?: Partial<Record<DerivativesInterval, number>>;
60
+ }) => DerivativesContext;
61
+
53
62
  declare const registerIndicatorEntries: (entries: readonly IndicatorPluginEntry[], source: string, scope?: string) => void;
54
63
  declare const getRegisteredIndicatorEntries: (scope?: string) => IndicatorPluginEntry[];
55
64
  declare const getPluginIndicatorCatalog: (scope?: string) => Indicator[];
@@ -119,4 +128,4 @@ type TrendlineEngine = {
119
128
  };
120
129
  declare const createTrendlineEngine: (initialCandles: KLineData[], options: TrendLineOptions) => TrendlineEngine;
121
130
 
122
- export { type CoinalyzePoint, type IndicatorRendererDescriptor, type PricePoint, type TrendlineEngine, alignSortedCandlesByTimestamp, alignSpreadRows, buildReturnsFromCandles, calculateCoinBtcCorrelation, calculatePearsonCorrelation, coinalyzePointsToRows, coinbaseProductFromSymbol, createSpreadSmoother, createTrendlineEngine, detectRawSupportResistance, getPluginIndicatorCatalog, getPluginIndicatorRenderers, getRegisteredIndicatorEntries, getSupportResistanceLevels, intervalToMs, mergeCoinalyzeMetrics, normalizeCoinalyzeSymbols, normalizeDerivativesIntervals, registerIndicatorEntries, resetIndicatorRegistryCache, rollingMeanStd, smoothSpreadSeries, toArrayData, toCoinalyzeTimestampMs, toFiniteNumber };
131
+ export { type CoinalyzePoint, type IndicatorRendererDescriptor, type PricePoint, type TrendlineEngine, alignSortedCandlesByTimestamp, alignSpreadRows, buildDerivativesContext, buildReturnsFromCandles, calculateCoinBtcCorrelation, calculatePearsonCorrelation, coinalyzePointsToRows, coinbaseProductFromSymbol, createSpreadSmoother, createTrendlineEngine, detectRawSupportResistance, getPluginIndicatorCatalog, getPluginIndicatorRenderers, getRegisteredIndicatorEntries, getSupportResistanceLevels, intervalToMs, mergeCoinalyzeMetrics, normalizeCoinalyzeSymbols, normalizeDerivativesIntervals, registerIndicatorEntries, resetIndicatorRegistryCache, rollingMeanStd, smoothSpreadSeries, toArrayData, toCoinalyzeTimestampMs, toFiniteNumber };
@@ -33,6 +33,7 @@ __export(indicators_exports, {
33
33
  alignSortedCandlesByTimestamp: () => alignSortedCandlesByTimestamp,
34
34
  alignSpreadRows: () => alignSpreadRows,
35
35
  applyIndicatorsToHistory: () => applyIndicatorsToHistory,
36
+ buildDerivativesContext: () => buildDerivativesContext,
36
37
  buildMlCandleIndicators: () => buildMlCandleIndicators,
37
38
  buildMlTimeframeIndicators: () => buildMlTimeframeIndicators,
38
39
  buildReturnsFromCandles: () => buildReturnsFromCandles,
@@ -264,6 +265,235 @@ var coinalyzePointsToRows = (points, interval, source) => points.map((point) =>
264
265
  source
265
266
  }));
266
267
 
268
+ // src/utils/derivativesContext.ts
269
+ var HOUR_MS = 60 * 60 * 1e3;
270
+ var DEFAULT_STALE_AFTER_MS = {
271
+ "15m": 45 * 60 * 1e3,
272
+ "1h": 3 * HOUR_MS
273
+ };
274
+ var DERIVATIVES_INTERVALS = ["15m", "1h"];
275
+ var toFiniteNumberOrNull = (value) => {
276
+ if (typeof value === "number" && Number.isFinite(value)) return value;
277
+ if (typeof value === "string" && value.trim()) {
278
+ const parsed = Number(value);
279
+ return Number.isFinite(parsed) ? parsed : null;
280
+ }
281
+ return null;
282
+ };
283
+ var toTimestampMs = (value) => {
284
+ if (value instanceof Date) {
285
+ const time = value.getTime();
286
+ return Number.isFinite(time) ? time : null;
287
+ }
288
+ const num = toFiniteNumberOrNull(value);
289
+ if (num == null) return null;
290
+ return num > 1e10 ? Math.floor(num) : Math.floor(num * 1e3);
291
+ };
292
+ var roundNullable = (value, digits = 6) => {
293
+ if (value == null || !Number.isFinite(value)) return null;
294
+ const multiplier = 10 ** digits;
295
+ return Math.round(value * multiplier) / multiplier;
296
+ };
297
+ var pctChange = (current, previous) => {
298
+ if (current == null || previous == null || !Number.isFinite(current) || !Number.isFinite(previous) || previous === 0) {
299
+ return null;
300
+ }
301
+ return (current - previous) / Math.abs(previous) * 100;
302
+ };
303
+ var normalizeRows = (rows, timestamp) => (rows ?? []).map((row) => ({
304
+ ...row,
305
+ tsMs: toTimestampMs(row.ts),
306
+ openInterest: toFiniteNumberOrNull(row.openInterest),
307
+ fundingRate: toFiniteNumberOrNull(row.fundingRate),
308
+ liqLong: toFiniteNumberOrNull(row.liqLong),
309
+ liqShort: toFiniteNumberOrNull(row.liqShort),
310
+ liqTotal: toFiniteNumberOrNull(row.liqTotal)
311
+ })).filter((row) => {
312
+ return row.tsMs != null && row.tsMs <= timestamp;
313
+ }).sort((a, b) => a.tsMs - b.tsMs);
314
+ var findRowAtOrBefore = (rows, targetTs) => {
315
+ for (let i = rows.length - 1; i >= 0; i -= 1) {
316
+ if (rows[i].tsMs <= targetTs) {
317
+ return rows[i];
318
+ }
319
+ }
320
+ return null;
321
+ };
322
+ var calculateZScore = (values, current) => {
323
+ const finite = values.filter(
324
+ (value) => typeof value === "number" && Number.isFinite(value)
325
+ );
326
+ if (current == null || finite.length < 3) return null;
327
+ const mean = finite.reduce((sum, value) => sum + value, 0) / finite.length;
328
+ const variance = finite.reduce((sum, value) => sum + (value - mean) ** 2, 0) / finite.length;
329
+ const std = Math.sqrt(variance);
330
+ if (!Number.isFinite(std) || std === 0) return 0;
331
+ return (current - mean) / std;
332
+ };
333
+ var calculateAverage = (values) => {
334
+ const finite = values.filter(
335
+ (value) => typeof value === "number" && Number.isFinite(value)
336
+ );
337
+ if (!finite.length) return null;
338
+ return finite.reduce((sum, value) => sum + value, 0) / finite.length;
339
+ };
340
+ var buildIntervalContext = (params) => {
341
+ const { interval, rows, timestamp, staleAfterMs } = params;
342
+ const normalizedRows = normalizeRows(rows, timestamp);
343
+ const latest = normalizedRows[normalizedRows.length - 1];
344
+ if (!latest) return null;
345
+ const openInterest = latest.openInterest;
346
+ const row1h = findRowAtOrBefore(normalizedRows, latest.tsMs - HOUR_MS);
347
+ const row4h = findRowAtOrBefore(normalizedRows, latest.tsMs - 4 * HOUR_MS);
348
+ const row24h = findRowAtOrBefore(normalizedRows, latest.tsMs - 24 * HOUR_MS);
349
+ const liqLong = latest.liqLong;
350
+ const liqShort = latest.liqShort;
351
+ const liqTotal = latest.liqTotal ?? (liqLong ?? 0) + (liqShort ?? 0);
352
+ const previousLiquidations = normalizedRows.slice(0, -1).map((row) => row.liqTotal ?? (row.liqLong ?? 0) + (row.liqShort ?? 0));
353
+ const avgPreviousLiquidations = calculateAverage(previousLiquidations);
354
+ const liqSpikeRatio = liqTotal != null && avgPreviousLiquidations != null && avgPreviousLiquidations > 0 ? liqTotal / avgPreviousLiquidations : null;
355
+ const liqImbalance = liqTotal != null && liqTotal > 0 ? ((liqShort ?? 0) - (liqLong ?? 0)) / liqTotal : null;
356
+ return {
357
+ interval,
358
+ asOfTs: latest.tsMs,
359
+ stale: timestamp - latest.tsMs > staleAfterMs,
360
+ points: normalizedRows.length,
361
+ openInterest: roundNullable(openInterest),
362
+ oiChangePct1h: roundNullable(
363
+ pctChange(openInterest, row1h?.openInterest ?? null),
364
+ 4
365
+ ),
366
+ oiChangePct4h: roundNullable(
367
+ pctChange(openInterest, row4h?.openInterest ?? null),
368
+ 4
369
+ ),
370
+ oiChangePct24h: roundNullable(
371
+ pctChange(openInterest, row24h?.openInterest ?? null),
372
+ 4
373
+ ),
374
+ fundingRate: roundNullable(latest.fundingRate, 8),
375
+ fundingZScore: roundNullable(
376
+ calculateZScore(
377
+ normalizedRows.map((row) => row.fundingRate),
378
+ latest.fundingRate
379
+ ),
380
+ 4
381
+ ),
382
+ liqLong: roundNullable(liqLong),
383
+ liqShort: roundNullable(liqShort),
384
+ liqTotal: roundNullable(liqTotal),
385
+ liqImbalance: roundNullable(liqImbalance, 4),
386
+ liqSpikeRatio: roundNullable(liqSpikeRatio, 4)
387
+ };
388
+ };
389
+ var getPrimaryContext = (intervals) => intervals["15m"] ?? intervals["1h"] ?? null;
390
+ var isCrowdedLong = (context) => context.fundingRate != null && context.fundingRate >= 5e-4 || context.fundingZScore != null && context.fundingZScore >= 1.5;
391
+ var isCrowdedShort = (context) => context.fundingRate != null && context.fundingRate <= -5e-4 || context.fundingZScore != null && context.fundingZScore <= -1.5;
392
+ var hasLiquidationSpike = (context) => context.liqSpikeRatio != null && context.liqSpikeRatio >= 2;
393
+ var detectPressure = (context) => {
394
+ if (!context) return "neutral";
395
+ if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance <= -0.35) {
396
+ return "long_flush";
397
+ }
398
+ if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance >= 0.35) {
399
+ return "short_flush";
400
+ }
401
+ if (isCrowdedLong(context)) return "crowded_long";
402
+ if (isCrowdedShort(context)) return "crowded_short";
403
+ return "neutral";
404
+ };
405
+ var collectRiskFlags = (contexts) => {
406
+ const flags = /* @__PURE__ */ new Set();
407
+ if (!contexts.length) {
408
+ flags.add("missing_derivatives");
409
+ return [...flags];
410
+ }
411
+ if (contexts.some((context) => context.stale)) {
412
+ flags.add("stale_derivatives");
413
+ }
414
+ for (const context of contexts) {
415
+ if (isCrowdedLong(context)) flags.add("crowded_long");
416
+ if (isCrowdedShort(context)) flags.add("crowded_short");
417
+ if (context.oiChangePct1h != null && context.oiChangePct1h < -1) {
418
+ flags.add("oi_falling");
419
+ }
420
+ if (context.oiChangePct1h != null && Math.abs(context.oiChangePct1h) < 0.15) {
421
+ flags.add("oi_not_confirming");
422
+ }
423
+ if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance <= -0.35) {
424
+ flags.add("long_liquidation_spike");
425
+ }
426
+ if (hasLiquidationSpike(context) && context.liqImbalance != null && context.liqImbalance >= 0.35) {
427
+ flags.add("short_liquidation_spike");
428
+ }
429
+ }
430
+ return [...flags];
431
+ };
432
+ var resolveDirectionAligned = (params) => {
433
+ const { direction, primary, pressure, riskFlags } = params;
434
+ if (!primary || primary.stale || riskFlags.includes("missing_derivatives")) {
435
+ return null;
436
+ }
437
+ if (direction === "LONG") {
438
+ if (pressure === "crowded_long" || riskFlags.includes("oi_falling")) {
439
+ return false;
440
+ }
441
+ if (pressure === "short_flush" || primary.oiChangePct1h != null && primary.oiChangePct1h > 0.25 && !riskFlags.includes("crowded_long")) {
442
+ return true;
443
+ }
444
+ return null;
445
+ }
446
+ if (pressure === "crowded_short" || riskFlags.includes("oi_falling")) {
447
+ return false;
448
+ }
449
+ if (pressure === "long_flush" || primary.oiChangePct1h != null && primary.oiChangePct1h > 0.25 && !riskFlags.includes("crowded_short")) {
450
+ return true;
451
+ }
452
+ return null;
453
+ };
454
+ var buildDerivativesContext = (params) => {
455
+ const {
456
+ symbol,
457
+ direction,
458
+ timestamp,
459
+ rowsByInterval,
460
+ intervals = DERIVATIVES_INTERVALS,
461
+ staleAfterMsByInterval = {}
462
+ } = params;
463
+ const intervalContexts = {};
464
+ for (const interval of intervals) {
465
+ const context = buildIntervalContext({
466
+ interval,
467
+ rows: rowsByInterval[interval],
468
+ timestamp,
469
+ staleAfterMs: staleAfterMsByInterval[interval] ?? DEFAULT_STALE_AFTER_MS[interval]
470
+ });
471
+ if (context) {
472
+ intervalContexts[interval] = context;
473
+ }
474
+ }
475
+ const contexts = Object.values(intervalContexts);
476
+ const primary = getPrimaryContext(intervalContexts);
477
+ const pressure = detectPressure(primary);
478
+ const riskFlags = collectRiskFlags(contexts);
479
+ return {
480
+ source: "coinalyze",
481
+ symbol,
482
+ timestamp,
483
+ intervals: intervalContexts,
484
+ summary: {
485
+ pressure,
486
+ directionAligned: resolveDirectionAligned({
487
+ direction,
488
+ primary,
489
+ pressure,
490
+ riskFlags
491
+ }),
492
+ riskFlags
493
+ }
494
+ };
495
+ };
496
+
267
497
  // src/utils/indicators.ts
268
498
  var import_technicalindicators = require("technicalindicators");
269
499
 
@@ -487,6 +717,17 @@ var DEFAULT_INDICATOR_PERIODS = {
487
717
  levelLookback: 20,
488
718
  levelDelay: 2
489
719
  };
720
+ var resolveIndicatorPeriods = (periods = {}) => {
721
+ const resolved = {
722
+ ...DEFAULT_INDICATOR_PERIODS
723
+ };
724
+ for (const [key, value] of Object.entries(periods)) {
725
+ if (typeof value === "number" && Number.isFinite(value)) {
726
+ resolved[key] = value;
727
+ }
728
+ }
729
+ return resolved;
730
+ };
490
731
  var ONE_HOUR_MS = 36e5;
491
732
  var ONE_DAY_MS = 864e5;
492
733
  var toMlCandle = (candle) => ({
@@ -569,10 +810,7 @@ var createIndicators = (data, btcData = [], options = {}) => {
569
810
  options.pluginRegistryScope
570
811
  );
571
812
  const includeMlPayload = options.includeMlPayload !== false;
572
- const indicatorPeriods = {
573
- ...DEFAULT_INDICATOR_PERIODS,
574
- ...options.periods || {}
575
- };
813
+ const indicatorPeriods = resolveIndicatorPeriods(options.periods);
576
814
  const closes = [];
577
815
  const highs = [];
578
816
  const lows = [];
@@ -901,10 +1139,7 @@ var createIndicators = (data, btcData = [], options = {}) => {
901
1139
  };
902
1140
  var buildMlTimeframeIndicators = (candles, periods = {}) => {
903
1141
  const result = {};
904
- const indicatorPeriods = {
905
- ...DEFAULT_INDICATOR_PERIODS,
906
- ...periods
907
- };
1142
+ const indicatorPeriods = resolveIndicatorPeriods(periods);
908
1143
  for (const timeframe of INDICATOR_TIMEFRAMES) {
909
1144
  const tfCandles = resampleCandles(candles, timeframe.minutes);
910
1145
  if (tfCandles.length === 0) continue;
@@ -1632,6 +1867,7 @@ var createTrendlineEngine = (initialCandles, options) => {
1632
1867
  alignSortedCandlesByTimestamp,
1633
1868
  alignSpreadRows,
1634
1869
  applyIndicatorsToHistory,
1870
+ buildDerivativesContext,
1635
1871
  buildMlCandleIndicators,
1636
1872
  buildMlTimeframeIndicators,
1637
1873
  buildReturnsFromCandles,
@@ -2,6 +2,7 @@ import {
2
2
  alignSortedCandlesByTimestamp,
3
3
  alignSpreadRows,
4
4
  applyIndicatorsToHistory,
5
+ buildDerivativesContext,
5
6
  buildMlCandleIndicators,
6
7
  buildMlTimeframeIndicators,
7
8
  buildReturnsFromCandles,
@@ -28,15 +29,16 @@ import {
28
29
  toArrayData,
29
30
  toCoinalyzeTimestampMs,
30
31
  toFiniteNumber
31
- } from "./chunk-JE3ACOXJ.mjs";
32
+ } from "./chunk-UK6VTOUX.mjs";
32
33
  import "./chunk-AYC2QVKI.mjs";
33
- import "./chunk-BHIX34VS.mjs";
34
- import "./chunk-KQQUP2YF.mjs";
34
+ import "./chunk-FNLPYYML.mjs";
35
+ import "./chunk-2ORZC66W.mjs";
35
36
  import "./chunk-M7QGVZ3J.mjs";
36
37
  export {
37
38
  alignSortedCandlesByTimestamp,
38
39
  alignSpreadRows,
39
40
  applyIndicatorsToHistory,
41
+ buildDerivativesContext,
40
42
  buildMlCandleIndicators,
41
43
  buildMlTimeframeIndicators,
42
44
  buildReturnsFromCandles,
@@ -49,7 +49,9 @@ declare const getDirectionalTpSlPrices: ({ price, direction, takeProfitDelta, st
49
49
 
50
50
  type AiRuntimeConfigLike = {
51
51
  AI_ENABLED?: boolean;
52
+ AI_MODE?: StrategyRuntimeAiOptions['mode'];
52
53
  MIN_AI_QUALITY?: number;
54
+ AI_REPLAY_ANALYSES?: StrategyRuntimeAiOptions['replayAnalyses'];
53
55
  };
54
56
  type MlRuntimeConfigLike = {
55
57
  ML_ENABLED?: boolean;
@@ -49,7 +49,9 @@ declare const getDirectionalTpSlPrices: ({ price, direction, takeProfitDelta, st
49
49
 
50
50
  type AiRuntimeConfigLike = {
51
51
  AI_ENABLED?: boolean;
52
+ AI_MODE?: StrategyRuntimeAiOptions['mode'];
52
53
  MIN_AI_QUALITY?: number;
54
+ AI_REPLAY_ANALYSES?: StrategyRuntimeAiOptions['replayAnalyses'];
53
55
  };
54
56
  type MlRuntimeConfigLike = {
55
57
  ML_ENABLED?: boolean;