@tradejs/node 1.0.2 → 1.0.3
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-NNJ3RLLL.mjs → ai-MDMDKAEE.mjs} +3 -3
- package/dist/backtest.d.mts +1 -1
- package/dist/backtest.d.ts +1 -1
- package/dist/backtest.js +214 -131
- package/dist/backtest.mjs +52 -25
- package/dist/{chunk-DE7ADBIR.mjs → chunk-3C76HVLA.mjs} +1 -0
- package/dist/{chunk-OB4CSYDJ.mjs → chunk-7ICOZAKA.mjs} +0 -4
- package/dist/chunk-CK2PW4L5.mjs +243 -0
- package/dist/{chunk-PXJJPAQT.mjs → chunk-H4HXW3EZ.mjs} +1 -1
- package/dist/chunk-MGFEID6K.mjs +268 -0
- package/dist/{chunk-ZIMX3JX2.mjs → chunk-QDYCJ2OK.mjs} +1 -1
- package/dist/cli.js +131 -99
- package/dist/cli.mjs +17 -15
- package/dist/connectors.d.mts +9 -9
- package/dist/connectors.d.ts +9 -9
- package/dist/connectors.js +110 -70
- package/dist/connectors.mjs +2 -2
- package/dist/pine.d.mts +0 -1
- package/dist/pine.d.ts +0 -1
- package/dist/pine.js +0 -4
- package/dist/pine.mjs +1 -1
- package/dist/registry.d.mts +10 -10
- package/dist/registry.d.ts +10 -10
- package/dist/registry.js +122 -81
- package/dist/registry.mjs +2 -2
- package/dist/strategies.js +132 -86
- package/dist/strategies.mjs +15 -10
- package/package.json +4 -4
- package/dist/chunk-E2QNOA5M.mjs +0 -227
- package/dist/chunk-MHCXPD2B.mjs +0 -201
package/dist/strategies.js
CHANGED
|
@@ -5751,7 +5751,7 @@ var init_tradejsConfig = __esm({
|
|
|
5751
5751
|
});
|
|
5752
5752
|
|
|
5753
5753
|
// src/strategy/manifests.ts
|
|
5754
|
-
var import_indicators, import_logger3,
|
|
5754
|
+
var import_indicators, import_logger3, createStrategyRegistryState, registryStateByProjectRoot, getStrategyRegistryState, toUniqueModules, getConfiguredPluginModuleNames, extractModuleEntries, extractStrategyPluginDefinition, extractIndicatorPluginDefinition, registerEntries, importStrategyPluginModule, ensureStrategyPluginsLoaded, ensureIndicatorPluginsLoaded, getStrategyCreator, getAvailableStrategyNames, getRegisteredStrategies, getRegisteredManifests, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies;
|
|
5755
5755
|
var init_manifests = __esm({
|
|
5756
5756
|
"src/strategy/manifests.ts"() {
|
|
5757
5757
|
"use strict";
|
|
@@ -5759,14 +5759,29 @@ var init_manifests = __esm({
|
|
|
5759
5759
|
import_logger3 = require("@tradejs/infra/logger");
|
|
5760
5760
|
init_tradejsConfig();
|
|
5761
5761
|
init_tradejsConfig();
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5762
|
+
createStrategyRegistryState = () => ({
|
|
5763
|
+
strategyCreators: /* @__PURE__ */ new Map(),
|
|
5764
|
+
strategyManifestsMap: /* @__PURE__ */ new Map(),
|
|
5765
|
+
pluginsLoadPromise: null
|
|
5766
|
+
});
|
|
5767
|
+
registryStateByProjectRoot = /* @__PURE__ */ new Map();
|
|
5768
|
+
getStrategyRegistryState = (cwd = getTradejsProjectCwd()) => {
|
|
5769
|
+
const projectRoot = getTradejsProjectCwd(cwd);
|
|
5770
|
+
let state = registryStateByProjectRoot.get(projectRoot);
|
|
5771
|
+
if (!state) {
|
|
5772
|
+
state = createStrategyRegistryState();
|
|
5773
|
+
registryStateByProjectRoot.set(projectRoot, state);
|
|
5774
|
+
}
|
|
5775
|
+
return {
|
|
5776
|
+
projectRoot,
|
|
5777
|
+
state
|
|
5778
|
+
};
|
|
5779
|
+
};
|
|
5765
5780
|
toUniqueModules = (modules = []) => [
|
|
5766
5781
|
...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
|
|
5767
5782
|
];
|
|
5768
|
-
getConfiguredPluginModuleNames = async () => {
|
|
5769
|
-
const config = await loadTradejsConfig();
|
|
5783
|
+
getConfiguredPluginModuleNames = async (cwd = getTradejsProjectCwd()) => {
|
|
5784
|
+
const config = await loadTradejsConfig(cwd);
|
|
5770
5785
|
return {
|
|
5771
5786
|
strategyModules: toUniqueModules(config.strategies),
|
|
5772
5787
|
indicatorModules: toUniqueModules(config.indicators)
|
|
@@ -5800,14 +5815,14 @@ var init_manifests = __esm({
|
|
|
5800
5815
|
);
|
|
5801
5816
|
return indicatorEntries ? { indicatorEntries } : null;
|
|
5802
5817
|
};
|
|
5803
|
-
registerEntries = (entries, source) => {
|
|
5818
|
+
registerEntries = (entries, source, state) => {
|
|
5804
5819
|
for (const entry of entries) {
|
|
5805
5820
|
const strategyName = entry.manifest?.name;
|
|
5806
5821
|
if (!strategyName) {
|
|
5807
5822
|
import_logger3.logger.warn("Skip strategy entry without name from %s", source);
|
|
5808
5823
|
continue;
|
|
5809
5824
|
}
|
|
5810
|
-
if (strategyCreators.has(strategyName)) {
|
|
5825
|
+
if (state.strategyCreators.has(strategyName)) {
|
|
5811
5826
|
import_logger3.logger.warn(
|
|
5812
5827
|
'Skip duplicate strategy "%s" from %s: already registered',
|
|
5813
5828
|
strategyName,
|
|
@@ -5815,8 +5830,8 @@ var init_manifests = __esm({
|
|
|
5815
5830
|
);
|
|
5816
5831
|
continue;
|
|
5817
5832
|
}
|
|
5818
|
-
strategyCreators.set(strategyName, entry.creator);
|
|
5819
|
-
strategyManifestsMap.set(strategyName, entry.manifest);
|
|
5833
|
+
state.strategyCreators.set(strategyName, entry.creator);
|
|
5834
|
+
state.strategyManifestsMap.set(strategyName, entry.manifest);
|
|
5820
5835
|
}
|
|
5821
5836
|
};
|
|
5822
5837
|
importStrategyPluginModule = async (moduleName) => {
|
|
@@ -5828,93 +5843,119 @@ var init_manifests = __esm({
|
|
|
5828
5843
|
moduleName
|
|
5829
5844
|
);
|
|
5830
5845
|
};
|
|
5831
|
-
ensureStrategyPluginsLoaded = async () => {
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
);
|
|
5854
|
-
|
|
5855
|
-
|
|
5846
|
+
ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
5847
|
+
const { projectRoot, state } = getStrategyRegistryState(cwd);
|
|
5848
|
+
if (!state.pluginsLoadPromise) {
|
|
5849
|
+
(0, import_indicators.resetIndicatorRegistryCache)(projectRoot);
|
|
5850
|
+
state.pluginsLoadPromise = (async () => {
|
|
5851
|
+
const { strategyModules, indicatorModules } = await getConfiguredPluginModuleNames(projectRoot);
|
|
5852
|
+
const strategySet = new Set(strategyModules);
|
|
5853
|
+
const indicatorSet = new Set(indicatorModules);
|
|
5854
|
+
const pluginModuleNames = [
|
|
5855
|
+
.../* @__PURE__ */ new Set([...strategyModules, ...indicatorModules])
|
|
5856
|
+
];
|
|
5857
|
+
if (!pluginModuleNames.length) {
|
|
5858
|
+
return;
|
|
5859
|
+
}
|
|
5860
|
+
for (const moduleName of pluginModuleNames) {
|
|
5861
|
+
try {
|
|
5862
|
+
const resolvedModuleName = resolvePluginModuleSpecifier(
|
|
5863
|
+
moduleName,
|
|
5864
|
+
projectRoot
|
|
5865
|
+
);
|
|
5866
|
+
const moduleExport = await importStrategyPluginModule(resolvedModuleName);
|
|
5867
|
+
if (strategySet.has(moduleName)) {
|
|
5868
|
+
const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
|
|
5869
|
+
if (!pluginDefinition) {
|
|
5870
|
+
import_logger3.logger.warn(
|
|
5871
|
+
'Skip strategy plugin "%s": export { strategyEntries } is missing',
|
|
5872
|
+
moduleName
|
|
5873
|
+
);
|
|
5874
|
+
} else {
|
|
5875
|
+
registerEntries(
|
|
5876
|
+
pluginDefinition.strategyEntries,
|
|
5877
|
+
moduleName,
|
|
5878
|
+
state
|
|
5879
|
+
);
|
|
5880
|
+
}
|
|
5856
5881
|
}
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5882
|
+
if (indicatorSet.has(moduleName)) {
|
|
5883
|
+
const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
|
|
5884
|
+
if (!indicatorPluginDefinition) {
|
|
5885
|
+
import_logger3.logger.warn(
|
|
5886
|
+
'Skip indicator plugin "%s": export { indicatorEntries } is missing',
|
|
5887
|
+
moduleName
|
|
5888
|
+
);
|
|
5889
|
+
} else {
|
|
5890
|
+
(0, import_indicators.registerIndicatorEntries)(
|
|
5891
|
+
indicatorPluginDefinition.indicatorEntries,
|
|
5892
|
+
moduleName,
|
|
5893
|
+
projectRoot
|
|
5894
|
+
);
|
|
5895
|
+
}
|
|
5896
|
+
}
|
|
5897
|
+
if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
|
|
5861
5898
|
import_logger3.logger.warn(
|
|
5862
|
-
'Skip
|
|
5863
|
-
moduleName
|
|
5864
|
-
);
|
|
5865
|
-
} else {
|
|
5866
|
-
(0, import_indicators.registerIndicatorEntries)(
|
|
5867
|
-
indicatorPluginDefinition.indicatorEntries,
|
|
5899
|
+
'Skip plugin "%s": no strategy/indicator sections requested in config',
|
|
5868
5900
|
moduleName
|
|
5869
5901
|
);
|
|
5870
5902
|
}
|
|
5871
|
-
}
|
|
5872
|
-
if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
|
|
5903
|
+
} catch (error) {
|
|
5873
5904
|
import_logger3.logger.warn(
|
|
5874
|
-
'
|
|
5875
|
-
moduleName
|
|
5905
|
+
'Failed to load plugin "%s": %s',
|
|
5906
|
+
moduleName,
|
|
5907
|
+
String(error)
|
|
5876
5908
|
);
|
|
5877
5909
|
}
|
|
5878
|
-
} catch (error) {
|
|
5879
|
-
import_logger3.logger.warn(
|
|
5880
|
-
'Failed to load plugin "%s": %s',
|
|
5881
|
-
moduleName,
|
|
5882
|
-
String(error)
|
|
5883
|
-
);
|
|
5884
5910
|
}
|
|
5885
|
-
}
|
|
5886
|
-
}
|
|
5887
|
-
|
|
5911
|
+
})();
|
|
5912
|
+
}
|
|
5913
|
+
await state.pluginsLoadPromise;
|
|
5888
5914
|
};
|
|
5889
|
-
ensureIndicatorPluginsLoaded = ensureStrategyPluginsLoaded;
|
|
5890
|
-
getStrategyCreator = async (name) => {
|
|
5891
|
-
await ensureStrategyPluginsLoaded();
|
|
5892
|
-
|
|
5915
|
+
ensureIndicatorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => ensureStrategyPluginsLoaded(cwd);
|
|
5916
|
+
getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
|
|
5917
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
5918
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5919
|
+
return state.strategyCreators.get(name);
|
|
5893
5920
|
};
|
|
5894
|
-
getAvailableStrategyNames = async () => {
|
|
5895
|
-
await ensureStrategyPluginsLoaded();
|
|
5896
|
-
|
|
5921
|
+
getAvailableStrategyNames = async (cwd = getTradejsProjectCwd()) => {
|
|
5922
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
5923
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5924
|
+
return [...state.strategyCreators.keys()].sort((a, b) => a.localeCompare(b));
|
|
5897
5925
|
};
|
|
5898
|
-
getRegisteredStrategies = () => {
|
|
5899
|
-
|
|
5926
|
+
getRegisteredStrategies = (cwd = getTradejsProjectCwd()) => {
|
|
5927
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5928
|
+
return Object.fromEntries(state.strategyCreators.entries());
|
|
5900
5929
|
};
|
|
5901
|
-
getRegisteredManifests = () => {
|
|
5902
|
-
|
|
5930
|
+
getRegisteredManifests = (cwd = getTradejsProjectCwd()) => {
|
|
5931
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5932
|
+
return [...state.strategyManifestsMap.values()];
|
|
5903
5933
|
};
|
|
5904
|
-
getStrategyManifest = (name) => {
|
|
5905
|
-
|
|
5934
|
+
getStrategyManifest = (name, cwd = getTradejsProjectCwd()) => {
|
|
5935
|
+
if (!name) {
|
|
5936
|
+
return void 0;
|
|
5937
|
+
}
|
|
5938
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5939
|
+
return state.strategyManifestsMap.get(name);
|
|
5906
5940
|
};
|
|
5907
|
-
isKnownStrategy = (name) => {
|
|
5908
|
-
|
|
5941
|
+
isKnownStrategy = (name, cwd = getTradejsProjectCwd()) => {
|
|
5942
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5943
|
+
return state.strategyCreators.has(name);
|
|
5909
5944
|
};
|
|
5910
|
-
registerStrategyEntries = (entries) => {
|
|
5911
|
-
|
|
5945
|
+
registerStrategyEntries = (entries, cwd = getTradejsProjectCwd()) => {
|
|
5946
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
5947
|
+
registerEntries(entries, "runtime", state);
|
|
5912
5948
|
};
|
|
5913
|
-
resetStrategyRegistryCache = () => {
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5949
|
+
resetStrategyRegistryCache = (cwd) => {
|
|
5950
|
+
const normalizedCwd = String(cwd ?? "").trim();
|
|
5951
|
+
if (!normalizedCwd) {
|
|
5952
|
+
registryStateByProjectRoot.clear();
|
|
5953
|
+
(0, import_indicators.resetIndicatorRegistryCache)();
|
|
5954
|
+
return;
|
|
5955
|
+
}
|
|
5956
|
+
const projectRoot = getTradejsProjectCwd(normalizedCwd);
|
|
5957
|
+
registryStateByProjectRoot.delete(projectRoot);
|
|
5958
|
+
(0, import_indicators.resetIndicatorRegistryCache)(projectRoot);
|
|
5918
5959
|
};
|
|
5919
5960
|
strategies = new Proxy(
|
|
5920
5961
|
{},
|
|
@@ -5923,10 +5964,10 @@ var init_manifests = __esm({
|
|
|
5923
5964
|
if (typeof property !== "string") {
|
|
5924
5965
|
return void 0;
|
|
5925
5966
|
}
|
|
5926
|
-
return strategyCreators.get(property);
|
|
5967
|
+
return getStrategyRegistryState().state.strategyCreators.get(property);
|
|
5927
5968
|
},
|
|
5928
5969
|
ownKeys: () => {
|
|
5929
|
-
return [...strategyCreators.keys()];
|
|
5970
|
+
return [...getStrategyRegistryState().state.strategyCreators.keys()];
|
|
5930
5971
|
},
|
|
5931
5972
|
getOwnPropertyDescriptor: () => ({
|
|
5932
5973
|
enumerable: true,
|
|
@@ -6399,6 +6440,7 @@ var buildMlPayload = (payload) => {
|
|
|
6399
6440
|
};
|
|
6400
6441
|
|
|
6401
6442
|
// src/strategyHelpers/runtime.ts
|
|
6443
|
+
init_tradejsConfig();
|
|
6402
6444
|
var formatAiError = (err) => {
|
|
6403
6445
|
const error = err;
|
|
6404
6446
|
const safeJson = (value) => {
|
|
@@ -6440,7 +6482,8 @@ var enrichSignalWithMl = async ({
|
|
|
6440
6482
|
const mlResult = await (0, import_ml2.fetchMlThreshold)({
|
|
6441
6483
|
strategy,
|
|
6442
6484
|
features,
|
|
6443
|
-
threshold: ml.mlThreshold
|
|
6485
|
+
threshold: ml.mlThreshold,
|
|
6486
|
+
projectRoot: getTradejsProjectCwd()
|
|
6444
6487
|
});
|
|
6445
6488
|
if (mlResult) {
|
|
6446
6489
|
signal.ml = mlResult;
|
|
@@ -6545,6 +6588,7 @@ var createLoadPineScript = (baseDir) => {
|
|
|
6545
6588
|
|
|
6546
6589
|
// src/strategyRuntime.ts
|
|
6547
6590
|
init_manifests();
|
|
6591
|
+
init_tradejsConfig();
|
|
6548
6592
|
|
|
6549
6593
|
// src/strategyHelpers/config.ts
|
|
6550
6594
|
var import_lodash2 = __toESM(require_lodash());
|
|
@@ -6768,6 +6812,7 @@ var createStrategyRuntime = ({
|
|
|
6768
6812
|
manifest: staticManifest,
|
|
6769
6813
|
strategyDirectory
|
|
6770
6814
|
}) => {
|
|
6815
|
+
const projectRoot = getTradejsProjectCwd();
|
|
6771
6816
|
const resolveManifest = (name) => {
|
|
6772
6817
|
if (!name) {
|
|
6773
6818
|
return void 0;
|
|
@@ -6775,11 +6820,11 @@ var createStrategyRuntime = ({
|
|
|
6775
6820
|
if (staticManifest?.name === name) {
|
|
6776
6821
|
return staticManifest;
|
|
6777
6822
|
}
|
|
6778
|
-
return getStrategyManifest(name);
|
|
6823
|
+
return getStrategyManifest(name, projectRoot);
|
|
6779
6824
|
};
|
|
6780
6825
|
const loadPineScript2 = createLoadPineScript(
|
|
6781
6826
|
strategyDirectory ? import_node_path2.default.resolve(strategyDirectory) : import_node_path2.default.resolve(
|
|
6782
|
-
|
|
6827
|
+
projectRoot,
|
|
6783
6828
|
"packages",
|
|
6784
6829
|
"strategies",
|
|
6785
6830
|
"src",
|
|
@@ -6874,7 +6919,8 @@ var createStrategyRuntime = ({
|
|
|
6874
6919
|
btcData,
|
|
6875
6920
|
btcBinanceData,
|
|
6876
6921
|
btcCoinbaseData,
|
|
6877
|
-
periods: (0, import_strategies.buildDefaultIndicatorPeriods)(config)
|
|
6922
|
+
periods: (0, import_strategies.buildDefaultIndicatorPeriods)(config),
|
|
6923
|
+
pluginRegistryScope: projectRoot
|
|
6878
6924
|
});
|
|
6879
6925
|
const strategyApi = (0, import_strategies.createStrategyAPI)({
|
|
6880
6926
|
strategy: strategyName,
|
package/dist/strategies.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildMlPayload
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-H4HXW3EZ.mjs";
|
|
4
4
|
import {
|
|
5
5
|
require_lodash
|
|
6
6
|
} from "./chunk-GKDBAF3A.mjs";
|
|
7
7
|
import {
|
|
8
8
|
createLoadPineScript
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7ICOZAKA.mjs";
|
|
10
10
|
import "./chunk-5YNMSWL3.mjs";
|
|
11
11
|
import {
|
|
12
12
|
MAX_AI_SERIES_POINTS,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
buildAiPayload,
|
|
16
16
|
buildAiSystemPrompt,
|
|
17
17
|
trimSeriesDeep
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QDYCJ2OK.mjs";
|
|
19
19
|
import {
|
|
20
20
|
ensureIndicatorPluginsLoaded,
|
|
21
21
|
ensureStrategyPluginsLoaded,
|
|
@@ -28,8 +28,10 @@ import {
|
|
|
28
28
|
registerStrategyEntries,
|
|
29
29
|
resetStrategyRegistryCache,
|
|
30
30
|
strategies
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import
|
|
31
|
+
} from "./chunk-CK2PW4L5.mjs";
|
|
32
|
+
import {
|
|
33
|
+
getTradejsProjectCwd
|
|
34
|
+
} from "./chunk-3C76HVLA.mjs";
|
|
33
35
|
import {
|
|
34
36
|
__toESM
|
|
35
37
|
} from "./chunk-6DZX6EAA.mjs";
|
|
@@ -185,7 +187,8 @@ var enrichSignalWithMl = async ({
|
|
|
185
187
|
const mlResult = await fetchMlThreshold({
|
|
186
188
|
strategy,
|
|
187
189
|
features,
|
|
188
|
-
threshold: ml.mlThreshold
|
|
190
|
+
threshold: ml.mlThreshold,
|
|
191
|
+
projectRoot: getTradejsProjectCwd()
|
|
189
192
|
});
|
|
190
193
|
if (mlResult) {
|
|
191
194
|
signal.ml = mlResult;
|
|
@@ -203,7 +206,7 @@ var enrichSignalWithAi = async ({
|
|
|
203
206
|
return void 0;
|
|
204
207
|
}
|
|
205
208
|
try {
|
|
206
|
-
const { askAI: askAI2 } = await import("./ai-
|
|
209
|
+
const { askAI: askAI2 } = await import("./ai-MDMDKAEE.mjs");
|
|
207
210
|
const analysis = await askAI2(signal);
|
|
208
211
|
if (typeof analysis?.quality === "number") {
|
|
209
212
|
const normalizedQuality = Math.round(analysis.quality);
|
|
@@ -484,6 +487,7 @@ var createStrategyRuntime = ({
|
|
|
484
487
|
manifest: staticManifest,
|
|
485
488
|
strategyDirectory
|
|
486
489
|
}) => {
|
|
490
|
+
const projectRoot = getTradejsProjectCwd();
|
|
487
491
|
const resolveManifest = (name) => {
|
|
488
492
|
if (!name) {
|
|
489
493
|
return void 0;
|
|
@@ -491,11 +495,11 @@ var createStrategyRuntime = ({
|
|
|
491
495
|
if (staticManifest?.name === name) {
|
|
492
496
|
return staticManifest;
|
|
493
497
|
}
|
|
494
|
-
return getStrategyManifest(name);
|
|
498
|
+
return getStrategyManifest(name, projectRoot);
|
|
495
499
|
};
|
|
496
500
|
const loadPineScript = createLoadPineScript(
|
|
497
501
|
strategyDirectory ? path.resolve(strategyDirectory) : path.resolve(
|
|
498
|
-
|
|
502
|
+
projectRoot,
|
|
499
503
|
"packages",
|
|
500
504
|
"strategies",
|
|
501
505
|
"src",
|
|
@@ -590,7 +594,8 @@ var createStrategyRuntime = ({
|
|
|
590
594
|
btcData,
|
|
591
595
|
btcBinanceData,
|
|
592
596
|
btcCoinbaseData,
|
|
593
|
-
periods: buildDefaultIndicatorPeriods(config)
|
|
597
|
+
periods: buildDefaultIndicatorPeriods(config),
|
|
598
|
+
pluginRegistryScope: projectRoot
|
|
594
599
|
});
|
|
595
600
|
const strategyApi = createStrategyAPI({
|
|
596
601
|
strategy: strategyName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/node",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Node-only TradeJS runtime for strategies, backtests, Pine loading, and plugin registries.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@langchain/core": "^0.3.68",
|
|
56
56
|
"@langchain/openai": "^0.6.11",
|
|
57
|
-
"@tradejs/core": "^1.0.
|
|
58
|
-
"@tradejs/infra": "^1.0.
|
|
59
|
-
"@tradejs/types": "^1.0.
|
|
57
|
+
"@tradejs/core": "^1.0.3",
|
|
58
|
+
"@tradejs/infra": "^1.0.3",
|
|
59
|
+
"@tradejs/types": "^1.0.3",
|
|
60
60
|
"chalk": "4.1.2",
|
|
61
61
|
"ioredis": "5.8.0",
|
|
62
62
|
"pinets": "0.8.12",
|
package/dist/chunk-E2QNOA5M.mjs
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
importTradejsModule,
|
|
3
|
-
loadTradejsConfig,
|
|
4
|
-
resolvePluginModuleSpecifier
|
|
5
|
-
} from "./chunk-DE7ADBIR.mjs";
|
|
6
|
-
|
|
7
|
-
// src/connectorsRegistry.ts
|
|
8
|
-
import { logger } from "@tradejs/infra/logger";
|
|
9
|
-
var connectorCreators = /* @__PURE__ */ new Map();
|
|
10
|
-
var providerToConnectorName = /* @__PURE__ */ new Map();
|
|
11
|
-
var pluginsLoadPromise = null;
|
|
12
|
-
var BUILTIN_CONNECTOR_NAMES = {
|
|
13
|
-
ByBit: "ByBit",
|
|
14
|
-
Binance: "Binance",
|
|
15
|
-
Coinbase: "Coinbase",
|
|
16
|
-
Test: "Test"
|
|
17
|
-
};
|
|
18
|
-
var normalizeProvider = (value) => String(value ?? "").trim().toLowerCase();
|
|
19
|
-
var toUniqueModules = (modules = []) => [
|
|
20
|
-
...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
|
|
21
|
-
];
|
|
22
|
-
var findConnectorNameInsensitive = (name) => {
|
|
23
|
-
const normalized = name.trim().toLowerCase();
|
|
24
|
-
if (!normalized) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
for (const existingName of connectorCreators.keys()) {
|
|
28
|
-
if (existingName.toLowerCase() === normalized) {
|
|
29
|
-
return existingName;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
33
|
-
};
|
|
34
|
-
var normalizeProviders = (providers, connectorName) => {
|
|
35
|
-
const list = Array.isArray(providers) ? providers.map((item) => normalizeProvider(item)).filter(Boolean) : [];
|
|
36
|
-
const deduped = [...new Set(list)];
|
|
37
|
-
if (deduped.length) {
|
|
38
|
-
return deduped;
|
|
39
|
-
}
|
|
40
|
-
return [normalizeProvider(connectorName)];
|
|
41
|
-
};
|
|
42
|
-
var registerProvider = (provider, connectorName, source) => {
|
|
43
|
-
const existing = providerToConnectorName.get(provider);
|
|
44
|
-
if (existing && existing !== connectorName) {
|
|
45
|
-
logger.warn(
|
|
46
|
-
'Skip duplicate connector provider "%s" from %s: already mapped to %s',
|
|
47
|
-
provider,
|
|
48
|
-
source,
|
|
49
|
-
existing
|
|
50
|
-
);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
providerToConnectorName.set(provider, connectorName);
|
|
54
|
-
};
|
|
55
|
-
var registerEntry = (entry, source) => {
|
|
56
|
-
const connectorName = String(entry?.name ?? "").trim();
|
|
57
|
-
if (!connectorName) {
|
|
58
|
-
logger.warn("Skip connector entry without name from %s", source);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (typeof entry.creator !== "function") {
|
|
62
|
-
logger.warn(
|
|
63
|
-
'Skip connector entry "%s" from %s: creator must be a function',
|
|
64
|
-
connectorName,
|
|
65
|
-
source
|
|
66
|
-
);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const existingByName = findConnectorNameInsensitive(connectorName);
|
|
70
|
-
if (existingByName) {
|
|
71
|
-
logger.warn(
|
|
72
|
-
'Skip duplicate connector "%s" from %s: already registered as %s',
|
|
73
|
-
connectorName,
|
|
74
|
-
source,
|
|
75
|
-
existingByName
|
|
76
|
-
);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
connectorCreators.set(connectorName, entry.creator);
|
|
80
|
-
const providers = normalizeProviders(entry.providers, connectorName);
|
|
81
|
-
for (const provider of providers) {
|
|
82
|
-
registerProvider(provider, connectorName, source);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
var registerEntries = (entries, source) => {
|
|
86
|
-
for (const entry of entries) {
|
|
87
|
-
registerEntry(entry, source);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
var extractConnectorPluginDefinition = (moduleExport) => {
|
|
91
|
-
if (!moduleExport || typeof moduleExport !== "object") {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
const candidate = moduleExport;
|
|
95
|
-
if (Array.isArray(candidate.connectorEntries)) {
|
|
96
|
-
return {
|
|
97
|
-
connectorEntries: candidate.connectorEntries
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
const defaultExport = candidate.default;
|
|
101
|
-
if (defaultExport && Array.isArray(defaultExport.connectorEntries)) {
|
|
102
|
-
return {
|
|
103
|
-
connectorEntries: defaultExport.connectorEntries
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
return null;
|
|
107
|
-
};
|
|
108
|
-
var importConnectorPluginModule = async (moduleName) => {
|
|
109
|
-
if (typeof importTradejsModule === "function") {
|
|
110
|
-
return importTradejsModule(moduleName);
|
|
111
|
-
}
|
|
112
|
-
return import(
|
|
113
|
-
/* webpackIgnore: true */
|
|
114
|
-
moduleName
|
|
115
|
-
);
|
|
116
|
-
};
|
|
117
|
-
var ensureConnectorPluginsLoaded = async () => {
|
|
118
|
-
if (pluginsLoadPromise) {
|
|
119
|
-
return pluginsLoadPromise;
|
|
120
|
-
}
|
|
121
|
-
pluginsLoadPromise = (async () => {
|
|
122
|
-
const config = await loadTradejsConfig();
|
|
123
|
-
const connectorModules = toUniqueModules(config.connectors);
|
|
124
|
-
if (!connectorModules.length) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
for (const moduleName of connectorModules) {
|
|
128
|
-
try {
|
|
129
|
-
const resolvedModuleName = resolvePluginModuleSpecifier(moduleName);
|
|
130
|
-
const moduleExport = await importConnectorPluginModule(resolvedModuleName);
|
|
131
|
-
const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
|
|
132
|
-
if (!pluginDefinition) {
|
|
133
|
-
logger.warn(
|
|
134
|
-
'Skip connector plugin "%s": export { connectorEntries } is missing',
|
|
135
|
-
moduleName
|
|
136
|
-
);
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
registerEntries(pluginDefinition.connectorEntries, moduleName);
|
|
140
|
-
} catch (error) {
|
|
141
|
-
logger.warn(
|
|
142
|
-
'Failed to load connector plugin "%s": %s',
|
|
143
|
-
moduleName,
|
|
144
|
-
String(error)
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
})();
|
|
149
|
-
return pluginsLoadPromise;
|
|
150
|
-
};
|
|
151
|
-
var getConnectorCreatorByName = async (connectorName) => {
|
|
152
|
-
await ensureConnectorPluginsLoaded();
|
|
153
|
-
const raw = String(connectorName ?? "").trim();
|
|
154
|
-
if (!raw) {
|
|
155
|
-
return void 0;
|
|
156
|
-
}
|
|
157
|
-
const direct = connectorCreators.get(raw);
|
|
158
|
-
if (direct) {
|
|
159
|
-
return direct;
|
|
160
|
-
}
|
|
161
|
-
const existing = findConnectorNameInsensitive(raw);
|
|
162
|
-
if (!existing) {
|
|
163
|
-
return void 0;
|
|
164
|
-
}
|
|
165
|
-
return connectorCreators.get(existing);
|
|
166
|
-
};
|
|
167
|
-
var getConnectorNameByProvider = async (provider) => {
|
|
168
|
-
await ensureConnectorPluginsLoaded();
|
|
169
|
-
const normalized = normalizeProvider(provider);
|
|
170
|
-
if (!normalized) {
|
|
171
|
-
return void 0;
|
|
172
|
-
}
|
|
173
|
-
return providerToConnectorName.get(normalized);
|
|
174
|
-
};
|
|
175
|
-
var getConnectorCreatorByProvider = async (provider) => {
|
|
176
|
-
const connectorName = await getConnectorNameByProvider(provider);
|
|
177
|
-
if (!connectorName) {
|
|
178
|
-
return void 0;
|
|
179
|
-
}
|
|
180
|
-
return connectorCreators.get(connectorName);
|
|
181
|
-
};
|
|
182
|
-
var resolveConnectorName = async (providerOrName) => {
|
|
183
|
-
const raw = String(providerOrName ?? "").trim();
|
|
184
|
-
if (!raw) {
|
|
185
|
-
return void 0;
|
|
186
|
-
}
|
|
187
|
-
const byProvider = await getConnectorNameByProvider(raw);
|
|
188
|
-
if (byProvider) {
|
|
189
|
-
return byProvider;
|
|
190
|
-
}
|
|
191
|
-
const byName = await getConnectorCreatorByName(raw);
|
|
192
|
-
if (!byName) {
|
|
193
|
-
return void 0;
|
|
194
|
-
}
|
|
195
|
-
return findConnectorNameInsensitive(raw) ?? void 0;
|
|
196
|
-
};
|
|
197
|
-
var getAvailableConnectorNames = async () => {
|
|
198
|
-
await ensureConnectorPluginsLoaded();
|
|
199
|
-
return [...connectorCreators.keys()].sort((a, b) => a.localeCompare(b));
|
|
200
|
-
};
|
|
201
|
-
var getAvailableConnectorProviders = async () => {
|
|
202
|
-
await ensureConnectorPluginsLoaded();
|
|
203
|
-
return [...providerToConnectorName.keys()].sort((a, b) => a.localeCompare(b));
|
|
204
|
-
};
|
|
205
|
-
var registerConnectorEntries = (entries) => {
|
|
206
|
-
registerEntries(entries, "runtime");
|
|
207
|
-
};
|
|
208
|
-
var resetConnectorRegistryCache = () => {
|
|
209
|
-
connectorCreators.clear();
|
|
210
|
-
providerToConnectorName.clear();
|
|
211
|
-
pluginsLoadPromise = null;
|
|
212
|
-
};
|
|
213
|
-
var DEFAULT_CONNECTOR_NAME = BUILTIN_CONNECTOR_NAMES.ByBit;
|
|
214
|
-
|
|
215
|
-
export {
|
|
216
|
-
BUILTIN_CONNECTOR_NAMES,
|
|
217
|
-
ensureConnectorPluginsLoaded,
|
|
218
|
-
getConnectorCreatorByName,
|
|
219
|
-
getConnectorNameByProvider,
|
|
220
|
-
getConnectorCreatorByProvider,
|
|
221
|
-
resolveConnectorName,
|
|
222
|
-
getAvailableConnectorNames,
|
|
223
|
-
getAvailableConnectorProviders,
|
|
224
|
-
registerConnectorEntries,
|
|
225
|
-
resetConnectorRegistryCache,
|
|
226
|
-
DEFAULT_CONNECTOR_NAME
|
|
227
|
-
};
|