マルチインジケーターブレイクアウトと反転取引戦略:始値レンジの最適化と組み合わせたデュアルエントリーシステム

EMA SMA RSI ATR VWAP ORB
作成日: 2025-04-01 16:00:37 最終変更日: 2025-04-01 16:00:37
コピー: 0 クリック数: 382
2
フォロー
319
フォロワー

マルチインジケーターブレイクアウトと反転取引戦略:始値レンジの最適化と組み合わせたデュアルエントリーシステム マルチインジケーターブレイクアウトと反転取引戦略:始値レンジの最適化と組み合わせたデュアルエントリーシステム

概要

多指数突破と逆転の取引戦略は,指数と価格の行動を技術的に分析する,市場における2つの主要な取引機会を捉えるための量化取引方法である.この戦略は,移動平均,相対的に強い指数 (RSI),平均リアルレンジ (ATR) および取引量加重平均価格 (VWAP) などの複数の技術指標を巧妙に統合し,開盤区間突破 (ORB) の仕組みを導入し,入場シグナルの信頼性を高めます.この戦略は,二重目的のストップデザインを採用し,自動でストップ損失を平衡の損失点に調整するリスク管理機構を備えています.

戦略原則

この戦略の核心となる原則は,複数の指標をフィルタリングして確認し,潜在的に有利な取引機会の3つのカテゴリーを特定することです.

  1. 逆転取引信号

    • 多頭反転:価格が50期単調移動平均を突破したときに発火する (SMA50),RSIは超売り値 (デフォルト30) よりも低く,価格はVWAPより低く,そして全体的なトレンドは上昇している (SMA200以上の価格).
    • 空頭逆転:価格がSMA50を下回り,RSIが超買い値 (デフォルト70) を上回り,価格がVWAPを上回り,全体的な傾向が下方 (SMA200を下回り) になると発火する.
  2. トレンドブレイク信号

    • 多頭突破: 9期指数移動平均 ((EMA9) の上に20期指数移動平均 ((EMA20) を突破すると,価格がVWAPより高く,全体的なトレンドが上向きになると触発されます.
    • 空気突破:EMA9を下回ってEMA20を突破し,VWAPより低い価格で,全体的な下向きのトレンドが発生する.
  3. オープン区間突破 (ORB) 信号

    • 多頭ORB:価格が開盤前特定の数の柱 (デフォルト15柱) を破り,取引量が開盤区間の平均取引量の既定倍数 (デフォルト1.5倍) を上回ったときに発動する.
    • 空頭ORB:価格が開盤前に形成された最低値を下回り,取引量が減価条件を満たしたときにトリガーされる.

戦略はATR指標を使用して動的ストップロスを計算し,特定の周期の最低価格/最高価格を遡って設定し,ATR値の倍数 (デフォルト0.5) を加減します.入場後,戦略は2つのストップストップ目標を設定します.

  • 第1目標 (TP1):リスクの0.5倍 (デフォルト),平仓25%のポジション
  • 2番目の目標 (TP2):リスクの1.1倍 (デフォルト) 残りの75%のポジションを平仓に

最初のストップ目標が達成されると,戦略は自動的にストップを入場価格に調整し,既得利益を効果的に保護する.

戦略的優位性

  1. 多様な入場信号戦略は,反転,突破,開場区間を突破する3つの異なる入場シグナルを統合することで,多種多様な市場環境に適応し,取引機会を効果的に増加させながら,高い信号品質を維持します.

  2. リスクの管理戦略は,分級のストップメカニズムを採用し,利益の一部を保持しながら,潜在的により大きな利益を維持します.最初のストップ目標に達すると,自動的にストップ損失を利益の均衡点に調整し,利益を走らせながら資本を保護します.

  3. ダイナミックストップ損失計算:ATR指標を用いたストップポジションの計算により,ストップレベルは市場の波動的な動向に合わせて調整され,現在の市場状況をより正確に反映し,過度に緊密なまたは過度に緩やかなストップ設定を避ける.

  4. 取引量確認:特にORB信号に取引量確認メカニズムを導入し,開拓区間の平均取引量の特定の倍数を超える取引量の要求を突破し,低品質の突破を効果的にフィルターする.

  5. トレンドフィルター長期トレンドの方向を200期簡易移動平均 ((SMA200) で判断し,取引の方向が主要トレンドと一致していることを確認し,取引の成功率を向上させる.

  6. 資金管理統合戦略: 資金管理機構を組み込み,取引ごとに使用する資金の割合を制限する (デフォルトの50%の資本),資金の多様化配置を確保し,単一の取引のリスクのを減らす.

戦略リスク

  1. 指標の遅れ策略は,移動平均などの遅滞指数に大きく依存し,急速に変化する市場では,入場時間を遅らせ,良い入場点を逃す,または不必要な損失を引き起こす可能性があります.

解決策:価格行動パターンの認識などの前向きな指標を増やすか,より長い周期の移動平均のパラメータを縮小して,市場の変化への感受性を高めるかを検討する.

  1. パラメータ感度調整可能なパラメータ (EMA長さ,RSI値,ATR係数など) の多さは,戦略の最適化を複雑にし,過去データに過度に適合して将来の市場での不良パフォーマンスを引き起こす可能性があります.

解決方法: 適切なパラメータ最適化方法 (前向き検証,モンテカルロ模擬など) を採用し,過度な最適化を避けるか,固定パラメータを使用し,より堅牢な規則設計に焦点を当てます.

  1. 多信号衝突: 特定の市場環境では,異なる入場シグナルにより,相反する取引の提案が生じ,戦略の不安定なパフォーマンスを引き起こす可能性があります.

解決策は,より厳格な信号優先システムを作ること,または,取引が高い確率でしか実行されないことを保証する追加の確認メカニズムを導入することです.

  1. 飛び降りる危険を防ぐ: 波動が強い,または流動性が低い市場では,価格がストップ・ポジションを超えて飛躍し,実際の損失が予想よりも大きくなる可能性があります.

解決方法: オプションのヘッジ戦略を使用するか,高波動性のある市場条件下でストップ距離を増やすか,一時的にポジションサイズを下げるかを検討する.

  1. システム上のリスクの口戦略: 複数の関連取引を同時に実行し,市場が激しく波動すると,複数の取引が同時に損失を招く可能性のあるシステミックリスクに直面する.

解決策:全局的なリスク管理を実施し,総ポジションの規模を制限するか,異なる資産クラス間の分散取引を行い,関連性のリスクを軽減する.

戦略最適化の方向性

  1. 機械学習モデルを導入する: 機械学習アルゴリズムを指標重量最適化または市場環境分類に適用し,異なる市場条件下での各指標の相対的重要性を自動的に調整し,戦略の適応性を向上させる.

最適化理由:従来の固定重量指標の組み合わせは,異なる市場段階に適応することが困難であり,機械学習は,歴史データから最適な指標の組み合わせのパターンを自動的に学習することができます.

  1. 市場情緒指標を統合する: 波動率指数 ((VIX) または高周波市場情緒指標を追加し,市場環境をよりよく認識し,入場条件とリスクパラメータを調整するのに戦略を助ける.

最適化理由:市場の情勢は短期的な価格動向に顕著な影響を与える.このような指標を統合することで,市場の転換点を早期に捉え,入場と出場のタイミングを最適化することができる.

  1. 動的に停止比率を調整ストップ・ターゲットは,歴史的な変動やサポート・レジスタンス・レベルに基づいて自動的に調整され,異なる変動環境で戦略が合理的な利益を得ることができます.

最適化理由: 固定のリスク・リターン比は,異なる市場環境で柔軟性がない可能性があり,ダイナミックな調整により,高波動市場ではより遠方の目標,低波動市場ではより保守的な目標が設定できます.

  1. タイムフィルターを導入する市場時間に基づくフィルタリングメカニズムに加入し,低波動性または不利な時間帯,例えば市場開店後の最初の数分または流動性が低い昼間の取引を避ける.

最適化理由:市場の活動は,1日の異なる時間帯で顕著な差異を示し,時間フィルタリングは,戦略が最も有利な取引時間に集中するのを助けます.

  1. ポジション規模を最適化する: 固定資金比率から波動性に基づくポジション規模計算に変換し,高波動期にポジションを自動的に小さくし,低波動期にポジションを適切に増やす.

最適化理由: リスクは市場の変動と直接に関連しており,動的ポジション管理により,より一貫したリスクレベルを維持し,長期のリスク調整後の収益を改善することができる.

要約する

多指数突破と逆転取引戦略は,複数の技術分析方法を融合した総合的な量化取引システムであり,逆転,トレンド突破と開拓区間の突破信号を統合し,優れたリスク管理と資金管理機構を組み合わせて,さまざまな市場環境における取引機会を捉えることを目的としています. 戦略の核心的な優点は,信号の多様性,リスク管理の改善,パラメータのカスタマイズ性の強さであり,特に短期間の取引に適しています.

ストラテジーソースコード
/*backtest
start: 2025-01-01 00:00:00
end: 2025-03-31 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy("Reversal & Breakout Strategy with ORB", overlay=true, pyramiding=2, initial_capital=50000)

// --- Inputs ---
ema9Length = input.int(9, "9 EMA Length", minval=1)
ema20Length = input.int(20, "20 EMA Length", minval=1)
sma50Length = input.int(50, "50 SMA Length", minval=1)
sma200Length = input.int(200, "200 SMA Length", minval=1)
rsiLength = input.int(14, "RSI Length", minval=1)
rsiOverbought = input.int(70, "RSI Overbought", minval=0, maxval=100)
rsiOversold = input.int(30, "RSI Oversold", minval=0, maxval=100)
atrLength = input.int(14, "ATR Length", minval=1)
stopMulti = input.float(0.5, "Stop Loss ATR Multiplier", minval=0.1, step=0.1)
stopLookback = input.int(7, "Stop Loss Lookback", minval=1)
rr1 = input.float(0.5, "Risk:Reward Target 1", minval=0.1, step=0.1)
rr2 = input.float(1.1, "Risk:Reward Target 2", minval=0.1, step=0.1)
target1Percent = input.float(25, "Profit % Target 1", minval=0, maxval=100)
orbBars = input.int(15, "Opening Range Bars", minval=1, tooltip="Number of bars to define the opening range (e.g., 15 bars = 30 min on 2-min chart)")
volThreshold = input.float(1.5, "Volume Threshold Multiplier", minval=1.0, step=0.1, tooltip="Volume must be this multiple of the opening range average")

// --- Indicators ---
// Moving Averages
ema9 = ta.ema(close, ema9Length)
ema20 = ta.ema(close, ema20Length)
sma50 = ta.sma(close, sma50Length)
sma200 = ta.sma(close, sma200Length)

// VWAP
vwapValue = ta.vwap(close)

// RSI
rsi = ta.rsi(close, rsiLength)

// ATR
atr = ta.atr(atrLength)

// --- Opening Range Breakout ---
var float openingRangeHigh = na
var float openingRangeLow = na
var float openingRangeAvgVol = na
if bar_index < orbBars
    openingRangeHigh := na
    openingRangeLow := na
    openingRangeAvgVol := na
else if bar_index == orbBars
    openingRangeHigh := ta.highest(high, orbBars)
    openingRangeLow := ta.lowest(low, orbBars)
    openingRangeAvgVol := ta.sma(volume, orbBars)

orbLong = not na(openingRangeHigh) and ta.crossover(close, openingRangeHigh) and volume > openingRangeAvgVol * volThreshold
orbShort = not na(openingRangeLow) and ta.crossunder(close, openingRangeLow) and volume > openingRangeAvgVol * volThreshold

// --- Trend Detection ---
trendUp = close > sma200
trendDown = close < sma200

// --- Reversal Conditions ---
reversalLong = ta.crossover(close, sma50) and rsi < rsiOversold and close < vwapValue and trendUp
reversalShort = ta.crossunder(close, sma50) and rsi > rsiOverbought and close > vwapValue and trendDown

// --- Range Breakout Conditions ---
breakoutLong = ta.crossover(ema9, ema20) and close > vwapValue and trendUp
breakoutShort = ta.crossunder(ema9, ema20) and close < vwapValue and trendDown

// Combine conditions
longCondition = (reversalLong or breakoutLong or orbLong)
shortCondition = (reversalShort or breakoutShort or orbShort)

// --- Calculate Position Size ---
equityPerPosition = 25000.0  // $50,000 / 2 positions
positionSizeLong = math.floor(equityPerPosition / close)
positionSizeShort = math.floor(equityPerPosition / close)

// --- Stop Loss Calculation ---
longStop = ta.lowest(low, stopLookback) - (atr * stopMulti)
shortStop = ta.highest(high, stopLookback) + (atr * stopMulti)

// --- Variables to Store Trade Levels ---
var float tradeStop = na
var float tradeTarget1 = na
var float tradeTarget2 = na
var float initialPositionSize = na
var bool breakEvenSet = false  // Track if stop has been moved to break-even
var float stopLevel = na       // Dedicated variable for stop loss in exits
var float target1Level = na    // Dedicated variable for first take profit
var float target2Level = na    // Dedicated variable for second take profit
var float qtyTotal = na        // Track total quantity

// --- Reset Levels Before New Trade ---
var bool newTrade = false
if longCondition or shortCondition
    newTrade := true
else
    newTrade := false

if strategy.position_size == 0 and newTrade
    tradeStop := na
    tradeTarget1 := na
    tradeTarget2 := na
    stopLevel := na
    target1Level := na
    target2Level := na
    initialPositionSize := na
    qtyTotal := na
    breakEvenSet := false

// --- Strategy Entries ---
if longCondition and strategy.position_size == 0
    strategy.entry("Long", strategy.long, qty=positionSizeLong * 2)
    tradeStop := longStop
    stopLevel := longStop
    stopDistance = close - tradeStop
    tradeTarget1 := close + (stopDistance * rr1)
    tradeTarget2 := close + (stopDistance * rr2)
    target1Level := tradeTarget1
    target2Level := tradeTarget2
    initialPositionSize := positionSizeLong * 2
    qtyTotal := positionSizeLong * 2
    breakEvenSet := false  // Reset break-even flag

if shortCondition and strategy.position_size == 0
    strategy.entry("Short", strategy.short, qty=positionSizeShort * 2)
    tradeStop := shortStop
    stopLevel := shortStop
    stopDistance = tradeStop - close
    tradeTarget1 := close - (stopDistance * rr1)
    tradeTarget2 := close - (stopDistance * rr2)
    target1Level := tradeTarget1
    target2Level := tradeTarget2
    initialPositionSize := positionSizeShort * 2
    qtyTotal := positionSizeShort * 2
    breakEvenSet := false  // Reset break-even flag

// --- Trade Exits ---
if strategy.position_size > 0
    qty_tp1 = qtyTotal * (target1Percent / 100)
    qty_tp2 = qtyTotal * ((100 - target1Percent) / 100)
    strategy.exit("Long Exit 1", "Long", qty=qty_tp1, stop=stopLevel, limit=target1Level)
    strategy.exit("Long Exit 2", "Long", qty=qty_tp2, stop=stopLevel, limit=target2Level)

if strategy.position_size < 0
    qty_tp1 = qtyTotal * (target1Percent / 100)
    qty_tp2 = qtyTotal * ((100 - target1Percent) / 100)
    strategy.exit("Short Exit 1", "Short", qty=qty_tp1, stop=stopLevel, limit=target1Level)
    strategy.exit("Short Exit 2", "Short", qty=qty_tp2, stop=stopLevel, limit=target2Level)

// --- Move Stop to Break-even ---
if strategy.position_size != 0 and not na(initialPositionSize) and not breakEvenSet
    if math.abs(strategy.position_size) < math.abs(initialPositionSize)
        tradeStop := strategy.position_avg_price
        stopLevel := strategy.position_avg_price
        tradeTarget1 := na  // Clear first target for plotting
        breakEvenSet := true  // Mark break-even as set

// --- Manual Close Fallback ---
if strategy.position_size > 0
    if close >= target2Level or close <= stopLevel
        strategy.close("Long", qty=qtyTotal, comment="Manual Close")

if strategy.position_size < 0
    if close <= target2Level or close >= stopLevel
        strategy.close("Short", qty=qtyTotal, comment="Manual Close")

// --- Reset Levels When No Position ---
if strategy.position_size == 0 and not newTrade
    tradeStop := na
    tradeTarget1 := na
    tradeTarget2 := na
    stopLevel := na
    target1Level := na
    target2Level := na
    initialPositionSize := na
    qtyTotal := na
    breakEvenSet := false

// --- Plotting ---
plot(tradeStop, title="Stop Loss", color=color.red, linewidth=1, style=plot.style_linebr)
plot(tradeTarget1, title="Take Profit 1", color=color.green, linewidth=1, style=plot.style_linebr)
plot(tradeTarget2, title="Take Profit 2", color=color.blue, linewidth=1, style=plot.style_linebr)