이중 EMA 윌리엄스 지표 트렌드 추적 전략

저자:차오장, 날짜: 2023-11-21 15:16:21
태그:

img

전반적인 설명

이 전략은 트렌드 방향을 파악하고 트렌드가 강할 때 트렌드를 추적하기 위해 이중 EMA 지표와 윌리엄스 지표를 결합합니다. 기본 아이디어는:

  1. 두 개의 EMA 콤보를 사용하여 가장 강한 트렌드를 제외한 모든 트렌드를 필터링합니다.
  2. 윌리엄스 지표는 현재 과잉 구매/ 과잉 판매 구역을 확인합니다.
  3. 새로운 최고치를 추구하고 하락을 죽이는 것을 피하기 위해 RSI 지표와 결합

원칙

이 전략은 이중 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()

더 많은