ROCとボリンジャーバンドを組み合わせる — スクイーズ明けの加速を変化率で確かめる設計
バンドの幅がしぼんだあと、価格がバンドの外へ出る。ボリンジャーバンドを使っていると何度も出会う場面ですが、そのまま値幅が広がっていく場合もあれば、1本だけ突き出てすぐにバンドの内側へ戻る場合もあります。ボリンジャーバンドは「いま値動きが散らばっているか、まとまっているか」を示すのが得意な一方、抜けた瞬間の勢いが強まっているのか弱まっているのかまでは教えてくれません。そこで、動きの速さを数値化するROC(Rate of Change/変化率)を重ね、バンド外への抜けに変化率の加速が伴っているか を判定材料に加える構成を考えます。スクイーズを使ったロジックでダマシの扱いに悩んでいる方や、ブレイク判定を一段細かくしたい方に向けた内容です。特定の設定が成果を約束するという話ではなく、判定の順序と役割分担を整理することが目的です。
ボリンジャーバンドの役割
ボリンジャーバンドは、移動平均(ミドルバンド)を中心に、標準偏差(価格のばらつきの大きさ)の一定倍を上下に加えて描く指標です。基本的な読み方はボリンジャーバンドの基礎で解説しています。
この構成でボリンジャーバンドに任せるのは、相場の状態を「収縮中」と「拡張中」に分けること です。上下バンドの間隔をミドルバンドで割った値はバンド幅(BandWidth)と呼ばれ、これが過去と比べて細くなっている状態がスクイーズです。値動きが落ち着いた期間の後には、値幅が広がる局面が来やすいという一般論があり、スクイーズはその「準備段階」を見つける手がかりになります。
単独使用時の限界は、方向と勢いを持たないことです。スクイーズはどちらへ放たれるかを示しませんし、バンド外で引けたという事実も、それが動きの始まりなのか、一時的な行き過ぎなのかを区別しません。バンドの拡張自体も、価格がすでに動いた結果として後から広がるものなので、拡張を確認してから判断すると、動きの初動からは遅れます。
ROCの役割
ROCは、n本前の終値と比べて現在の終値が何パーセント変化したかを示す指標です。ゼロを境にプラス圏・マイナス圏を行き来し、値の大きさが動きの速さを表します。方向フィルターとの組み合わせはROCと移動平均の組み合わせで扱っています。
ここでROCが担うのは、勢いが強まっている最中か、すでに弱まり始めているかを判定すること です。ROCの値そのものに加えて、前の足と比べて値が大きくなっているか(加速)、小さくなっているか(失速)という「傾き」を見るのがこの構成の要点になります。
ROC単独の限界は、状態の文脈を持たないことです。同じ変化率でも、値動きが静かな期間に出たのか、荒れた期間に出たのかで意味が変わりますが、ROCはその区別をしません。また、ゼロ付近を細かく往復するレンジ相場では、符号が頻繁に入れ替わり、そのまま売買判定に使うと判定が落ち着きません。
なぜこの組み合わせか
2つの指標は、「どんな局面か」と「その局面でいま何が起きているか」を分担する関係にあります。ボリンジャーバンドがスクイーズとバンド外引けで 舞台 を用意し、ROCがその瞬間の 勢いの向き を確かめます。
図1のA点とB点を比べると、役割分担が見えやすくなります。A点はスクイーズ中に価格がバンドの外へ突き出た場面ですが、ROCは前の足より弱まっています。値幅は一瞬広がったものの、動きの速さが伴っていない状態です。B点はスクイーズが明ける場面で、バンド外での確定とROCの加速が同じ足で重なっています。ボリンジャーバンドだけを見ていると同じ「上限バンド超え」に見える2つが、ROCを重ねることで別の場面として整理されます。ダマシの一般的な構造はブレイクアウトとダマシの基礎にまとめています。
この関係には、時間差を埋める効果もあります。バンド幅の拡張は動いた後に現れるのに対し、ROCの加速は抜けた足の時点で確認できます。拡張の確認を待たずに、抜けの質を足1本の範囲で評価できる点が、組み合わせる実務上の理由です。
一方で注意点もあります。第一に、ボリンジャーバンドとROCはどちらも終値から作られており、情報源としての独立性は高くありません。新しい情報が加わるというより、同じ値動きを別の角度から読み直していると捉えるのが実態に近い理解です。第二に、「加速」の判定は前の足との比較なので、ノイズの影響を受けます。足1本の差で結論を出さないよう、条件の厳しさは検証で決める必要があります。第三に、この構成は動きの「始まり」の判定材料であり、どこで動きが終わるかは別途設計が必要です。
パラメータをどう考えるか
決めるのは、ボリンジャーバンドの期間と偏差倍率、スクイーズを判定する参照期間と許容幅、ROCの期間の主に5つです。いずれも正解があるものではなく、方向性だけ整理します。
ボリンジャーバンドの期間と偏差倍率 は、一般的な設定から始め、時間足に合わせて調整する考え方が素直です。偏差倍率を大きくするとバンド外引けの頻度が減り、判定は厳しくなります。
スクイーズの判定 は、バンド幅の固定値で決めるより、過去一定期間のバンド幅と比べて相対的に細いかどうかで判定するほうが、銘柄や時間足を変えたときの挙動が安定します。参照期間を長くすると「本格的な収縮」だけを拾い、短くすると小さな収縮にも反応します。
ROCの期間 は、短くすると抜けた足への反応が速くなる代わりに符号の入れ替わりが増え、長くすると落ち着く代わりに初動の加速を捉えにくくなります。短期の時間足ほど短め、長期の時間足ほど長めという程度の方向性に留めておきます。
パラメータが複数あるため、同時に動かすとどれが効いたのか分からなくなります。片方の指標を固定してもう片方を振る進め方で、バックテストにより自分の銘柄・時間足での挙動を確かめてください。
cBot化する際の考慮点
この構成は「状態→事象→勢い」の3段で判定するため、各段で参照する足を揃えることが実装の中心になります。
計算順序: スクイーズ判定 → バンド外引けの確認 → ROCの符号と加速の確認、の順に固定します。スクイーズ判定はバンド外へ出る直前の足を対象にします。抜けた足そのものはバンド幅が広がり始めているため、そこで収縮を判定すると条件が成立しにくくなります。
確定足で揃える: 形成中のバーでは、バンドもROCも値が動き続けます。バンド外引けはLast(1)の確定足、比較対象のROCはLast(2)と、参照位置を明示的に決めておきます。
履歴不足: 必要本数は、ボリンジャーバンドの期間にスクイーズ参照期間を足した本数と、ROCの期間の大きいほうが基準です。足りなければ判定に進みません。
ギャップとイベント: 週明けや指標発表の直後は、ROCが一気に跳ねる一方でバンドは遅れて広がります。抜けと加速が形式上そろっても、実態は急変動の直後ということがあるため、時間帯フィルターとの併用を検討する価値があります。
// 例: スクイーズ → バンド外引け → ROCの加速、の順に確認する(すべて確定足ベース)
var bb = Indicators.BollingerBands(Bars.ClosePrices, BbPeriod, BbDeviation, MovingAverageType.Simple);
var roc = Indicators.PriceROC(Bars.ClosePrices, RocPeriod);
int need = Math.Max(BbPeriod + SqueezeLookback, RocPeriod) + 5;
if (Bars.Count < need) return; // 履歴不足のガード
// ① 抜ける直前の足がスクイーズ状態だったか(過去のバンド幅と比べて相対評価)
double minWidth = double.MaxValue;
for (int i = 2; i < 2 + SqueezeLookback; i++)
minWidth = Math.Min(minWidth, BandWidth(bb, i));
bool wasSqueezed = BandWidth(bb, 2) <= minWidth * SqueezeTolerance; // 許容幅は検証対象
// ② 確定足がバンドの外で引けたか
double close = Bars.ClosePrices.Last(1);
bool upperBreak = close > bb.Top.Last(1);
bool lowerBreak = close < bb.Bottom.Last(1);
// ③ ROCが抜けた方向と同じ符号で、前の足より強まっているか
double rocNow = roc.Result.Last(1);
double rocPrev = roc.Result.Last(2);
bool upAccel = rocNow > 0 && rocNow > rocPrev;
bool downAccel = rocNow < 0 && rocNow < rocPrev;
bool upsideCandidate = wasSqueezed && upperBreak && upAccel;
bool downsideCandidate = wasSqueezed && lowerBreak && downAccel;
// バンド幅 = (上限 - 下限) / ミドル(クラスのメンバーとして定義)
private double BandWidth(BollingerBands bb, int index)
{
double mid = bb.Main.Last(index);
return mid == 0 ? double.MaxValue : (bb.Top.Last(index) - bb.Bottom.Last(index)) / mid;
}
計算負荷はどちらの指標も軽く、OnBarでの運用なら問題になりません。スクイーズ判定のループが気になる場合は、バンド幅を毎足リストに積んでおき、参照期間ぶんだけ保持する形にすると見通しがよくなります。判定結果は売買そのものではなく「候補」として返す部品にしておくと、方向フィルターやリスク管理を後から差し替えやすくなります。
実装の流れ
処理を上流から並べると、次のようになります。
- 入力: 確定足を受け取り、ボリンジャーバンドとROCを更新します。
- 状態判定: 抜ける直前の足のバンド幅を過去と比べ、スクイーズ状態だったかを確認します。
- 事象判定: 確定足がバンドの外で引けたかを確認します。
- 勢い判定: ROCが抜けた方向と同じ符号で、前の足より強まっているかを確認します。ここで条件がそろわなければ見送りへ分岐します。
- リスク設計: 損切り幅とロットを決めて発注・管理へ引き渡します(ロットサイズの基礎)。
- 管理: 保有中はミドルバンドへの回帰やROCの失速を、手仕舞いを検討する判断材料として監視します。
ポイントは、ROCを「抜けの後」に置くことです。ROCの加速だけを先に拾うと、スクイーズと無関係な場面でも条件が成立し、この構成の意味が薄れます。
どう活用するか
「状態を決める指標」と「その瞬間の勢いを測る指標」を分ける考え方は、この2つに限らず応用が利きます。自作派の方は、Claude Codeを使ったcBot開発の題材として、まずスクイーズ判定だけを実装し、そこにROCの加速条件を足したときに候補がどう絞られるかをログで比べてみてください。収縮の検出をインジケーター側で確認したい場合は、Range Compression Detectorの設定ガイドも参考になります。
委託派の方は、ai-programming.xyzへの開発相談時に「スクイーズの判定基準」と「加速をどう定義するか」を先に共有しておくと、仕様が固まりやすくなります。教育派の方は、ROCの条件あり・なしで同じ期間を検証し、候補の数と中身がどう変わるかを比べる課題として扱うと、判定の順序が結果に与える影響を手を動かしながら確認できます。
本記事は一般的な情報提供を目的としています。投資助言ではありません。 取引判断はご自身の責任で行ってください。