동적 MA 크로스오버 트렌드 전략

저자:차오장, 날짜: 2023-12-19 11:49:30
태그:

img

전반적인 설명

이 전략은 진입 신호로 동적 저항/지원 대역과 MA 라인의 교차를 사용하며, 수익을 확보하기 위해 정지 이후 트렌드를 채택합니다.

전략 논리

  1. 역동적 저항 및 지원 수준을 계산하여 잠재적인 반전 구역을 식별하기 위해 퍼센틸 통계를 사용합니다.

  2. 가격이 반전 구역에 들어갈 때, 빠른 MA가 느린 MA를 넘어서거나 밑으로 넘어가는지 확인하여 거래 신호를 생성합니다.

  3. 진입 후, 트레일링 스톱 메커니즘을 시작하여 수익을 동적으로 잠금하고 트렌드를 따르십시오.

  4. 가격이 미리 정의된 스톱 로스 또는 수익을 취하는 수준에 도달하면 포지션을 닫습니다.

장점

  1. 동적 대역은 잠재적인 반전 영역을 식별하고 입력 정확도를 향상시키는 데 도움이됩니다.

  2. MA 크로스오버와 퍼센틸 채널을 결합하면 잘못된 신호를 피할 수 있습니다.

  3. 트래일링 스톱은 수익을 효과적으로 차단하고 과도한 인출을 방지합니다.

  4. 사용자 정의 가능한 매개 변수는 다른 시장 환경에 적합합니다.

위험성

  1. 트렌드가 아닌 시장에서 잘못된 신호가 발생할 수 있습니다.

  2. 부적절한 파라미터 조정으로 인해 너무 공격적인 입력입니다.

  3. 백테스트 데이터는 충분한 시장 주기를 다루어야 합니다.

  4. 간격을 방지하기 위해 라이브 거래에서 더 넓은 정지를 고려하십시오.

강화

  1. 다른 MA 기간 조합을 테스트합니다.

  2. 동적 대역 매개 변수를 조정하여 역전 식별을 최적화합니다.

  3. 각종 트레일링 스톱 매개 변수에서 주식 곡선에 미치는 영향을 평가합니다.

  4. 신뢰성을 높이기 위해 필터를 추가해보세요.

결론

이 전략의 전반적인 논리는 명확하다. 신호를 필터링하기 위해 동적 대역을 사용하며, MA 교차로로 트렌드 방향을 판단하고, 후속 정지 메커니즘으로 위험을 효과적으로 제어한다. 매개 변수 조정을 통해 추가 최적화는 생산에 대한 전략 성능을 지속적으로 향상시킬 수 있다.


/*backtest
start: 2022-12-12 00:00:00
end: 2023-12-18 00:00:00
period: 1d
basePeriod: 1h
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/
// © allanster

//@version=4

strategy("MA-EMA Crossover LT", shorttitle="MA-EMA XO", overlay=true)


//==================== STRATEGY CODE ======================

tradeType = input("BOTH", title="Trade Type ", options=["LONG", "SHORT", "BOTH"])

// === BACKTEST RANGE ===
FromMonth = 01//input(defval=01, title="From Month", minval=1)
FromDay = 01//input(defval=01, title="From Day", minval=1)
FromYear = input(defval=2017, title="From Year", minval=2000)
ToMonth = 12//input(defval=12, title="To Month", minval=1)
ToDay = 31//input(defval=31, title="To Day", minval=1)
ToYear = input(defval=9999, title="To Year", minval=2000)

testPeriod() =>
    time > timestamp(FromYear, FromMonth, FromDay, 00, 00) and 
       time < timestamp(ToYear, ToMonth, ToDay, 23, 59)

stopLossPercent = input(1.00, "Stop Loss Percent")
profitPercent_long = input(3.50, "Profit Percent LONG")
profitPercent_short = input(3.0, "Profit Percent SHORT")

atr_multi_PT = input(1.50, "ATR Multiple for PT")
atr_multi_SL = input(1.50, "ATR Multiple for SL")
//////////////////////////////

isLongOpen = false
isShortOpen = false

//Order open on previous ticker?
isLongOpen := nz(isLongOpen[1])
isShortOpen := nz(isShortOpen[1])

/////////////////////
//Trailing and Profit variables
trigger = 0.0
trigger := na

profitTrigger = 0.0
profitTrigger := na

//obtain values from last ticker
entryPrice = 0.0
entryPrice := nz(entryPrice[1])

stopLossLevel = 0.0
stopLossLevel := nz(stopLossLevel[1])

profitPriceLevel = 0.0
profitPriceLevel := nz(profitPriceLevel[1])


//If in active trade, lets load with current value    
if isLongOpen
    profitTrigger := profitPriceLevel ? high : na
    trigger := stopLossLevel ? ohlc4 : na
    trigger
if isShortOpen
    profitTrigger := profitPriceLevel ? low : na
    trigger := stopLossLevel ? ohlc4 : na
    trigger

isStopLoss = isLongOpen ? trigger < stopLossLevel : 
   isShortOpen ? trigger > stopLossLevel : na
isProfitCatch = isLongOpen ? profitTrigger > profitPriceLevel : 
   isShortOpen ? profitTrigger < profitPriceLevel : na

//===================      Optional Entry Condition    ============
src    = close
len = input(defval = 128, title = "DZ Length", type = input.integer, minval = 1)
// use_dz = input(false, title="Use Dynamic Zone")
pcntAbove = input(defval = 40, title = "Hi is Above X% of Sample", type = input.float, minval = 0, maxval = 100, step = 1.0)
pcntBelow = input(defval = 60, title = "Lo is Below X% of Sample", type = input.float, minval = 0, maxval = 100, step = 1.0)

smplAbove = percentile_nearest_rank(src, len, pcntAbove)
smplBelow = percentile_nearest_rank(src, len, 100 - pcntBelow)

above     = plot(src > smplAbove ? src : smplAbove, title = "Above Line", color = na)
probOB    = plot(smplAbove, title = "OB", color = color.green)
probOS    = plot(smplBelow, title = "OS", color = color.red)
below     = plot(src < smplBelow ? src : smplBelow, title = "Below Line", color = na)
fill(above,  probOB, color = #00FF00, transp = 80)
fill(below,  probOS, color = #FF0000, transp = 80)

// long_dz = close > smplAbove
// short_dz = close < smplBelow


//==============           Entry Conditions        =====================
timeframe = input("5D", title="MA16 Resolution", type=input.resolution)
_ma = sma(hlc3, 16)
ma=security(syminfo.tickerid, timeframe, _ma, barmerge.gaps_off, barmerge.lookahead_on)

_ema=ema(hlc3,7)
ema=security(syminfo.tickerid, timeframe, _ema, barmerge.gaps_off, barmerge.lookahead_on)


long = ma[1] > ema[1] ? crossover(ema, ma) : abs(ma - ema)/ma > 0.025 ? crossover(close, ema) : false
short = ma[1] < ema[1] ? crossunder(ema,ma) : abs(ma - ema)/ma > 0.025 ? crossunder(close, ema): false //:crossunder(close, ema) 

longEntry = (tradeType == "LONG" or tradeType == "BOTH") and long
shortEntry = (tradeType == "SHORT" or tradeType == "BOTH") and short

//Upon Entry, do this.
if longEntry or shortEntry
    entryPrice := ohlc4
    entryPrice

//set price points for new orders
use_dz_sl = input(true, title="Use DZ SL")
if isLongOpen 
    stopLossLevel := use_dz_sl? max(smplAbove, ma) : ema - 0.25*atr_multi_PT* atr(32) //ma
    profitTrail = ma + atr_multi_PT* atr(32)
    profitPriceLevel :=  max( (1 + 0.01 * profitPercent_long) * entryPrice, profitTrail)
    profitPriceLevel
if isShortOpen 
    stopLossLevel :=  use_dz_sl? min(smplBelow, ma) : ema + 0.25*atr_multi_PT* atr(32) //ma
    profitTrail = ma - atr_multi_PT* atr(32)
    profitPriceLevel := min( (1 - 0.01 * profitPercent_short) * entryPrice, profitTrail)
    profitPriceLevel

shortExit = isShortOpen[1] and (isStopLoss or isProfitCatch or longEntry)
longExit = isLongOpen[1] and (isStopLoss or isProfitCatch or shortEntry)


if (longExit or shortExit) and not(longEntry or shortEntry)
    trigger := na
    profitTrigger := na
    entryPrice := na
    stopLossLevel := na
    profitPriceLevel := na
    // highest := na
    // lowest := na
    // lowest

if testPeriod() and (tradeType == "LONG" or tradeType == "BOTH")
    strategy.entry("long", strategy.long, when=longEntry)
    strategy.close("long", when=longExit)

if testPeriod() and (tradeType == "SHORT" or tradeType == "BOTH")
    strategy.entry("short", strategy.short, when=shortEntry)
    strategy.close("short", when=shortExit)


//If the value changed to invoke a buy, lets set it before we leave
isLongOpen := longEntry ? true : longExit == true ? false : isLongOpen
isShortOpen := shortEntry ? true : shortExit == true ? false : isShortOpen


plotshape(isShortOpen, title="Short Open", color=color.red, style=shape.triangledown, location=location.bottom)
plotshape(isLongOpen, title="Long Open", color=color.green, style=shape.triangleup, location=location.bottom)

plotshape(entryPrice ? entryPrice : na, title="Entry Level", color=color.black, style=shape.cross, location=location.absolute)
plotshape(stopLossLevel ? stopLossLevel : na, title="Stop Loss Level", color=color.orange, style=shape.xcross, location=location.absolute)
plotshape(profitPriceLevel ? profitPriceLevel : na, title="Profit Level", color=color.blue, style=shape.xcross, location=location.absolute)
plotshape(profitTrigger[1] ? isProfitCatch : na, title="Profit Exit Triggered", style=shape.diamond, location=location.abovebar, color=color.blue, size=size.small)
plotshape(trigger[1] ? isStopLoss : na, title="Stop Loss Triggered", style=shape.diamond, location=location.belowbar, color=color.orange, size=size.small)

plot(ma, title="MA 16", color=color.yellow)
plot(ema, title="EMA 7", color=color.blue)

더 많은