@tradejs/node 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.
@@ -11,18 +11,32 @@ var getPinePlotSeries = (context, plotName) => {
11
11
  const data = context?.plots?.[name]?.data;
12
12
  return Array.isArray(data) ? data : [];
13
13
  };
14
- var getLatestPinePlotValue = (context, plotName) => {
14
+ var getLatestPineRawPlotValue = (context, plotName) => {
15
15
  const series = getPinePlotSeries(context, plotName);
16
16
  if (!series.length) return void 0;
17
17
  return series[series.length - 1]?.value;
18
18
  };
19
- var asFiniteNumber = (value) => {
19
+ var getLatestPineNumberPlotValue = (context, plotName) => toFiniteNumber(getLatestPineRawPlotValue(context, plotName)) ?? null;
20
+ var getLatestPineBooleanPlotValue = (context, plotName) => toPineBoolean(getLatestPineRawPlotValue(context, plotName));
21
+ var getLatestPineNumberPlotValues = (context, plotNames) => Object.fromEntries(
22
+ plotNames.map((plotName) => [
23
+ plotName,
24
+ getLatestPineNumberPlotValue(context, plotName)
25
+ ])
26
+ );
27
+ var getLatestPineBooleanPlotValues = (context, plotNames) => Object.fromEntries(
28
+ plotNames.map((plotName) => [
29
+ plotName,
30
+ getLatestPineBooleanPlotValue(context, plotName)
31
+ ])
32
+ );
33
+ var toFiniteNumber = (value) => {
20
34
  if (typeof value !== "number" || !Number.isFinite(value)) {
21
35
  return void 0;
22
36
  }
23
37
  return value;
24
38
  };
25
- var asPineBoolean = (value) => {
39
+ var toPineBoolean = (value) => {
26
40
  if (typeof value === "boolean") return value;
27
41
  if (typeof value === "number") return Number.isFinite(value) && value !== 0;
28
42
  return false;
@@ -32,7 +46,7 @@ var loadPinets = () => {
32
46
  const cjsPath = resolvedPath.includes("pinets.min.browser") ? resolvedPath.replace(/pinets\.min\.browser(\.es)?\.js$/, "pinets.min.cjs") : resolvedPath;
33
47
  return __require(cjsPath);
34
48
  };
35
- var loadPineScript = (filePath, fallback = "") => {
49
+ var loadPineScriptFile = (filePath, fallback = "") => {
36
50
  const resolvedPath = String(filePath || "").trim();
37
51
  if (!resolvedPath) {
38
52
  return fallback;
@@ -43,7 +57,7 @@ var loadPineScript = (filePath, fallback = "") => {
43
57
  return fallback;
44
58
  }
45
59
  };
46
- var createLoadPineScript = (baseDir) => {
60
+ var createPineScriptLoader = (baseDir) => {
47
61
  const resolvedBaseDir = path.resolve(baseDir);
48
62
  return (fileNameOrPath, fallback = "") => {
49
63
  const rawPath = String(fileNameOrPath || "").trim();
@@ -51,7 +65,7 @@ var createLoadPineScript = (baseDir) => {
51
65
  return fallback;
52
66
  }
53
67
  const resolvedPath = path.isAbsolute(rawPath) ? rawPath : path.resolve(resolvedBaseDir, rawPath);
54
- return loadPineScript(resolvedPath, fallback);
68
+ return loadPineScriptFile(resolvedPath, fallback);
55
69
  };
56
70
  };
57
71
  var MINUTE_MS = 6e4;
@@ -110,10 +124,14 @@ var runPineScript = async ({
110
124
 
111
125
  export {
112
126
  getPinePlotSeries,
113
- getLatestPinePlotValue,
114
- asFiniteNumber,
115
- asPineBoolean,
116
- loadPineScript,
117
- createLoadPineScript,
127
+ getLatestPineRawPlotValue,
128
+ getLatestPineNumberPlotValue,
129
+ getLatestPineBooleanPlotValue,
130
+ getLatestPineNumberPlotValues,
131
+ getLatestPineBooleanPlotValues,
132
+ toFiniteNumber,
133
+ toPineBoolean,
134
+ loadPineScriptFile,
135
+ createPineScriptLoader,
118
136
  runPineScript
119
137
  };
@@ -3,7 +3,7 @@ import {
3
3
  importTradejsModule,
4
4
  loadTradejsConfig,
5
5
  resolvePluginModuleSpecifier
6
- } from "./chunk-P2ZUWONT.mjs";
6
+ } from "./chunk-JU77QVJ3.mjs";
7
7
 
8
8
  // src/connectorsRegistry.ts
9
9
  import { logger } from "@tradejs/infra/logger";
@@ -0,0 +1,154 @@
1
+ import {
2
+ getStrategyManifest
3
+ } from "./chunk-WGOYR6AB.mjs";
4
+
5
+ // src/strategyHelpers/derivativesContext.ts
6
+ import {
7
+ buildDerivativesContext,
8
+ normalizeDerivativesIntervals
9
+ } from "@tradejs/core/indicators";
10
+ import { DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS } from "@tradejs/core/constants";
11
+ import { getDerivativesWindow } from "@tradejs/infra/timescale";
12
+ import { logger } from "@tradejs/infra/logger";
13
+ var DEFAULT_INTERVALS = ["15m", "1h"];
14
+ var DEFAULT_LOOKBACK_HOURS = 48;
15
+ var derivativesContextUnavailable = false;
16
+ var parseEnabledFlag = (value, env) => {
17
+ const normalized = String(value ?? "").trim().toLowerCase();
18
+ if (!normalized) return false;
19
+ if (["1", "true", "yes", "on"].includes(normalized)) return true;
20
+ if (normalized === "backtest") return env === "BACKTEST";
21
+ if (normalized === "live") return env !== "BACKTEST";
22
+ return false;
23
+ };
24
+ var parseLookbackMs = () => {
25
+ const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
26
+ const normalizedHours = Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_LOOKBACK_HOURS;
27
+ return normalizedHours * 60 * 60 * 1e3;
28
+ };
29
+ var parseIntervals = () => {
30
+ const fromEnv = normalizeDerivativesIntervals(
31
+ process.env.DERIVATIVES_CONTEXT_INTERVALS
32
+ );
33
+ return fromEnv.length ? fromEnv : DEFAULT_INTERVALS;
34
+ };
35
+ var getDerivativesContextReferenceSymbols = () => [
36
+ ...DERIVATIVES_CONTEXT_REFERENCE_SYMBOLS
37
+ ];
38
+ var normalizeSymbol = (symbol) => String(symbol || "").trim().toUpperCase();
39
+ var resolvePrimaryReferenceSymbol = (signalSymbol) => {
40
+ const symbol = normalizeSymbol(signalSymbol);
41
+ const referenceSymbols = getDerivativesContextReferenceSymbols();
42
+ return referenceSymbols.some((referenceSymbol) => referenceSymbol === symbol) ? symbol : referenceSymbols[0];
43
+ };
44
+ var buildReferenceDerivativesContext = (params) => {
45
+ const { targetSymbol, primaryReferenceSymbol, referenceContexts } = params;
46
+ const primaryContext = referenceContexts[primaryReferenceSymbol] ?? referenceContexts[getDerivativesContextReferenceSymbols()[0]];
47
+ if (!primaryContext) {
48
+ throw new Error("No derivatives reference contexts built");
49
+ }
50
+ return {
51
+ ...primaryContext,
52
+ targetSymbol,
53
+ primaryReferenceSymbol: primaryContext.symbol,
54
+ referenceSymbols: getDerivativesContextReferenceSymbols(),
55
+ referenceContexts
56
+ };
57
+ };
58
+ var isDerivativesContextEnabled = (env) => parseEnabledFlag(process.env.DERIVATIVES_CONTEXT_ENABLED, env);
59
+ var enrichSignalWithDerivativesContext = async (params) => {
60
+ const { signal, env, enabled = isDerivativesContextEnabled(env) } = params;
61
+ if (!enabled || derivativesContextUnavailable) {
62
+ return false;
63
+ }
64
+ try {
65
+ const intervals = parseIntervals();
66
+ const referenceSymbols = getDerivativesContextReferenceSymbols();
67
+ const lookbackMs = parseLookbackMs();
68
+ const contexts = await Promise.all(
69
+ referenceSymbols.map(async (symbol) => {
70
+ const rowsByInterval = await getDerivativesWindow({
71
+ symbol,
72
+ intervals,
73
+ endMs: signal.timestamp,
74
+ lookbackMs
75
+ });
76
+ return [
77
+ symbol,
78
+ buildDerivativesContext({
79
+ symbol,
80
+ direction: signal.direction,
81
+ timestamp: signal.timestamp,
82
+ rowsByInterval,
83
+ intervals
84
+ })
85
+ ];
86
+ })
87
+ );
88
+ const referenceContexts = Object.fromEntries(contexts);
89
+ const derivativesContext = buildReferenceDerivativesContext({
90
+ targetSymbol: signal.symbol,
91
+ primaryReferenceSymbol: resolvePrimaryReferenceSymbol(signal.symbol),
92
+ referenceContexts
93
+ });
94
+ signal.additionalIndicators = {
95
+ ...signal.additionalIndicators ?? {},
96
+ derivativesContext
97
+ };
98
+ return true;
99
+ } catch (error) {
100
+ derivativesContextUnavailable = true;
101
+ logger.warn(
102
+ "Derivatives context disabled after Timescale read failure: %s",
103
+ String(error)
104
+ );
105
+ return false;
106
+ }
107
+ };
108
+
109
+ // src/strategyAdapters/ml.ts
110
+ var defaultMlAdapter = {
111
+ normalizeStrategyConfig: (strategyConfig) => strategyConfig
112
+ };
113
+ var getStrategyMlAdapter = (strategy) => {
114
+ const strategyAdapter = getStrategyManifest(strategy)?.mlAdapter;
115
+ if (!strategyAdapter) return defaultMlAdapter;
116
+ return {
117
+ ...defaultMlAdapter,
118
+ ...strategyAdapter
119
+ };
120
+ };
121
+
122
+ // src/mlPayload.ts
123
+ var normalizeStrategyConfig = (strategyConfig, strategyName) => {
124
+ return getStrategyMlAdapter(strategyName).normalizeStrategyConfig?.(
125
+ strategyConfig
126
+ );
127
+ };
128
+ var buildMlPayload = (payload) => {
129
+ const strategyName = payload.signal?.strategy ?? payload.context?.strategyName;
130
+ const mlAdapter = getStrategyMlAdapter(strategyName);
131
+ const normalizedSignal = mlAdapter.normalizeSignal?.(payload.signal) ?? payload.signal;
132
+ const nextSignal = {
133
+ ...normalizedSignal,
134
+ indicators: {
135
+ ...normalizedSignal?.indicators ?? {}
136
+ }
137
+ };
138
+ const nextContext = payload.context ? {
139
+ ...payload.context,
140
+ strategyConfig: normalizeStrategyConfig(
141
+ payload.context.strategyConfig,
142
+ strategyName
143
+ )
144
+ } : void 0;
145
+ return {
146
+ signal: nextSignal,
147
+ context: nextContext
148
+ };
149
+ };
150
+
151
+ export {
152
+ enrichSignalWithDerivativesContext,
153
+ buildMlPayload
154
+ };
@@ -3,6 +3,9 @@ import fs from "fs";
3
3
  import path from "path";
4
4
  import { createRequire } from "module";
5
5
  import { fileURLToPath, pathToFileURL } from "url";
6
+ import {
7
+ normalizeTradejsConfigHooks
8
+ } from "@tradejs/core/config";
6
9
  import { logger } from "@tradejs/infra/logger";
7
10
  var CONFIG_FILE_NAMES = [
8
11
  "tradejs.config.ts",
@@ -35,10 +38,14 @@ var normalizeConfig = (rawConfig) => {
35
38
  const strategies = Array.isArray(config.strategies) ? config.strategies.map((value) => String(value || "").trim()).filter(Boolean) : [];
36
39
  const indicators = Array.isArray(config.indicators) ? config.indicators.map((value) => String(value || "").trim()).filter(Boolean) : [];
37
40
  const connectors = Array.isArray(config.connectors) ? config.connectors.map((value) => String(value || "").trim()).filter(Boolean) : [];
41
+ const hooks = normalizeTradejsConfigHooks(
42
+ config.hooks
43
+ );
38
44
  return {
39
45
  strategies,
40
46
  indicators,
41
- connectors
47
+ connectors,
48
+ ...hooks ? { hooks } : {}
42
49
  };
43
50
  };
44
51
  var getRequireFn = (cwd = getTradejsProjectCwd()) => createRequire(path.join(path.resolve(cwd), "__tradejs_loader__.js"));
@@ -209,7 +216,7 @@ var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
209
216
  cachedByCwd.set(cwd, config);
210
217
  if (!announcedConfigFile.has(configFilePath)) {
211
218
  announcedConfigFile.add(configFilePath);
212
- logger.log("info", "Loaded TradeJS config: %s", configFilePath);
219
+ logger.log("debug", "Loaded TradeJS config: %s", configFilePath);
213
220
  }
214
221
  return config;
215
222
  } catch (error) {
@@ -5,7 +5,7 @@ var getPositiveIntegerEnv = (name, fallback) => {
5
5
  const parsedValue = Number(rawValue);
6
6
  return Number.isInteger(parsedValue) && parsedValue > 0 ? parsedValue : fallback;
7
7
  };
8
- var DEFAULT_KLINE_CONCURRENCY_LIMIT = NODE_ENV === "production" ? 1 : 10;
8
+ var DEFAULT_KLINE_CONCURRENCY_LIMIT = NODE_ENV === "production" ? 5 : 10;
9
9
  var KLINE_CONCURRENCY_LIMIT = getPositiveIntegerEnv(
10
10
  "KLINE_CONCURRENCY_LIMIT",
11
11
  DEFAULT_KLINE_CONCURRENCY_LIMIT
@@ -8,9 +8,9 @@ var require_lodash = __commonJS({
8
8
  "use strict";
9
9
  (function() {
10
10
  var undefined;
11
- var VERSION = "4.17.21";
11
+ var VERSION = "4.18.1";
12
12
  var LARGE_ARRAY_SIZE = 200;
13
- var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
13
+ var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`", INVALID_TEMPL_IMPORTS_ERROR_TEXT = "Invalid `imports` option passed into `_.template`";
14
14
  var HASH_UNDEFINED = "__lodash_hash_undefined__";
15
15
  var MAX_MEMOIZE_SIZE = 500;
16
16
  var PLACEHOLDER = "__lodash_placeholder__";
@@ -1936,8 +1936,21 @@ var require_lodash = __commonJS({
1936
1936
  }
1937
1937
  function baseUnset(object, path) {
1938
1938
  path = castPath(path, object);
1939
- object = parent(object, path);
1940
- return object == null || delete object[toKey(last(path))];
1939
+ var index = -1, length = path.length;
1940
+ if (!length) {
1941
+ return true;
1942
+ }
1943
+ while (++index < length) {
1944
+ var key = toKey(path[index]);
1945
+ if (key === "__proto__" && !hasOwnProperty.call(object, "__proto__")) {
1946
+ return false;
1947
+ }
1948
+ if ((key === "constructor" || key === "prototype") && index < length - 1) {
1949
+ return false;
1950
+ }
1951
+ }
1952
+ var obj = parent(object, path);
1953
+ return obj == null || delete obj[toKey(last(path))];
1941
1954
  }
1942
1955
  function baseUpdate(object, path, updater, customizer) {
1943
1956
  return baseSet(object, path, updater(baseGet(object, path)), customizer);
@@ -3264,7 +3277,7 @@ var require_lodash = __commonJS({
3264
3277
  var index = -1, length = pairs == null ? 0 : pairs.length, result2 = {};
3265
3278
  while (++index < length) {
3266
3279
  var pair = pairs[index];
3267
- result2[pair[0]] = pair[1];
3280
+ baseAssignValue(result2, pair[0], pair[1]);
3268
3281
  }
3269
3282
  return result2;
3270
3283
  }
@@ -4648,8 +4661,13 @@ var require_lodash = __commonJS({
4648
4661
  options = undefined;
4649
4662
  }
4650
4663
  string = toString(string);
4651
- options = assignInWith({}, options, settings, customDefaultsAssignIn);
4652
- var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
4664
+ options = assignWith({}, options, settings, customDefaultsAssignIn);
4665
+ var imports = assignWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
4666
+ arrayEach(importsKeys, function(key) {
4667
+ if (reForbiddenIdentifierChars.test(key)) {
4668
+ throw new Error(INVALID_TEMPL_IMPORTS_ERROR_TEXT);
4669
+ }
4670
+ });
4653
4671
  var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '";
4654
4672
  var reDelimiters = RegExp2(
4655
4673
  (options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$",
@@ -3,7 +3,7 @@ import {
3
3
  importTradejsModule,
4
4
  loadTradejsConfig,
5
5
  resolvePluginModuleSpecifier
6
- } from "./chunk-P2ZUWONT.mjs";
6
+ } from "./chunk-JU77QVJ3.mjs";
7
7
 
8
8
  // src/strategy/manifests.ts
9
9
  import {
package/dist/cli.d.mts CHANGED
@@ -1,12 +1,30 @@
1
1
  import { TestStat, TestThresholdsKey, Connector, Signal, Interval } from '@tradejs/types';
2
+ import { TradejsConfigHooks } from '@tradejs/core/config';
3
+
4
+ declare const sendTextToTG: (message: string, options?: {
5
+ userName?: string;
6
+ markup?: Record<string, unknown>;
7
+ }) => Promise<any>;
8
+
9
+ interface TradejsProjectConfig {
10
+ strategies?: string[];
11
+ indicators?: string[];
12
+ connectors?: string[];
13
+ hooks?: TradejsConfigHooks;
14
+ }
15
+ declare const loadTradejsConfig: (cwd?: string) => Promise<TradejsProjectConfig>;
2
16
 
3
17
  declare const cleanFiles: (dir: string) => Promise<void>;
4
18
  declare const cleanRedis: (area: string) => Promise<void>;
5
- declare const update: (connector: Connector, interval: Interval, tickers: string[]) => Promise<void>;
19
+ declare const update: (connector: Connector, interval: Interval, tickers: string[], preloadDays?: number, options?: {
20
+ connectorLabel?: string;
21
+ preloadStart?: number;
22
+ preloadEnd?: number;
23
+ }) => Promise<void>;
6
24
  declare const drawStatInCLI: (stat: Partial<TestStat> | undefined, keys: TestThresholdsKey[]) => string[];
7
25
  declare const getTickers: (connector: Connector, include?: string, exclude?: string, limit?: number, chunk?: string) => Promise<string[]>;
8
- declare const makeScreenshots: (signals: Signal[], interval: Interval) => Promise<void>;
9
- declare const sendToAI: (signals: Signal[]) => Promise<void>;
10
- declare const sendToTG: (signals: Signal[], imgInterval: Interval) => Promise<void>;
26
+ declare const makeScreenshots: (signals: Signal[], interval: Interval, userName?: string) => Promise<void>;
27
+ declare const sendToAI: (signals: Signal[], userName?: string) => Promise<void>;
28
+ declare const sendToTG: (signals: Signal[], imgInterval: Interval, userName?: string) => Promise<void>;
11
29
 
12
- export { cleanFiles, cleanRedis, drawStatInCLI, getTickers, makeScreenshots, sendToAI, sendToTG, update };
30
+ export { cleanFiles, cleanRedis, drawStatInCLI, getTickers, loadTradejsConfig, makeScreenshots, sendTextToTG, sendToAI, sendToTG, update };
package/dist/cli.d.ts CHANGED
@@ -1,12 +1,30 @@
1
1
  import { TestStat, TestThresholdsKey, Connector, Signal, Interval } from '@tradejs/types';
2
+ import { TradejsConfigHooks } from '@tradejs/core/config';
3
+
4
+ declare const sendTextToTG: (message: string, options?: {
5
+ userName?: string;
6
+ markup?: Record<string, unknown>;
7
+ }) => Promise<any>;
8
+
9
+ interface TradejsProjectConfig {
10
+ strategies?: string[];
11
+ indicators?: string[];
12
+ connectors?: string[];
13
+ hooks?: TradejsConfigHooks;
14
+ }
15
+ declare const loadTradejsConfig: (cwd?: string) => Promise<TradejsProjectConfig>;
2
16
 
3
17
  declare const cleanFiles: (dir: string) => Promise<void>;
4
18
  declare const cleanRedis: (area: string) => Promise<void>;
5
- declare const update: (connector: Connector, interval: Interval, tickers: string[]) => Promise<void>;
19
+ declare const update: (connector: Connector, interval: Interval, tickers: string[], preloadDays?: number, options?: {
20
+ connectorLabel?: string;
21
+ preloadStart?: number;
22
+ preloadEnd?: number;
23
+ }) => Promise<void>;
6
24
  declare const drawStatInCLI: (stat: Partial<TestStat> | undefined, keys: TestThresholdsKey[]) => string[];
7
25
  declare const getTickers: (connector: Connector, include?: string, exclude?: string, limit?: number, chunk?: string) => Promise<string[]>;
8
- declare const makeScreenshots: (signals: Signal[], interval: Interval) => Promise<void>;
9
- declare const sendToAI: (signals: Signal[]) => Promise<void>;
10
- declare const sendToTG: (signals: Signal[], imgInterval: Interval) => Promise<void>;
26
+ declare const makeScreenshots: (signals: Signal[], interval: Interval, userName?: string) => Promise<void>;
27
+ declare const sendToAI: (signals: Signal[], userName?: string) => Promise<void>;
28
+ declare const sendToTG: (signals: Signal[], imgInterval: Interval, userName?: string) => Promise<void>;
11
29
 
12
- export { cleanFiles, cleanRedis, drawStatInCLI, getTickers, makeScreenshots, sendToAI, sendToTG, update };
30
+ export { cleanFiles, cleanRedis, drawStatInCLI, getTickers, loadTradejsConfig, makeScreenshots, sendTextToTG, sendToAI, sendToTG, update };