ダブル・ムービング・平均逆転戦略 (Dual Moving Average Reversion Strategy) は,典型的な短期間の平均逆転取引戦略である.この戦略は,異なるパラメータ設定を持つ2つの移動平均によって取引信号を生成する.トレンド逆転が起こるときに利益を得ることを目的としている.
この戦略は,2つの移動平均値を使用して取引信号を生成する.最初のMAマオペニングはトレンド方向を決定するために使用される.第2のMAマクロージングは取引信号を生成するために使用される.
マオペーニングが上昇すると,現在の市場は上昇傾向にあることを示します. マオペーニングが下がると,現在の市場は下落傾向にあることを示します. マクロセッシングは早期の逆転信号を生成するのにより敏感になるため,1以上の係数で掛けます.
具体的には,maopeningが上昇し,maclosingがmaopeningを下回ると,トレンド逆転を示します.戦略はショートポジションを開きます.maopeningが低下し,maclosingがmaopeningを下回ると,トレンド逆転を示します.戦略はロングポジションを開きます.
戦略のパラメータには,MAタイプ,長さ,データソースなどが含まれます.これらのパラメータを調整することで取引パフォーマンスを最適化することができます.エントリールール,ストップ損失など,いくつかの構成可能なオプションもあります.
双重MA逆転戦略の主な利点は以下の通りである.
短期間取引に適した小引き下げです.高速移動平均は,より小さな引き下げで短期的な逆転を迅速に捉えることができます.
2つのMAsのクロスオーバーは明確な取引信号を生成します.
複数の調整可能なパラメータで高度に構成可能. 2つのMAと係数のパラメータを最適化できます.
シンプルな論理と高周波の取引は,自動取引に非常に適しています.
ストップ・ロスのメカニズムで制御可能なリスク.移動ストップ・ロスのまたは価値ストップ・ロスの場合,単一の取引の損失を制限することができます.
この戦略にはいくつかのリスクもあります.
MAクロスオーバー信号の遅れ.MA自身は価格に遅れ.クロスオーバーは,トレンドがしばらく逆転した後に行われる可能性があります.
ウィップソー取引のリスク 逆転傾向はすぐに再び逆転し,連続した損失を引き起こす可能性があります
ストップ・ロスは単一の損失を制限するが,連続したストップ・ロスは大きなドローダウンにつながる.
過剰なパラメータ最適化は,ライブ取引で過剰なフィットメントと悪いパフォーマンスを引き起こす可能性があります.
解決策としては,
パラメータを最適化して より速いMAsを見つける
フィルターを追加します. 取引量や変動指標などです.
ストップ・ロスの位置を調整し,連続したストップ・ロスの確率を低下させる.
過剰配合のリスクを評価するためのパラメータセットの強度試験
この戦略は,次の側面においてさらに最適化することができる.
異なる種類のMAsをテストして より敏感なMASを検知します 例えばKAMA,ZLEMAなどです
最適な組み合わせを見つけるためにMA長さを最適化します.通常,短い期間がより良いパフォーマンスを有します.
接近,中位価格,典型的な価格など 様々なデータ源をテストします
ドンチアン・チャネルのような不適切な逆転信号を避けるためにトレンドフィルターを追加します
MACD,OBVなど,他の指標を確認するために追加します.
リスク管理メカニズムの強化 ストップ損失,最大損失など
最適な資産配分を見つけるために ポートフォリオの最適化
オーバーフィッティングのリスクを評価するためのパラメータの強度試験
ダブルMAリバーション (Dual MA Reversion) は,シンプルで実用的な短期取引戦略である.定量的な取引で短期的な逆転を捕捉するのに適している.しかし,遅れやウィップソー取引などのリスクは存在する.この戦略は,パラメータを最適化し,フィルターを追加し,リスク管理を強化し,良好な実際の取引パフォーマンスを備えた安定的かつ効率的な戦略を開発することによって改善することができる.
/*backtest start: 2023-10-17 00:00:00 end: 2023-11-16 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 = 100, pyramiding = 9, commission_value = 0.045, 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" maopeningtyp = 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 = input.source(ohlc4, title = "", inline=info_opening, group=info_opening) maopeninglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_opening, group=info_opening) //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) 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") 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") 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 = 0.0 maclosing = 0.0 os = maopeningsrc cs = maclosingsrc 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 := ma_func(maopeningtyp, maopeningsrc, maopeninglen) //MA Closing maclosing := ma_func(maclosingtyp, maclosingsrc, maclosinglen) * maclosingmul long1 = long1on == false ? 0 : long1shift == 0 ? 0 : long1lot == 0 ? 0 : maopening == 0 ? 0 : maopening * long1shift short1 = short1on == false ? 0 : short1shift == 0 ? 0 : short1lot == 0 ? 0 : maopening == 0 ? 0 : maopening * short1shift //Colors maopeningcol = maopening == 0 ? na : color.blue maclosingcol = maclosing == 0 ? na : color.fuchsia long1col = long1 == 0 ? na : color.green short1col = short1 == 0 ? na : color.red //Lines plot(maopening, offset = OFFS, color = maopeningcol) plot(maclosing, offset = OFFS, color = maclosingcol) 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 maopening > 0 and maclosing > 0 and 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()