모멘텀 브레이크오웃 최적화

저자:차오장, 날짜: 2024-01-17 16:44:30
태그:

img

전반적인 설명

모멘텀 브레이크아웃 최적화 전략 (Momentum Breakout Optimization strategy) 은 트레이딩 신호를 생성하고 모멘텀 지표에 따라 스톱 로스/트랙 노프트를 설정하는 트렌드 다음 전략이다. 이 전략은 가격과 이동 평균 사이의 크로스오버를 계산하여 시장 트렌드 방향을 판단하고 ATR 및 LinReg 채널을 사용하여 동적 스톱 로스 메커니즘을 구축한다. 한편, 이 전략은 더 나은 엔트리 가격을 위해 CMO 지표를 사용하여 과소매 / 과소매 수준을 식별하기도 한다.

전략 논리

    1. 트렌드 방향에 대한 기술적 지표로 가격의 ZLEMA 이동 평균을 계산
    1. ATR을 기반으로 긴 스톱 손실과 짧은 스톱 손실을 계산합니다.
    1. 오버구입/오버판매 구역을 식별하기 위한 CMO 지표를 계산하고, 이동평균을 입력 신호로 결합합니다.
    1. ATR, 이동 평균 및 가격 브레이크에 기반한 3 개의 거래 신호 세트를 생성합니다.
    • 이동평균과 스톱 로스 레벨의 크로스오버
    • 가격과 스톱 로스 레벨 사이의 크로스오버
    • 가격과 이동평균의 교차
    1. 매개 변수 설정을 통해 다른 신호 조합을 활성화/실용
    1. 리스크 관리에 대한 위험 비율 및 포지션 크기를 설정

전체 전략은 안정적인 트렌드를 따르는 여러 지표와 자동화된 스톱 로스를 결합하여 적절한 거래 기회를 보장하고 동시에 거래 위험을 통제합니다.

이점 분석

여러 지표의 조합

이 전략은 이동 평균, ATR, CMO 등을 포함한 지표의 조합을 사용합니다. 지표는 서로를 보완하고 추세 방향과 과잉 구매 / 과잉 판매 구역에 대한 더 신뢰할 수있는 판단을 제공합니다.

동적 후속 정지

ATR 기반의 동적 스톱 손실은 시장 변동성에 따라 스톱 손실 수준을 유연하게 조정하여 단일 거래 손실을 효과적으로 제어 할 수 있습니다.

종합적인 위험 관리

이 전략은 포지션 크기와 위험 비율을 설정하여 심각한 펀드 변동을 방지하기 위해 위험에 처한 자본의 최대 비율을 정의합니다.

풍부한 거래 신호

이 전략은 3 개의 거래 신호 세트를 제공합니다. 다른 신호 조합을 활성화함으로써 더 나은 백테스트 결과를 얻을 수 있습니다.

위험 분석

높은 거래 빈도

모든 신호 조합이 활성화되면 과도하게 빈번한 거래가 발생할 수 있습니다. 일부 신호만 사용함으로써 이것을 피할 수 있습니다.

매개 변수 설정에 민감하다

멀티 파라미터 모델은 파라미터 최적화를 더 복잡하고 민감하게 만듭니다. 최적의 파라미터 조합은 광범위한 테스트가 필요합니다.

브레이크오웃 신호에 대한 더 높은 드로다운

순수 가격/Stop Loss 브레이크오웃 신호의 경우, Stop Loss 범위는 더 넓어 단일 거래 손실과 드라우다운으로 이어질 수 있습니다. 이동 평균 신호와 결합하는 것이 좋습니다.

최적화 방향

다른 매개 변수 조합을 테스트합니다.

이동 평균 유형/길이, ATR 기간, CMO 기간과 같은 매개 변수를 최적화하여 최적의 일치를 찾습니다.

신호 사용 전략을 최적화

가장 좋은 사용 전략을 찾기 위해 이동 평균 신호, 스톱 손실 신호 또는 조합 신호만을 사용하여 성능을 테스트하십시오.

다른 제품에서 테스트 성능

다른 시장 유형에 대한 적응성을 분석하기 위해 지수, 외환, 상품 제품에 대한 전략을 백테스트합니다.

결론

이 전략은 트렌드 식별, 스톱 로스 구축, 과잉 구매 / 과잉 판매 검출을 위한 여러 지표를 통합한다. 매개 변수 및 신호 조합을 조정함으로써 만족스러운 위험 메트릭을 달성할 수 있다. 전체 시스템은 추가 라이브 테스트와 최적화를 위해 포괄적이고 신뢰할 수 있다.


/*backtest
start: 2024-01-09 00:00:00
end: 2024-01-16 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © KivancOzbilgic
//developer: @KivancOzbilgic
//author: @KivancOzbilgic

strategy(title="Profit Maximizer PMax", overlay=true,
     pyramiding=0, initial_capital=1000,
     commission_type=strategy.commission.cash_per_order,
     commission_value=0.025, slippage=2)


src = input(hl2, title="Source")
Periods = input(title="ATR Length", type=input.integer, defval=10)
Multiplier = input(title="ATR Multiplier", type=input.float, step=0.1, defval=3.0)
mav = input(title="Moving Average Type", defval="ZLEMA", options=["SMA", "EMA", "WMA", "TMA", "VAR", "WWMA", "ZLEMA", "TSF"])
length =input(10, "Moving Average Length", minval=1)
changeATR= input(title="Change ATR Calculation Method ?", type=input.bool, defval=true)
showsupport = input(title="Show Moving Average?", type=input.bool, defval=true)
showsignalsk = input(title="Show Crossing Signals?", type=input.bool, defval=true)
showsignalsc = input(title="Show Price/Pmax Crossing Signals?", type=input.bool, defval=false)
highlighting = input(title="Highlighter On/Off ?", type=input.bool, defval=true)

usePosSize = input(title="Use Position Sizing?", type=input.bool, defval=true)
riskPerc   = input(title="Risk %", type=input.float, defval=0.5, step=0.25)

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

endDate = input(title="End Date", type=input.integer,
     defval=1, minval=1, maxval=31)
endMonth = input(title="End Month", type=input.integer,
     defval=12, minval=1, maxval=12)
endYear = input(title="End Year", type=input.integer,
     defval=2021, minval=1800, maxval=2100)
     
// Look if the close time of the current bar
// falls inside the date range
inDateRange = true

atr2 = sma(tr, Periods)
atr= changeATR ? atr(Periods) : atr2
valpha=2/(length+1)
vud1=src>src[1] ? src-src[1] : 0
vdd1=src<src[1] ? src[1]-src : 0
vUD=sum(vud1,9)
vDD=sum(vdd1,9)
vCMO=nz((vUD-vDD)/(vUD+vDD))
VAR=0.0
VAR:=nz(valpha*abs(vCMO)*src)+(1-valpha*abs(vCMO))*nz(VAR[1])
wwalpha = 1/ length
WWMA = 0.0
WWMA := wwalpha*src + (1-wwalpha)*nz(WWMA[1])
zxLag = length/2==round(length/2) ? length/2 : (length - 1) / 2
zxEMAData = (src + (src - src[zxLag]))
ZLEMA = ema(zxEMAData, length)
lrc = linreg(src, length, 0)
lrc1 = linreg(src,length,1)
lrs = (lrc-lrc1)
TSF = linreg(src, length, 0)+lrs
getMA(src, length) =>
    ma = 0.0
    if mav == "SMA"
        ma := sma(src, length)
        ma

    if mav == "EMA"
        ma := ema(src, length)
        ma

    if mav == "WMA"
        ma := wma(src, length)
        ma

    if mav == "TMA"
        ma := sma(sma(src, ceil(length / 2)), floor(length / 2) + 1)
        ma

    if mav == "VAR"
        ma := VAR
        ma

    if mav == "WWMA"
        ma := WWMA
        ma

    if mav == "ZLEMA"
        ma := ZLEMA
        ma

    if mav == "TSF"
        ma := TSF
        ma
    ma
    
MAvg=getMA(src, length)
longStop = MAvg - Multiplier*atr
longStopPrev = nz(longStop[1], longStop)
longStop := MAvg > longStopPrev ? max(longStop, longStopPrev) : longStop
shortStop = MAvg + Multiplier*atr
shortStopPrev = nz(shortStop[1], shortStop)
shortStop := MAvg < shortStopPrev ? min(shortStop, shortStopPrev) : shortStop
dir = 1
dir := nz(dir[1], dir)
dir := dir == -1 and MAvg > shortStopPrev ? 1 : dir == 1 and MAvg < longStopPrev ? -1 : dir
PMax = dir==1 ? longStop: shortStop
plot(showsupport ? MAvg : na, color=#0585E1, linewidth=2, title="Moving Avg Line")
pALL=plot(PMax, color=color.red, linewidth=2, title="PMax", transp=0)

alertcondition(cross(MAvg, PMax), title="Cross Alert", message="PMax - Moving Avg Crossing!")
alertcondition(crossover(MAvg, PMax), title="Crossover Alarm", message="Moving Avg BUY SIGNAL!")
alertcondition(crossunder(MAvg, PMax), title="Crossunder Alarm", message="Moving Avg SELL SIGNAL!")
alertcondition(cross(src, PMax), title="Price Cross Alert", message="PMax - Price Crossing!")
alertcondition(crossover(src, PMax), title="Price Crossover Alarm", message="PRICE OVER PMax - BUY SIGNAL!")
alertcondition(crossunder(src, PMax), title="Price Crossunder Alarm", message="PRICE UNDER PMax - SELL SIGNAL!")


// Calculate position size
riskEquity  = (riskPerc / 100) * strategy.equity
atrCurrency = (atr(20) * syminfo.pointvalue)
posSize     = usePosSize ? floor(riskEquity / atrCurrency) : 1

//Long
buySignalk = crossover(MAvg, PMax)
plotshape(buySignalk and showsignalsk ? PMax*0.995 : na, title="Buy", text="BuyL", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0)


if(buySignalk and showsignalsk and inDateRange)
    strategy.entry(id="buySignalk", long=true, qty=posSize)
    
sellSignallk = crossunder(MAvg, PMax)
plotshape(sellSignallk and showsignalsk ? PMax*1.005 : na, title="Sell", text="SellL", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0)

if(sellSignallk and showsignalsk and inDateRange)
    strategy.order(id="sellSignallk", long=false, qty=strategy.position_size)
    
//Short
buySignalc = crossover(src, PMax)
plotshape(buySignalc and showsignalsc ? PMax*0.995 : na, title="Buy", text="BuyS", location=location.absolute, style=shape.labelup, size=size.tiny, color=#0F18BF, textcolor=color.white, transp=0)

if(buySignalc and showsignalsc and inDateRange)
    strategy.entry(id="BuyS", long=false, qty=posSize)

sellSignallc = crossunder(src, PMax)
plotshape(sellSignallc and showsignalsc ? PMax*1.005 : na, title="Sell", text="SellS", location=location.absolute, style=shape.labeldown, size=size.tiny, color=#0F18BF, textcolor=color.white, transp=0)

if(sellSignallc and showsignalsc and inDateRange)
    strategy.order(id="SellS", long=true, qty=abs(strategy.position_size))

mPlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0,display=display.none)

longFillColor = highlighting ? (MAvg>PMax ? color.green : na) : na
shortFillColor = highlighting ? (MAvg<PMax ? color.red : na) : na

fill(mPlot, pALL, title="UpTrend Highligter", color=longFillColor)
fill(mPlot, pALL, title="DownTrend Highligter", color=shortFillColor)

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

더 많은