平均逆転 ATR トレンド戦略

作者: リン・ハーンチャオチャン, 日付: 2023-09-21 11:42:06
タグ:

概要

この戦略は,価格変動の高低を活用して,ポジションのエントリーと出路のタイミングを決定する.価格変動が高いときにロングポジションを確立し,価格トレンドが有利であるときに利益を得ることを目的としています.

戦略の論理

  1. 価格変動を測定するためにATR指標を使用します.過去20期間のATRを計算し,移動平均値と標準偏差を得ます.現在のATR値が平均値プラス1つの標準偏差を超えると,価格変動は高いと考えられます.

  2. 価格動向を決定するために第一順位対数値値値変動率を使用する. 過去20期間の対数値値値接近値変動率を計算し,移動平均値を取得する. 現在の変動率が連続3日間の平均値を超えて陽性である場合,価格は上昇傾向とみなされる.

  3. 価格の変動が高く,価格が上昇傾向を示しているとき,ロングに行く.価格が引き下げられ,ストップロスはトリガーされ,クローズポジション.ストップロスは動的に調整され,最低価格マイナス2倍ATRを下回る.

利点分析

  1. 価格変動とトレンドを利用して,長期/短期間のタイミングを決定し,市場範囲で過剰な取引を避ける.

  2. ダイナミックストップ・ロスは 幅が広いストップで 過剰な損失を避けます

  3. バックテストでは 2015-2021年の年間収益率は159%で バイ・アンド・ホールディングスの収益率は120%を超えています

リスク分析

  1. 過度に攻撃的なATRパラメータは,侵入機会が少なくなる可能性があります. 周波数を増加させるためにパラメータを適度に緩和することができます.

  2. トレンドインジケーターは,実際のトレンドと矛盾する 偽信号を生む可能性があります. 潜在的な損失を避けるために,より多くの確認要素を追加する必要があります.

  3. バックテスト期間は6年だけ 過剰なフィットメントを避けるために 大きいサンプルと強度チェックが必要です

  4. フラッシュ・クラッシュなどの極端な条件では 性能を評価できない 手動介入や停止プログラムが必要

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

  1. 傾向の正確性を高めるために MACD,KDJなどの傾向確認指標を追加します.

  2. ATRパラメータを異なる製品と市場体制に基づいて調整し,波動性指標を最適化します.

  3. ブレイクアウトの大きさを測るために ブレイクアウト論理とトレンド加速因子を追加します

  4. ストップ・ロスの種類をテストします

  5. 貿易頻度,曲線の安定度,最大引き下げなどの指標で評価します

概要

この戦略は,波動性とトレンドを測定する利点を組み合わせて,増幅した波動性に入るために可能な逆転点を決定し,リスクを制御するためにダイナミックストップを使用する.バックテストでは,良質なアルファが生成されていることが示されています.しかし,6年間のサンプルは限られています.主要パラメータは市場特有のチューニングを必要とし,偽信号を減らすためにより多くの確認要因が必要です.ライブ取引に適用する前に包括的な強度チェックも必要です.全体的に,これは波動性に対する平均逆転のアイデアを提供します.しかし,堅牢な量戦略になるために,洗練と厳格な検証が必要です.


/*backtest
start: 2022-09-14 00:00:00
end: 2023-09-20 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 (kevinhhl)

//@version=4
strategy("Mean Reversion (ATR) Strategy [KL]",overlay=true,pyramiding=1)
ENUM_LONG = "Long"

// Timeframe {
backtest_timeframe_start = input(defval = timestamp("01 Apr 2000 13:30 +0000"), title = "Backtest Start Time", type = input.time)
USE_ENDTIME = input(false,title="Define backtest end-time (If false, will test up to most recent candle)")
backtest_timeframe_end = input(defval = timestamp("01 May 2021 19:30 +0000"), title = "Backtest End Time (if checked above)", type = input.time)
within_timeframe = true
// }

// Trailing stop loss {
ATR_X2_TSL = atr(input(14,title="Length of ATR for trailing stop loss")) * input(2.0,title="ATR Multiplier for trailing stop loss",type=input.float)
TSL_source = low
var stop_loss_price = float(0)
TSL_line_color = color.green, TSL_transp = 100
if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_X2_TSL 
else if strategy.position_size > 0
    stop_loss_price := max(stop_loss_price, TSL_source - ATR_X2_TSL)
    TSL_transp := 0
plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// }

// Variables for confirmations of entry {
_len_volat = input(20,title="Length of ATR to determine volatility")
_ATR_volat = atr(_len_volat)
_avg_atr = sma(_ATR_volat, _len_volat)
_std_volat = stdev(_ATR_volat,_len_volat)
signal_diverted_ATR = _ATR_volat > (_avg_atr + _std_volat) or _ATR_volat < (_avg_atr - _std_volat)

_len_drift = input(20,title="Length of Drift")//default set to const: _len_vol's default value
_prcntge_chng = log(close/close[1])
_drift = sma(_prcntge_chng, _len_drift) - pow(stdev(_prcntge_chng, _len_drift),2)*0.5
_chg_drift = _drift/_drift[1]-1
signal_uptrend = (_drift > _drift[1] and _drift > _drift[2]) or _drift > 0

entry_signal_all = signal_diverted_ATR and signal_uptrend
// }

alert_per_bar(msg)=>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + tostring(close) + "; atr=" + tostring(_ATR_volat) + ")"
    alert(tostring(prefix) + tostring(msg) + tostring(suffix), alert.freq_once_per_bar)

// MAIN {
if within_timeframe

    if strategy.position_size > 0 and strategy.position_size[1] > 0 and (stop_loss_price/stop_loss_price[1]-1) > 0.005
        alert_per_bar("TSL raised to " + tostring(stop_loss_price))

    // EXIT:
	if strategy.position_size > 0 and TSL_source <= stop_loss_price
	    exit_msg = close <= strategy.position_avg_price ? "stop loss" : "take profit"
        strategy.close(ENUM_LONG, comment=exit_msg)
    // ENTRY:
    else if entry_signal_all and (strategy.position_size == 0 or (strategy.position_size > 0 and close > stop_loss_price))
		entry_msg = strategy.position_size > 0 ? "adding" : "initial"
		strategy.entry(ENUM_LONG, strategy.long, comment=entry_msg)

if strategy.position_size == 0
    stop_loss_price := float(0)
// }


もっと