헐크 풀백 역전 (Hulk Pullback Reversal) 은 추락 단계에서 트렌드 반전을 식별하기 위해 이동 평균, MACD, RSI 및 ADX를 활용하는 전략이다. 특히 공격적인 트렌드 추종자를 대상으로, 역전 거래를위한 일반적인 추락 특성을 활용합니다.
이 전략은 EMA를 사용하여 전체 트렌드 방향을 결정하고 강점 / 약점 영역을 구축합니다. 가격이 강점에서 약점으로 물러날 때 전략은 잠재적 인 역전 기회를 식별합니다.
잘못된 항목을 필터링하기 위해 MACD는 단기 반전 신호를 확인하기 위해 통합됩니다. MACD 절대 값이 특정 임계치를 초과하면 반전 확률이 증가합니다. ADX는 또한 시장이 범위가 아닌 트렌드를 보장하는 수준 이상의 수준이 필요합니다.
마지막으로, RSI는 과잉 구매/ 과잉 판매 지역을 피하기 위해 작용합니다. RSI 값이 정의된 범위 내에 있을 때만 신호가 생성됩니다.
트레이드 수치는 EMA의 모든 크로스오버에 재설정됩니다. 또한 크로스오버 당 최대 트레이드 한도를 설정하여 과잉 트레이딩을 피할 수 있습니다.
조건이 충족되면 리버설 트레이드를 실행하기 위해 스톱 로스 및 영업률을 기반으로 주문을 합니다.
이 전략의 가장 큰 장점은 복수 지표 필터링이 신뢰성을 향상시키는 것으로 풀백 패턴을 활용하여 강점 / 약점 영역을 구축하기 위해 EMA를 사용하는 것입니다.
단일 오시레이터 지표와 비교하면 트렌드 결정의 추가가 불필요한 반전을 피하는 데 도움이됩니다. EMA 크로스오버 당 최대 거래를 제어하는 것도 과도한 거래를 방지합니다.
가장 큰 위험은 트렌드 추종자가 EMA를 직접 깨고 뒤로 물러나지 않을 때입니다. 이것은 잘못된 신호를 생성하고 손실을 유발할 것입니다. 하락세를 제어하기 위해 중지 손실이 필요합니다.
부적절한 지표 매개 변수 또한 신호 품질을 저하시킬 수 있습니다. 매개 변수는 여러 번 테스트하고 다른 시장 조건에 최적화해야합니다.
마지막으로, 너무 큰 스톱 로스 및 반전 후 지속적인 공격은 단일 거래 손실을 증가시킬 수 있습니다. 합리적인 스톱 및 리스크 관리는 필수적입니다.
이 전략은 다음과 같은 측면에서 최적화 될 수 있습니다.
다른 시장과 매개 변수를 테스트하여 EMA가 트렌드를 더 잘 측정할 수 있습니다.
MACD 매개 변수를 최적화하여 보다 정확하고 신뢰할 수 있는 반전 신호를 제공합니다.
너무 공격적인 과잉 구매/ 과잉 판매 수준을 피하기 위해 RSI 범위를 조정합니다.
스톱 로스를 최적화하고 수익률을 취하여 단일 거래 위험을 줄이십시오.
헐크 풀백 역전 전략은 공격적인 트렌드 추종자들의 역전 패턴을 구체적으로 대상으로 단기적 역전 기회를 효과적으로 포착합니다. 그것은 다층 트렌드 방향과 강도 필터링을 위해 EMA를 활용하며, 높은 신뢰성 진입 확인을 위해 MACD, RSI를 사용합니다. 적절한 매개 변수 테스트와 최적화는 다양한 시장 환경에 적응 할 수 있으므로 매우 실용적인 트렌드 역전 전략입니다.
/*backtest start: 2023-09-16 00:00:00 end: 2023-10-16 00:00:00 period: 3h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © npietronuto1 //@version=5 strategy("Hulk Scalper x35 Leverage", shorttitle = "Smash Pullback Strat", overlay=true, initial_capital=100, default_qty_type=strategy.percent_of_equity, default_qty_value=100) //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //RSI rsiLength = input.int(20) RsiTopInput = input.int(2) RsiBotInput = input.int(-2) // toprsiLine = hline(RsiTopInput, title = "Rsi Top Line", linestyle = hline.style_solid) // botrsiLine = hline(RsiBotInput, title = "Rsi Bottom Line", linestyle = hline.style_solid) rsi = ta.rsi(close, rsiLength) rsiWeighted = rsi - 50 //Zeros Rsi to look nicer //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ adxlen = input(14, title="ADX Smoothing") dilen = input(14, title="DI Length") dirmov(len) => up = ta.change(high) down = -ta.change(low) plusDM = na(up) ? na : (up > down and up > 0 ? up : 0) minusDM = na(down) ? na : (down > up and down > 0 ? down : 0) truerange = ta.rma(ta.tr, len) plus = fixnan(100 * ta.rma(plusDM, len) / truerange) minus = fixnan(100 * ta.rma(minusDM, len) / truerange) [plus, minus] adx(dilen, adxlen) => [plus, minus] = dirmov(dilen) sum = plus + minus adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen) sig = adx(dilen, adxlen) ADXfilterlevel = input.int(33, title = "ADX filter amount") // plot(sig, color=color.red, title="ADX") //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //MACD FastMacdLength = input.int(12, group = "MACD") SlowMacdLength = input.int(26, group = "MACD") SignalLength = input.int(11, group = "MACD") MacdTickAmountNeeded = input.float(5.45, title = "Tick Amount for entry", group = "MACD") res = input.timeframe("1", group = "MACD") // bullishgrow_col = input.color(defval = #3179f5) // bullishweaken_col = input.color(defval = #00e1ff) // bearishweaken_col = input.color(defval = #ff01f1) // bearishgrow_col = input.color(defval = #9d00e5) [FastMacd, SlowMacd, Macdhist] = ta.macd(close, FastMacdLength, SlowMacdLength, SignalLength) //Pull MACD from Lower timeframe MACD = request.security(syminfo.tickerid, res, Macdhist, gaps = barmerge.gaps_on) //Grow and Fall Color // getgrow_fall_col(Value) => // if Value >= 0 // if Value >= Value[1] // color.new(bullishgrow_col, transp = 10) // else if Value <= Value[1] // color.new(bullishweaken_col, transp = 10) // else if Value <= 0 // if Value <= Value[1] // color.new(bearishgrow_col, transp = 10) // else if Value >= Value[1] // color.new(bearishweaken_col, transp = 10) //CONDITIONS that check if MACD is overbought or oversold MACDisAboveBand = MACD > MacdTickAmountNeeded MACDisBelowBand = MACD < MacdTickAmountNeeded*-1 //Plot // plot(MACD, style = plot.style_columns, color = getgrow_fall_col(MACD)) //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //EMAs //Inputs EmaFastLength = input.int(50, title = "Ema Fast Length") EmaSlowLength = input.int(200, title = "Ema Slow Length") StrongUpTrendCol = input.color(color.rgb(74, 255, 163)) //WeakUptrend = input.color(color.rgb(74, 255, 163, 50)) StrongDownTrendCol = input.color(color.rgb(255, 71, 84)) //WeakDownTrend = input.color(color.rgb(255, 71, 84, 50)) //Calculations emaFast= ta.ema(close, EmaFastLength) emaSlow= ta.ema(close, EmaSlowLength) emaDist=emaFast-emaSlow EmaLengthFraction = emaDist/4 emafrac5 = emaSlow + EmaLengthFraction emafrac4 = emaSlow + EmaLengthFraction*2 emafrac3 = emaSlow + EmaLengthFraction*3 emafrac2 = emaSlow + EmaLengthFraction*4 UptrendCol_DowntrendCol= emaFast>=emaSlow ? StrongUpTrendCol:StrongDownTrendCol //Plot ema1p = plot(emaFast, color = color.new(#000000, transp = 100)) ema2p = plot(emafrac2, color = color.new(#000000, transp = 100)) ema3p = plot(emafrac3, color = color.new(#000000, transp = 100)) ema4p = plot(emafrac4, color = color.new(#000000, transp = 100)) ema5p = plot(emafrac5, color = color.new(#000000, transp = 100)) ema6p = plot(emaSlow, color = color.new(#000000, transp = 100)) fill(ema2p,ema3p, color = color.new(UptrendCol_DowntrendCol, 70)) fill(ema3p,ema4p, color = color.new(UptrendCol_DowntrendCol, 60)) fill(ema4p,ema5p, color = color.new(UptrendCol_DowntrendCol, 50)) fill(ema5p,ema6p, color = color.new(UptrendCol_DowntrendCol, 40)) //Conditons FastEma_above_SlowEma = emaFast > emaSlow FastEma_below_SlowEma = emaFast < emaSlow emaCrossEvent = ta.crossover(emaFast, emaSlow) or ta.crossover(emaSlow, emaFast) //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //Trade Cap per EMA X //Inputs MaxTrades_PerCross_Checkbox = input.bool(true, "Limit Trades Per Cross", group = "Filters") TrdCount = 0//Variable that keeps current trade count if(TrdCount[1] > 0)//Passes variable on to current candle TrdCount := TrdCount[1] //Reset trade count if EMAs X emaXevent = ta.crossover(emaFast, emaSlow) or ta.crossover(emaSlow, emaFast) // Check for EMA cross if(emaXevent) TrdCount := 0 //Conditions MaxTrades = input.int(6) IsMaxTrades_BelowCap = TrdCount[1] < MaxTrades //Condition that applies max trade count if(not MaxTrades_PerCross_Checkbox) IsMaxTrades_BelowCap := true //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ //STRATEGY LOGIC //Parameters TakeProfitInput = input.float(0.0135, title = "Take Profit %", group = "TP/SL") StopLossInput = input.float(0.011, title = "Stop Loss %", group = "TP/SL") //TP/SL calculations Long_takeProfit = close * (1 + TakeProfitInput) Long_stopLoss = close * (1 - StopLossInput) Short_takeProfit = close * (1 - TakeProfitInput) Short_stopLoss = close * (1 + StopLossInput) //LONG and Short LongConditionPt1 = close > emaSlow and MACDisBelowBand and sig > ADXfilterlevel LongConditionPt2 = FastEma_above_SlowEma and IsMaxTrades_BelowCap and strategy.position_size == 0 //Checks if Rsi Inbetween Lines LongConditionPt3 = rsiWeighted < RsiTopInput and rsiWeighted > RsiBotInput ShortConditionPt1 = close < emaSlow and MACDisAboveBand and sig > ADXfilterlevel ShortConditionPt2 = FastEma_below_SlowEma and IsMaxTrades_BelowCap and strategy.position_size == 0 //Checks if Rsi Inbetween Lines ShortConditionPt3 = rsiWeighted < RsiTopInput and rsiWeighted > RsiBotInput // longCondition = FastEma_above_SlowEma and MACDisBelowBand and IsMaxTrades_BelowCap and rsiWeighted < RsiTopInput and strategy.position_size == 0 longCondition = LongConditionPt1 and LongConditionPt2 and LongConditionPt3 if(longCondition) strategy.entry("long", strategy.long) strategy.exit("exit", "long", limit = Long_takeProfit, stop = Long_stopLoss) TrdCount := TrdCount + 1//ADD to Max Trades Count alert("Go Long with TP at" + str.tostring(Long_takeProfit) + "and SL at" + str.tostring(Long_stopLoss), alert.freq_once_per_bar_close) shortCondition = ShortConditionPt1 and ShortConditionPt2 and ShortConditionPt3 if(shortCondition ) strategy.entry("short", strategy.short) strategy.exit("exit", "short", limit = Short_takeProfit, stop = Short_stopLoss) TrdCount := TrdCount + 1 //ADD to Max Trades Count alert("Go Short with TP at" + str.tostring(Short_takeProfit) + "and SL at" + str.tostring(Short_stopLoss), alert.freq_once_per_bar_close)