Hull 이동 평균 및 스토카스틱 RSI 조합 거래 전략

저자:차오장, 날짜: 2023-10-18 12:40:23
태그:

img

전반적인 설명

이 전략은 트렌드 방향을 결정하기 위해 헐 이동 평균을 사용하여 엔트리 신호를 위해 스토카스틱 RSI와 결합합니다. HMA 중간선이 하위 라인을 넘어서면 긴 거래가 이루어지고 상위 라인을 넘어서면 짧은 거래가 이루어집니다. 또한 스토카스틱 RSI K 라인이 과소매 구역에서 D 라인을 넘어서면 긴 거래가 이루어지고, 과소매 구역에서 상위 라인을 넘어서면 짧은 거래가 이루어집니다.

전략 논리

이 전략의 주요 구성 요소는 트렌드 방향에 대한 Hull 이동 평균과 시시 엔트리 신호에 대한 스토카스틱 RSI입니다.

첫째로, 헐 MA 계산에는 중간, 상위 및 하위 대역에 대한 공식이 포함되어 있습니다. 중간 대역은 가중 이동 평균을 사용하며 상위 및 하위 대역은 중간 선에서 오프셋됩니다.

트렌드 방향은 중부 대와 상부/하부 대 사이의 관계에 의해 결정된다. 중부 선의 상향 크로스오버는 구매 압력과 상승 추세를 나타내고, 하향 크로스오버는 판매 압력과 하락 추세를 나타낸다.

스토카스틱 RSI 계산도 정의되어 있으며, 매끄러운 K 및 D 값도 포함됩니다. K 값은 RSI에 대한 SMA 매끄러움을 사용하지만, D 값은 K에 대한 두 번째 SMA 매끄러움을 사용합니다.

트렌드 방향이 결정된 후, 스톡 RSI K 라인이 상승 추세 중 과잉 구매 구역에서 D 라인을 넘어서면 긴 거래가 이루어집니다. 하락 추세 중 K 라인이 과잉 판매 구역에서 D 라인을 넘어서면 짧은 거래가 이루어집니다.

헐 트렌드 필터와 스톡 RSI 과잉 매수/ 과잉 판매 분석을 결합하면 거래에 대한 강력한 다중 요인 접근이 가능합니다.

장점

이 전략의 주요 이점은 다음과 같습니다.

  1. 헬스 MA는 전체 시장 동향 방향을 효과적으로 파악합니다.

  2. 스톡 RSI는 시간 엔트리에 대한 과잉 구매/ 과잉 판매 수준을 결정합니다.

  3. 둘을 함께 사용하면 잘못된 신호를 줄이고 강점을 결합합니다.

  4. 다양한 기호와 시간 프레임에 대한 매개 변수를 최적화하는 유연성.

  5. 선체 띠는 잠재적인 동적 지원과 저항을 식별합니다.

  6. 포지션 크기와 리스크 관리 규칙을 포함합니다.

  7. 선체 데이터 사전을 통해 멀티 자원을 사용할 수 있다

  8. 수익성을 높이고 사용량을 줄이기 위해 최적화 가능한 부품

위험성

고려해야 할 몇 가지 위험:

  1. 헬스 MA는 지연이 있고 트렌드 변경을 놓칠 수 있습니다.

  2. 스톡 RSI는 매개 변수가 최적화되지 않으면 과도한 신호를 생성할 수 있습니다.

  3. 헬스와 스톡 매개 변수 사이의 불일치는 나쁜 신호를 일으킬 수 있습니다.

  4. 너무 넓거나 좁은 선반은 신호 품질에 영향을 줄 것입니다.

  5. 최근 변동적인 시장은 중장기 지표에 도전합니다.

  6. 헬스와 스톡의 데이터 불일치로 잘못된 신호가 발생했어요

  7. 헐이 알아차리지 못하는 급격한 변화로 인해 손실이 발생할 수 있습니다.

  8. 여러 시간 프레임과 기호에 대한 확장 테스트가 필요합니다.

이 문제 들 을 해결 할 수 있는 몇 가지 방법:

  1. 추세 감수성을 높이기 위해 Hull MA 길이를 줄입니다.

  2. 가짜 크로스를 필터링하기 위해 스톡 RSI를 최적화해

  3. 최적의 헬스 밴드 채널 너비를 찾아라

  4. MACD와 같은 추가 확인 지표를 추가합니다.

  5. 위험을 통제하기 위해 스톱 로스 전략을 적용해야 합니다.

최적화 기회

이 전략을 개선할 수 있는 몇 가지 방법:

  1. 다양한 시간 프레임에서 더 많은 기호를 테스트하여 견고성을 확인합니다.

  2. 트레일링 스톱이나 이동 평균과 같은 스톱 손실 메커니즘을 포함합니다.

  3. 입력 규칙을 최적화하고 잘못된 신호를 줄이기 위해 더 엄격한 필터를 설정합니다.

  4. 지원과 저항을 더 잘 정의하기 위해 허스 밴드를 이용하는 것을 탐구합니다.

  5. 신호 신뢰성을 높이기 위해 추가 확인 지표를 평가합니다.

  6. 길이, 과잉 구매/ 과잉 판매 수준 등에 대한 매개 변수 최적화

  7. 더 나은 포지션 크기와 리스크 관리

  8. 추가 입력, 중지 손실 및 수익을 취하는 규칙 라이브 거래에 필수적입니다.

  9. 트렌드 감수성을 높이기 위해 선체 길이를 최적화해

  10. 신호 품질을 향상시키기 위해 필터 또는 확인 지표를 추가합니다.

  11. 동적 지원/항압 수준을 위해 배역을 탐색합니다.

  12. 주식 RSI 매개 변수를 최적화합니다.

  13. 고급 포지션 크기와 리스크 관리

결론

전체적으로 이것은 트렌드와 모멘텀을 결합한 효과적인 접근법이다. 그러나 고유한 지표 약점으로 인해 추가 최적화 및 리스크 제어 없이는 신호를 맹목적으로 신뢰해서는 안된다. 정제된 매개 변수, 추가 필터 및 스톱 손실로 이 전략은 잠재력을 제공합니다. 라이브 거래에 견고하고 수익성이 높이기 위해 매개 변수, 리스크 관리 및 포지션 사이징에 대한 더 광범위한 테스트가 필요합니다.


/*backtest
start: 2023-10-16 00:00:00
end: 2023-10-17 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
//Basic Hull Ma Pack tinkered by InSilico 
//Converted to Strategy by DashTrader
strategy("Hull Suite + Stoch RSI Strategy v1.1", overlay=true, pyramiding=1, initial_capital=100, default_qty_type= strategy.percent_of_equity, default_qty_value = 100, calc_on_order_fills=false, slippage=0,commission_type=strategy.commission.percent,commission_value=0.023)
strat_dir_input = input(title="Strategy Direction", defval="all", options=["long", "short", "all"])
strat_dir_value = strat_dir_input == "long" ? strategy.direction.long : strat_dir_input == "short" ? strategy.direction.short : strategy.direction.all
strategy.risk.allow_entry_in(strat_dir_value)
//////////////////////////////////////////////////////////////////////
// Testing Start dates
testStartYear = input(2016, "Backtest Start Year")
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)
//Stop date if you want to use a specific range of dates
testStopYear = input(2030, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(30, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,0,0)

stoch_upper_input = input(88, "Stoch Upper Threshold", type=input.float)
stoch_lower_input = input(5, "Stoch Lower Threshold", type=input.float)
sl = input(0.7, "SL %", type=input.float, step=0.1)
tp = input(2.1, "TP %", type=input.float, step=0.1)
// slowEMA = ema(close, slowEMA_input)

// vwap = vwap(close)
// rsi = rsi(close, rsi_input)


// stoch rsi
smoothK = 3
smoothD = 3
lengthRSI = 14
lengthStoch = 14
rsi1 = rsi(close, 14)
k = sma(stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK)
d = sma(k, smoothD)

testPeriod() =>
    time >= testPeriodStart and time <= testPeriodStop ? true : false
// Component Code Stop
//////////////////////////////////////////////////////////////////////
//INPUT
src = input(close, title="Source")
modeSwitch = input("Hma", title="Hull Variation", options=["Hma", "Thma", "Ehma"])
length = input(180, title="Length(180-200 for floating S/R , 55 for swing entry)")
switchColor = input(true, "Color Hull according to trend?")
candleCol = input(false,title="Color candles based on Hull's Trend?")
visualSwitch  = input(true, title="Show as a Band?")
thicknesSwitch = input(1, title="Line Thickness")
transpSwitch = input(40, title="Band Transparency",step=5)

//FUNCTIONS
//HMA
HMA(_src, _length) =>  wma(2 * wma(_src, _length / 2) - wma(_src, _length), round(sqrt(_length)))
//EHMA    
EHMA(_src, _length) =>  ema(2 * ema(_src, _length / 2) - ema(_src, _length), round(sqrt(_length)))
//THMA    
THMA(_src, _length) =>  wma(wma(_src,_length / 3) * 3 - wma(_src, _length / 2) - wma(_src, _length), _length)
    
//SWITCH
Mode(modeSwitch, src, len) =>
      modeSwitch == "Hma"  ? HMA(src, len) :
      modeSwitch == "Ehma" ? EHMA(src, len) : 
      modeSwitch == "Thma" ? THMA(src, len/2) : na
      
//OUT
HULL = Mode(modeSwitch, src, length)
MHULL = HULL[0]
SHULL = HULL[2]

//COLOR
hullColor = switchColor ? (HULL > HULL[2] ? #00ff00 : #ff0000) : #ff9800

//PLOT
///< Frame
Fi1 = plot(MHULL, title="MHULL", color=hullColor, linewidth=thicknesSwitch, transp=50)
Fi2 = plot(visualSwitch ? SHULL : na, title="SHULL", color=hullColor, linewidth=thicknesSwitch, transp=50)
///< Ending Filler
fill(Fi1, Fi2, title="Band Filler", color=hullColor, transp=transpSwitch)
///BARCOLOR
barcolor(color = candleCol ? (switchColor ? hullColor : na) : na)

bgcolor(color = k < stoch_lower_input  and crossover(k, d) ? color.green : na)
bgcolor(color = d > stoch_upper_input and crossover(d, k) ? color.red : na)

notInTrade = strategy.position_size == 0

if notInTrade and HULL[0] > HULL[2] and testPeriod() and k < stoch_lower_input and crossover(k, d)
// if HULL[0] > HULL[2] and testPeriod()
    stopLoss = close * (1 - sl / 100) 
    profit25 = close * (1 + (tp / 100) * 0.25)
    profit50 = close * (1 + (tp / 100) * 0.5)
    takeProfit = close * (1 + tp / 100)
    
    
    strategy.entry("long", strategy.long, alert_message="buy")
    strategy.exit("exit long 25%", "long", stop=stopLoss, limit=profit25, qty_percent=25, alert_message="profit_25")
    strategy.exit("exit long 50%", "long", stop=stopLoss, limit=profit50, qty_percent=25, alert_message="profit_50")
    strategy.exit("exit long", "long", stop=stopLoss, limit=takeProfit)
    
    // line.new(bar_index, profit25, bar_index + 4, profit25, color=color.green)
    // line.new(bar_index, profit50, bar_index + 4, profit50, color=color.green)
    // box.new(bar_index, stopLoss, bar_index + 4, close, border_color=color.red, bgcolor=color.new(color.red, 80))
    // box.new(bar_index, close, bar_index + 4, takeProfit, border_color=color.green, bgcolor=color.new(color.green, 80))

    
if notInTrade and HULL[0] < HULL[2] and testPeriod() and d > stoch_upper_input and crossover(d, k)
// if HULL[0] < HULL[2] and testPeriod()
    stopLoss = close * (1 + sl / 100)
    profit25 = close * (1 - (tp / 100) * 0.25)
    profit50 = close * (1 - (tp / 100) * 0.5)
    takeProfit = close * (1 - tp / 100)
    
    

    strategy.entry("short", strategy.short, alert_message="sell")
    strategy.exit("exit short 25%", "short", stop=stopLoss, limit=profit25, qty_percent=25, alert_message="profit_25")
    strategy.exit("exit short 50%", "short", stop=stopLoss, limit=profit50, qty_percent=25, alert_message="profit_50")
    strategy.exit("exit short", "short", stop=stopLoss, limit=takeProfit)
    
    // line.new(bar_index, profit25, bar_index + 4, profit25, color=color.green)
    // line.new(bar_index, profit50, bar_index + 4, profit50, color=color.green)
    // box.new(bar_index, stopLoss, bar_index + 4, close, border_color=color.red, bgcolor=color.new(color.red, 80))
    // box.new(bar_index, close, bar_index + 4, takeProfit, border_color=color.green, bgcolor=color.new(color.green, 80))

// var table winrateDisplay = table.new(position.bottom_right, 1, 1)
// table.cell(winrateDisplay, 0, 0, "Winrate: " + tostring(strategy.wintrades / strategy.closedtrades * 100, '#.##')+" %", text_color=color.white)

더 많은