Bollinger Bands をベースにした二重移動平均マッチング戦略

作者: リン・ハーンチャオチャン, 日付: 2023-11-24 15:32:57
タグ:

img

概要

ボリンジャー・バンドをベースとした二重移動平均マッチング戦略は,市場における価格とボリュームに沿ったトレンドフォロー戦略である.ボリンジャー・バンドと移動平均のクロスオーバーを取引信号として利用し,市場トレンドを自動的に特定し,ストップ・プロフィートとストップ・ロスのルールで取引できる定量戦略を実装する.

戦略原則

この戦略は,主にボリンジャーバンド指標と移動平均指標のクロスオーバー信号をベースに取引する.特に,中間レール,ボリンジャーバンドの上部レール,および5日から200日までの長さの7つの移動平均を同時に使用する.価格はボリンジャーバンドの中部と下部レールを下から上へと突破すると購入信号を生成し,価格がボリンジャーバンドの上部レールを上から下へと突破してトレンドを追求するときに販売信号を生成する.

さらに,この戦略は,ロングとショートポジションを判断するためのmoveToFract指標も導入している.この指標は,短期および長期移動平均値の配列順序を計算することによって,現在の市場傾向が上昇または下落しているかどうかを決定し,レンジバインド市場での間違った信号を生成することを避ける.最後に,設定可能なストップ・プロフィートとストップ・ロストルールと組み合わせて,取引戦略に従うより完全な傾向を形成する.

利点分析

  1. 異なる市場環境に合わせてパラメータの組み合わせをカスタマイズできる柔軟な構成
  2. 2つの異なる指標をフィルターとして組み合わせることで,誤った信号を減らすことができます.
  3. トレンド判断指標は,不安定な市場での逆転操作を回避できる
  4. ストップ・ロスの設定を追跡することで 利益を最大化できます

リスク分析

  1. パラメータは,過剰な取引を避けるために,異なる時間枠のサイクルに適するように適切に調整されるべきです.
  2. ストップ損失を追跡することは,急速な減少で損失を拡大する可能性があります.
  3. 十分な資金を確保しなければ,継続的な損失のリスクに耐えられない

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

  1. さらに最適化するために,黄金の十字架と死の十字架の判断を追加
  2. 異なる品種には異なるパラメータがあります.最適なパラメータのために機械学習を検討してください.
  3. トレンド・ボラティリティを決定し,リスク管理を強化するために波動性指数と組み合わせる

結論

一般的には,これは非常に実践的なトレンドフォロー戦略である.意思決定のためにインジケータークロスオーバーを使用し,また,間違った信号を効果的にフィルタリングするためにトレンド判断モジュールを組み込む.ストップ・プロフィートとストップ・ロスを設定した後,トレンドを完全にフォローして良いリターンを得ることができます.パラメータの組み合わせを調整し,より多くのフィルターを追加することで,この戦略はより多くの市場環境に適応するためにさらに最適化され,改善とアプリケーションの見通しに大きな余地があります.


/*backtest
start: 2023-10-24 00:00:00
end: 2023-11-23 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/
// © HeWhoMustNotBeNamed

//@version=4
strategy("BuyTheDip", overlay=true, initial_capital = 100000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, pyramiding = 1, commission_value = 0.01, calc_on_order_fills = true)

MAType = input(title="Moving Average Type", defval="sma", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
exitType = input(title="Exit Strategy", defval="Signal", options=["Signal", "TrailingStop", "Both"])
LookbackPeriod = input(30, minval=10,step=10)

BBStdDev = input(2, minval=1, maxval=10, step=0.5)
BBLength = input(60, minval=5, step=5)

atrLength = input(22)
atrMult = input(6)

tradeDirection = input(title="Trade Direction", defval=strategy.direction.all, options=[strategy.direction.all, strategy.direction.long, strategy.direction.short])
backtestYears = input(10, minval=1, step=1)
includePartiallyAligned = true
f_getMovingAverage(source, MAType, length)=>
    ma = sma(source, length)
    if(MAType == "ema")
        ma := ema(source,length)
    if(MAType == "hma")
        ma := hma(source,length)
    if(MAType == "rma")
        ma := rma(source,length)
    if(MAType == "vwma")
        ma := vwma(source,length)
    if(MAType == "wma")
        ma := wma(source,length)
    ma

f_getTrailingStop(atr, atrMult)=>
    stop = close - atrMult*atr
    stop := strategy.position_size > 0 ? max(stop, stop[1]) : stop
    stop

f_getMaAlignment(MAType, includePartiallyAligned)=>
    ma5 = f_getMovingAverage(close,MAType,5)
    ma10 = f_getMovingAverage(close,MAType,10)
    ma20 = f_getMovingAverage(close,MAType,20)
    ma30 = f_getMovingAverage(close,MAType,30)
    ma50 = f_getMovingAverage(close,MAType,50)
    ma100 = f_getMovingAverage(close,MAType,100)
    ma200 = f_getMovingAverage(close,MAType,200)

    upwardScore = 0
    upwardScore := close > ma5? upwardScore+1:upwardScore
    upwardScore := ma5 > ma10? upwardScore+1:upwardScore
    upwardScore := ma10 > ma20? upwardScore+1:upwardScore
    upwardScore := ma20 > ma30? upwardScore+1:upwardScore
    upwardScore := ma30 > ma50? upwardScore+1:upwardScore
    upwardScore := ma50 > ma100? upwardScore+1:upwardScore
    upwardScore := ma100 > ma200? upwardScore+1:upwardScore
    
    upwards = close > ma5 and ma5 > ma10 and ma10 > ma20 and ma20 > ma30 and ma30 > ma50 and ma50 > ma100 and ma100 > ma200
    downwards = close < ma5 and ma5 < ma10 and ma10 < ma20 and ma20 < ma30 and ma30 < ma50 and ma50 < ma100 and ma100 < ma200
    upwards?1:downwards?-1:includePartiallyAligned ? (upwardScore > 5? 0.5: upwardScore < 2?-0.5:upwardScore>3?0.25:-0.25) : 0
    
inDateRange = time >= timestamp(syminfo.timezone, year(timenow) - backtestYears, 01, 01, 0, 0)

exitBySignal = exitType == "Signal" or exitType == "Both"
exitByTrailingStop = exitType == "TrailingStop" or exitType == "Both"
maAlignment = f_getMaAlignment(MAType,includePartiallyAligned)
atr = atr(atrLength)

trailingStop = f_getTrailingStop(atr, atrMult)
maAligned = highest(maAlignment,LookbackPeriod)
[middle, upper, lower] = bb(close, BBLength, BBStdDev)

buyCondition = maAligned == 1 and (crossover(close, lower) or crossover(close, middle))
buyExitCondition = crossunder(close, upper)

strategy.entry("Buy", strategy.long, when=buyCondition and inDateRange, oca_name="oca_buy")
strategy.close("Buy", when=buyExitCondition and exitBySignal)
strategy.exit("ExitBuy", "Buy", stop = trailingStop, when=exitByTrailingStop )




もっと