듀얼 채널 추적 역전 전략 (Dual Channel Tracking Reversal strategy) 은 볼링거 밴드, 켈트너 채널 및 추진력 지표를 결합한 역전 거래 전략이다. 볼링거 밴드 및 켈트너 채널의 합성을 통해 가격 압축 구역을 식별하고 진입 및 출구에 대한 역전 신호를 결정하기 위해 추진력 지표를 사용합니다.
볼링거 밴드의 중간, 상위 및 하위 대역을 계산합니다.
켈트너 채널의 중간, 상위 및 하위 대역을 계산
볼링거 대역이 켈트너 채널 안에 있는지 확인합니다.
BB와 KC 중점에 대한 닫는 선형 회귀 기울기 밸브를 계산
ROC의 ROC와 EMA를 계산합니다.
압축 상태에서, val > 0과 ROC가 임계값을 초과할 때 길다
스톱 로스 및 영업 조건 설정
역전용으로 이중 채널 시스템을 결합함으로써 정확도가 향상되었습니다.
선형 회귀와 변화율을 사용하여 잘못된 신호를 피합니다.
제품 간 최적화를 위한 유연한 조정 가능한 매개 변수
스톱 로스/프로피트 취득으로 거래별로 효과적인 리스크 관리
전략의 실행 가능성을 검증하기 위한 충분한 백트테스트 데이터
압축 하는 것 은 항상 효과적 인 역행 을 가져오지 않는다
가짜 탈출은 잘못된 신호를 생성합니다.
너무 넓은 스톱 손실로 인해 과도한 단일 손실이 발생합니다.
불충분한 시험 기간
더 많은 제품에 대한 매개 변수 최적화
지원/저항 식별을 위한 기계 학습을 추가
분산 유효성을 향상시키기 위해 부피 변경을 포함합니다.
트렌드 지속성을 위해 여러 시간 프레임 분석을 수행
동적 스톱 로스/이익 취득을 최적화
이중 채널 추적 역전 전략은 역전 거래를 위해 볼린거 밴드 및 켈트너 채널과 같은 지표를 사용합니다. 매개 변수 최적화로 인해 일정 범위에서 브레이크아웃 유효성을 식별하기 위해 다른 제품에서 적응 할 수 있습니다. 그러나 역전 거래는 여전히 본질적인 위험을 지니고 있으며 지속적인 초과 수익을 위해 정확성을 향상시키기 위해 기계 학습 등을 추가로 통합해야합니다.
/*backtest start: 2023-10-02 00:00:00 end: 2023-11-01 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 // Credit for the initial Squeeze Momentum code to LazyBear, rate of change code is from Kiasaki strategy("Squeeze X BF 🚀", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0) /////////////// Time Frame /////////////// testStartYear = input(2012, "Backtest Start Year") testStartMonth = input(1, "Backtest Start Month") testStartDay = input(1, "Backtest Start Day") testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0) testStopYear = input(2019, "Backtest Stop Year") testStopMonth = input(12, "Backtest Stop Month") testStopDay = input(31, "Backtest Stop Day") testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0) testPeriod() => true /////////////// Squeeeeze /////////////// length = input(20, title="BB Length") mult = input(2.0,title="BB MultFactor") lengthKC=input(22, title="KC Length") multKC = input(1.5, title="KC MultFactor") useTrueRange = input(true, title="Use TrueRange (KC)") // Calculate BB source = close basis = sma(source, length) dev = mult * stdev(source, length) upperBB = basis + dev lowerBB = basis - dev // Calculate KC ma = sma(source, lengthKC) range = useTrueRange ? tr : (high - low) rangema = sma(range, lengthKC) upperKC = ma + rangema * multKC lowerKC = ma - rangema * multKC sqzOn = (lowerBB > lowerKC) and (upperBB < upperKC) sqzOff = (lowerBB < lowerKC) and (upperBB > upperKC) noSqz = (sqzOn == false) and (sqzOff == false) val = linreg(source - avg(avg(highest(high, lengthKC), lowest(low, lengthKC)),sma(close,lengthKC)), lengthKC,0) ///////////// Rate Of Change ///////////// roclength = input(30, minval=1), pcntChange = input(7, minval=1) roc = 100 * (source - source[roclength]) / source[roclength] emaroc = ema(roc, roclength / 2) isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2)) /////////////// Strategy /////////////// long = val > 0 and isMoving() short = val < 0 and isMoving() last_long = 0.0 last_short = 0.0 last_long := long ? time : nz(last_long[1]) last_short := short ? time : nz(last_short[1]) long_signal = crossover(last_long, last_short) short_signal = crossover(last_short, last_long) last_open_long_signal = 0.0 last_open_short_signal = 0.0 last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1]) last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1]) last_long_signal = 0.0 last_short_signal = 0.0 last_long_signal := long_signal ? time : nz(last_long_signal[1]) last_short_signal := short_signal ? time : nz(last_short_signal[1]) in_long_signal = last_long_signal > last_short_signal in_short_signal = last_short_signal > last_long_signal last_high = 0.0 last_low = 0.0 last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1]) last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1]) sl_inp = input(100.0, title='Stop Loss %') / 100 tp_inp = input(5000.0, title='Take Profit %') / 100 take_level_l = strategy.position_avg_price * (1 + tp_inp) take_level_s = strategy.position_avg_price * (1 - tp_inp) since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na slShort = strategy.position_avg_price * (1 + sl_inp) long_sl = in_long_signal ? slLong : na short_sl = in_short_signal ? slShort : na /////////////// Execution /////////////// if testPeriod() strategy.entry("Long", strategy.long, when=long) strategy.entry("Short", strategy.short, when=short) strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0) strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0) /////////////// Plotting /////////////// bcolor = iff(val > 0, iff(val > nz(val[1]), color.lime, color.green), iff(val < nz(val[1]), color.red, color.maroon)) plot(val, color=bcolor, linewidth=4) bgcolor(not isMoving() ? color.white : long ? color.lime : short ? color.red : na, transp=70) bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=50) hline(0, color = color.white)