双方向移動平均回帰取引戦略


作成日: 2024-01-15 12:15:14 最終変更日: 2024-01-15 12:15:14
コピー: 0 クリック数: 670
1
フォロー
1617
フォロワー

双方向移動平均回帰取引戦略

概要

双方向移動平均リバーション取引戦略 (Bidirectional Moving Average Reversion Trading Strategy) は,価格平均リバーション原理を利用して構築された定量取引戦略である.この戦略は,複数の移動平均線を設定して価格リバーションの機会を捉え,価格が平均線から一定量の偏移した後,フィールドに入って,価格が平均線に戻るまで待って,平仓の利回りを行う.

戦略原則

この戦略は,価格が常に平均値の波動を中心に動いていると仮定し,価格が平均値から大きく離れる場合,平均値に戻る可能性が高くなります.具体的には,この戦略は,3つの平均線を同時に設定します:開設平均線,開設平均線,開設平均線.価格が開設平均線に触れたときに,対照的な多額のポジションまたは空白のポジションが開きます.価格が開設平均線に触れたときに,以前のポジションを平らげます.最後に,価格が戻らないまま継続すると,限界平均線は損失を制御できます.

コードロジック的に見ると,開設平均線は多線と空白線に分かれ,それぞれ長線と短線で構成されている.それらの価格との偏差程度がポジションの大きさを決定する.さらに,平仓平均線は,平仓のタイミングを決定するために使用される独立した平均線である.価格がこの均線に運行される時,ポジションは平らげられる.

優位分析

双方向均線回帰の戦略の優位性は主に以下に示されています.

  1. 価格の逆転を捉え,トレンドの整合に適した市場
  2. リスクのコントロール
  3. カスタマイズ可能なパラメータの組み合わせ,適応性
  4. 簡単に理解し,パラメータを最適化できます.

この戦略は,低波動性,価格の波動範囲が小さい品種,特に収束段階に入っている品種に適用されます.それは,価格の一時的な逆転の機会を効果的に捕捉することができます.同時に,そのリスク管理策は,価格が戻らないとしても,損失を一定範囲で制御することができます.

リスク分析

双方向均等回帰の戦略にはいくつかのリスクがあります.

  1. この戦略は,価格が急激に上昇すると,連続してポジションを開き,最終的に爆破する可能性がある.
  2. 価格の変動が過大である場合,ポジションは限界損失に達し,強制的に平仓される可能性があります.
  3. パラメータ最適化リスク. この戦略のパラメータ設定は,その収益性に大きな影響を与える. パラメータ設定が不適切であれば,利益の確率を大幅に低下させる.

このリスクに対して,以下の方法で最適化できます.

  1. 倉庫開設制限を強め,過度に頻繁に倉庫開設を避ける
  2. ポジションを適切に縮小し,ポジションの破綻を防ぐ
  3. 平均線周期,平仓線パラメータなどの設定を最適化

最適化の方向

この戦略は,以下のような観点から,大きな最適化余地があります.

  1. ポジション開設条件の論理を高め,トレンド状況下での追いつきを防止する.
  2. 価格の大幅な波動のリスクを防ぐために,ポジションを低くする論理を追加
  3. 異なる種類の平均線指標を試し,より良いパラメータの組み合わせを探します.
  4. 機械学習によるパラメータの自動最適化
  5. 自動ストップ戦略を導入し,リスク管理を強化

要約する

双方向均線回帰取引戦略は,価格が移動均線から偏った後の回帰の機会を捕捉して利益を得る.それはリスクを効果的に制御し,パラメータ最適化によってよりよい利益を得ることができる.この戦略にもいくつかのリスクがあるが,ポジション開設の論理を完善し,ポジションのサイズを減らす方法などによって制御することができる.この戦略は,簡単に理解し,量化トレーダーによるさらなる研究と最適化の価値がある.

ストラテジーソースコード
/*backtest
start: 2023-12-15 00:00:00
end: 2024-01-14 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy(title = "hamster-bot MRS 2", overlay = true, default_qty_type = strategy.percent_of_equity, initial_capital = 100, default_qty_value = 30, pyramiding = 1, commission_value = 0.1, backtest_fill_limits_assumption = 1)
info_options = "Options"

on_close = input(false, title = "Entry on close", inline=info_options, group=info_options)
OFFS = input.int(0, minval = 0, maxval = 1, title = "| Offset View", inline=info_options, group=info_options)
trade_offset = input.int(0, minval = 0, maxval = 1, title = "Trade", inline=info_options, group=info_options)
use_kalman_filter = input.bool(false, title="Use Kalman filter", group=info_options)

//MA Opening
info_opening = "MA Opening Long"
maopeningtyp_l = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening, group=info_opening)
maopeningsrc_l = input.source(ohlc4, title = "", inline=info_opening, group=info_opening)
maopeninglen_l = input.int(3, minval = 1, title = "", inline=info_opening, group=info_opening)
long1on    = input(true, title = "", inline = "long1")
long1shift = input.float(0.96, step = 0.005, title = "Long", inline = "long1")
long1lot   = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "long1")

info_opening_s = "MA Opening Short"
maopeningtyp_s = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening_s, group=info_opening_s)
maopeningsrc_s = input.source(ohlc4, title = "", inline=info_opening_s, group=info_opening_s)
maopeninglen_s = input.int(3, minval = 1, title = "", inline=info_opening_s, group=info_opening_s)
short1on    = input(true, title = "", inline = "short1")
short1shift = input.float(1.04, step = 0.005, title = "short", inline = "short1")
short1lot   = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "short1")


//MA Closing
info_closing = "MA Closing"
maclosingtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_closing, group=info_closing)
maclosingsrc = input.source(ohlc4, title = "", inline=info_closing, group=info_closing)
maclosinglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_closing, group=info_closing)
maclosingmul = input.float(1, step = 0.005, title = "mul", inline=info_closing, group=info_closing)

startTime = input(timestamp("01 Jan 2010 00:00 +0000"), "Start date", inline = "period")
finalTime = input(timestamp("31 Dec 2030 23:59 +0000"), "Final date", inline = "period")

HMA(_src, _length) =>  ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
EHMA(_src, _length) =>  ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length)))
THMA(_src, _length) =>  ta.wma(ta.wma(_src,_length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length)
tema(sec, length)=>
    tema1= ta.ema(sec, length)
    tema2= ta.ema(tema1, length)
    tema3= ta.ema(tema2, length)
    tema_r = 3*tema1-3*tema2+tema3
donchian(len) => math.avg(ta.lowest(len), ta.highest(len))
ATR_func(_src, _len)=>
    atrLow = low - ta.atr(_len)
    trailAtrLow = atrLow
    trailAtrLow := na(trailAtrLow[1]) ? trailAtrLow : atrLow >= trailAtrLow[1] ? atrLow : trailAtrLow[1]
    supportHit = _src <= trailAtrLow
    trailAtrLow := supportHit ? atrLow : trailAtrLow
    trailAtrLow
f_dema(src, len)=>
    EMA1 = ta.ema(src, len)
    EMA2 = ta.ema(EMA1, len)
    DEMA = (2*EMA1)-EMA2
f_zlema(src, period) =>
    lag = math.round((period - 1) / 2)
    ema_data = src + (src - src[lag])
    zl= ta.ema(ema_data, period)
f_kalman_filter(src) =>
    float value1= na
    float value2 = na
    value1 := 0.2 * (src - src[1]) + 0.8 * nz(value1[1])
    value2 := 0.1 * (ta.tr) + 0.8 * nz(value2[1])
    lambda = math.abs(value1 / value2)
    alpha = (-math.pow(lambda, 2) + math.sqrt(math.pow(lambda, 4) + 16 * math.pow(lambda, 2)))/8
    value3 = float(na)
    value3 := alpha * src + (1 - alpha) * nz(value3[1])
//SWITCH
ma_func(modeSwitch, src, len, use_k_f=true) =>
      modeSwitch == "SMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.sma(src, len))  : ta.sma(src, len) :
      modeSwitch == "RMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.rma(src, len))  : ta.rma(src, len) :
      modeSwitch == "EMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.ema(src, len))  : ta.ema(src, len) :
      modeSwitch == "TEMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(tema(src, len))    : tema(src, len):
      modeSwitch == "DEMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(f_dema(src, len))  : f_dema(src, len):
      modeSwitch == "ZLEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_zlema(src, len)) : f_zlema(src, len):
      modeSwitch == "WMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.wma(src, len))  : ta.wma(src, len):
      modeSwitch == "VWMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.vwma(src, len)) : ta.vwma(src, len):
      modeSwitch == "Hma"   ? use_kalman_filter and use_k_f ? f_kalman_filter(HMA(src, len))     : HMA(src, len):
      modeSwitch == "Ehma"  ? use_kalman_filter and use_k_f ? f_kalman_filter(EHMA(src, len))    : EHMA(src, len):
      modeSwitch == "Thma"  ? use_kalman_filter and use_k_f ? f_kalman_filter(THMA(src, len/2))  : THMA(src, len/2):
      modeSwitch == "ATR"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ATR_func(src, len)): ATR_func(src, len) :
      modeSwitch == "L"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.lowest(len)): ta.lowest(len) :
      modeSwitch == "H"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.highest(len)): ta.highest(len) :
      modeSwitch == "DMA"   ? donchian(len) : na

//Var
sum = 0.0
maopening_l = 0.0
maopening_s = 0.0
maclosing = 0.0
pos = strategy.position_size
p = 0.0
p := pos == 0 ? (strategy.equity / 100) / close : p[1]
truetime = true
loss = 0.0
maxloss = 0.0
equity = 0.0

//MA Opening
maopening_l := ma_func(maopeningtyp_l, maopeningsrc_l, maopeninglen_l)
maopening_s := ma_func(maopeningtyp_s, maopeningsrc_s, maopeninglen_s)

//MA Closing
maclosing := ma_func(maclosingtyp, maclosingsrc, maclosinglen) * maclosingmul

long1 = long1on == false ? 0 : long1shift == 0 ? 0 : long1lot == 0 ? 0 : maopening_l == 0 ? 0 : maopening_l * long1shift
short1 = short1on == false ? 0 : short1shift == 0 ? 0 : short1lot == 0 ? 0 : maopening_s == 0 ? 0 : maopening_s * short1shift
//Colors
long1col = long1 == 0 ? na : color.green
short1col = short1 == 0 ? na : color.red
//Lines
// plot(maopening_l, offset = OFFS, color = color.new(color.green, 50))
// plot(maopening_s, offset = OFFS, color = color.new(color.red, 50))
plot(maclosing, offset = OFFS, color = color.fuchsia)
long1line = long1 == 0 ? close : long1
short1line = short1 == 0 ? close : short1
plot(long1line, offset = OFFS, color = long1col)
plot(short1line, offset = OFFS, color = short1col)

//Lots
lotlong1 = p * long1lot
lotshort1 = p * short1lot

//Entry
if truetime
    //Long
    sum := 0
    strategy.entry("L", strategy.long, lotlong1, limit = on_close ? na : long1, when = long1 > 0 and pos <= sum and (on_close ? close <= long1[trade_offset] : true))
    sum := lotlong1

    //Short
    sum := 0
    pos := -1 * pos
    strategy.entry("S", strategy.short, lotshort1, limit = on_close ? na : short1, when = short1 > 0 and pos <= sum and (on_close ? close >= short1[trade_offset] : true))
    sum := lotshort1

strategy.exit("Exit", na, limit = maclosing)
if time > finalTime
    strategy.close_all()