ATRに基づく平均逆転戦略

作者: リン・ハーンチャオチャン開催日:2023年10月17日 16:27:44
タグ:

img

概要

この戦略は,ATRが平均値から逸脱するかどうかを判断するために仮説テストを使用する.価格動向の予測と組み合わせると,ATRに基づいた平均逆転戦略を実装する.ATRの有意な逸脱は市場の潜在的な異常波動性を示する.価格動向が上昇すると予測される場合,ロングポジションを確立することができます.

戦略の論理

  1. 仮説のテスト

    • 2つのサンプルでtテストを行い,高速ATR期 (atr_fast) と遅いATR期 (atr_slow) の間を測ります.ゼロ仮説H0は,2つのサンプル平均値の間に有意な差がないということです.

    • 試験統計値が限界値 (reliability_factorによって指定された信頼区間) を超えると,ゼロ仮説は拒否され,つまり高速ATRは遅いATRから大幅に偏っていると考えられる.

  2. 価格動向予測

    • ロガリズム回帰の移動平均は,予想される漂移率 (漂移) として計算される.

    • 動向が増加している場合,現在の傾向は上昇傾向であると判断されます.

  3. 入場とストップ・ロスの出口

    • ロープは,高速と遅いATRが大きく異なる場合,トレンドが上昇している場合です.

    • ATR を使ってストップ・ロスを継続的に調整します.価格がストップ・ロスの下を突破したとき,ポジションを終了します.

利点分析

  • ATR偏差を決定するために仮説テストを使用することは,より科学的で適応的です.

  • 価格動向予測と組み合わせると,ATR偏差のみに基づいて間違った取引を避ける.

  • ストップロスの調整は継続的にダウンサイドリスクを管理します

リスク分析

  • 価格が暴落したときの損失を止めることができない.

  • 誤ったトレンド予測は,上位で購入につながるかもしれない.

  • パラメータの設定が正しくない場合,正しい入力を省略したり,不要な取引を追加したりします.

最適化 の 提案

  • 間違いを避けるため,多因子確認のための他の指標を追加することを検討します.

  • より安定した値を見つけるため,異なるATRパラメータの組み合わせをテストする.

  • 誤ったブレイクを避けるために キー価格レベルを突破する基準を追加します

結論

この戦略の全体的な論理は明らかである.異常波動性を検出するために仮説テストを使用することは合理的である.しかし,ATR偏差だけでは傾向を決定するには不十分である.正確性を向上させるために,より多くの確認要因が必要である.ストップ損失ルールは信頼性があるが,崖風のクラッシュに対して無効である.将来の改善はエントリー基準,パラメータ選択,ストップ損失最適化などの分野で行うことができる.


/*backtest
start: 2022-10-16 00:00:00
end: 2023-10-16 00:00:00
period: 1d
basePeriod: 1h
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/
// © DojiEmoji

//@version=5
strategy("Mean Reversion (ATR) Strategy v2 [KL] ", overlay=true, pyramiding=1)
var string ENUM_LONG = "Long"
var string GROUP_TEST = "Hypothesis testing"
var string GROUP_TSL = "Stop loss"
var string GROUP_TREND = "Trend prediction"

backtest_timeframe_start = input(defval=timestamp("01 Apr 2000 13:30 +0000"), title="Backtest Start Time")
within_timeframe = true

// TSL: calculate the stop loss price. {
ATR_TSL      = ta.atr(input(14, title="Length of ATR for trailing stop loss", group=GROUP_TSL)) * input(2.0, title="ATR Multiplier for trailing stop loss", group=GROUP_TSL)
TSL_source      = low
TSL_line_color  = color.green
TSL_transp      = 100
var stop_loss_price = float(0)

if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_TSL
else if strategy.position_size > 0
    stop_loss_price := math.max(stop_loss_price, TSL_source - ATR_TSL)
    TSL_transp := 0

plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// } end of "TSL" block

// Entry variables {
// ATR diversion test via Hypothesis testing (2-tailed):
//     H0 : atr_fast equals atr_slow
//     Ha : reject H0 if z_stat is above critical value, say reliability factor of 1.96 for a 95% confidence interval
len_fast    = input(14,title="Length of ATR (fast) for diversion test", group=GROUP_TEST)
atr_fast    = ta.atr(len_fast)
std_error   = ta.stdev(ta.tr, len_fast) / math.pow(len_fast, 0.5) // Standard Error (SE) = std / sq root(sample size)

atr_slow = ta.atr(input(28,title="Length of ATR (slow) for diversion test", group=GROUP_TEST))
test_stat = (atr_fast - atr_slow) / std_error
reject_H0 = math.abs(test_stat) > input.float(1.645,title="Reliability factor", tooltip="Strategy uses 2-tailed test; Confidence Interval = Point Estimate (avg ATR) +/- Reliability Factor x Standard Error; i.e use 1.645 for a 90% confidence interval", group=GROUP_TEST)

// main entry signal, subject to confirmation(s), gets passed onto the next bar
var _signal_diverted_ATR = false
if not _signal_diverted_ATR
    _signal_diverted_ATR := reject_H0


// confirmation: trend prediction; based on expected lognormal returns
_prcntge_chng = math.log(close / close[1]) 

// Expected return (drift) = average percentage change + half variance over the lookback period
len_drift = input(14, title="Length of drift", group=GROUP_TREND)
_drift = ta.sma(_prcntge_chng, len_drift) - math.pow(ta.stdev(_prcntge_chng, len_drift), 2) * 0.5
_signal_uptrend = _drift > _drift[1]

entry_signal_all = _signal_diverted_ATR and _signal_uptrend // main signal + confirmations
// } end of "Entry variables" block

// MAIN {
// Update the stop limit if strategy holds a position
if strategy.position_size > 0 and ta.change(stop_loss_price)
    strategy.exit(ENUM_LONG, comment="sl", stop=stop_loss_price)

// Entry
if within_timeframe and entry_signal_all
    strategy.entry(ENUM_LONG, strategy.long, comment=strategy.position_size > 0 ? "adding" : "initial")

// Alerts
_atr = ta.atr(14)
alert_helper(msg) =>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + str.tostring(close, "#.##") + "; atr=" + str.tostring(_atr, "#.##") + ")"
    alert(str.tostring(prefix) + str.tostring(msg) + str.tostring(suffix), alert.freq_once_per_bar)

if strategy.position_size > 0 and ta.change(strategy.position_size)
    if strategy.position_size > strategy.position_size[1]
        alert_helper("BUY")
    else if strategy.position_size < strategy.position_size[1]
        alert_helper("SELL")

// Clean up - set the variables back to default values once no longer in use
if strategy.position_size == 0
    stop_loss_price := float(0)
if ta.change(strategy.position_size)
    _signal_diverted_ATR := false
// } end of MAIN block

もっと