이동 평균 크로스오버 전략

저자:차오장, 날짜: 2023-10-27 16:19:00
태그:

img

전반적인 설명

이동평균 크로스오버 전략은 트렌드 방향을 결정하고 거래 신호를 생성하기 위해 이중 이동평균의 크로스오버 신호를 사용하는 모멘텀 전략이다. 2개의 간단한 이동평균과 1개의 기하급수적인 이동평균을 사용하여 중장기 거래 전략에 속하는 크로스오버에 따라 길고 짧은 것을 판단한다.

전략 논리

이 전략은 3개의 이동 평균을 사용합니다.

  • EMA1: 빠른 선으로 작용하는 짧은 기간의 기하급수적 이동 평균
  • SMA1: 느린 라인 역할을 하는 더 긴 기간 간단한 이동 평균
  • SMA2: 추세 방향을 결정하는 더 긴 기간 간단한 이동 평균

이 전략은 EMA1, SMA1 및 SMA2 사이의 관계를 기반으로 트렌드를 판단합니다.

  • 상향 트렌드: EMA1 > SMA1 > SMA2
  • 하향 추세: EMA1 < SMA1 < SMA2

입구 신호:

  • 긴 입력: 빠른 라인이 느린 라인의 위를 넘을 때
  • 짧은 입력: 빠른 라인이 느린 라인의 아래를 넘을 때

출구 신호:

  • 롱 클로즈: 빠른 선이 느린 선 아래로 넘어가면
  • 단축: 빠른 선이 느린 선 위에 넘어가면

이 전략은 여러 매개 변수 구성을 제공하며, 입출에 대한 조정 가능한 이동 평균을 제공합니다.

이점 분석

이 전략의 장점:

  1. 동력을 포착합니다. 트렌드 변화, 동력 전략을 감지합니다.
  2. 유연한 구성: 여러 MA 선택, 유연한 매개 변수 조정
  3. 트렌드 필터링: 트렌드를 결정하기 위해 장기 MA를 사용하며 트렌드 반대 거래를 피합니다.
  4. 리스크 관리: 설정 가능한 스톱 로스 및 영업 리스크 제어

위험 분석

이 전략의 위험은:

  1. 윙사: 발작 전에 장기간 윙사면 여러 가지 잘못된 신호가 발생할 수 있습니다.
  2. MA 매개 변수에 민감함: MA 기간의 부적절한 조정은 과민성 또는 느림으로 이어질 수 있습니다.
  3. 지연: 이동 평균의 본질적인 지연 특성으로 가장 좋은 입시 시기를 놓칠 수 있습니다.
  4. 기본 요소가 없습니다: 순전히 기술 지표에 기반하고 기본 요소가 고려되지 않습니다.

Whipsaw 위험은 MA 기간을 조정함으로써 완화 될 수 있습니다. 매개 변수 감수성은 최적화로 해결 될 수 있습니다. 다른 주요 지표를 통합함으로써 지연 위험은 감소 할 수 있습니다.

최적화 방향

잠재적인 최적화:

  1. 신호 품질을 향상시키기 위해 RSI, 볼링거 밴드와 같은 다른 기술적 필터를 추가하십시오.
  2. 최적의 매개 변수를 찾기 위해 MA 기간을 최적화
  3. 추세와 신호 신뢰성을 판단하기 위해 기계 학습 모델을 통합
  4. 거래 부피를 고려하여 저용량 조건에서 거짓 브레이크를 피합니다.
  5. 경제주기에 반하는 거래를 피하기 위한 근본적인 요소를 포함

결론

이동 평균 크로스오버 전략은 직선적이고, 빠르고 느린 MAs의 교차를 통해 트렌드와 타이밍을 판단합니다. 이의 장점은 유연한 구성으로 추진력을 잡는 것이지만, 윙사와 레이깅과 같은 위험이 있습니다. 추가 필터와 같은 최적화로 매우 실용적인 양적 거래 전략이 될 수 있습니다.


/*backtest
start: 2023-09-26 00:00:00
end: 2023-10-26 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/
// © Decam9

//@version=5
strategy(title = "Moving Average Crossover", shorttitle = "MA Crossover Strategy", overlay=true,
     initial_capital = 100000,default_qty_type = strategy.percent_of_equity, default_qty_value = 10)

//Moving Average Inputs
EMA1 = input.int(title="Fast EMA", group = "Moving Averages:", 
     inline = "EMAs", defval=5, minval = 1)
isDynamicEMA = input.bool(title = "Dynamic Exponential Moving Average?", defval = true,
     inline = "EMAs", group = "Moving Averages:", tooltip = "Changes the source of the MA based on trend")

SMA1 = input.int(title = "Slow SMA", group = "Moving Averages:",
     inline = "SMAs", defval = 10, minval = 1)
isDynamicSMA = input.bool(title = "Dynamic Simple Moving Average?", defval = false,
     inline = "SMAs", group = "Moving Averages:", tooltip = "Changes the source of the MA based on trend")

SMA2 = input.int(title="Trend Determining SMA", group = "Moving Averages:",
     inline = "MAs", defval=13, minval = 1)

//Moving Averages
Trend = ta.sma(close, SMA2)
Fast = ta.ema(isDynamicEMA ? (close > Trend ? low : high) : close, EMA1)
Slow = ta.sma(isDynamicSMA ? (close > Trend ? low : high) : close, SMA1)

//Allowed Entries
islong = input.bool(title = "Long", group = "Allowed Entries:",
     inline = "Entries",defval = true)
isshort = input.bool(title = "Short", group = "Allowed Entries:",
     inline = "Entries", defval= true)

//Entry Long Conditions
buycond = input.string(title="Buy when", group = "Entry Conditions:", 
     inline = "Conditions",defval="Fast-Slow Crossing", 
     options=["Fast-Slow Crossing", "Fast-Trend Crossing","Slow-Trend Crossing"])
     
intrendbuy = input.bool(title = "In trend", defval = true, group = "Entry Conditions:",
     inline = "Conditions", tooltip = "In trend if price is above SMA 2")

//Entry Short Conditions
sellcond = input.string(title="Sell when", group = "Entry Conditions:", 
     inline = "Conditions2",defval="Fast-Slow Crossing", 
     options=["Fast-Slow Crossing", "Fast-Trend Crossing","Slow-Trend Crossing"])
     
intrendsell = input.bool(title = "In trend",defval = true, group = "Entry Conditions:",
     inline = "Conditions2", tooltip = "In trend if price is below SMA 2?")

//Exit Long Conditions
closebuy = input.string(title="Close long when", group = "Exit Conditions:", 
     defval="Fast-Slow Crossing", options=["Fast-Slow Crossing", "Fast-Trend Crossing","Slow-Trend Crossing"])

//Exit Short Conditions
closeshort = input.string(title="Close short when", group = "Exit Conditions:", 
     defval="Fast-Slow Crossing", options=["Fast-Slow Crossing", "Fast-Trend Crossing","Slow-Trend Crossing"])
     

//Filters
filterlong =input.bool(title = "Long Entries", inline = 'linefilt', group = 'Apply Filters to', 
     defval = true)
filtershort =input.bool(title = "Short Entries", inline = 'linefilt', group = 'Apply Filters to', 
     defval = true)
filterend =input.bool(title = "Exits", inline = 'linefilt', group = 'Apply Filters to', 
     defval = true)
usevol =input.bool(title = "", inline = 'linefiltvol', group = 'Relative Volume Filter:', 
     defval = false)
rvol = input.int(title = "Volume >", inline = 'linefiltvol', group = 'Relative Volume Filter:', 
     defval = 1)
len_vol = input.int(title = "Avg. Volume Over Period", inline = 'linefiltvol', group = 'Relative Volume Filter:', 
     defval = 30, minval = 1,
     tooltip="The current volume must be greater than N times the M-period average volume.")
useatr =input.bool(title = "", inline = 'linefiltatr', group = 'Volatility Filter:', 
     defval = false)
len_atr1 = input.int(title = "ATR", inline = 'linefiltatr', group = 'Volatility Filter:', 
     defval = 5, minval = 1)
len_atr2 = input.int(title = "> ATR", inline = 'linefiltatr', group = 'Volatility Filter:', 
     defval = 30, minval = 1,
     tooltip="The N-period ATR must be greater than the M-period ATR.")
usersi =input.bool(title = "", inline = 'linersi', group = 'Overbought/Oversold Filter:', 
     defval = false)
rsitrhs1 = input.int(title = "", inline = 'linersi', group = 'Overbought/Oversold Filter:', 
     defval = 0, minval=0, maxval=100)
rsitrhs2 = input.int(title = "< RSI (14) <", inline = 'linersi', group = 'Overbought/Oversold Filter:', 
     defval = 100, minval=0, maxval=100,
     tooltip="RSI(14) must be in the range between N and M.")
issl =  input.bool(title = "SL", inline = 'linesl1', group = 'Stop Loss / Take Profit:', 
     defval = false)
slpercent =  input.float(title = ", %", inline = 'linesl1', group = 'Stop Loss / Take Profit:', 
     defval = 10, minval=0.0)
istrailing =  input.bool(title = "Trailing", inline = 'linesl1', group = 'Stop Loss / Take Profit:', 
     defval = false)
istp =  input.bool(title = "TP", inline = 'linetp1', group = 'Stop Loss / Take Profit:', 
     defval = false)
tppercent =  input.float(title = ", %", inline = 'linetp1', group = 'Stop Loss / Take Profit:', 
     defval = 20)
     
//Conditions for Crossing
fscrossup = ta.crossover(Fast,Slow)
fscrossdw = ta.crossunder(Fast,Slow)
ftcrossup = ta.crossover(Fast,Trend)
ftcrossdw = ta.crossunder(Fast,Trend)
stcrossup = ta.crossover(Slow,Trend)
stcrossdw = ta.crossunder(Slow,Trend)

//Defining in trend
uptrend = Fast >= Slow and Slow >= Trend
downtrend = Fast <= Slow and Slow <= Trend
justCrossed = ta.cross(Fast,Slow) or ta.cross(Slow,Trend)


//Entry Signals
crosslong = if intrendbuy
    (buycond =="Fast-Slow Crossing" and uptrend ? fscrossup:(buycond =="Fast-Trend Crossing" and uptrend ? ftcrossup:(buycond == "Slow-Trend Crossing" and uptrend ? stcrossup : na))) 
else
    (buycond =="Fast-Slow Crossing"?fscrossup:(buycond=="Fast-Trend Crossing"?ftcrossup:stcrossup))

crossshort = if intrendsell
    (sellcond =="Fast-Slow Crossing" and downtrend ? fscrossdw:(sellcond =="Fast-Trend Crossing" and downtrend ? ftcrossdw:(sellcond == "Slow-Trend Crossing" and downtrend ? stcrossdw : na))) 
else
    (sellcond =="Fast-Slow Crossing"?fscrossdw:(buycond=="Fast-Trend Crossing"?ftcrossdw:stcrossdw))
crossexitlong = (closebuy =="Fast-Slow Crossing"?fscrossdw:(closebuy=="Fast-Trend Crossing"?ftcrossdw:stcrossdw))
crossexitshort = (closeshort =="Fast-Slow Crossing"?fscrossup:(closeshort=="Fast-Trend Crossing"?ftcrossup:stcrossup))


// Filters
rsifilter = usersi?(ta.rsi(close,14) > rsitrhs1 and ta.rsi(close,14) < rsitrhs2):true
volatilityfilter = useatr?(ta.atr(len_atr1) > ta.atr(len_atr2)):true
volumefilter = usevol?(volume > rvol*ta.sma(volume,len_vol)):true
totalfilter = volatilityfilter and volumefilter and rsifilter

//Filtered signals
golong  = crosslong  and islong  and (filterlong?totalfilter:true) 
goshort = crossshort and isshort and (filtershort?totalfilter:true)
endlong  = crossexitlong and (filterend?totalfilter:true)
endshort = crossexitshort and (filterend?totalfilter:true)

// Entry price and TP
startprice = ta.valuewhen(condition=golong or goshort, source=close, occurrence=0)
pm = golong?1:goshort?-1:1/math.sign(strategy.position_size)
takeprofit = startprice*(1+pm*tppercent*0.01)
// fixed stop loss
stoploss = startprice * (1-pm*slpercent*0.01)
// trailing stop loss
if istrailing and strategy.position_size>0
    stoploss := math.max(close*(1 - slpercent*0.01),stoploss[1])
else if istrailing and strategy.position_size<0
    stoploss := math.min(close*(1 + slpercent*0.01),stoploss[1])
    
if golong and islong
    strategy.entry("long",   strategy.long )
if goshort and isshort
    strategy.entry("short",  strategy.short)
if endlong
    strategy.close("long")
if endshort
    strategy.close("short")

// Exit via SL or TP
strategy.exit(id="sl/tp long", from_entry="long", stop=issl?stoploss:na, 
              limit=istp?takeprofit:na)
strategy.exit(id="sl/tp short",from_entry="short",stop=issl?stoploss:na, 
              limit=istp?takeprofit:na)



더 많은