ダブルトップ・ダブルボトムとRSIダイバージェンスの組み合わせ — 反転候補を二段構えで確認する設計
チャートの形が反転を示唆しているように見えても、それが勢いの衰えを伴っているかどうかは、価格の形だけでは分かりません。本記事では、天井圏・底値圏に現れるダブルトップ/ダブルボトムと、価格とRSIの高値・安値が食い違うダイバージェンスを重ね、同じスイング点を価格軸とモメンタム軸の両方から読む二段構えの判定を整理します。片方だけでは曖昧さが残る反転候補を、性質の違う二つの尺度で選別するという考え方です。想定読者は、反転狙いのロジックをcBotへ落とし込みたい方、パターン認識の実装で「どこまでを同じ形とみなすか」の線引きに悩んでいる方です。特定の設定値を推奨するものではありません。
ダブルトップ・ダブルボトムの役割
ダブルトップは、ほぼ同じ水準で二度上値を止められた形、ダブルボトムはその上下反転版です。基本的な形状の定義はダブルトップ・ダブルボトムの基礎にまとめているため、ここでは判定材料としての性質に絞って扱います。
この形の持ち味は、参照点が明確なことです。二つの山(または谷)と、その間にできる折り返し水準(ネックライン)という三つの座標だけで構成されており、機械的に定義しやすい構造をしています。同じ水準で二度止められたという事実は、その価格帯に反対方向の注文が溜まっていた可能性を示す痕跡として読めます。関連する考え方はサポートとレジスタンスの基礎でも扱っています。
単独使用時の限界は二つあります。第一に、「ほぼ同水準」の許容幅を決める客観的な基準が形の中に無いことです。どこまでのズレを同じ高さとみなすかで、検出される形の数は大きく変わります。第二に、二つ目の山が押し戻されて初めて形が成立するため、判定は常に事後的になります。さらに、単に上下動を繰り返しているだけのレンジと、意味のある反転の形は、輪郭だけを見ても区別がつきません。
RSIダイバージェンスの役割
RSIは、一定期間の値上がり幅と値下がり幅の比率を0〜100の範囲へ正規化するオシレーターです。読み方の基本はRSIとモメンタムの基礎を参照してください。ダイバージェンス(背離)は、価格が高値を切り上げているのにRSIの高値は切り下がる、といった食い違いを指します。詳細はダイバージェンスの基礎で扱っています。
背離が伝えているのは、価格そのものではなく値動きの内訳の変化です。同じ高さまで上げていても、そこへ至る過程の上げ幅が細くなっていれば、RSIの値は前回より小さく出ます。つまり「同じ場所まで来たが、来かたが違う」という差分を数値化する仕組みだと言えます。
単独使用時の弱点は、発生位置が定まらないことです。強い一方向の相場では背離が何度も現れては解消され、そのたびに反応していると判定が過剰になります。また、背離は勢いの変化を示すだけで、どこまで進んだら区切りとみなすかという基準を持ちません。時間軸を決める役割は、別の材料に委ねる必要があります。
なぜこの組み合わせか
この二つを重ねる根拠は、参照する座標が同じという点にあります。ダブルトップが比べるのは二つのスイング高値であり、RSIダイバージェンスが比べるのも同じ二つのスイング高値です。片方は価格の高さを、もう片方はそのときのモメンタム値を見ている。つまり同一の観測点に、性質の異なる二本の物差しを当てる構造になります。
この重なりが、互いの弱点をちょうど埋めます。ダブルトップ側が抱えていた「同水準の山が意味のある反転なのか単なる踊り場なのか判断できない」という曖昧さに対して、RSIの切り下がりは内訳が変化したという別系統の情報を与えます。逆に、RSIダイバージェンス側が抱えていた「どこで発生したものを拾えばよいか決められない」という問題に対して、形状の成立条件が観測位置を固定します。一般論として、位置を決める役割と質を評価する役割が補完関係にあると考えられます。
ノイズフィルターとしての働きも、この構造から素直に説明できます。片方だけを条件にすると、レンジ内の細かな上下や、トレンド途中の一時的な息切れまで拾ってしまいます。二つの独立した根拠が同じ座標で揃うことを要求すれば、候補は自然に絞られます。
ただしトレードオフは明確です。条件を重ねるほど成立回数は減り、検証に必要な標本を集めるまでに時間がかかります。二つ目の山が確定するまで判定できないという遅延も、形状側の性質としてそのまま残ります。そして両方が揃っても、そこから反転せずに元の方向へ進む展開は普通に起こります。ブレイクアウトとダマシの基礎で触れたように、条件の一致は反転の確約ではありません。判定とは切り離した損切りルールを別立てで用意することが、この設計を成り立たせる前提になります。
パラメータをどう考えるか
調整対象は、スイング点の検出幅、山の高さの許容差、二つの山の間隔、RSIの期間の四つに整理できます。
- スイング検出幅: 候補足の左右に何本の安い足を要求するかで、拾う山の粒度が決まります。広げるほど大きな波だけが残り、狭めるほど細かい凹凸まで山として扱われます
- 高さの許容差: 価格差の絶対値で決めると銘柄や時間足ごとに意味が変わってしまうため、ATRの倍率で表す方式が扱いやすくなります。変動の大きい局面では自動的に許容が広がり、静かな局面では狭まります
- 二つの山の間隔: 最小・最大のバー数を決めておかないと、隣接した二本の足や、遠く離れた無関係な山同士が組になります
- RSI期間と差の下限: 期間を短くすると背離の判定が敏感になり、わずかな差でも成立します。何ポイント以上の切り下がりを有意とみなすかを別パラメータで持つと、感度を独立に調整できます
いずれも「これが正解」と言える値はありません。時間足を変えれば適切な粒度も変わるため、バックテストの基礎で扱った手順に沿って、狙う時間軸ごとに検出頻度と挙動を確かめてから採用する流れになります。
cBot化する際の考慮点
このロジックの実装上の特徴は、判定対象が現在足の値ではなく、過去に確定した離散的な点の列である点です。バンドやオシレーターの比較とは扱い方が変わります。
- スイング点の確定遅延を設計に織り込む: ある足が山かどうかは、右側に一定本数が出揃うまで確定しません。最新足で判定しようとすると、後から結果が変わるリペイントの原因になります。常に
swingRight本ぶん過去を評価対象にします - 点の列を保持する: 検出したスイング点は、足のインデックス・価格・そのときのRSI値をまとめて配列に積みます。毎足で全履歴を走査し直すのではなく、新しく確定した点だけを追加する差分更新にすると計算負荷を抑えられます
- 同じ添字で両方の値を取る: 価格とRSIは必ず同一インデックスから読みます。片方を最新値、片方をスイング時点の値にすると、比較の意味が崩れます
- ウォームアップ不足への防御: RSIもATRも一定本数がないと安定しません。
Bars.Countの下限チェックを検出処理の前段に置きます - 重複トリガーの抑制: 一度成立した組に対して、その後の足で何度も同じ判定が返ります。成立した山のインデックスを記録し、同じ組では一度だけ扱うフラグを持たせます
- ポジション管理との連携: ネックラインと二つ目の山の距離は、形の中で機械的に求められる数少ない値です。損切り幅の基準として使えるかどうかを、設計の早い段階で検討しておくと後工程が楽になります
// OnBar内: 右側 swingRight 本が出揃った足だけをスイング高値の候補として確定させる
int idx = Bars.Count - 1 - swingRight;
bool isSwingHigh = idx > swingLeft;
for (int k = 1; k <= swingLeft && isSwingHigh; k++)
if (Bars.HighPrices[idx - k] >= Bars.HighPrices[idx]) isSwingHigh = false;
for (int k = 1; k <= swingRight && isSwingHigh; k++)
if (Bars.HighPrices[idx + k] >= Bars.HighPrices[idx]) isSwingHigh = false;
if (isSwingHigh)
_highs.Add(new Swing { Index = idx, Price = Bars.HighPrices[idx], Rsi = _rsi.Result[idx] });
// 直近2つの確定スイング高値を、価格軸とモメンタム軸の両方で比較する
if (_highs.Count >= 2)
{
var a = _highs[_highs.Count - 2];
var b = _highs[_highs.Count - 1];
int gap = b.Index - a.Index;
bool similarPeaks = Math.Abs(b.Price - a.Price) <= _atr.Result[b.Index] * tolerance;
bool rsiLower = b.Rsi < a.Rsi - rsiMargin;
bool spacingOk = gap >= minGap && gap <= maxGap;
bool candidate = similarPeaks && rsiLower && spacingOk; // 形と勢いが揃った状態
}
ダブルボトム側は、高値を安値に、切り下がりを切り上がりに置き換えれば同じ構造で書けます。上下で別々のコードを持たず、比較演算子を引数化した共通処理にまとめておくと保守が楽になります。
実装の流れ
処理は「点の検出 → 形状の判定 → モメンタムの照合 → 確認 → 行動」という一方向の流れに整理できます。
- 点の検出: 確定済みの足からスイング高値・安値を抽出し、価格とRSI値を組にして保持する
- 形状の判定: 直近2点の高さの差がATR基準の許容内か、間隔が想定範囲かを確認する
- モメンタムの照合: 同じ2点のRSI値を比べ、背離が成立しているかを判定する
- 確認: ネックラインを終値で抜けたか、あるいは別途決めた確認条件を満たしたかを見る
- 行動決定と記録: 三段すべてが揃った場合のみ候補として扱い、各段の判定値をログに残す
段を分けて記録しておくと、どの条件が候補を落としているかを後から数えられます。形状で落ちているのか、背離で落ちているのか、確認段で落ちているのかが分かれば、感覚ではなく記録に基づいて調整箇所を選べます。スイング点の抽出そのものを目視で確かめたい場合は、Swing Point Auto Markerのような可視化ツールを併用すると、コードの検出結果とチャート上の見え方を突き合わせやすくなります。
どう活用するか
「同じ観測点に、性質の異なる二本の物差しを当てる」という骨格は、この組み合わせに限らず応用が利きます。参照する座標を揃えたまま評価軸だけを差し替えれば、別の指標でも同じ設計パターンが成立します。ご自身で開発される場合は、本記事のスイング検出と条件分離の考え方を、Claude Codeへ渡す仕様メモの出発点として使ってみてください。開発そのものを依頼したい場合は、ai-programming.xyzで要件のご相談を受け付けています。基礎から順に学びたい場合は、スクールでパターン認識と状態管理の実装を段階的に扱っています。
本記事は一般的な情報提供を目的としています。投資助言ではありません。 取引判断はご自身の責任で行ってください。