ケルトナーチャネルに基づく柔軟なロングおよびショート取引戦略

ATR EMA SMA MA TR
作成日: 2025-02-10 15:07:12 最終変更日: 2025-02-10 15:07:12
コピー: 4 クリック数: 448
1
フォロー
1617
フォロワー

ケルトナーチャネルに基づく柔軟なロングおよびショート取引戦略

概要

これは,ケルトナーチャンネル (Keltner Channel) に基づく柔軟な取引戦略である.この戦略は,価格突破チャネルの上下をモニタリングすることによって,多空双方向取引をサポートする.この戦略の核心は,移動平均 (MA) を使用して価格チャネルを構築し,実際の波幅 (ATR) と組み合わせてチャネルの幅を動的に調整することで,異なる市場環境下で戦略の適応性を維持するものである.

戦略原則

戦略は以下の基本原則に基づいています.

  1. EMAまたはSMAによる価格計算の中央トレンド,チャネル中軌道を形成する
  2. ATR,TR,またはRangeの変動率を使用して,通路の上下を構成する
  3. 価格が上線を突破すると多信号をトリガーし,下線を突破すると空信号をトリガーします.
  4. 取引実行の信頼性を高めるため,単一のストップ・ローズ委託メカニズムによる入場と出場
  5. フレキシブルな取引モードの選択をサポートする:多額取引,空白取引,双方向取引

戦略的優位性

  1. 適応性 - ATRでチャネル幅を動的に調整することで,異なる市場の変動状況に戦略が適応できます.
  2. リスク管理の完善 - ストップ・ロズ・委託単一メカニズムを使用して取引を行い,リスクを効果的に管理する
  3. 操作の柔軟性 - 市場特性と取引好みに合わせて調整可能な複数の取引モードをサポート
  4. 証明された有効性 - 仮想通貨と株式市場,特に波動性の高い市場での良好なパフォーマンス
  5. 透明度 - 取引シグナルとポジションの状態を直感的に表示する

戦略リスク

  1. 震動市場リスク - 横盤の震動市場では頻繁に偽のブレイクシグナルが生じる可能性がある
  2. スリップポイントリスク - 流動性が低い市場では,ストップ・ロスト委託は大きなスリップポイントに直面する可能性があります.
  3. トレンド反転リスク - 急なトレンド反転で大きな損失を被る可能性
  4. パラメータの感受性 - 経路のパラメータの選択は,戦略のパフォーマンスに重要な影響を与える

戦略最適化の方向性

  1. トレンドフィルターの導入 - トレンド判断指標を追加することで偽の突破信号を減らす
  2. ダイナミックパラメータ最適化 - 市場の変動状況に応じてチャネルパラメータを動的に調整する
  3. 利潤の保護のためにモバイル・ストップ機能を追加
  4. 交差量確認を増やす - 交差量指標を組み合わせて信号の信頼性を高める
  5. ポジション管理の最適化 - リスク管理の最適化のためのダイナミックなポジション管理の導入

要約する

この戦略は,設計され,論理的に明確な取引システムであり,ケイトナー通路と複数の技術指標の柔軟な使用により,市場機会を効果的に捕捉することが可能である.この戦略は,異なるリスクの好みのトレーダーに適したカスタマイズ性が強い.継続的な最適化と改善により,この戦略は,さまざまな市場環境で安定したパフォーマンスを維持すると見込まれている.

ストラテジーソースコード
/*backtest
start: 2022-02-11 00:00:00
end: 2025-02-08 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=6
strategy(title = "Jaakko's Keltner Strategy", overlay = true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100)

// ──────────────────────────────────────────────────────────────────────────────
// ─── USER INPUTS ─────────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
length      = input.int(20,     minval=1,  title="Keltner MA Length")
mult        = input.float(2.0,             title="Multiplier")
src         = input(close,                 title="Keltner Source")
useEma      = input.bool(true,             title="Use Exponential MA")
BandsStyle  = input.string(title = "Bands Style", defval  = "Average True Range", options = ["Average True Range", "True Range", "Range"])
atrLength   = input.int(10,                title="ATR Length")

// Choose which side(s) to trade
tradeMode = input.string(title   = "Trade Mode", defval  = "Long Only", options = ["Long Only", "Short Only", "Both"])

// ──────────────────────────────────────────────────────────────────────────────
// ─── KELTNER MA & BANDS ───────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
f_ma(source, length, emaMode) =>
    maSma = ta.sma(source, length)
    maEma = ta.ema(source, length)
    emaMode ? maEma : maSma

ma    = f_ma(src, length, useEma)
rangeMa = BandsStyle == "True Range" ? ta.tr(true) : BandsStyle == "Average True Range" ? ta.atr(atrLength) : ta.rma(high - low, length)

upper = ma + rangeMa * mult
lower = ma - rangeMa * mult

// ──────────────────────────────────────────────────────────────────────────────
// ─── CROSS CONDITIONS ─────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
crossUpper = ta.crossover(src, upper) // potential long signal
crossLower = ta.crossunder(src, lower) // potential short signal

// ──────────────────────────────────────────────────────────────────────────────
// ─── PRICE LEVELS FOR STOP ENTRY (LONG) & STOP ENTRY (SHORT) ─────────────────
// ──────────────────────────────────────────────────────────────────────────────
bprice = 0.0
bprice := crossUpper ? high + syminfo.mintick : nz(bprice[1])

sprice = 0.0
sprice := crossLower ? low - syminfo.mintick : nz(sprice[1])

// ──────────────────────────────────────────────────────────────────────────────
// ─── BOOLEAN FLAGS FOR PENDING LONG/SHORT ─────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
crossBcond = false
crossBcond := crossUpper ? true : crossBcond[1]

crossScond = false
crossScond := crossLower ? true : crossScond[1]

// Cancel logic for unfilled orders (same as original)
cancelBcond = crossBcond and (src < ma or high >= bprice)
cancelScond = crossScond and (src > ma or low <= sprice)

// ──────────────────────────────────────────────────────────────────────────────
// ─── LONG SIDE ────────────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
if (tradeMode == "Long Only" or tradeMode == "Both")  // Only run if mode is long or both
    // Cancel unfilled long if invalid
    if cancelBcond
        strategy.cancel("KltChLE")

    // Place long entry
    if crossUpper
        strategy.entry("KltChLE", strategy.long, stop=bprice, comment="Long Entry")

    // If we are also using “Both,” we rely on short side to flatten the long.
    // But if “Long Only,” we can exit on crossLower or do nothing.
    // Let’s do a "stop exit" if in "Long Only" (like the improved version).
    if tradeMode == "Long Only"
        // Cancel unfilled exit
        if cancelScond
            strategy.cancel("KltChLX")

        // Place exit if crossLower
        if crossLower
            strategy.exit("KltChLX", from_entry="KltChLE", stop=sprice, comment="Long Exit")

// ──────────────────────────────────────────────────────────────────────────────
// ─── SHORT SIDE ───────────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
if (tradeMode == "Short Only" or tradeMode == "Both") // Only run if mode is short or both
    // Cancel unfilled short if invalid
    if cancelScond
        strategy.cancel("KltChSE")

    // Place short entry
    if crossLower
        strategy.entry("KltChSE", strategy.short, stop=sprice, comment="Short Entry")

    // If “Short Only,” we might do a symmetrical exit approach for crossUpper
    // Or if "Both," going long automatically flattens the short in a no-hedge account.
    // Let's replicate "stop exit" for short side if "Short Only" is chosen:
    if tradeMode == "Short Only"
        // Cancel unfilled exit
        if cancelBcond
            strategy.cancel("KltChSX")

        // Place exit if crossUpper
        if crossUpper
            strategy.exit("KltChSX", from_entry="KltChSE", stop=bprice, comment="Short Exit")

// ──────────────────────────────────────────────────────────────────────────────
// ─── OPTIONAL VISUALS ─────────────────────────────────────────────────────────
// ──────────────────────────────────────────────────────────────────────────────
barcolor(strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : na)

plotshape(    strategy.position_size > 0 and strategy.position_size[1] <= 0, title     = "BUY",  text      = '🚀',  style     = shape.labelup,    location  = location.belowbar,     color     = color.green,     textcolor = color.white,      size      = size.small)

plotshape(    strategy.position_size <= 0 and strategy.position_size[1] > 0,     title     = "SELL",     text      = '☄️',     style     = shape.labeldown,     location  = location.abovebar,     color     = color.red,       textcolor = color.white,     size      = size.small)

plotshape(crossLower, style=shape.triangledown, color=color.red, location=location.abovebar, title="CrossLower Trigger")