ボリンジャーバンドとATRダイナミックトレンドトラッキング戦略:マルチタイムフレーム定量取引システム

ATR BB 多时间框架确认 趋势跟踪 突破交易 动态支撑阻力 自适应交易 波动率过滤
作成日: 2025-04-08 09:51:56 最終変更日: 2025-04-08 09:51:56
コピー: 0 クリック数: 458
2
フォロー
319
フォロワー

ボリンジャーバンドとATRダイナミックトレンドトラッキング戦略:マルチタイムフレーム定量取引システム ボリンジャーバンドとATRダイナミックトレンドトラッキング戦略:マルチタイムフレーム定量取引システム

戦略概要

ブリンベルトとATR動向トレンドトラッキング戦略は,ブリンベルトの突破信号と平均実際の波動範囲 (ATR) の動向調整機能を組み合わせた高度な量化取引システムで”,追跡ライン” (Follow Line) 機構を通じて市場トレンドを識別し,追跡する.この戦略は,特に,多時間枠 (HTF) の確認機構を導入し,より高い時間枠のトレンド方向に応じて取引信号をフィルタリングすることができ,戦略の安定性と収益性を大幅に向上させる.このシステムは,選択可能な取引時期のフィルタリング,ATR波動率の自律調整,HTFのトレンドの変化に対するリアルタイムの反応機構などの多くの高級機能も含んでいます.

戦略原則

この戦略の核心は”追跡ライン”メカニズムで,市場動向を動的に認識し,それに適応する.

  1. ブリン帯信号生成システムはまず標準ブリン帯 (((Bollinger Bands) を計算し,価格が上線を突破すると看板信号 (((1) を発生し,下線を突破すると下落信号 (((-1) を発生し,帯内では信号は中性である (((0) である.

  2. 追跡ラインの計算: ブリン帯信号と現在の価格位置に応じて,システムは一時的な追跡線値を計算する.看板信号の場合,追跡線は現在のK線低点減算ATR値 ((ATRフィルタを有効にする時) または直接低点を使用する.看板信号の場合,追跡線は現在のK線高点加算ATR値または直接高点を使用する.

  3. 追跡ラインのロック策略は”棘輪”の論理を採用し,追跡線を維持します.上昇傾向では,新しい追跡線値は,一時的な値と前の値の大きいもの;下降傾向では,一時的な値と前の値の小さいもの.これは,追跡線がトレンドの方向にのみ移動し,ダイナミックなサポート/抵抗レベルを形成することを保証します.

  4. トレンドが確定: 現在の追跡線と前回の追跡線値を比較することによって,システムはトレンドの方向を決定します. 上は多頭トレンドを表示する ((1)),下は空頭トレンドを表示する ((-1),平らには前のトレンドを維持する。

  5. 多時間枠分析策略は,類似の論理を使用して,より高い時間枠で追跡ラインとトレンド状態を計算し,適切なより高い時間枠を自動的にまたは手動で選択できます (例えば,1分は15分HTFに自動的に対応します).

  6. 入学条件: 取引時間枠のトレンドが中性または下降から上昇に変化し,HTFが上昇傾向であると認めるとき,多行シグナルを生成する.逆に,空調シグナルを生成する.

  7. 出場条件: 取引時間枠のトレンドが逆方向に変化したとき,またはHTFのトレンドが逆方向に変化したとき (新バージョン v2.5) 戦略平仓は,現在のポジションである。

  8. タイムフィルター:特定の取引時間内でのみ取引を行うことを選択できます (通常の米株取引時間0930-1600のように).

戦略的優位性

  1. 適応力がある: トラッキングラインメカニズムは,市場の波動性,特にATRフィルタを有効にすると,自動的に調整することができ,異なる波動率環境にダイナミックな適応能力を提供します.

  2. トレンド確認メカニズム: 多時間枠確認機能は”ノイズ”取引を効果的にフィルターし,HTFのトレンド方向が一致するときにのみ取引し,信号品質を大幅に向上させる.

  3. フレキシブルな設定オプション: 戦略は,ブリン帯周期と偏差,ATR周期,時間フィルター,HTF選択方法など,さまざまな市場と取引品種に応じて最適化できる豊富なパラメータ設定を提供します.

  4. 高い応答性: v2.5版の新バージョンのHTFトレンド変化反応機構は,戦略が大きなトレンドの変化により迅速に反応し,早期に損失を止め,重度の逆転を回避できるようにする.

  5. ビジュアルアシスタント戦略: 取引時間枠とHTFの追跡線をグラフに描き,選択的に買入シグナルラベルを表示して取引の論理を直感的に説明します.

  6. ポジション管理:pyramiding=0を設定することで,同じ方向での複数の入場を防止し,不必要なリスクの蓄積を回避する.

戦略リスク

  1. 偽の突破の危険性: ブリン帯とHTFの確認を使用しているにもかかわらず,特に高波動率の環境下では,市場が偽のブレークを発生させる可能性があります. 解決策: ブリン帯偏差値を増やしたり,確認周期を延長したり,さらに追加のブレーク確認メカニズムを追加することもできます.

  2. パラメータ感度策略性能はATR周期,ブリン帯設定などのパラメータに敏感である. 解決策:特定の取引品種に最も適したパラメータの組み合わせをリターンで見つけ,過度に最適化によって引き起こされる曲線適合問題を避ける.

  3. トレンドの変化の遅れ: トレンドの初期段階では,トラッキングラインのメカニズムが遅い反応を起こす可能性があり,入場が少し遅くなる. 解決策: 応答速度を向上させるために,より小さなATR倍数またはブリン帯周期を使用することを検討できますが,信号の質と応答性をバランスする必要があります.

  4. タイムフレーム依存誤ったHTF選択は過度のフィルタリングや信号衝突を引き起こす可能性があります. 解決策: 自動HTF選択機能を使用することをお勧めします.

  5. 資金管理の欠陥策略自体は完全な資金管理メカニズムを含まない. 解決方法: 実用的には,固定パーセントリスクまたはATR倍数停止などの適切なストップ・ストラトジーとポジション管理規則を組み合わせる.

戦略最適化の方向性

  1. 強化信号フィルタリング: 入場シグナルを確認するために,相対的に強い指標 ((RSI) またはランダムな指標 ((Stochastic) などの他の技術指標を導入することを検討し,指標がオーバーバイ/オーバーセール状態を示している場合にのみ取引を実行します. これは,偽の突破シグナルをさらに減少させ,勝利率を向上させます.

  2. 動態参数調整市場状況に基づく自己適応パラメータの調整メカニズムを開発できる.例えば,高波動環境ではブリン帯偏差値を自動的に増加させ,低波動環境では偏差値を減少させ,戦略が異なる市場条件により適したものにすることができる.

  3. HTTP トレンド判断を最適化する: HTFのトレンド確認アルゴリズムは,指数移動平均の交差や他のトレンド指標を導入することで,より安定したトレンド判断を得るために,トラッキングラインの方向だけに依存するのではなく,改善することができます.

  4. 資金管理の改善: 市場波動と口座規模の動向に応じてポジションサイズを調整する包括的な資金管理システムを統合し,ATRに基づくストップ・ローズレベルと利益目標を設定し,リスク調整後のリターンを最大化します.

  5. 市場状況分析を追加する: 市場環境分類を導入し,トレンド市場と震動市場を区別し,市場状況に応じて戦略パラメータまたは取引ルールを自動的に調整し,その戦略に適さない市場環境で取引を一時停止する.

  6. 多戦略統合: この戦略を構成要素として,他の補完的な戦略 (逆転戦略や突破確認戦略など) と組み合わせて,異なる市場環境下でのパフォーマンスをバランスする完全な戦略の組み合わせを形成する.

要約する

ブリンバンドとATRの動向トレンド追跡戦略は,ブリンバンド,ATRとマルチタイムフレーム分析を組み合わせて,市場トレンドを効果的に識別し,追跡する巧妙に設計された量化取引システムである.この戦略の核心的な優点は,自律性と柔軟性であり,市場状況の動向に合わせて調整することができ,HTF確認メカニズムを通じて信号の質と勝率を向上させることができる.

パラメータの感受性や偽突破の問題などのいくつかの固有のリスクがあるにもかかわらず,これらは適切なパラメータ最適化と追加のフィルタリングメカニズムによって緩和できます. 強化された信号フィルタリング,動的パラメータ調整,資金管理の改善などの戦略最適化方向は,戦略のパフォーマンスをさらに向上させるための明確な経路を提供します.

全体として,この戦略は中長期のトレンドトレーダーに特に適しており,トレンドの変化を認識し,有利な市場条件下で取引を行うための堅固な枠組みを提供します.合理的なパラメータ設定と適切なリスク管理により,この戦略は様々な市場環境で安定したリターンを生み出す可能性があります.

ストラテジーソースコード
/*backtest
start: 2024-07-20 00:00:00
end: 2025-04-07 00:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/

//@version=6
//@fenyesk
//Optional Working Hours and ATR based TP/SL removed
// Added Optional Higher Timeframe Confirmation with Auto/Manual Selection
// Revised for improved profitability: Trend-following Entries/Exits
// v2.5: React to HTF trend changes as well

strategy('Follow Line Strategy Version 2.5 (React HTF)', overlay = true, process_orders_on_close = true, default_qty_type = strategy.percent_of_equity, default_qty_value = 1, pyramiding = 0) // Version bump overlay=true, process_orders_on_close=true, default_qty_type=strategy.percent_of_equity, default_qty_value=1, pyramiding=0) // Prevent multiple entries in the same direction )

// --- Settings ---
// Indicator Parameters
atrPeriodInput = input.int(defval = 5, title = 'ATR Period', minval = 1, group = 'Indicator Settings')
bbPeriodInput = input.int(defval = 21, title = 'Bollinger Bands Period', minval = 1, group = 'Indicator Settings')
bbDeviationInput = input.float(defval = 1.00, title = 'Bollinger Bands Deviation', minval = 0.1, step = 0.1, group = 'Indicator Settings')
useAtrFilterInput = input.bool(defval = true, title = 'Use ATR for Follow Line Offset?', group = 'Indicator Settings')
showSignalsInput = input.bool(title = 'Show Trade Signals on Chart?', defval = true, group = 'Indicator Settings')



// --- Higher Timeframe Confirmation ---
htf_group = 'Higher Timeframe Confirmation'
useHTFConfirmationInput = input.bool(false, title = 'Enable HTF Confirmation?', group = htf_group)
htfSelectionMethodInput = input.string('Auto', title = 'HTF Selection Method', options = ['Auto', 'Manual'], group = htf_group)
manualHTFInput = input.timeframe('240', title = 'Manual Higher Timeframe', group = htf_group) // Default to 4h if Manual
showHTFLineInput = input.bool(false, title = 'Show HTF Follow Line?', group = htf_group)

// --- Determine Higher Timeframe ---
// Revised function with explicit return variable
f_getAutoHTF() =>
    string htfResult = 'D' // Initialize with a default value (e.g., Daily)
    if timeframe.isintraday
        if timeframe.multiplier <= 1 and timeframe.isminutes
            htfResult := '15' // 1min -> 15min
            htfResult
        else if timeframe.multiplier <= 5 and timeframe.isminutes
            htfResult := '240' // 5min -> 4h (240min)
            htfResult
        else if timeframe.multiplier <= 30 and timeframe.isminutes
            htfResult := '240' // 15-30min -> 4h (240min)
            htfResult
        else if timeframe.multiplier == 60 and timeframe.isminutes // 1 hour
            htfResult := 'D' // 1h -> 1 Day
            htfResult
        else if timeframe.multiplier <= 240 and timeframe.isminutes // Up to 4 hours
            htfResult := 'W' // 4h -> 1 Week
            htfResult
    // else // The default "D" is already set if none of the above match
    // htfResult := "D" // Default for other intraday -> 1 Day (already default)
    else if timeframe.isdaily // Daily
        htfResult := 'M' // 1 Day -> 1 Month
        htfResult
    else if timeframe.isweekly // Weekly
        htfResult := 'M' // 1 Week -> 1 Month
        htfResult
    else // Monthly or higher (or unknown)
        htfResult := '3M' // Default to 3 Months
        htfResult
    htfResult // Explicitly return the variable value

autoHTF = f_getAutoHTF()
selectedHTF = htfSelectionMethodInput == 'Auto' ? autoHTF : manualHTFInput

// --- Trade Timeframe Calculations ---
// Bollinger Bands calculation
bbMiddle_trade = ta.sma(close, bbPeriodInput)
bbStdDev_trade = ta.stdev(close, bbPeriodInput)
BBUpper_trade = bbMiddle_trade + bbStdDev_trade * bbDeviationInput
BBLower_trade = bbMiddle_trade - bbStdDev_trade * bbDeviationInput

// ATR calculation
atrValue_trade = ta.atr(atrPeriodInput)

// Signal initialization for Trade TF
var float followLine_trade = na
var int bbSignal_trade = 0
var int trend_trade = 0 // Renamed from iTrend

// Determine BB signal based on current close (Trade TF)
if close > BBUpper_trade
    bbSignal_trade := 1
    bbSignal_trade
else if close < BBLower_trade
    bbSignal_trade := -1
    bbSignal_trade
else
    bbSignal_trade := 0 // Reset signal if price is within bands
    bbSignal_trade

// Calculate potential new FollowLine value for the current bar (Trade TF)
float tempFollowLine_trade = na // Explicit type
if bbSignal_trade == 1
    tempFollowLine_trade := useAtrFilterInput ? low - atrValue_trade : low
    tempFollowLine_trade
else if bbSignal_trade == -1
    tempFollowLine_trade := useAtrFilterInput ? high + atrValue_trade : high
    tempFollowLine_trade

// Determine the final FollowLine for the current bar, applying the "ratchet" logic (Trade TF)
if bbSignal_trade == 1 // Price closed above upper BB
    followLine_trade := na(followLine_trade[1]) ? tempFollowLine_trade : math.max(tempFollowLine_trade, nz(followLine_trade[1], tempFollowLine_trade))
    followLine_trade
else if bbSignal_trade == -1 // Price closed below lower BB
    followLine_trade := na(followLine_trade[1]) ? tempFollowLine_trade : math.min(tempFollowLine_trade, nz(followLine_trade[1], tempFollowLine_trade))
    followLine_trade
else // Price closed within bands, FollowLine continues from previous bar
    if not na(followLine_trade[1])
        followLine_trade := followLine_trade[1]
        followLine_trade
        // else followLine_trade remains na if followLine_trade[1] was na

// Trend direction determination (Based on current FollowLine vs previous FollowLine - Trade TF)
if not na(followLine_trade) and not na(followLine_trade[1])
    if followLine_trade > followLine_trade[1]
        trend_trade := 1
        trend_trade
    else if followLine_trade < followLine_trade[1]
        trend_trade := -1
        trend_trade
    else
        trend_trade := nz(trend_trade[1], 0) // Maintain previous trend if line is flat but valid
        trend_trade
else if not na(followLine_trade) and na(followLine_trade[1])
    trend_trade := bbSignal_trade == 1 ? 1 : bbSignal_trade == -1 ? -1 : 0 // Use ternary for initial trend
    trend_trade
else if na(followLine_trade)
    trend_trade := 0 // Reset trend if FollowLine becomes invalid
    trend_trade


// --- Higher Timeframe Calculations ---
// Function revised to return only one value (as float) based on parameter
f_calculateHTFData(htf_close, htf_high, htf_low, return_type) =>
    // Explicitly type potentially 'na' indicator results
    float htf_atrValue = ta.atr(atrPeriodInput)
    float htf_bbMiddle = ta.sma(htf_close, bbPeriodInput)
    float htf_bbStdDev = ta.stdev(htf_close, bbPeriodInput)
    float htf_BBUpper = na
    float htf_BBLower = na

    // Calculate BBands only if middle/stdev are valid
    if not na(htf_bbMiddle) and not na(htf_bbStdDev)
        htf_BBUpper := htf_bbMiddle + htf_bbStdDev * bbDeviationInput
        htf_BBLower := htf_bbMiddle - htf_bbStdDev * bbDeviationInput
        htf_BBLower

    // Determine BB signal (HTF) - Default to 0
    int htf_bbSignal = 0
    // Check if bands are valid before comparing
    if not na(htf_BBUpper) and not na(htf_BBLower)
        if htf_close > htf_BBUpper
            htf_bbSignal := 1
            htf_bbSignal
        else if htf_close < htf_BBLower
            htf_bbSignal := -1
            htf_bbSignal

    // Calculate potential new FollowLine (HTF)
    float htf_tempFollowLine = na // Explicitly typed float
    if htf_bbSignal == 1
        htf_tempFollowLine := useAtrFilterInput and not na(htf_atrValue) ? htf_low - htf_atrValue : htf_low
        htf_tempFollowLine
    else if htf_bbSignal == -1
        htf_tempFollowLine := useAtrFilterInput and not na(htf_atrValue) ? htf_high + htf_atrValue : htf_high
        htf_tempFollowLine

    // Maintain FollowLine state using 'var'
    var float htf_followLine = na
    var int htf_trend = 0

    // Determine the final FollowLine (HTF)
    if htf_bbSignal == 1
        htf_followLine := na(htf_followLine[1]) ? htf_tempFollowLine : math.max(htf_tempFollowLine, nz(htf_followLine[1], htf_tempFollowLine))
        htf_followLine
    else if htf_bbSignal == -1
        htf_followLine := na(htf_followLine[1]) ? htf_tempFollowLine : math.min(htf_tempFollowLine, nz(htf_followLine[1], htf_tempFollowLine))
        htf_followLine
    else
        if not na(htf_followLine[1])
            htf_followLine := htf_followLine[1]
            htf_followLine
            // else htf_followLine remains na if htf_followLine[1] was na (unless reset below)

    // Reset FollowLine if it's based on invalid temp line
    if na(htf_tempFollowLine) and htf_bbSignal != 0 // If the signal existed but calc failed (e.g., na ATR)
        htf_followLine := na // Reset line
        htf_followLine

    // Determine Trend (HTF)
    if not na(htf_followLine) and not na(htf_followLine[1])
        if htf_followLine > htf_followLine[1]
            htf_trend := 1
            htf_trend
        else if htf_followLine < htf_followLine[1]
            htf_trend := -1
            htf_trend
        else
            htf_trend := nz(htf_trend[1], 0)
            htf_trend
    else if not na(htf_followLine) and na(htf_followLine[1])
        htf_trend := htf_bbSignal == 1 ? 1 : htf_bbSignal == -1 ? -1 : 0
        htf_trend
    else if na(htf_followLine) // Trend is 0 if line becomes (or is) na
        htf_trend := 0
        htf_trend

    // Return the requested value as float type (or na)
    float return_value = na
    if return_type == 'line'
        return_value := htf_followLine
        return_value
    else if return_type == 'trend'
        return_value := float(htf_trend) // Convert int trend to float for consistent return type
        return_value

    return_value // Return the single calculated value


// Explicitly declare variables that will receive the security call result
float followLine_htf = na
int trend_htf = 0 // Initialize with a default value (0 for neutral)

// Request HTF data UNCONDITIONALLY
followLine_htf_result = request.security(syminfo.tickerid, selectedHTF, f_calculateHTFData(close, high, low, 'line'), lookahead = barmerge.lookahead_off)
trend_htf_result_float = request.security(syminfo.tickerid, selectedHTF, f_calculateHTFData(close, high, low, 'trend'), lookahead = barmerge.lookahead_off)

// Conditionally assign the results based on whether the HTF feature is enabled
if useHTFConfirmationInput or showHTFLineInput
    // Assign results, handling potential 'na' values safely
    followLine_htf := followLine_htf_result // Assign float/na directly
    trend_htf := na(trend_htf_result_float) ? 0 : int(nz(trend_htf_result_float)) // Convert float result back to int, default to 0 if na
    trend_htf
else // If HTF features are disabled, set variables to 'na'
    followLine_htf := na
    trend_htf := 0 // or na if preferred
    trend_htf




// HTF Filter
// Use the potentially 'na' followLine_htf and the guaranteed non-'na' trend_htf
htfConfirmsLong = not useHTFConfirmationInput or useHTFConfirmationInput and trend_htf == 1
htfConfirmsShort = not useHTFConfirmationInput or useHTFConfirmationInput and trend_htf == -1

// --- Entry/Exit Conditions ---
// Buy & Sell Conditions (Based on Trade TF trend crossover)
longCondition_trade = nz(trend_trade[1]) <= 0 and trend_trade == 1
shortCondition_trade = nz(trend_trade[1]) >= 0 and trend_trade == -1

// Combined Entry Conditions with Filters
goLong = htfConfirmsLong and longCondition_trade  and strategy.position_size <= 0 // Only enter long if flat or short & HTF confirms
goShort = htfConfirmsShort and shortCondition_trade  and strategy.position_size >= 0 // Only enter short if flat or long & HTF confirms

// Exit conditions based on *either* TTF or HTF changing trend against the position
exitLong = trend_trade == -1 or trend_htf == -1 // TTF to short OR HTF to short
exitShort = trend_trade == 1 or trend_htf == 1 // TTF to long OR HTF to long


// --- Strategy Execution ---

if goLong
    strategy.close('Short', comment = 'Close Short for Long')
    strategy.entry('Long', strategy.long, comment = 'Enter Long')

if goShort
    strategy.close('Long', comment = 'Close Long for Short')
    strategy.entry('Short', strategy.short, comment = 'Enter Short')

if exitLong
    strategy.close('Long', comment = 'Exit Long')

if exitShort
    strategy.close('Short', comment = 'Exit Short')

// --- Alerts ---
// Alerts trigger on the same bar as the entry condition, respecting all filters
// NOTE: Removed dynamic HTF from message as alertcondition requires const string
alertcondition(goLong, title = 'FL Buy Signal', message = 'Follow Line Buy Signal - {{ticker}} {{interval}}')
alertcondition(goShort, title = 'FL Sell Signal', message = 'Follow Line Sell Signal - {{ticker}} {{interval}}')
alertcondition(goLong or goShort, title = 'FL Signal', message = 'Follow Line Signal - {{ticker}} {{interval}}')

// --- Plotting ---
// Plot the Trade Timeframe Follow Line
lineColor_trade = trend_trade > 0 ? color.new(color.blue, 0) : trend_trade < 0 ? color.new(color.red, 0) : color.new(color.gray, 0)
plot(followLine_trade, color = lineColor_trade, linewidth = 2, title = 'Follow Line (Trade TF)')

// Plot the Higher Timeframe Follow Line (optional)
// Use the potentially 'na' followLine_htf and the guaranteed non-'na' trend_htf for coloring
lineColor_htf = trend_htf > 0 ? color.new(color.aqua, 0) : trend_htf < 0 ? color.new(color.orange, 0) : color.new(color.gray, 70)
plot(showHTFLineInput and useHTFConfirmationInput ? followLine_htf : na, color = lineColor_htf, linewidth = 2, style = plot.style_circles, title = 'Follow Line (HTF)', offset = 0)

// Plot shapes on the bar the trade signal occurs (based on trade TF condition), placing them AT the calculated Trade TF price level.
// Use the original trade long/short conditions for plotting shapes for clarity, before plots
plotshape(longCondition_trade and showSignalsInput and not na(followLine_trade) and not na(atrValue_trade) ? followLine_trade - atrValue_trade : na, text = 'BUY', style = shape.labelup, location = location.absolute, color = color.new(color.blue, 0), textcolor = color.new(color.white, 0), offset = 0, size = size.auto)
plotshape(shortCondition_trade and showSignalsInput and not na(followLine_trade) and not na(atrValue_trade) ? followLine_trade + atrValue_trade : na, text = 'SELL', style = shape.labeldown, location = location.absolute, color = color.new(color.red, 0), textcolor = color.new(color.white, 0), offset = 0, size = size.auto)

// Plot BBands for reference if desired
// plot(BBUpper_trade, "Upper BB", color=color.gray)
// plot(BBLower_trade, "Lower BB", color=color.gray)