移動平均クロスオーバートレンド戦略


作成日: 2023-10-27 16:19:00 最終変更日: 2023-10-27 16:19:00
コピー: 0 クリック数: 662
1
フォロー
1617
フォロワー

移動平均クロスオーバートレンド戦略

概要

移動平均線交差戦略は,動向方向を判断するために,双移動平均線交差信号を利用して,買入と売却のシグナルを生成する,モメンタム戦略である.この戦略は,2つの単純な移動平均線と1つの指数移動平均線を使用し,それらの交差状況に基づいて多空を判断し,中短期取引戦略に属する.

戦略原則

この戦略は3つの移動平均を用います.

  • EMA1:短期の指数移動平均で,快線を表す
  • SMA1: 遅い線を表すより長い周期の単純移動平均
  • SMA2:トレンドの方向を判断するより長い周期の単純移動平均

EMA1,SMA1,SMA2の大きさの関係でトレンドを判断する戦略:

  • 上昇傾向:EMA1 > SMA1 > SMA2
  • ダウン傾向:EMA1 < SMA1 < SMA2

入力信号:

  • 速線で遅線を横切るときに多めに入る
  • 空頭入口:速線下を通過する際の空頭

終了信号:

  • 速線下を通過する際の平衡
  • 空頭退場:速線で遅線を抜いたとき平仓

この戦略は,入場と退場を判断するために異なる移動平均を選択できる複数のパラメータ配置を提供します.

優位分析

この戦略の利点は以下の通りです.

  1. 市場動向の変化を捉えるための戦略
  2. 柔軟な構成: 移動平均の選択肢を多く提供し,柔軟に設定できます.
  3. 傾向フィルタリング:長期移動平均を使ってトレンドの方向を判断し,逆転取引を避ける
  4. リスク管理: ストップ・ローズとストップ・ストップを設定し,単一取引のリスクを制御

リスク分析

この戦略には以下のリスクもあります.

  1. whipsaws: 突破前に続く揺れが起こり,偽突破が繰り返される
  2. sensitive to MA parameters:移動平均のパラメータを正しく設定しない場合,過度に頻繁または不十分に敏感になる可能性がある
  3. 遅滞:移動平均は本質的に遅滞しており,突破の最適なタイミングを逃す可能性があります.
  4. no fundamentals:基本を考慮しない,純粋に技術的な指数で動いている

whipsawsのリスクに対して,移動平均周期を適切に調整することができる.パラメータの感受性のリスクに対して,パラメータを最適化することができる.後退性のリスクに対して,他の先行指標と組み合わせて最適化することができる.

最適化の方向

この戦略は以下の点で最適化できます.

  1. RSI,ブリン帯など,他の技術指標のフィルターを追加し,信号の質を向上させる
  2. 移動平均の周期パラメータを最適化して,最適なパラメータを探します.
  3. 傾向と信号信頼性を判断する機械学習モデル
  4. 取引量との組み合わせにより,低量価格の偽突破を回避する.
  5. 基本要素を組み合わせて逆周期的な取引を避ける

要約する

移動平均線交差戦略は,全体的に比較的単純で直接的で,急激な平均線の交差によってトレンドの方向と参加のタイミングを判断する. この戦略の優点は,モメンタムを捕捉でき,柔軟な配置パラメータであるが,一定のウィップソーリスク,落後リスクなどの問題もある. 他の指標を導入して,フィルタリングを最適化することで,この戦略は,非常に実用的な量化取引戦略になることができる.

ストラテジーソースコード
/*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)