@tradejs/node 1.0.3 → 1.0.4
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-MDMDKAEE.mjs → ai-G7ATN4YL.mjs} +3 -3
- package/dist/backtest.js +41 -8
- package/dist/backtest.mjs +4 -4
- package/dist/{chunk-MGFEID6K.mjs → chunk-CIY64D57.mjs} +7 -4
- package/dist/{chunk-QDYCJ2OK.mjs → chunk-LMAKIC3C.mjs} +1 -1
- package/dist/{chunk-3C76HVLA.mjs → chunk-P2ZUWONT.mjs} +29 -2
- package/dist/{chunk-H4HXW3EZ.mjs → chunk-RBE4PZER.mjs} +1 -1
- package/dist/{chunk-CK2PW4L5.mjs → chunk-ZY6ULOWK.mjs} +7 -4
- package/dist/cli.js +9 -3
- package/dist/cli.mjs +12 -6
- package/dist/connectors.js +35 -5
- package/dist/connectors.mjs +2 -2
- package/dist/registry.js +35 -5
- package/dist/registry.mjs +2 -2
- package/dist/strategies.js +321 -81
- package/dist/strategies.mjs +290 -80
- package/package.json +6 -5
package/dist/strategies.js
CHANGED
|
@@ -5546,7 +5546,7 @@ var init_aiShared = __esm({
|
|
|
5546
5546
|
});
|
|
5547
5547
|
|
|
5548
5548
|
// src/tradejsConfig.ts
|
|
5549
|
-
var import_fs, import_path, import_module, import_url, import_logger2, CONFIG_FILE_NAMES, TS_MODULE_RE, cachedByCwd, announcedConfigFile, tsNodeRegistered, getTradejsProjectCwd, normalizeConfig, getRequireFn, ensureTsNodeRegistered, toImportSpecifier, isTsModulePath, isRelativeModulePath, isBareModuleSpecifier, importConfigFile, importTradejsModule, resolveExportedConfig, findConfigFilePath, resolvePluginModuleSpecifier, loadTradejsConfig;
|
|
5549
|
+
var import_fs, import_path, import_module, import_url, import_logger2, CONFIG_FILE_NAMES, TS_MODULE_RE, cachedByCwd, announcedConfigFile, tsNodeRegistered, tsconfigPathsRegisteredByCwd, getTradejsProjectCwd, normalizeConfig, getRequireFn, ensureTsNodeRegistered, ensureTsconfigPathsRegistered, toImportSpecifier, isTsModulePath, isRelativeModulePath, isBareModuleSpecifier, importConfigFile, importTradejsModule, resolveExportedConfig, findConfigFilePath, resolvePluginModuleSpecifier, loadTradejsConfig;
|
|
5550
5550
|
var init_tradejsConfig = __esm({
|
|
5551
5551
|
"src/tradejsConfig.ts"() {
|
|
5552
5552
|
"use strict";
|
|
@@ -5566,6 +5566,7 @@ var init_tradejsConfig = __esm({
|
|
|
5566
5566
|
cachedByCwd = /* @__PURE__ */ new Map();
|
|
5567
5567
|
announcedConfigFile = /* @__PURE__ */ new Set();
|
|
5568
5568
|
tsNodeRegistered = false;
|
|
5569
|
+
tsconfigPathsRegisteredByCwd = /* @__PURE__ */ new Set();
|
|
5569
5570
|
getTradejsProjectCwd = (cwd) => {
|
|
5570
5571
|
const explicit = String(cwd ?? "").trim();
|
|
5571
5572
|
if (explicit) {
|
|
@@ -5607,6 +5608,28 @@ var init_tradejsConfig = __esm({
|
|
|
5607
5608
|
});
|
|
5608
5609
|
tsNodeRegistered = true;
|
|
5609
5610
|
};
|
|
5611
|
+
ensureTsconfigPathsRegistered = async (cwd = getTradejsProjectCwd()) => {
|
|
5612
|
+
const projectRoot = getTradejsProjectCwd(cwd);
|
|
5613
|
+
if (tsconfigPathsRegisteredByCwd.has(projectRoot)) {
|
|
5614
|
+
return;
|
|
5615
|
+
}
|
|
5616
|
+
const tsconfigPathsModule = await import("tsconfig-paths");
|
|
5617
|
+
const loadConfig = tsconfigPathsModule.loadConfig;
|
|
5618
|
+
const register = tsconfigPathsModule.register;
|
|
5619
|
+
if (typeof loadConfig !== "function" || typeof register !== "function") {
|
|
5620
|
+
return;
|
|
5621
|
+
}
|
|
5622
|
+
const loadedConfig = loadConfig(projectRoot);
|
|
5623
|
+
if (loadedConfig.resultType !== "success") {
|
|
5624
|
+
return;
|
|
5625
|
+
}
|
|
5626
|
+
register({
|
|
5627
|
+
baseUrl: loadedConfig.absoluteBaseUrl,
|
|
5628
|
+
paths: loadedConfig.paths,
|
|
5629
|
+
addMatchAll: false
|
|
5630
|
+
});
|
|
5631
|
+
tsconfigPathsRegisteredByCwd.add(projectRoot);
|
|
5632
|
+
};
|
|
5610
5633
|
toImportSpecifier = (moduleName) => {
|
|
5611
5634
|
if (moduleName.startsWith("file://")) {
|
|
5612
5635
|
return moduleName;
|
|
@@ -5634,6 +5657,7 @@ var init_tradejsConfig = __esm({
|
|
|
5634
5657
|
if (ext === ".ts" || ext === ".mts") {
|
|
5635
5658
|
const requireFn = getRequireFn(import_path.default.dirname(configFilePath));
|
|
5636
5659
|
await ensureTsNodeRegistered();
|
|
5660
|
+
await ensureTsconfigPathsRegistered(import_path.default.dirname(configFilePath));
|
|
5637
5661
|
return requireFn(configFilePath);
|
|
5638
5662
|
}
|
|
5639
5663
|
return import(
|
|
@@ -5641,7 +5665,7 @@ var init_tradejsConfig = __esm({
|
|
|
5641
5665
|
configFileUrl
|
|
5642
5666
|
);
|
|
5643
5667
|
};
|
|
5644
|
-
importTradejsModule = async (moduleName) => {
|
|
5668
|
+
importTradejsModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
|
|
5645
5669
|
const normalized = String(moduleName ?? "").trim();
|
|
5646
5670
|
if (!normalized) {
|
|
5647
5671
|
return {};
|
|
@@ -5655,13 +5679,15 @@ var init_tradejsConfig = __esm({
|
|
|
5655
5679
|
}
|
|
5656
5680
|
}
|
|
5657
5681
|
const requireFn = getRequireFn(
|
|
5658
|
-
import_path.default.isAbsolute(modulePath) ? import_path.default.dirname(modulePath) :
|
|
5682
|
+
import_path.default.isAbsolute(modulePath) ? import_path.default.dirname(modulePath) : cwd
|
|
5659
5683
|
);
|
|
5660
5684
|
if (isTsModulePath(modulePath)) {
|
|
5661
5685
|
await ensureTsNodeRegistered();
|
|
5686
|
+
await ensureTsconfigPathsRegistered(cwd);
|
|
5662
5687
|
return requireFn(modulePath);
|
|
5663
5688
|
}
|
|
5664
5689
|
if (isBareModuleSpecifier(normalized)) {
|
|
5690
|
+
await ensureTsconfigPathsRegistered(cwd);
|
|
5665
5691
|
return requireFn(normalized);
|
|
5666
5692
|
}
|
|
5667
5693
|
try {
|
|
@@ -5672,6 +5698,7 @@ var init_tradejsConfig = __esm({
|
|
|
5672
5698
|
} catch (error) {
|
|
5673
5699
|
if (isTsModulePath(modulePath)) {
|
|
5674
5700
|
await ensureTsNodeRegistered();
|
|
5701
|
+
await ensureTsconfigPathsRegistered(cwd);
|
|
5675
5702
|
return requireFn(modulePath);
|
|
5676
5703
|
}
|
|
5677
5704
|
throw error;
|
|
@@ -5834,9 +5861,9 @@ var init_manifests = __esm({
|
|
|
5834
5861
|
state.strategyManifestsMap.set(strategyName, entry.manifest);
|
|
5835
5862
|
}
|
|
5836
5863
|
};
|
|
5837
|
-
importStrategyPluginModule = async (moduleName) => {
|
|
5864
|
+
importStrategyPluginModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
|
|
5838
5865
|
if (typeof importTradejsModule === "function") {
|
|
5839
|
-
return importTradejsModule(moduleName);
|
|
5866
|
+
return importTradejsModule(moduleName, cwd);
|
|
5840
5867
|
}
|
|
5841
5868
|
return import(
|
|
5842
5869
|
/* webpackIgnore: true */
|
|
@@ -5863,7 +5890,10 @@ var init_manifests = __esm({
|
|
|
5863
5890
|
moduleName,
|
|
5864
5891
|
projectRoot
|
|
5865
5892
|
);
|
|
5866
|
-
const moduleExport = await importStrategyPluginModule(
|
|
5893
|
+
const moduleExport = await importStrategyPluginModule(
|
|
5894
|
+
resolvedModuleName,
|
|
5895
|
+
projectRoot
|
|
5896
|
+
);
|
|
5867
5897
|
if (strategySet.has(moduleName)) {
|
|
5868
5898
|
const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
|
|
5869
5899
|
if (!pluginDefinition) {
|
|
@@ -6678,10 +6708,151 @@ var getEntrySkipReason = ({
|
|
|
6678
6708
|
}
|
|
6679
6709
|
return "ENTRY_POLICY_BLOCKED";
|
|
6680
6710
|
};
|
|
6711
|
+
var buildHookCtx = ({
|
|
6712
|
+
connector,
|
|
6713
|
+
strategyName,
|
|
6714
|
+
userName,
|
|
6715
|
+
symbol,
|
|
6716
|
+
strategyConfig,
|
|
6717
|
+
env,
|
|
6718
|
+
isConfigFromBacktest
|
|
6719
|
+
}) => ({
|
|
6720
|
+
connector,
|
|
6721
|
+
strategyName,
|
|
6722
|
+
userName,
|
|
6723
|
+
symbol,
|
|
6724
|
+
strategyConfig,
|
|
6725
|
+
env,
|
|
6726
|
+
isConfigFromBacktest
|
|
6727
|
+
});
|
|
6728
|
+
var buildHookEntry = ({
|
|
6729
|
+
decision,
|
|
6730
|
+
runtime
|
|
6731
|
+
}) => ({
|
|
6732
|
+
context: decision.entryContext,
|
|
6733
|
+
orderPlan: decision.orderPlan,
|
|
6734
|
+
signal: decision.signal,
|
|
6735
|
+
runtime: {
|
|
6736
|
+
raw: decision.runtime,
|
|
6737
|
+
resolved: runtime
|
|
6738
|
+
}
|
|
6739
|
+
});
|
|
6740
|
+
var buildHookPolicy = ({
|
|
6741
|
+
quality,
|
|
6742
|
+
makeOrdersEnabled,
|
|
6743
|
+
minAiQuality
|
|
6744
|
+
}) => ({
|
|
6745
|
+
aiQuality: quality,
|
|
6746
|
+
makeOrdersEnabled,
|
|
6747
|
+
minAiQuality
|
|
6748
|
+
});
|
|
6749
|
+
var buildMlHookContext = ({
|
|
6750
|
+
signal,
|
|
6751
|
+
env,
|
|
6752
|
+
ml
|
|
6753
|
+
}) => {
|
|
6754
|
+
if (env === "BACKTEST") {
|
|
6755
|
+
return {
|
|
6756
|
+
config: ml,
|
|
6757
|
+
attempted: false,
|
|
6758
|
+
applied: false,
|
|
6759
|
+
skippedReason: "BACKTEST"
|
|
6760
|
+
};
|
|
6761
|
+
}
|
|
6762
|
+
if (!ml) {
|
|
6763
|
+
return {
|
|
6764
|
+
attempted: false,
|
|
6765
|
+
applied: false,
|
|
6766
|
+
skippedReason: "NO_RUNTIME"
|
|
6767
|
+
};
|
|
6768
|
+
}
|
|
6769
|
+
if (ml.enabled === false) {
|
|
6770
|
+
return {
|
|
6771
|
+
config: ml,
|
|
6772
|
+
attempted: false,
|
|
6773
|
+
applied: false,
|
|
6774
|
+
skippedReason: "DISABLED"
|
|
6775
|
+
};
|
|
6776
|
+
}
|
|
6777
|
+
if (!ml.strategyConfig) {
|
|
6778
|
+
return {
|
|
6779
|
+
config: ml,
|
|
6780
|
+
attempted: false,
|
|
6781
|
+
applied: false,
|
|
6782
|
+
skippedReason: "NO_STRATEGY_CONFIG"
|
|
6783
|
+
};
|
|
6784
|
+
}
|
|
6785
|
+
if (typeof ml.mlThreshold !== "number") {
|
|
6786
|
+
return {
|
|
6787
|
+
config: ml,
|
|
6788
|
+
attempted: false,
|
|
6789
|
+
applied: false,
|
|
6790
|
+
skippedReason: "NO_THRESHOLD"
|
|
6791
|
+
};
|
|
6792
|
+
}
|
|
6793
|
+
if (signal.ml) {
|
|
6794
|
+
return {
|
|
6795
|
+
config: ml,
|
|
6796
|
+
attempted: true,
|
|
6797
|
+
applied: true,
|
|
6798
|
+
result: signal.ml
|
|
6799
|
+
};
|
|
6800
|
+
}
|
|
6801
|
+
return {
|
|
6802
|
+
config: ml,
|
|
6803
|
+
attempted: true,
|
|
6804
|
+
applied: false,
|
|
6805
|
+
skippedReason: "NO_RESULT"
|
|
6806
|
+
};
|
|
6807
|
+
};
|
|
6808
|
+
var buildAiHookContext = ({
|
|
6809
|
+
env,
|
|
6810
|
+
ai,
|
|
6811
|
+
quality
|
|
6812
|
+
}) => {
|
|
6813
|
+
if (env === "BACKTEST") {
|
|
6814
|
+
return {
|
|
6815
|
+
config: ai,
|
|
6816
|
+
attempted: false,
|
|
6817
|
+
applied: false,
|
|
6818
|
+
skippedReason: "BACKTEST"
|
|
6819
|
+
};
|
|
6820
|
+
}
|
|
6821
|
+
if (!ai) {
|
|
6822
|
+
return {
|
|
6823
|
+
attempted: false,
|
|
6824
|
+
applied: false,
|
|
6825
|
+
skippedReason: "NO_RUNTIME"
|
|
6826
|
+
};
|
|
6827
|
+
}
|
|
6828
|
+
if (ai.enabled === false) {
|
|
6829
|
+
return {
|
|
6830
|
+
config: ai,
|
|
6831
|
+
attempted: false,
|
|
6832
|
+
applied: false,
|
|
6833
|
+
skippedReason: "DISABLED"
|
|
6834
|
+
};
|
|
6835
|
+
}
|
|
6836
|
+
if (typeof quality === "number") {
|
|
6837
|
+
return {
|
|
6838
|
+
config: ai,
|
|
6839
|
+
attempted: true,
|
|
6840
|
+
applied: true,
|
|
6841
|
+
quality
|
|
6842
|
+
};
|
|
6843
|
+
}
|
|
6844
|
+
return {
|
|
6845
|
+
config: ai,
|
|
6846
|
+
attempted: true,
|
|
6847
|
+
applied: false,
|
|
6848
|
+
skippedReason: "NO_QUALITY"
|
|
6849
|
+
};
|
|
6850
|
+
};
|
|
6681
6851
|
var handleExitDecision = async ({
|
|
6682
6852
|
connector,
|
|
6683
6853
|
symbol,
|
|
6684
6854
|
decision,
|
|
6855
|
+
market,
|
|
6685
6856
|
onRuntimeError
|
|
6686
6857
|
}) => {
|
|
6687
6858
|
try {
|
|
@@ -6695,7 +6866,8 @@ var handleExitDecision = async ({
|
|
|
6695
6866
|
await onRuntimeError?.({
|
|
6696
6867
|
stage: "closePosition",
|
|
6697
6868
|
error: err,
|
|
6698
|
-
decision
|
|
6869
|
+
decision,
|
|
6870
|
+
market
|
|
6699
6871
|
});
|
|
6700
6872
|
import_logger5.logger.error("close order error: %s %s", symbol, err);
|
|
6701
6873
|
return "ORDER_ERROR";
|
|
@@ -6708,7 +6880,12 @@ var executeEntryDecision = async ({
|
|
|
6708
6880
|
decision,
|
|
6709
6881
|
runtime,
|
|
6710
6882
|
manifest,
|
|
6711
|
-
|
|
6883
|
+
hookCtx,
|
|
6884
|
+
market,
|
|
6885
|
+
entry,
|
|
6886
|
+
policy,
|
|
6887
|
+
ml,
|
|
6888
|
+
ai,
|
|
6712
6889
|
invokeHook,
|
|
6713
6890
|
notifyRuntimeError
|
|
6714
6891
|
}) => {
|
|
@@ -6718,13 +6895,15 @@ var executeEntryDecision = async ({
|
|
|
6718
6895
|
"beforePlaceOrder",
|
|
6719
6896
|
manifest?.hooks?.beforePlaceOrder,
|
|
6720
6897
|
{
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
runtime,
|
|
6898
|
+
ctx: hookCtx,
|
|
6899
|
+
market,
|
|
6724
6900
|
decision,
|
|
6725
|
-
|
|
6901
|
+
entry,
|
|
6902
|
+
policy,
|
|
6903
|
+
ml,
|
|
6904
|
+
ai
|
|
6726
6905
|
},
|
|
6727
|
-
{ decision,
|
|
6906
|
+
{ decision, entry, market }
|
|
6728
6907
|
);
|
|
6729
6908
|
try {
|
|
6730
6909
|
await runtime.beforePlaceOrder?.();
|
|
@@ -6733,7 +6912,8 @@ var executeEntryDecision = async ({
|
|
|
6733
6912
|
stage: "runtime.beforePlaceOrder",
|
|
6734
6913
|
error,
|
|
6735
6914
|
decision,
|
|
6736
|
-
|
|
6915
|
+
entry,
|
|
6916
|
+
market
|
|
6737
6917
|
});
|
|
6738
6918
|
throw error;
|
|
6739
6919
|
}
|
|
@@ -6756,13 +6936,18 @@ var executeEntryDecision = async ({
|
|
|
6756
6936
|
"afterPlaceOrder",
|
|
6757
6937
|
manifest?.hooks?.afterPlaceOrder,
|
|
6758
6938
|
{
|
|
6759
|
-
|
|
6939
|
+
ctx: hookCtx,
|
|
6940
|
+
market,
|
|
6760
6941
|
decision,
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6942
|
+
entry,
|
|
6943
|
+
policy,
|
|
6944
|
+
ml,
|
|
6945
|
+
ai,
|
|
6946
|
+
order: {
|
|
6947
|
+
result: signal
|
|
6948
|
+
}
|
|
6764
6949
|
},
|
|
6765
|
-
{ decision,
|
|
6950
|
+
{ decision, entry, market }
|
|
6766
6951
|
);
|
|
6767
6952
|
return signal;
|
|
6768
6953
|
}
|
|
@@ -6782,13 +6967,18 @@ var executeEntryDecision = async ({
|
|
|
6782
6967
|
"afterPlaceOrder",
|
|
6783
6968
|
manifest?.hooks?.afterPlaceOrder,
|
|
6784
6969
|
{
|
|
6785
|
-
|
|
6970
|
+
ctx: hookCtx,
|
|
6971
|
+
market,
|
|
6786
6972
|
decision,
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6973
|
+
entry,
|
|
6974
|
+
policy,
|
|
6975
|
+
ml,
|
|
6976
|
+
ai,
|
|
6977
|
+
order: {
|
|
6978
|
+
result: decision.code
|
|
6979
|
+
}
|
|
6790
6980
|
},
|
|
6791
|
-
{ decision,
|
|
6981
|
+
{ decision, entry, market }
|
|
6792
6982
|
);
|
|
6793
6983
|
} catch (err) {
|
|
6794
6984
|
if (signal) {
|
|
@@ -6798,7 +6988,8 @@ var executeEntryDecision = async ({
|
|
|
6798
6988
|
stage: "placeOrder",
|
|
6799
6989
|
error: err,
|
|
6800
6990
|
decision,
|
|
6801
|
-
|
|
6991
|
+
entry,
|
|
6992
|
+
market
|
|
6802
6993
|
});
|
|
6803
6994
|
import_logger5.logger.error("order error: %s %s", symbol, err);
|
|
6804
6995
|
return signal ?? "ORDER_ERROR";
|
|
@@ -6855,33 +7046,37 @@ var createStrategyRuntime = ({
|
|
|
6855
7046
|
strategyName,
|
|
6856
7047
|
userName,
|
|
6857
7048
|
symbol,
|
|
6858
|
-
config,
|
|
7049
|
+
strategyConfig: config,
|
|
6859
7050
|
env,
|
|
6860
7051
|
isConfigFromBacktest
|
|
6861
7052
|
};
|
|
7053
|
+
const getHookCtx = (name = strategyName) => buildHookCtx({
|
|
7054
|
+
...hookBase,
|
|
7055
|
+
strategyName: name
|
|
7056
|
+
});
|
|
6862
7057
|
const notifyRuntimeError = async ({
|
|
6863
7058
|
stage,
|
|
6864
7059
|
error,
|
|
6865
7060
|
decision,
|
|
6866
|
-
|
|
7061
|
+
entry,
|
|
7062
|
+
market
|
|
6867
7063
|
}) => {
|
|
6868
7064
|
const errorStrategyName = decision?.kind === "entry" ? decision.entryContext.strategy : strategyName;
|
|
6869
7065
|
const errorManifest = resolveManifest(errorStrategyName) ?? strategyManifest;
|
|
6870
|
-
const errorHookBase = {
|
|
6871
|
-
...hookBase,
|
|
6872
|
-
strategyName: errorStrategyName
|
|
6873
|
-
};
|
|
6874
7066
|
const onRuntimeError = errorManifest?.hooks?.onRuntimeError;
|
|
6875
7067
|
if (!onRuntimeError) {
|
|
6876
7068
|
return;
|
|
6877
7069
|
}
|
|
6878
7070
|
try {
|
|
6879
7071
|
await onRuntimeError({
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
error,
|
|
7072
|
+
ctx: getHookCtx(errorStrategyName),
|
|
7073
|
+
market,
|
|
6883
7074
|
decision,
|
|
6884
|
-
|
|
7075
|
+
entry,
|
|
7076
|
+
error: {
|
|
7077
|
+
stage,
|
|
7078
|
+
cause: error
|
|
7079
|
+
}
|
|
6885
7080
|
});
|
|
6886
7081
|
} catch (hookError) {
|
|
6887
7082
|
import_logger5.logger.error(
|
|
@@ -6908,7 +7103,8 @@ var createStrategyRuntime = ({
|
|
|
6908
7103
|
stage,
|
|
6909
7104
|
error,
|
|
6910
7105
|
decision: errorContext.decision,
|
|
6911
|
-
|
|
7106
|
+
entry: errorContext.entry,
|
|
7107
|
+
market: errorContext.market
|
|
6912
7108
|
});
|
|
6913
7109
|
return void 0;
|
|
6914
7110
|
}
|
|
@@ -6947,39 +7143,45 @@ var createStrategyRuntime = ({
|
|
|
6947
7143
|
indicatorsState
|
|
6948
7144
|
});
|
|
6949
7145
|
await invokeHook("onInit", strategyManifest?.hooks?.onInit, {
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
7146
|
+
ctx: getHookCtx(),
|
|
7147
|
+
market: {
|
|
7148
|
+
data,
|
|
7149
|
+
btcData
|
|
7150
|
+
}
|
|
6953
7151
|
});
|
|
6954
7152
|
return async (candle, btcCandle) => {
|
|
6955
7153
|
data.push(candle);
|
|
6956
7154
|
btcData.push(btcCandle);
|
|
6957
7155
|
indicatorsState.setCurrentBar(candle, btcCandle);
|
|
7156
|
+
const market = {
|
|
7157
|
+
candle,
|
|
7158
|
+
btcCandle
|
|
7159
|
+
};
|
|
6958
7160
|
const decision = await core(candle, btcCandle);
|
|
6959
7161
|
const decisionStrategyName = decision.kind === "entry" ? decision.entryContext.strategy : strategyName;
|
|
6960
7162
|
const decisionManifest = resolveManifest(decisionStrategyName) ?? strategyManifest;
|
|
6961
|
-
const
|
|
6962
|
-
...hookBase,
|
|
6963
|
-
strategyName: decisionStrategyName
|
|
6964
|
-
};
|
|
7163
|
+
const decisionHookCtx = getHookCtx(decisionStrategyName);
|
|
6965
7164
|
await invokeHook(
|
|
6966
7165
|
"afterCoreDecision",
|
|
6967
7166
|
decisionManifest?.hooks?.afterCoreDecision,
|
|
6968
7167
|
{
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
btcCandle
|
|
7168
|
+
ctx: decisionHookCtx,
|
|
7169
|
+
market,
|
|
7170
|
+
decision
|
|
6973
7171
|
},
|
|
6974
|
-
{ decision }
|
|
7172
|
+
{ decision, market }
|
|
6975
7173
|
);
|
|
6976
7174
|
if (decision.kind === "skip") {
|
|
6977
|
-
await invokeHook(
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
7175
|
+
await invokeHook(
|
|
7176
|
+
"onSkip",
|
|
7177
|
+
decisionManifest?.hooks?.onSkip,
|
|
7178
|
+
{
|
|
7179
|
+
ctx: decisionHookCtx,
|
|
7180
|
+
market,
|
|
7181
|
+
decision
|
|
7182
|
+
},
|
|
7183
|
+
{ decision, market }
|
|
7184
|
+
);
|
|
6983
7185
|
return decision.code;
|
|
6984
7186
|
}
|
|
6985
7187
|
const makeOrdersEnabled = typeof config.MAKE_ORDERS === "boolean" ? config.MAKE_ORDERS : true;
|
|
@@ -6991,10 +7193,11 @@ var createStrategyRuntime = ({
|
|
|
6991
7193
|
"beforeClosePosition",
|
|
6992
7194
|
decisionManifest?.hooks?.beforeClosePosition,
|
|
6993
7195
|
{
|
|
6994
|
-
|
|
7196
|
+
ctx: decisionHookCtx,
|
|
7197
|
+
market,
|
|
6995
7198
|
decision
|
|
6996
7199
|
},
|
|
6997
|
-
{ decision }
|
|
7200
|
+
{ decision, market }
|
|
6998
7201
|
);
|
|
6999
7202
|
if (closeGate?.allow === false) {
|
|
7000
7203
|
return closeGate.reason ? `CLOSE_BLOCKED_BY_HOOK:${closeGate.reason}` : "CLOSE_BLOCKED_BY_HOOK";
|
|
@@ -7003,11 +7206,18 @@ var createStrategyRuntime = ({
|
|
|
7003
7206
|
connector,
|
|
7004
7207
|
symbol,
|
|
7005
7208
|
decision,
|
|
7006
|
-
|
|
7209
|
+
market,
|
|
7210
|
+
onRuntimeError: async ({
|
|
7211
|
+
stage,
|
|
7212
|
+
error,
|
|
7213
|
+
decision: exitDecision,
|
|
7214
|
+
market: errorMarket
|
|
7215
|
+
}) => {
|
|
7007
7216
|
await notifyRuntimeError({
|
|
7008
7217
|
stage,
|
|
7009
7218
|
error,
|
|
7010
|
-
decision: exitDecision
|
|
7219
|
+
decision: exitDecision,
|
|
7220
|
+
market: errorMarket
|
|
7011
7221
|
});
|
|
7012
7222
|
}
|
|
7013
7223
|
});
|
|
@@ -7018,6 +7228,11 @@ var createStrategyRuntime = ({
|
|
|
7018
7228
|
manifest: decisionManifest
|
|
7019
7229
|
});
|
|
7020
7230
|
const signal = decision.signal;
|
|
7231
|
+
const entry = buildHookEntry({
|
|
7232
|
+
decision,
|
|
7233
|
+
runtime
|
|
7234
|
+
});
|
|
7235
|
+
let ml;
|
|
7021
7236
|
if (signal) {
|
|
7022
7237
|
try {
|
|
7023
7238
|
await enrichSignalWithMl({
|
|
@@ -7030,23 +7245,31 @@ var createStrategyRuntime = ({
|
|
|
7030
7245
|
stage: "enrichSignalWithMl",
|
|
7031
7246
|
error,
|
|
7032
7247
|
decision,
|
|
7033
|
-
|
|
7248
|
+
entry,
|
|
7249
|
+
market
|
|
7034
7250
|
});
|
|
7035
7251
|
throw error;
|
|
7036
7252
|
}
|
|
7253
|
+
ml = buildMlHookContext({
|
|
7254
|
+
signal,
|
|
7255
|
+
env,
|
|
7256
|
+
ml: runtime.ml
|
|
7257
|
+
});
|
|
7037
7258
|
await invokeHook(
|
|
7038
7259
|
"afterEnrichMl",
|
|
7039
7260
|
decisionManifest?.hooks?.afterEnrichMl,
|
|
7040
7261
|
{
|
|
7041
|
-
|
|
7262
|
+
ctx: decisionHookCtx,
|
|
7263
|
+
market,
|
|
7042
7264
|
decision,
|
|
7043
|
-
|
|
7044
|
-
|
|
7265
|
+
entry,
|
|
7266
|
+
ml
|
|
7045
7267
|
},
|
|
7046
|
-
{ decision,
|
|
7268
|
+
{ decision, entry, market }
|
|
7047
7269
|
);
|
|
7048
7270
|
}
|
|
7049
7271
|
let quality;
|
|
7272
|
+
let ai;
|
|
7050
7273
|
if (signal) {
|
|
7051
7274
|
try {
|
|
7052
7275
|
quality = await enrichSignalWithAi({
|
|
@@ -7061,24 +7284,36 @@ var createStrategyRuntime = ({
|
|
|
7061
7284
|
stage: "enrichSignalWithAi",
|
|
7062
7285
|
error,
|
|
7063
7286
|
decision,
|
|
7064
|
-
|
|
7287
|
+
entry,
|
|
7288
|
+
market
|
|
7065
7289
|
});
|
|
7066
7290
|
throw error;
|
|
7067
7291
|
}
|
|
7292
|
+
ai = buildAiHookContext({
|
|
7293
|
+
env,
|
|
7294
|
+
ai: runtime.ai,
|
|
7295
|
+
quality
|
|
7296
|
+
});
|
|
7068
7297
|
await invokeHook(
|
|
7069
7298
|
"afterEnrichAi",
|
|
7070
7299
|
decisionManifest?.hooks?.afterEnrichAi,
|
|
7071
7300
|
{
|
|
7072
|
-
|
|
7301
|
+
ctx: decisionHookCtx,
|
|
7302
|
+
market,
|
|
7073
7303
|
decision,
|
|
7074
|
-
|
|
7075
|
-
signal,
|
|
7076
|
-
|
|
7304
|
+
entry,
|
|
7305
|
+
ml: ml ?? buildMlHookContext({ signal, env, ml: runtime.ml }),
|
|
7306
|
+
ai
|
|
7077
7307
|
},
|
|
7078
|
-
{ decision,
|
|
7308
|
+
{ decision, entry, market }
|
|
7079
7309
|
);
|
|
7080
7310
|
}
|
|
7081
7311
|
const minAiQuality = runtime.ai?.minQuality ?? 4;
|
|
7312
|
+
const policy = buildHookPolicy({
|
|
7313
|
+
quality,
|
|
7314
|
+
makeOrdersEnabled,
|
|
7315
|
+
minAiQuality
|
|
7316
|
+
});
|
|
7082
7317
|
const shouldMakeOrder = shouldExecuteEntryDecision({
|
|
7083
7318
|
makeOrdersEnabled,
|
|
7084
7319
|
env,
|
|
@@ -7102,15 +7337,15 @@ var createStrategyRuntime = ({
|
|
|
7102
7337
|
"beforeEntryGate",
|
|
7103
7338
|
decisionManifest?.hooks?.beforeEntryGate,
|
|
7104
7339
|
{
|
|
7105
|
-
|
|
7340
|
+
ctx: decisionHookCtx,
|
|
7341
|
+
market,
|
|
7106
7342
|
decision,
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
minAiQuality
|
|
7343
|
+
entry,
|
|
7344
|
+
policy,
|
|
7345
|
+
ml,
|
|
7346
|
+
ai
|
|
7112
7347
|
},
|
|
7113
|
-
{ decision,
|
|
7348
|
+
{ decision, entry, market }
|
|
7114
7349
|
);
|
|
7115
7350
|
if (entryGate?.allow === false) {
|
|
7116
7351
|
const skipReason = entryGate.reason ? `HOOK_BEFORE_ENTRY_GATE:${entryGate.reason}` : "HOOK_BEFORE_ENTRY_GATE";
|
|
@@ -7126,7 +7361,12 @@ var createStrategyRuntime = ({
|
|
|
7126
7361
|
decision,
|
|
7127
7362
|
runtime,
|
|
7128
7363
|
manifest: decisionManifest,
|
|
7129
|
-
|
|
7364
|
+
hookCtx: decisionHookCtx,
|
|
7365
|
+
market,
|
|
7366
|
+
entry,
|
|
7367
|
+
policy,
|
|
7368
|
+
ml,
|
|
7369
|
+
ai,
|
|
7130
7370
|
invokeHook,
|
|
7131
7371
|
notifyRuntimeError
|
|
7132
7372
|
});
|
|
@@ -7138,13 +7378,13 @@ var createStrategyRuntime = ({
|
|
|
7138
7378
|
var createCloseOppositeBeforePlaceOrderHook = ({
|
|
7139
7379
|
isEnabled
|
|
7140
7380
|
}) => {
|
|
7141
|
-
return async ({
|
|
7142
|
-
if (!isEnabled(
|
|
7381
|
+
return async ({ ctx, entry }) => {
|
|
7382
|
+
if (!isEnabled(ctx.strategyConfig)) {
|
|
7143
7383
|
return;
|
|
7144
7384
|
}
|
|
7145
7385
|
await closeOppositePositionsBeforeOpen({
|
|
7146
|
-
connector,
|
|
7147
|
-
entryContext
|
|
7386
|
+
connector: ctx.connector,
|
|
7387
|
+
entryContext: entry.context
|
|
7148
7388
|
});
|
|
7149
7389
|
};
|
|
7150
7390
|
};
|