多要素移動平均傾向 戦略に従った

作者: リン・ハーンチャオチャン開催日:2024年1月18日 12:07:52
タグ:

img

概要

これは,ビットコインとイーサリアムに適した簡単な移動平均トレンドフォロー戦略です.トレンド方向を特定するために移動平均値,MACD,RSIなどの複数の指標を組み合わせ,長期トレンド追跡のために固定ポジションサイズを採用します.

戦略の論理

この戦略の基本論理は,20日間のEMAが100日間のSMAを上回り,100日間のSMAが200日間のSMAを上回るとロングに行くこと.20日間のEMAが100日間のSMAを下回るとポジションを閉じることである.つまり,トレンド方向を決定するために異なる期間の3つの移動平均を使用する.

戦略は,20日間のEMA,100日間のSMA,および200日間のSMAの値を計算し,トレンドを判断するためにそれらの大きさの関係を比較する.20日間のEMAが100日間のSMAを超えると,価格は上昇し始めていることを意味します.この時点で,100日間のSMAも200日間のSMAよりも大きい場合は,中期および長期間のトレンドも上昇していることを示します.これは強力なロング信号です.

ロングポジションに入ると,戦略はトレンドをフォローするポジションを継続する.20日間のEMAが再び100日間のSMAを下回ると,短期的なトレンド逆転信号が発生したことを示します.この時点で,戦略は損失を止めるためにポジションを閉じることを選択します.

さらに,この戦略は,傾向を確認するためにMACDやRSIなどの指標も組み込む.MACDのDIFライン,DEMAライン,HISTバーラインがすべて上昇し,RSIインジケーターが50を超えるとのみ,ロングポジションを開くことを選択する.

利点

この戦略の最大の利点は,中期および長期間のトレンドを効果的に追跡できる明確なトレンド取引規則を策定することです. 具体的な利点は以下の通りです.

  1. 傾向を判断するために複数の移動平均を組み合わせて使用します これは比較的信頼性があります

  2. 短期的な市場変動に動揺することなく,トレンドの動きを追跡するために長期の保有ポジションを採用する.

  3. 戦略信号の確認のためにMACDとRSIなどの指標を組み合わせることで 偽のブレイクをフィルタリングできます

  4. EMAとSMA線の黄金十字と死十字を用いて 入口と出口を決定する規則は単純で明確です

  5. ストップ・ロスを通して損失を制限することでリスクを効果的に制御できる.

リスク と 解決策

この戦略にはいくつかのリスクもあります.主な問題は,傾向が逆転するときに損失を間に合うように止めることができないことです.具体的なリスクと解決策は以下のとおりです.

  1. 傾向の逆転点を時間的に追跡できない: 移動平均周期を短縮するか,包括的な判断のためにより多くの指標を追加します.

  2. 長期保持時間がより大きな損失につながります. 適切な終了ラインを短縮して,時宜のストップ損失を保持します.

  3. 移動平均指標は遅れている傾向があります. 活動的なストップ損失に一定の割合のストップ損失線を追加します.

オプティマイゼーションの方向性

この戦略は,次の側面でも最適化できます.

  1. 最適なパラメータを見つけるために 移動平均周期の組み合わせをテストします

  2. 他の指標やモデルでトレンドやエントリータイミングを判断してください.ボリンジャーバンド,KDインジケーターなど.

  3. マシンラーニングやその他の方法を使用してパラメータを動的に最適化します.例えば,ストップ損失幅を調整するために強化学習を使用します.

  4. 偽のブレイクアウトを避けるために取引量指標を組み込む.例えば,残高量,取引量など.

  5. 自動ストップ・ロースとストップ・ロース追跡システムを開発し,市場状況に基づいてストップ・ロースポジションを調整することができる.

結論

概要すると,この戦略は,シンプルで直接的なトレンドフォロー戦略である.トレンド方向を決定するために移動平均値,シグナルをフィルターするためにMACDとRSIを使用する.トレンド動きを追跡するために比較的長い保持期間を採用する.中期および長期的トレンド機会を効果的に把握することができる.同時に,トレンド逆転を特定するのも遅くなるリスクもあります.パラメータ最適化,指標を追加などを通じて将来の改善やアップグレードを行うことができます.


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

//@version=4
strategy(title="BTC_Long_Only_TV01_200507", overlay=true)

//////////// !!!!!!!!!!!!!!!! WORK BEST IN 2 HOURS for BTC, ETH and ETHXBT !!!!!!!!!!!!!!!!!!! /////////////////////
//280820 - After long esting this is the best script for ETHUSD in 4 hours. From 01/01/2020 til 28/08/2020


[macdLine, macdSignalLine, macdHist] = macd(close, 12, 26, 7)  

//_rsi_len = input(14, title="RSI length")
_rsi_len = 14 
  
NewValue = 0
PreviousValue = 0
leverage = 1

smaPercentageIncrease = 0.0
SMA_PERCENT_INCREASE = 0.0
float atrValue = 0
bool bPositionOpened = false
float stockPositionSize = 0 
float volatilityPercentage = 0.0
bool bDisplayArrow = false 
bool bEMAIsRising = false
bool bSMAIsRising = false
bool bSMASlowIsRising = false
bool bMACDIsRising = false
bool bMACDHistIsRising = false
bool bMACDSignalIsRising = false

float stopLoss = input (5, "StopLoss in %", type=input.float) //StopLoss associated with the order
//Best for alt versus BTC float stopLoss = input (3, "StopLoss in %", type=input.float) //StopLoss associated with the order 
float positionSize = 1000
float currentPrice = close 
float stopLossPrice = 0
float entryPrice = 0


//-----------------------------------------------------------


// === INPUT BACKTEST RANGE ONE YEAR 
//FromDay   = input(defval = 01, title = "From Day", minval = 1, maxval = 31)
//FromMonth = input(defval = 01, title = "From Month", minval = 1, maxval = 12)
//FromYear  = input(defval = 2020, title = "From Year", minval = 2017)
FromDay   = 01
FromMonth = 01
FromYear  = 2020

//ToDay     = input(defval = 01, title = "To Day", minval = 1, maxval = 31)
//ToMonth   = input(defval = 01, title = "To Month", minval = 1, maxval = 12)
//ToYear    = input(defval = 2023, title = "To Year", minval = 2017)
ToDay     = 14
ToMonth   = 05
ToYear    = 2029

// === FUNCTION EXAMPLE ===
start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        // backtest finish window
window()  => true // create function "within window of time"


//FUNCTION DEFINITIONS
//----------------------
IsRising(data, loopBack) =>
    bIsRising = true
    for n = 1 to loopBack
        if data[n] > data[n-1]
            bIsRising := false
        continue
    bIsRising
    
IsFalling(data, loopBack) =>
    bIsFalling = true
    for n = 1 to loopBack
        if data[n] < data[n-1]
            bIsFalling := false
        continue
    bIsFalling
    
// END OF FUNCTION DEFINITIONS //


emaLength = 20
smaLength = 100
smaSlowLength = 200
 
ema = ema(close, emaLength) 
sma = sma(close, smaLength)
smaSlow = sma(close, smaSlowLength)

plot(sma, color=color.green)
plot(smaSlow, color=color.orange)
plot(ema, color=color.yellow)

//reload previous values
stopLossPrice := na(stopLossPrice[1]) ? 0.0 : stopLossPrice[1]
entryPrice := na(entryPrice[1]) ? 0.0 : entryPrice[1]
bPositionOpened := na(bPositionOpened[1]) ? false : bPositionOpened[1]
positionSize := na(positionSize[1]) ? 1000 : positionSize[1]
stockPositionSize := na(stockPositionSize[1]) ? 0 : stockPositionSize[1]
//leverage := na(leverage[1]) ? 1 : leverage[1]

bEMAIsRising := IsRising(ema, 2) 
bSMAIsRising := IsRising(sma, 3)
bMACDIsRising := IsRising(macdLine, 3)
bMACDHistIsRising := IsRising(macdHist, 1)
bSMASlowIsRising := IsRising(smaSlow, 10)
bMACDSignalIsRising := IsRising(macdSignalLine, 3)


atrValue := atr(14)
volatilityPercentage := (atrValue/currentPrice)*100 //calcute the volatility. Percentage of the actual price

 
if (window()) 
    //Check if we can open a LONG
    if (bPositionOpened == false and bSMASlowIsRising == true and bMACDIsRising == true and bEMAIsRising == true and bSMAIsRising == true and ema[0] > sma[0] and sma[0] < currentPrice)
        //Enter in short position 
        stockPositionSize := (positionSize*leverage)/currentPrice //Calculate the position size based on the actual price and the position Size (in $) configured.
        
        //calculate exit values
        stopLossPrice := currentPrice*(1-stopLoss/100) 
        strategy.entry("myPosition", strategy.long, qty=stockPositionSize, comment="BUY at " + tostring(currentPrice))
        entryPrice := currentPrice //store the entry price
        bPositionOpened := true  
        bDisplayArrow := true 
        
    if (bPositionOpened == true and (currentPrice <= stopLossPrice or crossunder(ema[1], sma[1])))
        strategy.close("myPosition", comment="" + tostring(currentPrice) ) //Stop
        //uncomment the below line to make the bot investing the full portfolio amount to test compounding effect.
        //positionSize := positionSize + ((stockPositionSize * currentPrice) - (positionSize*leverage)) 
        //reset some flags 
        bPositionOpened := false 
        bDisplayArrow := true 
        entryPrice := 0.0
        


もっと