この戦略は,スーパートレンド指標とMACD指標からの潜在的なトレンド逆転シグナルと,RSI指標からの過剰購入/過剰売却シグナルを組み合わせ,エントリーとアウトシグナルのための比較的安定的かつ効率的なシステムを形成します.戦略名は"スーパートレンドMACD定量戦略"です.
この戦略の基本論理は,入口信号の基準としてスーパートレンド指標とMACD指標を組み合わせ使用することにある.
スーパートレンドの部分では,戦略はスーパートレンド指標の方向転換を潜在的な逆転信号として採用する. スーパートレンドの方向が上から下へと回転すると,購入信号が生成される. 方向が下から上へと回転すると,販売信号が生成される.
MACDの部分では,戦略は,潜在的逆転機会を特定するために,低時間枠 (毎日) でMACD指標の傾斜とゼロラインクロスオーバーを使用する.MACD傾斜絶対値は大きく (
入力シグナルについては,戦略では,取引オーダーを送信する前に,スーパートレンド信号とMACD信号が同じ方向にある必要があります.
また,出口シグナルについては,戦略はRSIインジケーターからのオーバーバイト/オーバーセールシグナルも採用している.RSIが80を超えると,セールシグナルが生成される.RSIが20を下回ると,買いシグナルが生成される.これらは逆転タイミングを決定するのに役立ちます.
この戦略の最大の利点は,指標信号の多様性です.異なる指標が互いに補完し,全体的な信号をより安定し信頼性のあるものにすることができます.
スーパートレンド逆転シグナルは,比較的強い短期トレンドを捉えることができる.MACD傾斜は,誤った逆転に誤導されないように中長期トレンド強さを判断することができる.RSIは,過剰購入/過剰販売レベルを表示することによって,範囲内市場における最高のエントリーと出口タイミングを提供することができる.複数の指標からの信号を積み重ねることで,いくつかの騒々しい取引をフィルタリングし,より高い勝利率を達成することができる.
また,タイムフレーム設計も合理的です.スーパートレンドは時間フレームを使用し,MACDは日時フレームを使用します.これは取引頻度とトレンド判断の安定性の両方を保証します.
この戦略の主なリスクは,異なる指標の間の信号を混同する高い確率である.例えば,MACD信号が同期しない間,スーパートレンドは誤った逆転を与える可能性があります.これは不必要な損失につながる可能性があります.
さらに,退出タイミングを決定するためのRSIは,最大保持期間を防ぐために,あまりにも早くまたは遅すぎることもあります.
最後に,MACD傾斜値が大きすぎると,逆転の機会が弱くなる可能性があります.
この戦略は,次の側面からさらに最適化できます.
ストップ・ロスのメカニズムを導入します ストップ・ロスは一定パーセントを超えるとします
MACD 傾斜判断のための動的
RSI出口判断のための引き戻し条件を追加します.RSIが80を超えた後に重要なコールバックが必要になります.
マックドをボリュームでテストし,信号信頼性を向上させるかどうかを確認します.
最適な設定を見つけるために自動パラメータ調節を試す
超トレンドMACD定量戦略は,複数の指標からのシグナルを組み合わせてエントリー・アウトシグナルを提供する.その利点は安定したシグナルと比較的高い勝利率にある.パラメータ最適化によりさらなる改善を達成することができる.リスクと最適化方向性は主にパラメータオーバーフィッティングの問題に焦点を当てている.全体として,この戦略はライブ取引に強力な実用的な価値を持っています.
/*backtest start: 2022-12-19 00:00:00 end: 2023-12-25 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy("SuperTrend.MACD Strategy", overlay=false, default_qty_type=strategy.percent_of_equity, default_qty_value=100, initial_capital=100000, pyramiding=5, process_orders_on_close=true) // ---------------- Utility Functions ---------------- getArrayValue(float[] arr, int ago) => if ago >= 0 array.get(arr, ago >= array.size(arr) ? na: array.size(arr) + -1 * ago -1) else na filterNA(float[] a, s, int y) => int x = 0 if not na(s[0]) array.push(a, s[0]) if array.size(a) > y array.shift(a) a pine_rsi(float[] x, int y) => x0 = getArrayValue(x, 0) x1 = getArrayValue(x, 1) u = math.max(x0 - x1, 0) // upward ta.change d = math.max(x1 - x0, 0) // downward ta.change rs = ta.rma(u, y) / ta.rma(d, y) res = 100 - 100 / (1 + rs) res turnAround(float[] arr) => int isTurnAround = 0 now = getArrayValue(arr, 0) p1 = getArrayValue(arr, 1) p2 = getArrayValue(arr, 2) if p1 > now and p1 > p2 isTurnAround := -1 else if p1 < now and p1 < p2 isTurnAround := 1 intergerizeSignal(i) => i>0 ? 1 : i<0 ? -1 : 0 linreg(float[] y, int n, int offset=0) => float slope = na float intercept = na int endcursor = offset + n - 1 if array.size(y) > endcursor float sumX = 0 float sumX2 = 0 float sumY = 0 float sumY2 = 0 float sumXY = 0 for i=offset to endcursor yv = array.get(y, i) sumY += yv sumY2 += math.pow(yv, 2) sumX += i sumX2 += math.pow(i, 2) sumXY += i*yv // Pearson correlation coefficient r = (n * sumXY - sumX * sumY) / math.sqrt((n * sumY2 - math.pow(sumY, 2)) * (n * sumX2 - math.pow(sumX, 2))) // Coefficient of determination r2 = math.pow(r, 2) meanX = sumX / n meanY = sumY / n slope := (n * sumXY - sumX * sumY) / (n * sumX2 - math.pow(sumX, 2)) intercept := meanY - slope * meanX [slope, intercept] isStartOfDay() => dayofweek != dayofweek[1] // ---------------- Variables ---------------- varip float st_signal = 0 varip float macd_signal = 0 varip float macd_close_signal = 0 varip float histo_signal = 0 var int openSignal = 0 var int closeSignal = 0 // -------------------------------- Supertrend Signal (Open) -------------------------------- // ST calculation atrPeriod = input(10, "Supertrend ATR Length") factor = input.float(2.0, "Supertrend Factor", step = 0.01) [_, direction] = ta.supertrend(factor, atrPeriod) st_direction_change = ta.change(direction) if st_direction_change < 0 st_signal := 4 if st_direction_change > 0 st_signal := -4 // -------------------------------- MACD Signal (Open + Close) -------------------------------- // MACD Calculation fastLength = input(12, title="MACD Fast Length") slowLength = input(26, title="MACD Slow Length") signalLength = input(9, title="MACD Signal Length") macdSlowTimeframe = input.timeframe("D", "MACD Timeframe") macdSlopeLookbackOpen = input(7, title="MACD Slope Lookback - Open") macdSlopeLookbackClose = input(3, title="MACD Slope Lookback - Close") dailyClose = request.security(syminfo.tickerid, macdSlowTimeframe, close, barmerge.gaps_on) [macdLine, signalLine, _] = ta.macd(dailyClose, fastLength, slowLength, signalLength) // MACD Slope calculation varip macdHistory = array.new<float>(0) varip macdSlowSlopeArr = array.new<float>(0) varip float macdSlowSlope = na varip float macdCloseSlope = na if not na(macdLine[0]) array.push(macdHistory, macdLine[0]) if array.size(macdHistory) > macdSlopeLookbackOpen array.shift(macdHistory) [s1, _] = linreg(macdHistory, macdSlopeLookbackOpen) macdSlowSlope := s1 array.push(macdSlowSlopeArr, macdSlowSlope) if array.size(macdSlowSlopeArr) > macdSlopeLookbackClose array.shift(macdSlowSlopeArr) [s2, _] = linreg(macdSlowSlopeArr, macdSlopeLookbackClose) macdCloseSlope := s2 // MACD Signal Calculation // > open signal threshold_macdSlowSlope = input.float(0.75, "MACD Slope Open Threshold", step = 0.05) macdSlowSlopeOverThreshold = math.abs(macdSlowSlope) >= threshold_macdSlowSlope macdSlowSlopeTrend = macdSlowSlope - getArrayValue(macdSlowSlopeArr, 1) macdSlowSlopeTrendConfirm = macdSlowSlope*macdSlowSlopeTrend >0 if (macdSlowSlopeOverThreshold and macdSlowSlopeTrendConfirm) macd_signal := 3*macdSlowSlope/math.abs(macdSlowSlope) else macd_signal := 0 // > close signal int macdCloseSignal = 0 macdCloseSignal := intergerizeSignal(macdCloseSlope) // Histogram signal Calculation histSlow = macdLine - signalLine if (ta.crossover(histSlow, 0)) histo_signal := 2 if (ta.crossunder(histSlow, 0)) histo_signal := -2 // -------------------------------- RSI Signal (Close) -------------------------------- int rsiCloseSignal = 0 varip float rsiSlow = na rsiPeriod = input(14, title="RSI Period") varip dailyCloseRSIFilter = array.new_float() // rewrite pine_rsi to remove NaN value from series at calculation dailyCloseRSIFilter := filterNA(dailyCloseRSIFilter, dailyClose, rsiPeriod) if not na(dailyClose[0]) rsiSlow := pine_rsi(dailyCloseRSIFilter, rsiPeriod) if rsiSlow > 80 rsiCloseSignal := -1 else if rsiSlow < 20 rsiCloseSignal := 1 else rsiCloseSignal := 0 // -------------------------------- Overall Signal -------------------------------- // Close signal closeSignals = array.from(macdCloseSignal, rsiCloseSignal) closeSignal := array.includes(closeSignals, 1) ? 1 : array.includes(closeSignals, -1) ? -1 : 0 closeSignal := closeSignal * 5 // Open signal if (macd_signal * st_signal > 0) and (macd_signal * macd_close_signal >= 0) openSignal := intergerizeSignal(st_signal) openSignal := openSignal * 6 else openSignal := 0 // -------------------------------- Order -------------------------------- // if strategy.position_size == 0 if openSignal * closeSignal >=0 if openSignal > 0 strategy.entry("Long Entry", strategy.long) else if openSignal < 0 strategy.entry("Short Entry", strategy.short) if strategy.position_size != 0 if closeSignal < 0 strategy.close("Long Entry") if closeSignal > 0 strategy.close("Short Entry") // -------------------------------- Plot -------------------------------- plot(closeSignal, title="Close Signal", color=color.red, linewidth = 1, style=plot.style_area) plot(openSignal, title="Open Signal", color=color.green, linewidth = 1, style=plot.style_area) plot(st_signal, title="ST Signal", color=color.black, linewidth = 1, style=plot.style_circles) plot(macd_signal, title="MACD Signal", color=color.blue, linewidth = 1, style=plot.style_circles) // plot(macdSlowSlope, title="macd slow slope", color=color.purple, linewidth = 1, style=plot.style_line) // plot(macdCloseSlope, title="macd slow slope", color=color.lime, linewidth = 1, style=plot.style_line) hline(0, "Zero Line", color=color.gray)