移動平均乖離率で日本株(製造業)の押し目を自動検出するPython

先月、トヨタとデンソーの株を持ちながら「なんか最近下がってきたな。買い増すべき?」ってずっとモヤモヤしてた。でも子供が泣いてる横で株価チャートを凝視する余裕なんてなくて。。。結局タイミングを逃して高値で買い増してしまったのが悔しかった。それで「押し目を自動で教えてくれる仕組みが欲しい」と思ってPythonで作ってみた次第です。

移動平均乖離率とは?

まず「乖離率」って何かというと、現在の株価が移動平均線からどれくらい離れているか(%)を数値化したものです。式にするとこう:

乖離率 = (現在値 ÷ 移動平均値 − 1) × 100

例えばトヨタ株(7203)の25日移動平均が3,000円で、今日の株価が2,850円だったとしたら乖離率は −5% です。株価が移動平均線より5%下に離れているという意味ですね。

製造業の日本株は景気に連動しやすく、下落しすぎると平均回帰する性質(いわゆる「自律反発」)があります。乖離率がマイナス5〜7%を超えてくると、歴史的に見て「そろそろ反発してもおかしくない」水準になりやすい。これを毎朝自動でスキャンしよう、というのが今回の狙いです。

なぜ僕が製造業株にこだわるのか

前職が製造業関係だったこともあって、トヨタ・デンソー・コマツ・ファナックあたりは決算を読む感覚がある程度ある。業績を理解している銘柄の方がノイズに動じにくくて、精神的に安定してトレードできるんですよね。逆にゲームとかバイオは決算発表のたびにドキドキしすぎて。。。自分のメンタルを守るためにも、なじみのある業種に絞るのが大事だと思ってます。

Pythonコードを書く前の準備

今回使うライブラリは yfinance(株価データ取得)と pandas(データ処理)だけ。両方なければインストールしましょう。

pip install yfinance pandas

スクリーニング対象の銘柄コードをリストで持っておきます。Yahoo Financeでは日本株は末尾に .T をつける形式です。

乖離率スクリーニングのPythonコード

import yfinance as yf
import pandas as pd
from datetime import datetime, timedelta

# 対象銘柄(日本の製造業中心)
TICKERS = [
    "7203.T",  # トヨタ自動車
    "6902.T",  # デンソー
    "6301.T",  # コマツ
    "6954.T",  # ファナック
    "7011.T",  # 三菱重工
    "6752.T",  # パナソニック
    "6501.T",  # 日立製作所
    "7267.T",  # ホンダ
    "6857.T",  # アドバンテスト
    "4063.T",  # 信越化学
]

# パラメータ
MA_PERIOD = 25        # 25日移動平均
THRESHOLD = -5.0      # 乖離率のしきい値(%)

def calc_ma_deviation(ticker: str, period: int = MA_PERIOD) -> dict | None:
    """移動平均乖離率を計算して返す"""
    try:
        # 直近60日分のデータを取得(MAを計算するのに十分な量)
        end = datetime.today()
        start = end - timedelta(days=90)
        df = yf.download(ticker, start=start, end=end, progress=False)

        if df.empty or len(df) < period:
            return None

        # 終値で計算
        close = df["Close"]
        ma = close.rolling(window=period).mean()

        latest_close = float(close.iloc[-1])
        latest_ma = float(ma.iloc[-1])
        deviation = (latest_close / latest_ma - 1) * 100

        return {
            "ticker": ticker,
            "close": round(latest_close, 1),
            "ma25": round(latest_ma, 1),
            "deviation_pct": round(deviation, 2),
        }
    except Exception as e:
        print(f"{ticker}: エラー → {e}")
        return None

def screen_stocks(tickers: list, threshold: float = THRESHOLD) -> pd.DataFrame:
    """乖離率がしきい値以下の銘柄を抽出"""
    results = []
    for t in tickers:
        data = calc_ma_deviation(t)
        if data:
            results.append(data)

    df = pd.DataFrame(results)
    if df.empty:
        return df

    # しきい値フィルタ&乖離率昇順(より大きく下がってる順)
    filtered = df[df["deviation_pct"] <= threshold].sort_values("deviation_pct")
    return filtered

if __name__ == "__main__":
    print(f"=== 移動平均乖離率スクリーニング ({datetime.today().strftime('%Y-%m-%d')}) ===")
    print(f"条件: 25日MA乖離率 ≤ {THRESHOLD}%\n")

    result = screen_stocks(TICKERS)

    if result.empty:
        print("条件に該当する銘柄はありませんでした")
    else:
        print(result.to_string(index=False))
        print(f"\n→ {len(result)}銘柄が条件に該当")

実行結果のイメージ

実際に動かすとこんな感じで出力されます:

=== 移動平均乖離率スクリーニング (2026-06-21) ===
条件: 25日MA乖離率 ≤ -5.0%

  ticker    close    ma25  deviation_pct
  6301.T   2780.0  2980.5          -6.73
  7011.T   1450.0  1520.0          -4.61  ← しきい値に惜しくも届かず除外
  6902.T   4120.0  4380.0          -5.94

→ 2銘柄が条件に該当

これを見て「コマツが-6.7%も下がってる。ちょっと調べよう」という次のアクションに繋げる流れです。スクリーニングはあくまで候補出しで、最終判断は自分でやること。そこは忘れずに。

毎朝自動実行する方法(Windowsタスクスケジューラ)

せっかくコードを書いたので、毎朝8時に自動で動かしましょう。Windowsならタスクスケジューラが使えます。

1. スクリプトを C:\scripts\ma_screen.py に保存
2. 出力をファイルに書き出すように末尾を書き換え:

    # main関数の最後に追記
    output_path = f"C:/scripts/result_{datetime.today().strftime('%Y%m%d')}.txt"
    with open(output_path, "w", encoding="utf-8") as f:
        f.write(result.to_string(index=False) if not result.empty else "該当銘柄なし")
    print(f"結果を保存しました: {output_path}")

3. タスクスケジューラで「毎日8:00にPythonでma_screen.pyを実行」と設定する

これで、朝起きてファイルを開くだけで「今日買い場候補の銘柄」が分かるようになります。僕は次のステップでこれをLINE通知と連携させる予定です(それはまた別記事で)。

まとめ

移動平均乖離率スクリーニングのポイントをまとめると:

・乖離率 = (現在値 ÷ MA − 1) × 100 で計算
・製造業株は平均回帰性が強い → マイナス5〜7%が狙い目の目安
・yfinanceで無料取得 → pandasで計算 → 毎朝自動実行で「見逃し」を防ぐ

個人的には「コードを書いて初めて投資に向き合えてる気がする」という謎の達成感があります(笑)。次は今回のスクリーニング結果をSlackかLINEに自動送信して、より使いやすくしたい。

タイトルとURLをコピーしました