평균 회귀 ATR 추세 전략


생성 날짜: 2023-09-21 11:42:06 마지막으로 수정됨: 2023-09-21 11:42:06
복사: 1 클릭수: 704
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

개요

이 전략은 가격 변동률의 높낮이를 사용하여 입점 또는 퇴출 시점을 판단합니다. 목표는 가격 변동률이 높을 때 다중 입점을 구축하고 가격 추세가 유리한 방향으로 바뀌면 입장을 종료합니다.

전략 원칙

  1. ATR 지표를 사용하여 가격 변동률을 측정한다. 최근 20주기의 ATR 값을 계산하고 이동 평균과 표준 차이를 계산한다. 현재 ATR 값이 평균보다 높고 표준 차이를 더하면 가격 변동률이 높다고 간주한다.

  2. 1단 대수 가격 변화율을 사용하여 가격 동향을 결정한다. 최근 20주기의 대수 종식 가격 변화율을 계산하여 이동 평균을 산출한다. 만약 현재 변화율이 3일 연속 평균보다 크며 양성이라면 가격이 상승 추세에 있다고 본다.

  3. 가격 변동률이 높고 가격이 상승하는 경향이 있을 때 더 많은 포지션을 니다. 가격이 반등을 일으키고, 막상 가격이 촉발될 때 평점. 막상 가격의 동적 조정, 항상 최저 가격 빼기 ATR의 2배 사이에 유지됩니다.

우위 분석

  1. 가격 변동의 높고 낮고 추세 판단을 통해 더 많은 공백 시간을 활용하여 불안정한 시장에서 자주 거래하는 것을 피하십시오.

  2. 동적으로 스톱로스 가격을 조정하여 스톱로스가 너무 느슨해져 큰 손실을 초래하는 것을 피하십시오.

  3. 2015년에서 2021년 사이에 이 전략의 연간 수익률은 159%로, Buy and Hold 전략의 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)
// }