この戦略は,価格の変動率の高低を利用して,ポジションへの入場または退出のタイミングを判断し,価格の変動率が高いときに多頭ポジションを確立し,価格の傾向が有利に転じるときにポジションを閉じて利益を上げることを目的としています.
ATR指数を使用して価格変動率を測定する.最近20周期のATR値を計算し,その移動平均と標準差を計算する.現在のATR値が平均を超え,1つの標準差を加えると,価格変動率が高いと考えられる.
一段対数値の価格変化率を使用して価格トレンドを判定する.最近20サイクルにおける対数値の閉店価格変化率を計算し,移動平均を計算し,現在の変化率が3日連続で平均値より大きく,正である場合,価格が上昇傾向にあると考えられる.
価格の変動率が高く,価格が上昇傾向にあるとき,多額のポジションを開きます.価格が逆転し,ストップ・ロスの価格が誘発されたとき,平仓します.ストップ・ロスの価格の動態調整は,常に最低価格減算ATRの2倍の間を維持します.
価格の波動やトレンド判断を利用して空売りを多く行うことで,波動の多い市場で頻繁に取引を避けることができます.
ストップ・ロスの価格を動的に調整し,ストップ・ロスが過度に緩やかになり,大きな損失を招くのを避ける.
2015年から2021年にかけて,この戦略の年収は159%で,Buy and Hold戦略の120%をはるかに上回っている.
ATRパラメータの設定が過度に激進化されすぎると,アクセス機会が過少になる可能性がある。パラメータは,適切な範囲を拡張して,アクセス頻度を高めることができる。
トレンド判断指標は,誤判を起こす可能性があり,実際のトレンドと一致しない.潜在的な損失を避けるために,確認因子を追加する必要があります.
回測周期は6年,サンプル区間を拡大し,安定性検査を行う必要があり,過適合を回避する.
極端な状況下でのパフォーマンスを判断できない.例えば,迅速な独占状態で,人工介入が必要か,プログラム停止を設定するなど.
MACD,KDJなどのトレンド確認指標を追加し,トレンドの方向をより正確に判断します.
ATRパラメータは,異なる品種,市場状況に応じて自主的に調整して,波動率を最適化判断することができる.
突破判断モジュールを追加し,トレンド加速因子を配置し,突破が発生した場合のポジションを拡大する.
パーセンテージ・ストープ,波動・ストープなど,さまざまなストープの効果をテストする.
取引回数,収益曲線の安定性,最大撤退などの評価を行い,戦略の安定性を確保する.
この戦略は,価格の変動率とトレンド判断の優位性を統合し,変動が加剧した場合には価格が逆転する可能性のあるタイミングを判断し,リスクを制御するためにダイナミックなストップを設定し,反測結果から優れた超利益を達成した.しかし,サンプリング区間はわずか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)
// }