이 전략은 트렌드 방향을 파악하고 트렌드가 강할 때 트렌드를 추적하기 위해 이중 EMA 지표와 윌리엄스 지표를 결합합니다. 기본 아이디어는:
이 전략은 이중 EMA 지표에서 단기 및 장기 EMA를 활용합니다. 단기 EMA가 장기 EMA를 넘을 때 엔트리 신호가 생성됩니다. 단기 EMA가 장기 EMA를 넘을 때 출구 신호가 생성됩니다. 이중 EMA를 사용하여 중장기 트렌드를 캡처합니다.
또한, 윌리엄스 지표는 반전을 식별하는 데 사용됩니다. 윌리엄스 지표는 주기적 인 최고와 최저치를 살펴봄으로써 과소매 또는 과소매를 결정합니다. 과소매가 발생하면 판매 신호가 생성됩니다. 과소매가 발생하면 구매 신호가 생성됩니다.
구체적인 논리는 다음과 같습니다.
긴 진입: 단기 EMA는 중기 EMA와 장기 EMA를 넘어서며, 윌리엄스 지표는 과잉 판매 구역을 표시하고 역전 기회를 나타내는 최저점을 형성합니다.
단기 엔트리: 단기 EMA는 중기 EMA와 장기 EMA를 넘어서고, 윌리엄스 지표는 과잉 매수 구역을 표시하고 역전 기회를 나타내는 가장 높은 지점을 형성합니다.
또한 RSI 지표는 거래 신호를 더욱 확인하고 새로운 최고치를 추구하고 맹목적으로 하락을 피하기 위해 도입됩니다.
이 전략의 가장 큰 장점은 이중 EMA를 사용하여 유효하지 않은 트렌드를 필터링하고 중장기 가장 강력한 트렌드를 추적하는 것입니다. 이것은 소음을 필터링하고 유효하지 않은 거래를 줄입니다.
윌리엄스 지표 를 도입 하는 것 은 또한 매우 효과적 이다. 첫째, 이 지표 는 적시에 포지션 을 닫을 수 있는 반전 기회 를 식별 한다. 둘째, 이 지표 는 추세 신호 의 효과 를 더욱 확인 한다.
이중 EMA와 윌리엄스의 조합은 이 전략이 중장기 제품에서 좋은 추적 수익을 달성 할 수 있도록 허용하며 동시에 반전을 확인하고 손실을 제한합니다.
주요 위험은 트렌드 반전 지점을 식별하는 데에 있습니다. 윌리엄스 지표와 RSI 지표가 반전 거래의 효과를 보장하지만, 어려움은 여전히 높으며 새로운 최고치를 추구하고 하락을 죽일 위험을 완전히 피할 수 없습니다.
또한 이중 EMA 자체는 약간의 지연을 가지고 있습니다. 단기 및 중장기 트렌드가 분리되면 특정 식별 어려움이 발생할 수 있습니다.
이 전략은 다음과 같은 방법으로 최적화 될 수 있습니다.
더 나은 매개 변수를 찾기 위해 더 많은 EMA 사이클 콤보를 테스트하십시오.
ATR, 변동성 지수 등에 기반한 적응력 있는 출구 메커니즘을 강화하여 반전을 판단합니다
트렌드 및 반전을 예측하기 위해 LSTM 등을 사용하여 기계 학습을 도입하십시오
엘리엇 파동 이론 등을 이용한 역전 거래 규칙을 개선
시장 조건에 기초한 적응형 위치 크기를 도입
이 전략은 중장기 트렌드를 포착하고 주요 트렌드 동안 더 높은 수익을 달성하기 위해 이중 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()