트렌드 추종 더블 EMA 윌리엄스 지표 전략


생성 날짜: 2023-11-21 15:16:21 마지막으로 수정됨: 2023-11-21 15:16:21
복사: 0 클릭수: 630
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

트렌드 추종 더블 EMA 윌리엄스 지표 전략

개요

이 전략은 트렌드 방향을 식별하기 위해 EMA와 윌리엄스 지표를 결합하여 트렌드가 강할 때 추적합니다. 기본 아이디어는 다음과 같습니다.

  1. 이중 EMA 조합을 사용하여 가장 강력한 트렌드를 필터링합니다.
  2. 윌리엄스 지표는 현재 오버 바이 오버 셀 영역에 있음을 확인합니다.
  3. RSI와 결합하여 상승과 하락을 추적하는 것을 피하십시오.

원칙

이 전략은 쌍 EMA 지표의 단기 EMA와 장기 EMA를 사용합니다. 단기 EMA가 상향으로 긴 EMA를 통과하면 구매 신호를 생성하고, 단기 EMA가 상향으로 긴 EMA를 통과하면 판매 신호를 생성하여 쌍 EMA를 사용하여 중·장기 트렌드를 캡처합니다.

또한, 이 전략은 윌리엄스 지표와 결합하여 역전 상황을 식별한다. 윌리엄스 지표는 주기적 고점과 낮은 점을 판단하여 가격이 과매매 또는 과매매 상태에 있는지 판단한다. 윌리엄스 지표가 과매매를 표시할 때 판매 신호를 생성하고 과매를 표시할 때 구매 신호를 생성한다.

코드는 다음과 같이 정의합니다.

다중 입점: 단기 EMA 상단 중기 EMA와 장기 EMA, 그리고 윌리엄스 지표는 초매 지역을 표시하고 초매 지역이 가장 낮은 지점을 형성하여 반전 기회를 나타냅니다. 이 시점에 구매 신호가 생성됩니다.

공백 입시: 단기 EMA 아래 중간 EMA와 장기 EMA를 통과하고, 윌리엄스 지표는 초매구역을 표시하고, 초매구역에서 최고점을 형성하여 역전 기회를 나타냅니다. 이 때 판매 신호가 발생한다.

이 전략은 또한 RSI 지표를 도입하여 거래 신호를 더욱 확인하고, 맹목적으로 추격하는 것을 피합니다.

장점

이 전략의 가장 큰 장점은 이중 EMA를 사용하여 무효 트렌드를 많이 필터링하고, 단지 가장 강력한 중장기 트렌드를 선택하여 추적함으로써 소음을 필터링하여 무효 거래를 줄이는 것입니다.

또한, 윌리엄스 지표의 도입은 매우 좋은 효과를 가지고 있습니다. 하나는 역전 기회를 식별하여 적시에 평정 할 수 있습니다. 두 번째는 트렌드 신호의 유효성을 추가로 확인 할 수 있습니다.

이중 EMA와 윌리엄스의 조합을 사용하면, 이 전략은 중장기 품종에서 좋은 추적 수익을 얻을 수 있으며, 반전을 식별하고 손실을 제한할 수 있습니다.

위험

이 전략의 주요 위험은 트렌드 반전의 지점을 식별하는 데 있습니다. 반전 거래의 유효성을 보장하기 위해 윌리엄스 지표와 RSI 지표를 도입했음에도 불구하고 반전 거래의 난이도는 여전히 크며, 추락의 위험을 완전히 피할 수 없습니다.

또한, 이중 EMA 포트폴리오는 그 자체로 다소 뒤처져 있다. 단기 경향과 중장기 경향이 분리되었을 때에도 전략에 약간의 식별 어려움을 초래할 수 있다.

최적화

이 전략은 다음과 같은 부분에서 최적화될 수 있습니다.

  1. 더 많은 EMA 주기 조합을 테스트하여 더 나은 변수를 찾으십시오.

  2. ATR, 변동성 지수와 같은 지표를 사용하여 트렌드 반전을 판단하는 적응 탈퇴 메커니즘을 추가합니다.

  3. 트렌드 및 역전 예측을 위해 LSTM와 같은 기계 학습 요소를 추가합니다.

  4. 파동 이론과 같은 방법을 사용하여 역거래 규칙을 더 개선하십시오.

  5. 시장 상황에 따라 포지션 규모를 조정하는 적응 포지션 관리를 도입합니다.

요약하다

이 전략은 두 개의 EMA와 윌리엄스 지표가 중장기 트렌드를 캡처하는 데 성공하여 큰 트렌드에서 더 높은 수익을 얻습니다. 동시에, 윌리엄스 지표의 도입은 전략이 반전을 식별하고 적시에 손실을 중지 할 수있게합니다. 다음 단계에서는 더 많은 지표와 모델을 도입하여 전략의 안정성을 더욱 강화합니다.

전략 소스 코드
/*backtest
start: 2022-11-20 00:00:00
end: 2022-11-29 05:20:00
period: 1h
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/
// © B_L_A_C_K_S_C_O_R_P_I_O_N
// v 1.1

//@version=4
strategy("vijkirti buy sell 99%", overlay=true, default_qty_type=strategy.cash, default_qty_value=1000, currency='USD')

// *************Appearance*************
theme = input(type=input.string, defval="dark", options=["light","dark"], group="Appearance")
show_fractals = input(false, "Show Fractals", group="Appearance")
show_ema = input(false, "Show EMAs", group="Appearance")

// *************colors*************
color_green = color.green
color_red = color.red
color_yellow = color.yellow
color_orange = color.orange
color_blue = color.blue
color_white = color.white

// *************WF*************
// Define "n" as the number of periods and keep a minimum value of 2 for error handling.
n = input(title="Fractal Periods", defval=2, minval=2, type=input.integer, group="Williams Fractals")

// UpFractal
bool upflagDownFrontier = true
bool upflagUpFrontier0 = true
bool upflagUpFrontier1 = true
bool upflagUpFrontier2 = true
bool upflagUpFrontier3 = true
bool upflagUpFrontier4 = true

for i = 1 to n
    upflagDownFrontier := upflagDownFrontier and (high[n-i] < high[n])
    upflagUpFrontier0 := upflagUpFrontier0 and (high[n+i] < high[n])
    upflagUpFrontier1 := upflagUpFrontier1 and (high[n+1] <= high[n] and high[n+i + 1] < high[n])
    upflagUpFrontier2 := upflagUpFrontier2 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+i + 2] < high[n])
    upflagUpFrontier3 := upflagUpFrontier3 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+i + 3] < high[n])
    upflagUpFrontier4 := upflagUpFrontier4 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+4] <= high[n] and high[n+i + 4] < high[n])
flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or upflagUpFrontier3 or upflagUpFrontier4

upFractal = (upflagDownFrontier and flagUpFrontier)

// downFractal
bool downflagDownFrontier = true
bool downflagUpFrontier0 = true
bool downflagUpFrontier1 = true
bool downflagUpFrontier2 = true
bool downflagUpFrontier3 = true
bool downflagUpFrontier4 = true

for i = 1 to n
    downflagDownFrontier := downflagDownFrontier and (low[n-i] > low[n])
    downflagUpFrontier0 := downflagUpFrontier0 and (low[n+i] > low[n])
    downflagUpFrontier1 := downflagUpFrontier1 and (low[n+1] >= low[n] and low[n+i + 1] > low[n])
    downflagUpFrontier2 := downflagUpFrontier2 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+i + 2] > low[n])
    downflagUpFrontier3 := downflagUpFrontier3 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+i + 3] > low[n])
    downflagUpFrontier4 := downflagUpFrontier4 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+4] >= low[n] and low[n+i + 4] > low[n])
flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4

downFractal = (downflagDownFrontier and flagDownFrontier)

plotshape(downFractal and show_fractals, style=shape.triangleup, location=location.belowbar, offset=-n, color=color_green)
plotshape(upFractal and show_fractals, style=shape.triangledown, location=location.abovebar, offset=-n, color=color_red)

// *************EMA*************
len_a = input(20, minval=1, title="EMA Length A", group="EMA")
src_a = input(close, title="EMA Source A", group="EMA")
offset_a = input(title="EMA Offset A", type=input.integer, defval=0, minval=-500, maxval=500, group="EMA")
out_a = ema(src_a, len_a)
plot(show_ema ? out_a : na, title="EMA A", color=color_green, offset=offset_a)

len_b = input(50, minval=1, title="EMA Length B", group="EMA")
src_b = input(close, title="EMA Source B", group="EMA")
offset_b = input(title="EMA Offset B", type=input.integer, defval=0, minval=-500, maxval=500, group="EMA")
out_b = ema(src_b, len_b)
ema_b_color = (theme == "dark") ? color_yellow : color_orange
plot(show_ema ? out_b : na, title="EMA B", color=ema_b_color, offset=offset_b)

len_c = input(100, minval=1, title="EMA Length C", group="EMA")
src_c = input(close, title="EMA Source C", group="EMA")
offset_c = input(title="EMA Offset C", type=input.integer, defval=0, minval=-500, maxval=500, group="EMA")
out_c = ema(src_c, len_c)
ema_c_color = (theme == "dark") ? color_white : color_blue
plot(show_ema ? out_c : na, title="EMA C", color=ema_c_color, offset=offset_c)

// *************RSI*************
rsi_len = input(14, minval=1, title="RSI Length", group="RSI")
rsi_src = input(close, "RSI Source", type = input.source, group="RSI")
up = rma(max(change(rsi_src), 0), rsi_len)
down = rma(-min(change(rsi_src), 0), rsi_len)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))

// *************Calculation*************
long = (out_a > out_b) and (out_a > out_c) and downFractal and low[2] > out_c and rsi[2] < rsi
short = (out_a < out_b) and (out_a < out_c) and upFractal and high[2] < out_c and rsi[2] > rsi

plotshape(long, style=shape.labelup, color=color_green, location=location.belowbar, title="long label", text= "L", textcolor=color_white)
plotshape(short, style=shape.labeldown, color=color_red, location=location.abovebar, title="short label", text= "S", textcolor=color_white)

// *************End of Signals calculation*************

// Make input options that configure backtest date range
startDate = input(title="Start Date", type=input.integer,
     defval=1, minval=1, maxval=31, group="Orders")
startMonth = input(title="Start Month", type=input.integer,
     defval=1, minval=1, maxval=12, group="Orders")
startYear = input(title="Start Year", type=input.integer,
     defval=2018, minval=1800, maxval=2100, group="Orders")

endDate = input(title="End Date", type=input.integer,
     defval=1, minval=1, maxval=31, group="Orders")
endMonth = input(title="End Month", type=input.integer,
     defval=12, minval=1, maxval=12, group="Orders")
endYear = input(title="End Year", type=input.integer,
     defval=2022, minval=1800, maxval=2100, group="Orders")

// Look if the close time of the current bar
// falls inside the date range
inDateRange = (time >= timestamp(syminfo.timezone, startYear,
         startMonth, startDate, 0, 0)) and
     (time < timestamp(syminfo.timezone, endYear, endMonth, endDate, 0, 0))

// Make inputs that set the take profit % (optional)
longProfitPerc = input(title="Long Take Profit (%)",
     type=input.float, minval=0.0, step=0.1, defval=0.5, group="Orders") * 0.01

shortProfitPerc = input(title="Short Take Profit (%)",
     type=input.float, minval=0.0, step=0.1, defval=0.5, group="Orders") * 0.01

// Figure out take profit price
longExitPrice  = strategy.position_avg_price * (1 + longProfitPerc)
shortExitPrice = strategy.position_avg_price * (1 - shortProfitPerc)

// Plot take profit values for confirmation
plot(series=(strategy.position_size > 0) ? longExitPrice : na,
     color=color_green, style=plot.style_circles,
     linewidth=1, title="Long Take Profit")
plot(series=(strategy.position_size < 0) ? shortExitPrice : na,
     color=color_green, style=plot.style_circles,
     linewidth=1, title="Short Take Profit")

// Submit entry orders
if (inDateRange and long and strategy.opentrades == 0)
    strategy.entry(id="Long", long=true)

if (inDateRange and short and strategy.opentrades == 0)
    strategy.entry(id="Short", long=false)
    
// Set stop loss level with input options (optional)
longLossPerc = input(title="Long Stop Loss (%)",
     type=input.float, minval=0.0, step=0.1, defval=3.1, group="Orders") * 0.01

shortLossPerc = input(title="Short Stop Loss (%)",
     type=input.float, minval=0.0, step=0.1, defval=3.1, group="Orders") * 0.01

// Determine stop loss price
longStopPrice  = strategy.position_avg_price * (1 - longLossPerc)
shortStopPrice = strategy.position_avg_price * (1 + shortLossPerc)

// Plot stop loss values for confirmation
plot(series=(strategy.position_size > 0) ? longStopPrice : na,
     color=color_red, style=plot.style_cross,
     linewidth=1, title="Long Stop Loss")
plot(series=(strategy.position_size < 0) ? shortStopPrice : na,
     color=color_red, style=plot.style_cross,
     linewidth=1, title="Short Stop Loss")

// Submit exit orders based on calculated stop loss price
if (strategy.position_size > 0)
    strategy.exit(id="ExL",limit=longExitPrice, stop=longStopPrice)

if (strategy.position_size < 0)
    strategy.exit(id="ExS", limit=shortExitPrice, stop=shortStopPrice)

// Exit open market position when date range ends
if (not inDateRange)
    strategy.close_all()