@tradejs/strategies 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/chunk-37ZWRG3W.mjs +128 -0
- package/dist/chunk-H4MHFD4B.mjs +62 -0
- package/dist/{chunk-MOBKL73M.mjs → chunk-IMLNXICX.mjs} +183 -41
- package/dist/{chunk-XMRB45ZO.mjs → chunk-QVWMBYYM.mjs} +92 -45
- package/dist/chunk-SOVTOGY4.mjs +163 -0
- package/dist/{chunk-H2TU2YMA.mjs → chunk-TDUTYEGH.mjs} +111 -76
- package/dist/{chunk-GNQJ5TVU.mjs → chunk-UK4YHD2E.mjs} +34 -38
- package/dist/index.d.mts +294 -13
- package/dist/index.d.ts +294 -13
- package/dist/index.js +1825 -906
- package/dist/index.mjs +51 -18
- package/dist/{strategy-FYNNJDOH.mjs → strategy-ABIO65CR.mjs} +2 -33
- package/dist/{strategy-AFIGEHDS.mjs → strategy-D7H5J3C4.mjs} +1 -71
- package/dist/{strategy-LC2FSFVN.mjs → strategy-HQIPCUOY.mjs} +1 -72
- package/dist/{strategy-Y4SOK6FF.mjs → strategy-JQIJILHQ.mjs} +28 -109
- package/dist/strategy-QEIPAPY4.mjs +373 -0
- package/dist/{strategy-6TS2NFSC.mjs → strategy-WYN4FZ5S.mjs} +2 -125
- package/dist/{strategy-OI4WRB3S.mjs → strategy-XTUKPYPM.mjs} +466 -120
- package/package.json +5 -5
- package/dist/chunk-3PN7ZSJJ.mjs +0 -27
- package/dist/chunk-RDK2JK3K.mjs +0 -28
|
@@ -166,26 +166,28 @@ var buildVolumeDivergenceSetupFeatures = ({
|
|
|
166
166
|
|
|
167
167
|
// src/VolumeDivergence/adapters/ai.ts
|
|
168
168
|
var VOLUME_DIVERGENCE_CONTEXT_PROMPT = `
|
|
169
|
-
|
|
170
|
-
-
|
|
171
|
-
- Bullish divergence
|
|
172
|
-
- Bearish divergence
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
- confirmationDistancePct
|
|
183
|
-
- additionalIndicators.deltaAtPivot
|
|
169
|
+
VolumeDivergence addon:
|
|
170
|
+
- This is a reversal setup built on price and normalized-volume divergence, not a breakout strategy.
|
|
171
|
+
- Bullish divergence means price makes a lower low while volume makes a higher low.
|
|
172
|
+
- Bearish divergence means price makes a higher high while volume makes a lower high.
|
|
173
|
+
- For a bullish signal, do not overstate quality if price still failed to bounce meaningfully away from the current pivot low or failed to reclaim enough structure.
|
|
174
|
+
- For a bearish signal, mirror that logic: do not overstate quality if price failed to move down meaningfully away from the current pivot high.
|
|
175
|
+
- If \`payload.additionalIndicators.volumeDivergenceContext.confirmationReady=false\`, this is usually not a fully confirmed reversal yet; quality is often \`<= 4\` and a retest or confirmation is often still needed.
|
|
176
|
+
- For live approval, treat \`confirmationReady\` as much more important than \`structureAdvanced\`; structure advance alone does not mean the reversal is entry-ready.
|
|
177
|
+
- For a reversal setup, do not automatically reward quality just because the coin or BTC MA bias already matches the signal direction.
|
|
178
|
+
- For LONG with \`entryTiming=structure_advance\`, avoid \`quality=5\`; that is an intermediate phase, not a fully confirmed reversal.
|
|
179
|
+
- Be stricter for SHORT than for LONG: a bearish reversal should require cleaner follow-through, and bias or delta conflict should reduce quality more aggressively.
|
|
180
|
+
- If \`deltaAtPivot\` conflicts with the reversal direction or the coin/BTC bias conflicts with the signal, do not overstate quality just because divergence exists.
|
|
181
|
+
- Use \`divergenceAmplitudeAtrRatio\`, \`reclaimPct\`, and \`confirmationCandleQuality\` as explicit setup features describing how meaningful the divergence is relative to ATR, how much structure price reclaimed, and how strong the confirmation candle was.
|
|
182
|
+
- \`confirmationDistancePct\` tells you how far price moved beyond the confirmation level; do not overstate quality when confirmation exists only marginally.
|
|
183
|
+
- \`additionalIndicators.deltaAtPivot\` is a proxy net-volume value on the pivot candle, not true lower-timeframe TradingView volume delta.
|
|
184
|
+
- If \`payload.additionalIndicators.derivativesContext\` exists, use Coinalyze-derived open interest, funding, and liquidations as positioning context: a liquidation flush can strengthen reversal odds, while crowded positioning against the trade or stale or missing data should not mechanically increase quality.
|
|
184
185
|
`;
|
|
185
186
|
var VOLUME_DIVERGENCE_PAYLOAD_PROMPT = `
|
|
186
|
-
-
|
|
187
|
+
- \`payload.additionalIndicators.volumeDivergenceContext\` contains a compact divergence-strength summary:
|
|
187
188
|
divergenceKind / confirmationPrice / confirmationReady / structureAdvanced / reboundFromPivotPct / confirmationDistancePct / priceDisplacementPct / divergenceAmplitudeAtrRatio / reclaimPct / confirmationCandleQuality / volumeDivergenceStrength / deltaAligned / coinBiasAligned / btcBiasAligned / deterministicQuality / approvalAllowedNow / structuralHardBlockReasons / maxAllowedQuality.
|
|
188
|
-
-
|
|
189
|
+
- Use this context as the explicit strategy-specific summary instead of trying to derive the same conclusion again only from generic candles.
|
|
190
|
+
- If \`payload.additionalIndicators.derivativesContext\` exists, it is a Coinalyze-derived summary of derivatives state at signal time; \`stale\` or \`missing_derivatives\` means that Coinalyze context must not be used.
|
|
189
191
|
`;
|
|
190
192
|
var toFiniteNumberOrNull = (value) => {
|
|
191
193
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -622,13 +624,13 @@ var clampQuality = (quality, maxAllowedQuality) => Math.max(1, Math.min(5, Math.
|
|
|
622
624
|
var getHardBlockReasonText = (reason) => {
|
|
623
625
|
switch (reason) {
|
|
624
626
|
case "no_rebound_from_pivot":
|
|
625
|
-
return "
|
|
627
|
+
return "price failed to move away from the pivot in the reversal direction";
|
|
626
628
|
case "weak_divergence_amplitude":
|
|
627
|
-
return "
|
|
629
|
+
return "divergence amplitude is too small relative to ATR";
|
|
628
630
|
case "weak_reclaim":
|
|
629
|
-
return "
|
|
631
|
+
return "price reclaimed too little structure after the pivot";
|
|
630
632
|
case "weak_confirmation_candle":
|
|
631
|
-
return "confirmation candle
|
|
633
|
+
return "confirmation candle is too weak";
|
|
632
634
|
default:
|
|
633
635
|
return reason;
|
|
634
636
|
}
|
|
@@ -638,9 +640,9 @@ var buildGuardrailReason = (context) => {
|
|
|
638
640
|
return `VolumeDivergence guardrail: ${context.hardBlockReasons.map(getHardBlockReasonText).join("; ")}.`;
|
|
639
641
|
}
|
|
640
642
|
if (!context.confirmationReady && context.entryTiming == null) {
|
|
641
|
-
return "VolumeDivergence guardrail: reversal
|
|
643
|
+
return "VolumeDivergence guardrail: reversal is visible, but the confirmation level has not been cleared yet.";
|
|
642
644
|
}
|
|
643
|
-
return "VolumeDivergence guardrail: quality
|
|
645
|
+
return "VolumeDivergence guardrail: quality is limited by confirmation state and the strength of reversal away from the pivot.";
|
|
644
646
|
};
|
|
645
647
|
var postProcessAnalysis = ({
|
|
646
648
|
signal,
|
|
@@ -668,8 +670,8 @@ var postProcessAnalysis = ({
|
|
|
668
670
|
takeProfitPrice: null,
|
|
669
671
|
stopLossPrice: null,
|
|
670
672
|
qualityReason: analysis.qualityReason || buildGuardrailReason(context),
|
|
671
|
-
triggerInvalidation: analysis.triggerInvalidation || (context.confirmationPrice != null ?
|
|
672
|
-
comment: analysis.comment || (context.hardBlockReasons.length > 0 ? `VolumeDivergence
|
|
673
|
+
triggerInvalidation: analysis.triggerInvalidation || (context.confirmationPrice != null ? `Wait for reversal confirmation relative to level ${context.confirmationPrice}.` : "Wait for a confirmed reversal after the pivot."),
|
|
674
|
+
comment: analysis.comment || (context.hardBlockReasons.length > 0 ? `VolumeDivergence rejected: ${context.hardBlockReasons.map(getHardBlockReasonText).join("; ")}.` : "VolumeDivergence remains in watch mode until the reversal is confirmed.")
|
|
673
675
|
};
|
|
674
676
|
}
|
|
675
677
|
return {
|
|
@@ -697,7 +699,7 @@ ${VOLUME_DIVERGENCE_PAYLOAD_PROMPT}`,
|
|
|
697
699
|
const context = getVolumeDivergenceContextFromPayload(payload, signal);
|
|
698
700
|
return `
|
|
699
701
|
|
|
700
|
-
|
|
702
|
+
Additional VolumeDivergence context:
|
|
701
703
|
- divergenceKind=${context.divergenceKind ?? "n/a"}
|
|
702
704
|
- confirmationPrice=${context.confirmationPrice ?? "n/a"}
|
|
703
705
|
- confirmationReady=${context.confirmationReady}
|
|
@@ -724,15 +726,15 @@ ${VOLUME_DIVERGENCE_PAYLOAD_PROMPT}`,
|
|
|
724
726
|
- maxAllowedQuality=${context.maxAllowedQuality}
|
|
725
727
|
- hardBlockReasons=${context.hardBlockReasons.join(", ") || "none"}
|
|
726
728
|
|
|
727
|
-
|
|
728
|
-
-
|
|
729
|
-
- confirmationReady=false
|
|
730
|
-
-
|
|
731
|
-
-
|
|
729
|
+
Interpretation rules for VolumeDivergence:
|
|
730
|
+
- first evaluate whether there is a real reversal away from the pivot, not just divergence on paper;
|
|
731
|
+
- \`confirmationReady=false\` usually means the reversal is not fully confirmed yet;
|
|
732
|
+
- if price did not bounce away from the current pivot in the signal direction, do not treat the setup as confirmed;
|
|
733
|
+
- delta or bias conflict should reduce quality, not be ignored.
|
|
732
734
|
`;
|
|
733
735
|
},
|
|
734
|
-
mapEntryRuntimeFromConfig: (
|
|
735
|
-
|
|
736
|
+
mapEntryRuntimeFromConfig: (config2) => mapAiRuntimeFromConfig(
|
|
737
|
+
config2
|
|
736
738
|
)
|
|
737
739
|
};
|
|
738
740
|
|
|
@@ -757,33 +759,78 @@ var volumeDivergenceMlAdapter = {
|
|
|
757
759
|
normalizeStrategyConfig: (strategyConfig) => {
|
|
758
760
|
return toVolumeDivergenceMlStrategyConfig(strategyConfig);
|
|
759
761
|
},
|
|
760
|
-
mapEntryRuntimeFromConfig: (
|
|
762
|
+
mapEntryRuntimeFromConfig: (config2) => mapMlRuntimeFromConfig(config2, {
|
|
761
763
|
strategyConfig: toVolumeDivergenceMlStrategyConfig(
|
|
762
|
-
|
|
764
|
+
config2
|
|
763
765
|
)
|
|
764
766
|
})
|
|
765
767
|
};
|
|
766
768
|
|
|
767
|
-
// src/VolumeDivergence/hooks.ts
|
|
768
|
-
import { createCloseOppositeBeforePlaceOrderHook } from "@tradejs/node/strategies";
|
|
769
|
-
var volumeDivergenceBeforePlaceOrderHook = createCloseOppositeBeforePlaceOrderHook({
|
|
770
|
-
isEnabled: (config) => Boolean(config.CLOSE_OPPOSITE_POSITIONS)
|
|
771
|
-
});
|
|
772
|
-
|
|
773
769
|
// src/VolumeDivergence/manifest.ts
|
|
774
770
|
var volumeDivergenceManifest = {
|
|
775
771
|
name: "VolumeDivergence",
|
|
776
|
-
hooks: {
|
|
777
|
-
beforePlaceOrder: volumeDivergenceBeforePlaceOrderHook
|
|
778
|
-
},
|
|
779
772
|
aiAdapter: volumeDivergenceAiAdapter,
|
|
780
773
|
mlAdapter: volumeDivergenceMlAdapter
|
|
781
774
|
};
|
|
782
775
|
|
|
776
|
+
// src/VolumeDivergence/config.ts
|
|
777
|
+
var config = {
|
|
778
|
+
ENV: "BACKTEST",
|
|
779
|
+
INTERVAL: "15",
|
|
780
|
+
MAKE_ORDERS: true,
|
|
781
|
+
CLOSE_OPPOSITE_POSITIONS: false,
|
|
782
|
+
BACKTEST_PRICE_MODE: "mid",
|
|
783
|
+
AI_ENABLED: false,
|
|
784
|
+
AI_MODE: "llm",
|
|
785
|
+
ML_ENABLED: false,
|
|
786
|
+
ML_THRESHOLD: 0.1,
|
|
787
|
+
MIN_AI_QUALITY: 3,
|
|
788
|
+
FEE_PERCENT: 5e-3,
|
|
789
|
+
MAX_LOSS_VALUE: 10,
|
|
790
|
+
MA_FAST: 14,
|
|
791
|
+
MA_MEDIUM: 49,
|
|
792
|
+
MA_SLOW: 50,
|
|
793
|
+
OBV_SMA: 10,
|
|
794
|
+
ATR: 14,
|
|
795
|
+
ATR_PCT_SHORT: 7,
|
|
796
|
+
ATR_PCT_LONG: 30,
|
|
797
|
+
BB: 20,
|
|
798
|
+
BB_STD: 2,
|
|
799
|
+
MACD_FAST: 12,
|
|
800
|
+
MACD_SLOW: 26,
|
|
801
|
+
MACD_SIGNAL: 9,
|
|
802
|
+
LEVEL_LOOKBACK: 20,
|
|
803
|
+
LEVEL_DELAY: 2,
|
|
804
|
+
NORMALIZATION_LENGTH: 100,
|
|
805
|
+
PIVOT_LOOKBACK_LEFT: 8,
|
|
806
|
+
PIVOT_LOOKBACK_RIGHT: 3,
|
|
807
|
+
MIN_BARS_BETWEEN_PIVOTS: 4,
|
|
808
|
+
MAX_BARS_BETWEEN_PIVOTS: 36,
|
|
809
|
+
ALLOW_STRUCTURE_ADVANCE_ENTRY: false,
|
|
810
|
+
MIN_DIVERGENCE_AMPLITUDE_ATR_RATIO: 0.35,
|
|
811
|
+
MIN_RECLAIM_PCT: 105,
|
|
812
|
+
MIN_CONFIRMATION_CANDLE_QUALITY: 0.58,
|
|
813
|
+
BULLISH: {
|
|
814
|
+
enable: true,
|
|
815
|
+
direction: "LONG",
|
|
816
|
+
TP: 4,
|
|
817
|
+
SL: 1.3,
|
|
818
|
+
minRiskRatio: 2
|
|
819
|
+
},
|
|
820
|
+
BEARISH: {
|
|
821
|
+
enable: true,
|
|
822
|
+
direction: "SHORT",
|
|
823
|
+
TP: 4,
|
|
824
|
+
SL: 1.3,
|
|
825
|
+
minRiskRatio: 2
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
|
|
783
829
|
export {
|
|
784
830
|
getVolumeDivergenceEntryThresholds,
|
|
785
831
|
buildVolumeDivergenceSetupFeatures,
|
|
786
832
|
volumeDivergenceAiAdapter,
|
|
787
833
|
volumeDivergenceMlAdapter,
|
|
788
|
-
volumeDivergenceManifest
|
|
834
|
+
volumeDivergenceManifest,
|
|
835
|
+
config
|
|
789
836
|
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// src/TrendShift/adapters/ai.ts
|
|
2
|
+
import { mapAiRuntimeFromConfig } from "@tradejs/core/strategies";
|
|
3
|
+
var getTrendShiftContext = (payload) => {
|
|
4
|
+
const additional = payload.additionalIndicators;
|
|
5
|
+
const raw = additional?.trendShiftContext ?? {};
|
|
6
|
+
const hardBlockReasons = [];
|
|
7
|
+
if (!raw.confirmedFlip) {
|
|
8
|
+
hardBlockReasons.push("unconfirmed_flip");
|
|
9
|
+
}
|
|
10
|
+
if (!raw.flipDistanceOk) {
|
|
11
|
+
hardBlockReasons.push("weak_flip_distance");
|
|
12
|
+
}
|
|
13
|
+
if (raw.coinBiasAligned === false) {
|
|
14
|
+
hardBlockReasons.push("coin_bias_conflict");
|
|
15
|
+
}
|
|
16
|
+
const slopeAbs = Math.abs(raw.avgSlopePct ?? 0);
|
|
17
|
+
const distanceAtrRatio = raw.distanceAtrRatio ?? 0;
|
|
18
|
+
const closeVsAvgPctAbs = Math.abs(raw.closeVsAvgPct ?? 0);
|
|
19
|
+
let deterministicQuality = 3;
|
|
20
|
+
if (hardBlockReasons.length > 0) {
|
|
21
|
+
deterministicQuality = raw.confirmedFlip ? 2 : 1;
|
|
22
|
+
} else if (distanceAtrRatio >= 0.8 && slopeAbs >= 0.09 && closeVsAvgPctAbs >= 0.12) {
|
|
23
|
+
deterministicQuality = 5;
|
|
24
|
+
} else if (distanceAtrRatio >= 0.45 && slopeAbs >= 0.04 && closeVsAvgPctAbs >= 0.05) {
|
|
25
|
+
deterministicQuality = 4;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
...raw,
|
|
29
|
+
deterministicQuality,
|
|
30
|
+
approvalAllowedNow: deterministicQuality >= 4,
|
|
31
|
+
hardBlockReasons
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
var reasonText = (reason) => {
|
|
35
|
+
switch (reason) {
|
|
36
|
+
case "unconfirmed_flip":
|
|
37
|
+
return "the internal flip is not confirmed yet";
|
|
38
|
+
case "weak_flip_distance":
|
|
39
|
+
return "price moved away from the adaptive average too weakly";
|
|
40
|
+
case "coin_bias_conflict":
|
|
41
|
+
return "coin MA bias conflicts with the flip direction";
|
|
42
|
+
default:
|
|
43
|
+
return reason;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var trendShiftAiAdapter = {
|
|
47
|
+
buildPayload: ({ signal, basePayload }) => ({
|
|
48
|
+
...basePayload,
|
|
49
|
+
additionalIndicators: {
|
|
50
|
+
...basePayload.additionalIndicators,
|
|
51
|
+
trendShiftContext: signal.additionalIndicators?.trendShiftContext
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
postProcessAnalysis: ({ payload, analysis }) => {
|
|
55
|
+
const context = getTrendShiftContext(payload);
|
|
56
|
+
const requestedDirection = analysis.direction === "LONG" || analysis.direction === "SHORT" ? analysis.direction : context.signalDirection;
|
|
57
|
+
if (context.approvalAllowedNow === true && requestedDirection != null) {
|
|
58
|
+
return {
|
|
59
|
+
...analysis,
|
|
60
|
+
direction: requestedDirection,
|
|
61
|
+
quality: context.deterministicQuality,
|
|
62
|
+
approved: true
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
...analysis,
|
|
67
|
+
direction: null,
|
|
68
|
+
quality: context.deterministicQuality,
|
|
69
|
+
approved: false,
|
|
70
|
+
rejectReason: context.hardBlockReasons.length > 0 ? context.hardBlockReasons.map(reasonText).join("; ") : "the flip still does not look strong enough for live approval"
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
buildHumanPromptAddon: ({ payload }) => {
|
|
74
|
+
const context = getTrendShiftContext(payload);
|
|
75
|
+
return `
|
|
76
|
+
Additional TrendShift context:
|
|
77
|
+
- signalDirection=${context.signalDirection ?? "n/a"}
|
|
78
|
+
- confirmedFlip=${String(context.confirmedFlip)}
|
|
79
|
+
- bullFlip=${String(context.bullFlip)}
|
|
80
|
+
- bearFlip=${String(context.bearFlip)}
|
|
81
|
+
- flipDistanceOk=${String(context.flipDistanceOk)}
|
|
82
|
+
- closeVsAvgPct=${String(context.closeVsAvgPct ?? "n/a")}
|
|
83
|
+
- bandWidthPct=${String(context.bandWidthPct ?? "n/a")}
|
|
84
|
+
- avgSlopePct=${String(context.avgSlopePct ?? "n/a")}
|
|
85
|
+
- distanceAtrRatio=${String(context.distanceAtrRatio ?? "n/a")}
|
|
86
|
+
- coinBias=${context.coinBias ?? "n/a"}
|
|
87
|
+
- coinBiasAligned=${String(context.coinBiasAligned)}
|
|
88
|
+
- deterministicQuality=${context.deterministicQuality}
|
|
89
|
+
- approvalAllowedNow=${context.approvalAllowedNow}
|
|
90
|
+
- hardBlockReasons=${JSON.stringify(context.hardBlockReasons)}
|
|
91
|
+
|
|
92
|
+
Interpretation rules for TrendShift:
|
|
93
|
+
- This is a trend-state flip strategy, not a forecast of future impulse.
|
|
94
|
+
- If approvalAllowedNow=false, do not describe the signal as a fully confirmed live entry.
|
|
95
|
+
- If hardBlockReasons is not empty, explain exactly what is still missing for confirmation.
|
|
96
|
+
`.trim();
|
|
97
|
+
},
|
|
98
|
+
mapEntryRuntimeFromConfig: (config2) => mapAiRuntimeFromConfig(
|
|
99
|
+
config2
|
|
100
|
+
)
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/TrendShift/manifest.ts
|
|
104
|
+
var trendShiftManifest = {
|
|
105
|
+
name: "TrendShift",
|
|
106
|
+
aiAdapter: trendShiftAiAdapter
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/TrendShift/config.ts
|
|
110
|
+
var config = {
|
|
111
|
+
ENV: "BACKTEST",
|
|
112
|
+
INTERVAL: "15",
|
|
113
|
+
MAKE_ORDERS: true,
|
|
114
|
+
CLOSE_OPPOSITE_POSITIONS: false,
|
|
115
|
+
BACKTEST_PRICE_MODE: "mid",
|
|
116
|
+
AI_ENABLED: false,
|
|
117
|
+
AI_MODE: "llm",
|
|
118
|
+
ML_ENABLED: false,
|
|
119
|
+
ML_THRESHOLD: 0.1,
|
|
120
|
+
MIN_AI_QUALITY: 3,
|
|
121
|
+
FEE_PERCENT: 5e-3,
|
|
122
|
+
MAX_LOSS_VALUE: 10,
|
|
123
|
+
MA_FAST: 14,
|
|
124
|
+
MA_MEDIUM: 49,
|
|
125
|
+
MA_SLOW: 50,
|
|
126
|
+
OBV_SMA: 10,
|
|
127
|
+
ATR: 14,
|
|
128
|
+
ATR_PCT_SHORT: 7,
|
|
129
|
+
ATR_PCT_LONG: 30,
|
|
130
|
+
BB: 20,
|
|
131
|
+
BB_STD: 2,
|
|
132
|
+
MACD_FAST: 12,
|
|
133
|
+
MACD_SLOW: 26,
|
|
134
|
+
MACD_SIGNAL: 9,
|
|
135
|
+
TRENDSHIFT_MULTIPLICATIVE_FACTOR: 4,
|
|
136
|
+
TRENDSHIFT_SLOPE: 12,
|
|
137
|
+
TRENDSHIFT_ATR_LENGTH: 150,
|
|
138
|
+
TRENDSHIFT_WIDTH_PCT: 75,
|
|
139
|
+
TRENDSHIFT_CONFIRM_FLIP_WITH_CLOSE: true,
|
|
140
|
+
TRENDSHIFT_MIN_FLIP_DISTANCE_ATR: 0.15,
|
|
141
|
+
TRENDSHIFT_EXIT_ON_OPPOSITE_FLIP: true,
|
|
142
|
+
TRENDSHIFT_MAX_FIGURE_POINTS: 180,
|
|
143
|
+
LONG: {
|
|
144
|
+
enable: true,
|
|
145
|
+
direction: "LONG",
|
|
146
|
+
TP: 2.8,
|
|
147
|
+
SL: 1.1,
|
|
148
|
+
minRiskRatio: 1.6
|
|
149
|
+
},
|
|
150
|
+
SHORT: {
|
|
151
|
+
enable: true,
|
|
152
|
+
direction: "SHORT",
|
|
153
|
+
TP: 2.8,
|
|
154
|
+
SL: 1.1,
|
|
155
|
+
minRiskRatio: 1.6
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export {
|
|
160
|
+
trendShiftAiAdapter,
|
|
161
|
+
trendShiftManifest,
|
|
162
|
+
config
|
|
163
|
+
};
|