평균 반전 ATR 트렌드 전략

저자:차오장, 날짜: 2023-09-21 11:42:06
태그:

전반적인 설명

이 전략은 가격 변동성의 높고 낮은 점을 활용하여 입상 및 출입 시기를 결정합니다. 가격 변동성이 높을 때 긴 포지션을 설정하고 가격 트렌드가 유리한 경우 이익을 취하는 것을 목표로합니다.

전략 논리

  1. 가격 변동성을 측정하기 위해 ATR 지표를 사용하십시오. 지난 20 기간 동안 ATR을 계산하고 이동 평균과 표준편차를 얻으십시오. 현재 ATR 값이 평균 더하기 한 표준편차를 초과하면 가격 변동성이 높다고 간주됩니다.

  2. 가격 트렌드를 결정하기 위해 1차 순위 로그아리듬 가격 변화율을 사용한다. 지난 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)
// }


더 많은