グランビルの法則:移動平均と価格の関係で売買の場面を分ける
- 200日線で8法則を定義すると、19年で買い法則は合計49回、1法則あたり9〜19回しか出なかった
- 60営業日後で見ると、買い4法則の平均+2.50%は全日平均+2.24%とほぼ同じ。はっきり違ったのは売り5(平均−0.58%)くらい
- 買い4法則のどれかで買って60日持つと、年率2.0%・最大下落率−52.4%・取引18回。19年で18回と、取引がかなり少ない
グランビルの法則は「線の向き」と「価格の位置」の組み合わせ
グランビルの法則は、移動平均線(#001)と価格の関係から、買いの場面を4つ、売りの場面を4つに分けたものです。米国の分析家ジョセフ・グランビルが考案したとされ、もとは200日線を使う前提でした。今回も200日線で調べます。
見るのは2つだけです。1つは移動平均線が上向きか下向きか。もう1つは価格が線の上にあるか下にあるか、どれだけ離れているかです。買いと売りは、ちょうど上下を反転させた関係になっています。
8つを「機械的なルール」に直す
本に書かれた法則は「横ばいに近づいたら」「大きく離れたら」のようにあいまいです。検証するには、誰がやっても同じ日になる定義が必要です。今回は次のように決めました。線の向きは、200日線の今日の値と20営業日前の値の差で判定します。乖離率は「終値 ÷ 200日線 − 1」です(#014は25日線で同じものを扱いました)。
乖離率 = 終値 ÷ 200日線 − 1
| 法則 | 今回の定義(すべて終値で判定) | 回数 |
|---|---|---|
| 買い1 | 終値が200日線を上抜け。線は横ばい以上で、直前60日のどこかで下向きだった | 10 |
| 買い2 | 終値が200日線を上抜け。線は直前60日ずっと上向きで、割り込みは20日以内 | 19 |
| 買い3 | 線が上向き。乖離率が0〜2%まで近づき、割らずに2%を上抜け(直前60日に5%以上離れていた) | 11 |
| 買い4 | 線が下向き。乖離率が−15%を下抜け | 9 |
| 売り5 | 買い1の上下を反転(上向きだった線が横ばい以下になり、終値が下抜け) | 7 |
| 売り6 | 買い2の上下を反転(下向きの線を一時上抜け、再び下抜け) | 7 |
| 売り7 | 買い3の上下を反転(乖離率が−2〜0%まで近づき、−2%を下抜け) | 14 |
| 売り8 | 線が上向き。乖離率が+15%を上抜け | 24 |
同じ法則が20営業日以内に続けて出た場合は、最初の1回だけを数えています。200日線を終値が上抜けた日は19年で81回ありました。間隔の制限なしで数えると、そのうち買い1の形が14回、買い2の形が33回で、残りの34回は「線が下向きのままの上抜け」でした。これはどちらの法則にも当たりません。
「グランビルの法則は8つの売買サイン」と思われがちですが、200日線のような長い線では、1つの法則が出るのは平均して年に1回前後です。今回の定義では、19年で最も多い売り8でも24回、最も少ない売り5・売り6は7回でした。短い移動平均線を使えば回数は増えますが、それはもう元の法則とは別物です。
実際の日経平均で見てみる
直近500営業日では、2024年9〜12月に買い2が3回(9月20日・10月28日・12月3日)、10月4日に買い3が出ました。上向きの200日線のまわりで、価格が行ったり来たりしていた時期です。
2025年は2月3日(38,520円)と5月15日(37,755円)に売り5が出ています。その間の4月7日(31,136円)は、200日線38,423円に対して乖離率−18.96%で、買い4に当たりました。この日の20営業日後は+18.60%、60営業日後は+27.78%です。6月16日(38,311円)には買い1も出ています。
その後は上昇が続き、売り8(+15%を上抜け)が2025年9月12日(44,768円)、2026年3月10日(54,248円)、7月21日(66,232円)と3回出ました。ただし、最初の2回は60営業日後にそれぞれ+13.56%・+20.59%とさらに上がっています。乖離率は2026年6月22日に34.68%まで広がり、10月2日は終値68,309円・200日線60,309円で13.26%です。
検証①:法則ごとに、その後の相場を数える
ルール:各法則が出た日の終値から、20営業日後・60営業日後までのリターンを集計しました。比べる相手は「すべての日」の平均(20営業日後+0.75%、60営業日後+2.24%)です。条件は共通の検証ルールのとおりです。
| 法則 | 回数 | 20日後 平均 | 上昇率 | 60日後 平均 | 上昇率 | 前半/後半 |
|---|---|---|---|---|---|---|
| 買い1 上向き転換+上抜け | 10 | −1.01% | 60% | 1.63% | 70% | 6/4 |
| 買い2 押し目の割り込み→回復 | 19 | 2.23% | 63% | 2.64% | 68% | 6/13 |
| 買い3 割らずに反発 | 11 | 0.19% | 36% | 2.19% | 64% | 2/9 |
| 買い4 下に大きく離れる | 9 | −0.04% | 56% | 3.54% | 78% | 7/2 |
| 売り5 下向き転換+下抜け | 7 | −1.91% | 29% | −0.58% | 29% | 3/4 |
| 売り6 戻りの上抜け→失敗 | 7 | −2.13% | 29% | 1.13% | 43% | 2/5 |
| 売り7 届かずに反落 | 14 | 1.08% | 71% | 2.84% | 57% | 8/6 |
| 売り8 上に大きく離れる | 24 | −0.21% | 42% | 2.32% | 65% | 12/12 |
| 買い1〜4のいずれか | 49 | 0.70% | 55% | 2.50% | 69% | — |
| 売り5〜8のいずれか | 52 | −0.35% | 46% | 1.90% | 55% | — |
| すべての日 | 4,760 | 0.75% | 58.0% | 2.24% | 58.4% | — |
20営業日後で法則どおりに動いたのは、買い2(+2.23%)と、売り5(−1.91%)・売り6(−2.13%)でした。どれも「価格が200日線をまたいだ日」です。一方、買い1は20営業日後に平均−1.01%と、逆に下がっています。2007年10月11日(20日後−9.66%)や2011年5月11日(−4.21%)のように、上抜けた直後に失速した例が響いています。売り7は、反落したはずの後に71%の確率で上がりました。
60営業日後になると、差はほとんど消えます。買い4法則の平均はどれも+1.63%〜+3.54%で、全日平均+2.24%の前後です。買い4の+3.54%は8法則で最も高いものの、9回のうち7回が前半(2008年と2016年)に集中しています。2025年4月7日(+27.78%)と2020年3月12日(+21.09%)の2回を除くと、残り7回の平均は−2.43%とマイナスです。2008年9月18日には、−15%の下抜けで買った後の60日間で−25.04%と、リーマン・ショックの下げをそのまま受けました。
7〜24回では「差がある」とは言えない
たとえば売り5の7回で平均−0.58%。7回のうち1回でも結果が違えば、平均は大きく動きます。買い2の19回でも、60日後の結果は最大+16.71%から最小−9.52%まで散らばっています。表の差のほとんどは、偶然の範囲と区別できません。確かに言えるのは「どの法則も、全日平均と比べて大きく有利・不利ではなかった」ことまでです。
検証②:買い4法則で売買する
ルール:買い1〜4のいずれかが出た日の終値で買い、60営業日後の終値で売る。保有中に別の買い法則が出たら、その日から60営業日に延長します(主ルール)。比較として、売り5〜8のいずれかが出るまで持つ版、20営業日で売る版、買い4を除いた版、単純に「終値が200日線の上の間だけ保有」も試しました。条件は共通の検証ルールのとおりです。
| 戦略 | 最終資産 | 年率 | 最大下落率 | 取引 | 勝率 | PF | 保有率 |
|---|---|---|---|---|---|---|---|
| 買い持ち | 3.93倍 | 7.3% | −61.4% | — | — | — | 100% |
| 買い1〜4→60日保有 | 1.48倍 | 2.0% | −52.4% | 18 | 61% | 1.79 | 40% |
| 買い1〜4→売り5〜8で売り | 2.76倍 | 5.4% | −50.3% | 17 | 71% | 3.15 | 44% |
| 買い1〜4→20日保有 | 1.07倍 | 0.3% | −42.6% | 39 | 51% | 1.17 | 19% |
| 買い1〜3→60日保有(買い4なし) | 1.47倍 | 2.0% | −32.5% | 15 | 67% | 2.09 | 32% |
| 200日線の上の間保有 | 2.17倍 | 4.1% | −34.5% | 81 | 15% | 1.35 | 62% |
主ルールは年率2.0%、最大下落率−52.4%でした。買い持ちの年率7.3%に遠く及ばず、下落率も買い持ちの−61.4%と大差ありません。保有期間が延長でつながるため、19年で取引はわずか18回、1回の平均保有は106.4日です。
最大の下落は、2008年10月27日(7,163円)を底とする時期です。2007年10月11日の買い1で買った後、2008年1月・2月・4月に買い4が続けて出て保有が延び、7月7日まで持って−23.68%。さらに9月18日の買い4で買い直し、12月17日に売って−25.24%でした。下がり続ける相場では、買い4が「まだ下がる途中」で何度も出てしまいます。買い4を除くと最大下落率は−32.5%まで小さくなりますが、取引は15回に減ります。
反対に、最大の勝ちも買い4でした。2025年4月7日(31,136円)に買い、9月10日(43,838円)に売って+40.59%。2020年3月12日の買い4も+20.89%です。急落の年の結果が、主ルールの成績を大きく左右しています。
売り5〜8で降りる版は年率5.4%、PF3.15と見栄えのする数字です。ただ、取引17回で、期間を160日にすると年率1.15%、240日で2.59%まで落ちます。売り法則も7〜24回しか出ないため、出口の日付が数回ずれるだけで成績が大きく変わります。最初から60日保有を主ルールにしたのは、検証①の60営業日後の集計とそろえ、出口の選び方で数字を作らないためです。
主ルールは前半(〜2016年9月)が年率−4.60%、後半が8.79%と、時期による差も極端です。後半は買い持ちも年率15.26%(前半は−0.57%)の上昇相場で、何を買っても上がりやすい時期でした。
期間を160日・240日に変えると
200日を±20%変えると、160日線では年率3.91%(取引22回、最大下落率−37.2%)、240日線では1.87%(取引18回、−49.6%)でした。どちらもプラスですが、法則ごとの回数は大きく入れ替わります。たとえば買い1は160日線で16回、200日線で10回、240日線で9回です。法則の境目が、線の期間に敏感だということです。
読み解き
- 8法則の差は、サンプルの少なさに埋もれている。200日線では1法則あたり7〜24回しか出ない。60営業日後の平均はほぼすべて全日平均+2.24%の前後で、例外の売り5(−0.58%)も7回だけ。
- 買い4は「急落の年」に結果を委ねる法則。2020年・2025年は大きく勝ち、2008年は−25.04%で大きく負けた。主ルールの最大下落率−52.4%も、2008年の買い4の連続が原因。
- 8つに分けるより、200日線の上か下かだけの方が安定していた。「200日線の上の間保有」は年率4.1%・最大下落率−34.5%・取引81回(#024で比較に使ったものと同じ)。法則を細かく分けるほど回数が減り、検証できなくなる。
成績のまとめ(買い1〜4で買い、60日保有)
取引は19年で18回と、かなり少ない。年率2.0%は買い持ちの3割以下で、最大下落率−52.4%も買い持ちに近い。前半−4.6%・後半8.8%と時期による差も大きく、成績の多くは2020年・2025年の買い4の2回に支えられている。8法則を個別に比べられるだけのデータは、200日線の日足では集まらなかった。
自分で試す(TradingView)
//@version=6
indicator("グランビルの8法則(200日線)", overlay = true)
len = input.int(200, "移動平均の期間")
near = input.float(2.0, "買い3・売り7の近さ(%)") / 100
far = input.float(15.0, "買い4・売り8の乖離(%)") / 100
ma = ta.sma(close, len)
dev = close / ma - 1
slope = ma - ma[20] // 20営業日前との差で向きを判定
lo60 = ta.lowest(slope, 60)
hi60 = ta.highest(slope, 60)
xu = ta.crossover(close, ma)
xd = ta.crossunder(close, ma)
above21 = math.sum(close > ma ? 1 : 0, 21)[1]
below21 = math.sum(close < ma ? 1 : 0, 21)[1]
devLo10 = ta.lowest(dev, 10)
devHi10 = ta.highest(dev, 10)
devHi60 = ta.highest(dev, 60)
devLo60 = ta.lowest(dev, 60)
devDn = ta.crossunder(dev, -far)
devUp = ta.crossover(dev, far)
// 同じ法則が20営業日以内に続いたら最初の1回だけ
cool(bool cond) =>
var int last = -1000
bool ok = cond and bar_index - last > 20
if ok
last := bar_index
ok
b1 = cool(xu and slope >= 0 and lo60 < 0)
b2 = cool(xu and lo60 > 0 and above21 >= 1)
b3 = cool(slope > 0 and dev[1] > 0 and dev[1] <= near and dev > near and devLo10 > 0 and devHi60 >= near + 0.03)
b4 = cool(slope < 0 and devDn)
s5 = cool(xd and slope <= 0 and hi60 > 0)
s6 = cool(xd and hi60 < 0 and below21 >= 1)
s7 = cool(slope < 0 and dev[1] < 0 and dev[1] >= -near and dev < -near and devHi10 < 0 and devLo60 <= -near - 0.03)
s8 = cool(slope > 0 and devUp)
plot(ma, "200日線", color = color.blue, linewidth = 2)
plotshape(b1, "買い1", shape.labelup, location.belowbar, color.green, text = "1", textcolor = color.white)
plotshape(b2, "買い2", shape.labelup, location.belowbar, color.green, text = "2", textcolor = color.white)
plotshape(b3, "買い3", shape.labelup, location.belowbar, color.green, text = "3", textcolor = color.white)
plotshape(b4, "買い4", shape.labelup, location.belowbar, color.green, text = "4", textcolor = color.white)
plotshape(s5, "売り5", shape.labeldown, location.abovebar, color.red, text = "5", textcolor = color.white)
plotshape(s6, "売り6", shape.labeldown, location.abovebar, color.red, text = "6", textcolor = color.white)
plotshape(s7, "売り7", shape.labeldown, location.abovebar, color.red, text = "7", textcolor = color.white)
plotshape(s8, "売り8", shape.labeldown, location.abovebar, color.red, text = "8", textcolor = color.white)

