ダブルチャネル追跡逆転戦略は,ボリンジャーバンド,ケルターチャネル,インパクト指標を組み合わせた逆転取引戦略である.ボリンジャーバンドとケルターチャネルの合成を通じて価格圧縮ゾーンを特定し,インパクト指標を使用してエントリーと出口の逆転信号を決定する.
ボリンジャー・バンドの 中間,上,下帯を計算する
ケルトナーチャネルのための中,上,下帯を計算する
ボリンジャー帯がケルトナーチャネルの中にいるかどうかを判定する
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)