Эта стратегия сочетает в себе потенциальные сигналы обратного тренда от индикатора Supertrend и индикатора MACD вместе с сигналами перекупленности/перепроданности от индикатора RSI, чтобы сформировать относительно стабильную и эффективную систему сигналов входа и выхода.
Основная логика этой стратегии заключается в совместном использовании индикатора Supertrend и индикатора MACD в качестве критериев для сигналов входа.
На стороне Супертенда стратегия использует изменение направления индикатора Супертенда в качестве потенциального сигнала обратного движения. Когда направление Супертенда поворачивается сверху вниз, генерируется сигнал покупки. Когда направление поворачивается сверху вниз, генерируется сигнал продажи.
На стороне MACD стратегия использует перекресток наклона и нулевой линии индикатора MACD на более низких временных отрезках (ежедневно) для выявления потенциальных возможностей перемены. Когда абсолютное значение наклона MACD большое (выше порога) и наклон поддерживает восходящий тренд, генерируется сигнал. Если линия MACD пересекает нулевую линию, генерируется вспомогательный сигнал.
Для входных сигналов стратегия требует, чтобы сигнал Supertrend и сигнал MACD находились в одном направлении перед отправкой торговых ордеров.
Кроме того, для сигналов выхода стратегия также использует сигналы перекупа / перепродажи от индикатора RSI. Когда RSI превышает 80, генерируется сигнал продажи. Когда RSI опускается ниже 20, генерируется сигнал покупки. Они помогают определить время обратного движения.
Наибольшее преимущество этой стратегии заключается в разнообразии индикаторных сигналов, которые могут дополнять друг друга и сделать общий сигнал более стабильным и надежным.
Сигналы обратного движения супертенденции могут улавливать относительно сильные краткосрочные тенденции; наклон MACD может оценивать силу средне-долгосрочного тренда, чтобы не быть введенным в заблуждение ложными обратными движениями; RSI может обеспечить лучшее время входа и выхода на рынке с диапазоном, указывая на уровни перекупленности / перепроданности. Складывание сигналов из нескольких индикаторов может отфильтровать некоторые шумные сделки и достичь более высокого уровня выигрыша.
Кроме того, дизайн временных рамок также является разумным. Supertrend использует часовые временные рамки, в то время как MACD использует ежедневные временные рамки. Это обеспечивает как частоту торговли, так и стабильность в суждении о тренде.
Основным риском этой стратегии является высокая вероятность путаницы сигналов между различными индикаторами. Например, Supertrend может давать ложное изменение, в то время как сигнал MACD не синхронизируется. Это может привести к ненужным потерям.
Кроме того, RSI для определения времени выхода может быть слишком ранним или слишком поздним, что препятствует максимальному периоду хранения.
Наконец, чрезмерный порог наклона MACD также может упустить более слабые возможности для обратного движения.
Эта стратегия может быть дополнительно оптимизирована из следующих аспектов:
Внедрить механизм остановки потерь, когда потеря превышает определенный процент.
Добавить динамический порог для оценки наклона MACD. Повысить порог наклона, когда волатильность рынка высока, и снизить порог, когда рынок стабилен.
Добавить условие pullback для выхода RSI. Требуется значительный callback после того, как RSI превышает 80 перед рассмотрением закрытия позиции.
Проверка MACD с объемом и посмотреть, улучшает ли он надежность сигнала
Попробовать автоматическую настройку параметров для поиска оптимальных настроек
Супертенд 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)