MACD 분산 및 멀티 타임 프레임 이동 평균 전략

저자:차오장, 날짜: 2023-11-01 16:37:17
태그:

img

전반적인 설명

이 전략은 MACD 지표와 멀티 타임 프레임 이동 평균을 통합하여 트렌드 및 트렌드 역전 신호를 모두 활용하는 이중 방향 거래 전략을 형성합니다. 이 전략은 역전 기회를 활용하면서 트렌딩 시장에서 추가 수익을 창출 할 수 있습니다.

전략 논리

  1. 긴/단기 방향을 결정하기 위해 여러 시간 프레임 필터로 서로 다른 기간을 가진 두 그룹 EMA를 사용하십시오: 황소 필터로 1 시간 이상의 15 분 빠른 EMA, 곰 필터로 1 시간 이하의 15 분 빠른 EMA.

  2. MACD가 오차를 형성할 때 가능한 반전을 식별합니다 (히스토그램이 가격에서 오차합니다).

  3. 황소 필터가 켜져 있을 때, 호황적 분리가 발견되면 (가격은 새로운 최고가지만 MACD는 그렇지 않은 경우), MACD가 신호선을 넘어서게 될 때까지 기다립니다. 곰 필터가 켜져 있을 때, 호황적 분리가 발견되면, MACD가 신호선을 넘어서게 될 때까지 기다립니다.

  4. 스톱 로즈는 가장 높은 가격 범위와 가장 낮은 가격 범위에 따라 동적으로 설정됩니다. 이윤은 스톱 로즈의 배수입니다.

  5. MACD 히스토그램이 반대 방향으로 0선을 넘을 때 포지션을 닫습니다.

이점 분석

  1. 멀티 타임 프레임 EMA 컴보는 주요 트렌드 방향을 필터링하여 역 트렌드 거래를 피합니다.

  2. MACD 오차는 가격 반전 기회를 포착하여 반전 전략에 적합합니다.

  3. 동적인 후속 스톱 손실은 수익을 차단하고 피해를 방지합니다.

  4. 스톱 로스 거리를 기준으로 수익을 취하면 예상 수익을 얻을 수 있습니다.

위험 분석

  1. EMA 필터는 통합 과정에서 잘못된 방향을 제시할 수 있습니다.

  2. MACD 오차 후 역행 크기가 충분하지 않으면 손실이 발생할 수 있습니다.

  3. 부적절한 스톱 손실 거리 설정은 너무 느슨하거나 너무 단단할 수 있습니다.

  4. 제한된 리버스 룸 수익 제한.

  5. 제대로 된 시간 반전 입력 필요, 너무 일찍 또는 늦게 둘 다 손실을 일으킬 수 있습니다.

최적화 방향

  1. 트렌드를 더 잘 판단하기 위해 다른 EMA 조합을 테스트합니다.

  2. 좀 더 민감한 MACD 매개 변수 설정을 시도해보세요.

  3. 다른 스톱 로스/프로피트 취업 비율을 테스트합니다.

  4. 거짓 반전을 피하기 위해 추가 필터를 추가합니다. 예를 들어 글로벌 트렌드에 대한 더 높은 시간 프레임 EMA.

  5. 더 성숙한 반전을 위해 반전 입력 확인을 최적화합니다.

결론

이 전략은 트렌드 필터링, 역전 신호, 동적 스톱/트랙 이윤 관리를 활용하여 트렌드를 거래하고 역전에서 이윤을 창출한다. 적절한 매개 변수 조정 및 최적화 필터는 다양한 시장 조건에 적응하여 위험을 제어하면서 안정적인 이윤을 창출한다. 이는 다재다능성과 실용적 가치를 가지고 있으며, 여러 시간 프레임 분석을 지표와 통합하는 전형적인 예이다.


/*backtest
start: 2023-01-01 00:00:00
end: 2023-06-16 00:00: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/
// © maxits
//@version=4

// MACD Divergence + Multi Time Frame EMA
// This Strategy uses 3 indicators: the Macd and two emas in different time frames
// The configuration of the strategy is:
// Macd standar configuration (12, 26, 9) in 1H resolution
// 10 periods ema, in 1H resolution
// 5 periods ema, in 15 minutes resolution

// We use the two emas to filter for long and short positions. 
// If 15 minutes ema is above 1H ema, we look for long positions
// If 15 minutes ema is below 1H ema, we look for short positions 

// We can use an aditional filter using a 100 days ema, so when the 15' and 1H emas are above the daily ema we take long positions
// Using this filter improves the strategy 

// We wait for Macd indicator to form a divergence between histogram and price
// If we have a bullish divergence, and 15 minutes ema is above 1H ema, we wait for macd line to cross above signal line and we open a long position
// If we have a bearish divergence, and 15 minutes ema is below 1H ema, we wait for macd line to cross below signal line and we open a short position

// We close both position after a cross in the oposite direction of macd line and signal line
// Also we can configure a Take profit parameter and a trailing stop loss


// strategy("Macd + MTF EMA",
//          overlay=true,
//          initial_capital=1000,
//          default_qty_value=20,
//          default_qty_type=strategy.percent_of_equity,
//          commission_value=0.1,
//          pyramiding=0)

// User Inputs
i_time          = input(defval = timestamp("01 Apr 2018 13:30 +0000"), title = "Start Time",  type = input.time)    // Starting  time for backtest
f_time          = input(defval = timestamp("30 Sep 2021 13:30 +0000"), title = "Finish Time", type = input.time)    // Finishing time for backtest

long_pos        = input(title="Show Long Positions",  defval=true, type=input.bool)                                 // Enable Long  Positions
short_pos       = input(title="Show Short Positions", defval=true, type=input.bool)                                 // Enable Short Positions
src             = input(close, title="Source")                                                                      // Price value to calculate indicators

emas_properties = input(title="============ EMAS Properties ============", defval=false, type=input.bool)           // Properties

mtf_15          = input(title="Fast EMA", type=input.resolution, defval="15")                                         // Resolucion para MTF EMA 15 minutes
ma_15_length    = input(5, title = "Fast EMA Period")                                                              // MTF EMA 15 minutes Length
mtf_60          = input(title="Slow EMA", type=input.resolution, defval="60")                                         // Resolucion para MTF EMA 60 minutes
ma_60_length    = input(10, title = "Slow EMA Period")                                                              // MTF EMA 60 minutes Length

e_new_filter    = input(title="Enable a Third Ema filter?", defval=true, type=input.bool) 
slowest_ema_len = input(100, title = "Fast EMA Period")
slowest_ema_res = input(title="Slowest EMA", type=input.resolution, defval="D")
macd_res        = input(title="MACD TimeFrame", type=input.resolution, defval="")                                   // MACD Time Frame

macd_properties = input(title="============ MACD Properties ============", defval="")                               // Properties

fast_len        = input(title="Fast Length", type=input.integer, defval=12)                                         // Fast MA Length
slow_len        = input(title="Sign Length", type=input.integer, defval=26)                                         // Sign MA Length
sign_len        = input(title="Sign Length", type=input.integer, defval=9) 

syst_properties = input(title="============ System Properties ============", defval="")                             // Properties

lookback        = input(title="Lookback period", type=input.integer, defval=14, minval=1)                            // Candles to lookback for swing high or low
multiplier      = input(title="Profit Multiplier based on Stop Loss", type=input.float, defval=6.0, minval=0.1)     // Profit multiplier based on stop loss
shortStopPer    = input(title="Short Stop Loss Percentage", type=input.float, defval=1.0, minval=0.0)/100           
longStopPer     = input(title="Long Stop Loss Percentage",  type=input.float, defval=2.0, minval=0.0)/100


// Indicators

[macd, signal, hist] = security(syminfo.tickerid, macd_res, macd(src, fast_len, slow_len, sign_len))
ma_15  = security(syminfo.tickerid, mtf_15, ema(src, ma_15_length))
ma_60  = security(syminfo.tickerid, mtf_60, ema(src, ma_60_length))
ma_slo = security(syminfo.tickerid, slowest_ema_res, ema(src, slowest_ema_len))

// Macd Plot

col_grow_above = #26A69A
col_grow_below = #FFCDD2
col_fall_above = #B2DFDB
col_fall_below = #EF5350

plot(macd,   color=color.new(color.blue, 0))              // Solo para visualizar que se plotea correctamente
plot(signal, color=color.new(color.orange, 0))
plot(hist,   style=plot.style_columns,
     color=(hist >= 0 ? (hist[1] < hist ? col_grow_above : col_fall_above) : 
     (hist[1] < hist ? col_grow_below : col_fall_below)))


// MTF EMA Plot
 
bullish_filter = e_new_filter ? ma_15 > ma_60 and ma_60 > ma_slo : ma_15 > ma_60 
bearish_filter = e_new_filter ? ma_15 < ma_60 and ma_60 < ma_slo : ma_15 < ma_60
    
plot(ma_15,  color=color.new(color.blue, 0))
plot(ma_60,  color=color.new(color.yellow, 0))
plot(e_new_filter ? ma_slo : na, color = ma_60 > ma_slo ? color.new(color.green, 0) : color.new(color.red, 0))

////////////////////////////////////////////// Logic For Divergence

zero_cross = false                                     
zero_cross := crossover(hist,0) or crossunder(hist,0)  //Cruce del Histograma a la linea 0
// plot(zero_cross ? 1 : na)

// MACD DIVERGENCE TOPS (Bearish Divergence) 

highest_top  = 0.0
highest_top := (zero_cross == true ? 0.0 : (hist > 0 and hist > highest_top[1] ? hist : highest_top[1]))
prior_top    = 0.0
prior_top   := (crossunder(hist,0) ? highest_top[1] : prior_top[1])  // Búsqueda del Maximo en MACD
// plot(highest_top)
// plot(prior_top)

highest_top_close  = 0.0
highest_top_close := (zero_cross == true ? 0.0 : (hist > 0 and hist > highest_top[1] ? close : highest_top_close[1]))
prior_top_close    = 0.0
prior_top_close   := (crossunder(hist,0) ? highest_top_close[1] : prior_top_close[1]) // Búsqueda del Maximo en pRECIO
// plot(highest_top_close)
// plot(prior_top_close)

top = false 
top := highest_top[1] < prior_top[1]
     and highest_top_close[1] > prior_top_close[1]
     and hist < hist[1]
     and crossunder(hist,0)                         // Bearish Divergence: top == true 


// MACD DIVERGENCE BOTTOMS (Bullish Divergence) 

lowest_bottom  = 0.0
lowest_bottom := (zero_cross == true ? 0.0 : (hist < 0 and hist < lowest_bottom[1] ? hist : lowest_bottom[1]))
prior_bottom   = 0.0
prior_bottom  := (crossover(hist,0) ? lowest_bottom[1] : prior_bottom[1])

lowest_bottom_close = 0.0
lowest_bottom_close := (zero_cross == true ? 0.0 : (hist < 0 and hist < lowest_bottom[1] ? close : lowest_bottom_close[1]))
prior_bottom_close = 0.0
prior_bottom_close := (crossover(hist,0) ? lowest_bottom_close[1] : prior_bottom_close[1])

bottom = false
bottom := lowest_bottom[1] > prior_bottom[1]
     and lowest_bottom_close[1] < prior_bottom_close[1]
     and hist > hist[1]
     and crossover(hist,0)                              // Bullish Divergence: bottom == true 


////////////////////////////////////////////// System Conditions //////////////////////////////////////////////

inTrade     = strategy.position_size != 0       // In Trade
longTrade   = strategy.position_size  > 0       // Long position
shortTrade  = strategy.position_size  < 0       // Short position
notInTrade  = strategy.position_size == 0       // No trade
entryPrice  = strategy.position_avg_price       // Position Entry Price

////////////////////////////////////////////// Long Conditions //////////////////////////////////////////////

sl = lowest(low, lookback)                  // Swing Low for Long Entry

longStopLoss    = 0.0                       // Trailing Stop Loss calculation
longStopLoss   := if (longTrade)
    astopValue  = sl * (1 - longStopPer)
    max(longStopLoss[1], astopValue)
else
    0

longTakeProf  = 0.0                         // Profit calculation based on stop loss
longTakeProf := if (longTrade)
    profitValue = entryPrice + (entryPrice - longStopLoss) * multiplier
    max(longTakeProf[1], profitValue)
else
    0
    
// Long Entry Conditions

if bottom and notInTrade and bullish_filter and long_pos
    strategy.entry(id="Go Long", long=strategy.long, comment="Long Position")

// strategy.close(id="Go Long", when=zero_cross)

if longTrade
    strategy.exit("Exit Long", "Go Long", limit = longTakeProf, stop = longStopLoss)

plot(longTrade and longStopLoss ? longStopLoss  : na, title="Long Stop Loss",  color=color.new(color.red, 0),   style=plot.style_linebr)
plot(longTrade and longTakeProf ? longTakeProf  : na, title="Long Take Prof",  color=color.new(color.green, 0), style=plot.style_linebr)

////////////////////////////////////////////// Short Conditions //////////////////////////////////////////////

sh = highest(high, lookback) // Swing High for Short Entry

shortStopLoss  = 0.0 
shortStopLoss := if (shortTrade)
    bstopValue = sh * (1 + shortStopPer)
    min(shortStopLoss[1], bstopValue)
else 
    999999
    
shortTakeProf    = 0.0    
shortTakeProf   := if (shortTrade)
    SprofitValue = entryPrice - (shortStopLoss - entryPrice) * multiplier
    min(SprofitValue, shortTakeProf[1])
else 
    999999
    
// Short Entry
if top and notInTrade and bearish_filter and short_pos
    strategy.entry(id="Go Short", long=strategy.short, comment="Short Position")

// strategy.close(id="Go Short", when=zero_cross)

if shortTrade
    strategy.exit("Exit Short", "Go Short", limit = shortTakeProf, stop = shortStopLoss)


plot(shortTrade and shortStopLoss ? shortStopLoss : na, title="Short Stop Loss", color=color.new(color.red, 0),   style=plot.style_linebr)
plot(shortTrade and shortTakeProf ? shortTakeProf : na, title="Short Take Prof", color=color.new(color.green, 0), style=plot.style_linebr)






더 많은