멀티타임 프레임 MA 몬드리안 크로스오버 전략


생성 날짜: 2023-11-16 17:28:43 마지막으로 수정됨: 2023-11-16 17:28:43
복사: 0 클릭수: 664
avatar of ChaoZhang ChaoZhang
1
집중하다
1621
수행원

멀티타임 프레임 MA 몬드리안 크로스오버 전략

이 전략은 주로 다중 시간 프레임 (MTF) 의 MA 라인 교차를 사용하여 트렌드 방향을 판단하고, 특정 조건 필터 신호와 결합하여 트렌드 방향이 명확할 때 더 많이 살거나 더 적게 팔 것을 선택하며, 트렌드 추적 유형 전략에 속한다.

전략 원칙

  1. 사용자 정의된 응답 시간 범위를 입력하십시오.

  2. 양선 음선 합성된 Heikin-Ashi 도표를 입력하거나 입력하지 않는지, 기본적으로 사용한다.

  3. 각각 느린 MA선, 빠른 MA선, 그리고 선택적인 제3항의 진동상태에 사용되는 MA선을 정의한다.

  4. 각 MA 라인에 대해 MA 타입, 시간 주기 및 파라미터 등을 사용자 정의할 수 있다.

  5. 빠른 MA 위쪽을 뚫고 느린 MA 위쪽을 뚫고 구매 신호를 형성하고, 낮은 MA 위쪽을 뚫고 판매 신호를 형성한다.

  6. 선택적으로 제3MA선을 다중 방향 필터로 사용할 수 있으며, 종결 가격이 제3MA를 초과할 때만 구매 신호를 생성한다.

  7. 전략. 엔트리 모듈을 사용하여 자동 거래.

  8. 한 손 당 거래 수를 사용자 정의하거나 고정 거래 수를 사용할 수 있습니다.

전략적 이점

  1. MTF 구조를 사용하면, 다른 MA 라인이 다른 주기를 채택하여 여러 시간 스케일의 경향 특성을 식별할 수 있다.

  2. 사용자 정의 가능한 MA 유형, 평평한 MA를 선택하여 안정성을 높일 수 있으며, 반응敏捷의 MA를 선택 할 수 있다.

  3. 이키-아시 (Heikin-Ashi) 와 결합하면 가짜 돌파구를 필터링할 수 있다.

  4. 3번째 MA선을 추가로 추가하여 다중 방향 필터로 사용할 수 있습니다.

  5. 다양한 시장 환경에 맞게 MA 주기 파라미터를 유연하게 조정할 수 있다.

  6. 전략. 엔트리 모듈을 사용하여 수동 간섭 없이 자동으로 주문할 수 있습니다.

  7. 최적화 파라미터를 재검토하여 최적의 파라미터 조합을 찾도록 지원한다.

전략적 위험

  1. MA 교차 전략은 파격적인 가짜 신호에 민감하며, 불필요한 거래가 발생할 수 있다. MA 주기를 적절히 조정하거나 필터링 조건을 추가하여 위험을 줄일 수 있다.

  2. 충격적인 상황에서는, MA 라인이 교차하는 경우가 많으며, 손실을 초래할 수 있다. MA 간격을 적절히 넓히거나 MA 사이클을 연장하여 위험을 줄일 수 있다.

  3. 고정 거래량은 위험을 통제할 수 없습니다. 계좌 자금의 비율로 거래량을 설정하는 것이 고려될 수 있습니다.

  4. 거래비용과 슬라이포인트도 전략의 수익성에 영향을 미칩니다. 승리율이 충분히 높을 수 있도록 파라미터를 적절히 조정할 수 있습니다.

최적화 방향

  1. 다양한 MA 유형을 테스트하여 최적의 파라미터 조합을 찾습니다. Smooth MA는 안정성을 향상시키고, 빠른 MA는 민첩성을 향상시킵니다.

  2. MA의 매개 변수를 최적화하여, 적절한 길이는 트렌드를 식별하는데 도움이 되며, 짧게는 민감도를 높여줍니다. 최적의 균형점을 찾습니다.

  3. 포지션 개시 조건을 최적화하여, 다중 필터링을 강화하는 것을 고려할 수 있으며, 불안한 시장에서 포지션을 개시하는 것을 피할 수 있습니다.

  4. 특정 품종에 대한 MA 주기 파라미터를 최적화하여 그 품종 거래 환경에 가장 적합한 파라미터를 찾을 수 있다.

  5. 거래량 에너지 지표 등과 같은 다른 지표와 결합하여 전략 안정성을 높이기 위한 필터로 고려할 수 있다.

  6. 피드백 데이터에 대한 변수 조합 최적화, 전략 효과를 높이기 위해 최적의 변수를 찾습니다.

요약하다

다중 시간 프레임 MA 교차 전략은 전체적으로 더 일반적인 트렌드 추적 전략에 속한다. 그것의 장점은 간단하고, 변수를 조정하는 유연하며, 다른 시장 환경에 적응할 수 있다는 것이다. 그러나 또한 약간의 잘못된 신호 위험이 있다. 변수 최적화 및 보조 필터링 조건을 추가하여 개선할 수 있으며, 재측정에서 최적의 변수 조합을 찾는다. 이 전략은 트렌드가 명백한 시장에 더 적합하며, 불안한 상황에서 신중하게 사용하거나 거래를 중단해야 한다. 전체적으로 말하자면, 더 전통적인 트렌드 추적 전략으로서, 다중 시간 프레임 MA 교차 전략은 여전히 전문적으로 연구하고 적용할 가치가 있다.

전략 소스 코드
/*backtest
start: 2023-11-08 00:00:00
end: 2023-11-15 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(shorttitle="MZ MA Cross",title="MA MTF Cross Strategy", overlay=true, calc_on_order_fills=false, calc_on_every_tick=false, default_qty_type=strategy.fixed, default_qty_value=5,commission_value=0.1)

timeFrameticker  = input('D',type=input.resolution, title="Chart Timeframe")
uha   =input(true, title="Use Heikin Ashi Candles")

// Use only Heikinashi Candles for all calculations
haclose = uha ? security(heikinashi(syminfo.tickerid), timeFrameticker, close) : security(syminfo.tickerid, timeFrameticker, close)
haopen = uha ? security(heikinashi(syminfo.tickerid), timeFrameticker, open) : security(syminfo.tickerid, timeFrameticker, open)
hahigh = uha ? security(heikinashi(syminfo.tickerid), timeFrameticker, high) : security(syminfo.tickerid, timeFrameticker, high)
halow = uha ?security(heikinashi(syminfo.tickerid), timeFrameticker, low) : security(syminfo.tickerid, timeFrameticker, low)

//Backtest dates
fromMonth = input(defval = 1,    title = "From Month",      type = input.integer, minval = 1, maxval = 12)
fromDay   = input(defval = 1,    title = "From Day",        type = input.integer, minval = 1, maxval = 31)
fromYear  = input(defval = 2021, title = "From Year",       type = input.integer, minval = 1970)
thruMonth = input(defval = 12,    title = "Thru Month",      type = input.integer, minval = 1, maxval = 12)
thruDay   = input(defval = 30,    title = "Thru Day",        type = input.integer, minval = 1, maxval = 31)
thruYear  = input(defval = 2021, title = "Thru Year",       type = input.integer, minval = 1970)

showDate  = input(defval = true, title = "Show Date Range", type = input.bool)

start     = timestamp(fromYear, fromMonth, fromDay, 00, 00)        // backtest start window
finish    = timestamp(thruYear, thruMonth, thruDay, 23, 59)        // backtest finish window
window()  => true

src = security(heikinashi(syminfo.tickerid), timeFrameticker, close)

//  INPUT MA TYPE
slowMAtype = input(title="Slow MA Type", type=input.string, defval="LRC", options=["SMA","EMA","DEMA","TEMA","LRC","WMA","MF","VAMA","TMA","HMA", "JMA", "Kijun v2", "EDSMA","McGinley"])
fastMAtype = input(title="Fast MA Type", type=input.string, defval="EDSMA", options=["SMA","EMA","DEMA","TEMA","LRC","WMA","MF","VAMA","TMA","HMA", "JMA", "Kijun v2", "EDSMA","McGinley"])
upMAcond =input(false, title="Use Uptrend Conditional 3rd MA for Confirmation")
upMAtype=input(title="Uptrend Conditional MA Type", type=input.string, defval="HMA", options=["SMA","EMA","DEMA","TEMA","LRC","WMA","MF","VAMA","TMA","HMA", "JMA", "Kijun v2", "EDSMA","McGinley"])


//  INPUT RESOLUTION
slowMAresolution = input("D",type=input.resolution, title="Slow MA Resolution")
fastMAresolution = input("D",type=input.resolution, title="Fast MA Resolution")
upMAresolution = input("D",type=input.resolution, title="Uptrend Conditional MA Resolution")
haMAslow = uha ? security(heikinashi(syminfo.tickerid), slowMAresolution, close) : security(syminfo.tickerid, slowMAresolution, close)
haMAfast = uha ?security(heikinashi(syminfo.tickerid), fastMAresolution, close) : security(syminfo.tickerid, fastMAresolution, close)
haMAup =  uha ?security(heikinashi(syminfo.tickerid), upMAresolution, close) : security(syminfo.tickerid, upMAresolution, close)

//  INPUT LENGTHS
slowMAlength = input(50, minval=1, title="Slow MA Length")
fastMAlength = input(30, minval=1, title="Fast MA Length")
upMAlength =  input(200, minval=1, title="Uptrend Conditional MA Length")

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////                      MA Function                         //////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

//           Pre-reqs
//
tema(src, len) =>
    ema1 = ema(src, len)
    ema2 = ema(ema1, len)
    ema3 = ema(ema2, len)
    (3 * ema1) - (3 * ema2) + ema3
kidiv = input(defval=1,maxval=4,  title="Kijun MOD Divider")

jurik_phase = input(title="* Jurik (JMA) Only - Phase", type=input.integer, defval=3)
jurik_power = input(title="* Jurik (JMA) Only - Power", type=input.integer, defval=1)
volatility_lookback = input(10, title="* Volatility Adjusted (VAMA) Only - Volatility lookback length")
//                  MF
beta = input(0.8,minval=0,maxval=1,step=0.1,  title="Modular Filter, General Filter Only - Beta")
feedback = input(false, title="Modular Filter Only - Feedback")
z = input(0.5,title="Modular Filter Only - Feedback Weighting",step=0.1, minval=0, maxval=1)
//EDSMA
ssfLength = input(title="EDSMA - Super Smoother Filter Length", type=input.integer, minval=1, defval=20)
ssfPoles = input(title="EDSMA - Super Smoother Filter Poles", type=input.integer, defval=2, options=[2, 3])

//----
//                  EDSMA
get2PoleSSF(src, length) =>
    PI = 2 * asin(1)
    arg = sqrt(2) * PI / length
    a1 = exp(-arg)
    b1 = 2 * a1 * cos(arg)
    c2 = b1
    c3 = -pow(a1, 2)
    c1 = 1 - c2 - c3
    
    ssf = 0.0
    ssf := c1 * src + c2 * nz(ssf[1]) + c3 * nz(ssf[2])

get3PoleSSF(src, length) =>
    PI = 2 * asin(1)

    arg = PI / length
    a1 = exp(-arg)
    b1 = 2 * a1 * cos(1.738 * arg)
    c1 = pow(a1, 2)

    coef2 = b1 + c1
    coef3 = -(c1 + b1 * c1)
    coef4 = pow(c1, 2)
    coef1 = 1 - coef2 - coef3 - coef4

    ssf = 0.0
    ssf := coef1 * src + coef2 * nz(ssf[1]) + coef3 * nz(ssf[2]) + coef4 * nz(ssf[3])

//          MA Main function
ma(type, src, len) =>
    float result = 0
    if type=="TMA"
        result := sma(sma(src, ceil(len / 2)), floor(len / 2) + 1)
    if type=="MF"
        ts=0.,b=0.,c=0.,os=0.
        //----
        alpha = 2/(len+1)
        a = feedback ? z*src + (1-z)*nz(ts[1],src) : src
        //----
        b := a > alpha*a+(1-alpha)*nz(b[1],a) ? a : alpha*a+(1-alpha)*nz(b[1],a)
        c := a < alpha*a+(1-alpha)*nz(c[1],a) ? a : alpha*a+(1-alpha)*nz(c[1],a)
        os := a == b ? 1 : a == c ? 0 : os[1]
        //----
        upper = beta*b+(1-beta)*c
        lower = beta*c+(1-beta)*b 
        ts := os*upper+(1-os)*lower
        result := ts
    if type=="LRC"
        result := linreg(src, len, 0)
    if type=="SMA" // Simple
        result := sma(src, len)
    if type=="EMA" // Exponential
        result := ema(src, len)
    if type=="DEMA" // Double Exponential
        e = ema(src, len)
        result := 2 * e - ema(e, len)
    if type=="TEMA" // Triple Exponential
        e = ema(src, len)
        result := 3 * (e - ema(e, len)) + ema(ema(e, len), len)
    if type=="WMA" // Weighted
        result := wma(src, len)
    if type=="VAMA" // Volatility Adjusted
        /// Copyright © 2019 to present, Joris Duyck (JD)
        mid=ema(src,len)
        dev=src-mid
        vol_up=highest(dev,volatility_lookback)
        vol_down=lowest(dev,volatility_lookback)
        result := mid+avg(vol_up,vol_down)
    if type=="HMA" // Hull
        result := wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len)))
    if type=="JMA" // Jurik
        /// Copyright © 2018 Alex Orekhov (everget)
        /// Copyright © 2017 Jurik Research and Consulting.
        phaseRatio = jurik_phase < -100 ? 0.5 : jurik_phase > 100 ? 2.5 : jurik_phase / 100 + 1.5
        beta = 0.45 * (len - 1) / (0.45 * (len - 1) + 2)
        alpha = pow(beta, jurik_power)
        jma = 0.0
        e0 = 0.0
        e0 := (1 - alpha) * src + alpha * nz(e0[1])
        e1 = 0.0
        e1 := (src - e0) * (1 - beta) + beta * nz(e1[1])
        e2 = 0.0
        e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
        jma := e2 + nz(jma[1])
        result := jma
    if type=="Kijun v2"
        kijun = avg(lowest(len), highest(len))//, (open + close)/2)
        conversionLine = avg(lowest(len/kidiv), highest(len/kidiv))
        delta = (kijun + conversionLine)/2
        result :=delta
    if type=="McGinley"
        mg = 0.0
        mg := na(mg[1]) ? ema(src, len) : mg[1] + (src - mg[1]) / (len * pow(src/mg[1], 4))
        result :=mg
    if type=="EDSMA"
    
        zeros = src - nz(src[2])
        avgZeros = (zeros + zeros[1]) / 2
        
        // Ehlers Super Smoother Filter 
        ssf = ssfPoles == 2
             ? get2PoleSSF(avgZeros, ssfLength)
             : get3PoleSSF(avgZeros, ssfLength)
        
        // Rescale filter in terms of Standard Deviations
        stdev = stdev(ssf, len)
        scaledFilter = stdev != 0
             ? ssf / stdev
             : 0
        
        alpha = 5 * abs(scaledFilter) / len
        
        edsma = 0.0
        edsma := alpha * src + (1 - alpha) * nz(edsma[1])
        result :=  edsma
    result
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////


//  MA DEFINITION
slowMA = ma(slowMAtype, haMAslow , slowMAlength)
//fastMA = ma(fastMAtype, slowMA , fastMAlength)
fastMA = ma(fastMAtype, haMAfast , fastMAlength)
upMA = ma(upMAtype, haMAup , upMAlength)
closeMA = ma('SMA', src , 2)

//  Strategy Conditions
L1 = crossover(fastMA,slowMA)
L2 = close > upMA
S1 = crossunder(fastMA,slowMA)
S2 = close < upMA
longcondition = upMAcond ? L1 and L2 : L1
shortcondition = upMAcond ? S1 or S2 : S1

//  Plots
color_fill_uptrend = color.new(#4caf50, 80)
color_fill_downtrend = color.new(#c2185b, 80)
plot(slowMA, title='Slow MA', color=color.olive, linewidth=2)
plot(fastMA, title='Fast MA', color=color.teal, linewidth=2)
cls=plot(closeMA, title='Source Line', color=na, linewidth=1)
up = plot(upMA, title='Uptrend Conditional MA', color=color.purple, linewidth=2)
fill(up,cls, color = close > upMA ? color_fill_uptrend : color_fill_downtrend )

//plotshape(longcondition, style = shape.triangleup, color = color.green, location = location.belowbar, text = "Long", size = size.small)
//plotshape(shortcondition, style = shape.triangledown, color = color.red, location = location.abovebar, text = "Short", size = size.small)


strategy.entry(id="long", long = true, when = longcondition and window())
strategy.close("long", when = shortcondition and window())

//if (longcondition)
//    strategy.entry("BUY", strategy.long, when = window())

//if (shortcondition)
//    strategy.entry("SELL", strategy.short, when = window())