PythonでGoogle Trendsデータを株式投資に活用:検索トレンドシグナルの実装

Python実装・コード

Google Trendsは特定キーワードの検索量推移を無料で取得できるサービスです。企業名や製品名の検索急増が株価に先行するケースがあります。ということで、この記事ではpytrendsで検索トレンドを取得し、株価との相関分析からシグナル生成まで実装をまとめます。

📘 外部参考Google Trends 公式pytrends(PythonラッパーGitHub)

必要ライブラリのインストール

pip install pytrends yfinance pandas matplotlib scikit-learn

Google Trendsデータの取得

from pytrends.request import TrendReq
import pandas as pd
import yfinance as yf

def get_trends_data(keyword, timeframe='today 5-y', geo='JP'):
    pytrend = TrendReq(hl='ja-JP', tz=540)
    pytrend.build_payload([keyword], timeframe=timeframe, geo=geo)
    df = pytrend.interest_over_time()
    if df.empty:
        return None
    df = df.drop(columns=['isPartial'], errors='ignore')
    df.index = pd.to_datetime(df.index)
    return df

def get_stock_data(ticker, period='5y'):
    stock = yf.download(ticker, period=period, progress=False)
    weekly = stock['Close'].resample('W').last()
    return weekly.to_frame('price')

keyword = 'NVIDIA'
ticker = 'NVDA'
trends = get_trends_data(keyword)
prices = get_stock_data(ticker)
print(len(trends), len(prices))

株価とトレンドのラグ相関分析

検索トレンドが株価変化に何週間先行するかをラグ相関で検証します。

import numpy as np
from scipy import stats

def analyze_correlation(trends_df, price_df, keyword, lag_weeks=4):
    merged = pd.merge(
        trends_df.rename(columns={keyword: 'trend'}),
        price_df, left_index=True, right_index=True, how='inner'
    )
    merged['trend_change'] = merged['trend'].pct_change()
    merged['price_change'] = merged['price'].pct_change()
    merged = merged.dropna()

    correlations = {}
    for lag in range(-lag_weeks, lag_weeks + 1):
        if lag >= 0:
            corr = merged['trend_change'].corr(merged['price_change'].shift(-lag))
        else:
            corr = merged['trend_change'].shift(abs(lag)).corr(merged['price_change'])
        correlations[lag] = corr

    best_lag = max(correlations, key=lambda x: abs(correlations[x]))
    best_corr = correlations[best_lag]
    print(f"最強相関: ラグ {best_lag} 週, 相関係数 {best_corr:.3f}")
    return merged, correlations

トレンド急上昇シグナルの生成

検索トレンドが急上昇(閾値を超えた)タイミングを買いシグナルとして活用する戦略を実装します。

def generate_trend_signals(merged_df, threshold=0.3, holding_weeks=4):
    df = merged_df.copy()
    df['signal'] = (df['trend_change'] > threshold).astype(int)
    df['forward_return'] = df['price_change'].rolling(holding_weeks).sum().shift(-holding_weeks)

    signal_returns = df[df['signal'] == 1]['forward_return'].dropna()
    no_signal_returns = df[df['signal'] == 0]['forward_return'].dropna()

    print(f"シグナル発生回数: {len(signal_returns)}回")
    print(f"シグナルあり 平均リターン: {signal_returns.mean():.3%}")
    print(f"シグナルなし 平均リターン: {no_signal_returns.mean():.3%}")

    t_stat, p_value = stats.ttest_ind(signal_returns, no_signal_returns)
    print(f"p値: {p_value:.4f} {'(有意)' if p_value < 0.05 else '(有意差なし)'}")

    return df

latest_trend_change = 0.35  # 直近のトレンド変化率(例)
current_signal = latest_trend_change > 0.3
print(f"現在のシグナル: {'買いシグナル' if current_signal else '待機'}")

複数銘柄スクリーニングへの応用

def screen_stocks_by_trends(watchlist, timeframe='today 1-y'):
    results = []
    for item in watchlist:
        keyword = item['keyword']
        ticker = item['ticker']
        try:
            trends = get_trends_data(keyword, timeframe=timeframe)
            if trends is None:
                continue
            recent = trends[keyword].tail(4)
            trend_change_4w = (recent.iloc[-1] - recent.iloc[0]) / (recent.iloc[0] + 1)
            results.append({
                'keyword': keyword,
                'ticker': ticker,
                'trend_change_4w': trend_change_4w,
                'signal': 'BUY' if trend_change_4w > 0.25 else ('SELL' if trend_change_4w < -0.25 else 'HOLD')
            })
        except Exception as e:
            print(f"{keyword}: エラー {e}")
    return pd.DataFrame(results).sort_values('trend_change_4w', ascending=False)

watchlist = [
    {'keyword': 'NVIDIA株', 'ticker': 'NVDA'},
    {'keyword': 'トヨタ自動車', 'ticker': '7203.T'},
    {'keyword': 'ソニー株', 'ticker': '6758.T'},
]
screening = screen_stocks_by_trends(watchlist)
print(screening.to_string())

Discord通知との連携

import requests

def send_discord_notification(webhook_url, message):
    payload = {"content": message}
    requests.post(webhook_url, json=payload)

def run_daily_screening(watchlist, discord_webhook_url):
    screening = screen_stocks_by_trends(watchlist, timeframe='today 3-m')
    buy_signals = screening[screening['signal'] == 'BUY']
    if not buy_signals.empty:
        lines = ["Google Trendsシグナル検出
"]
        for _, row in buy_signals.iterrows():
            lines.append(f"BUY: {row['keyword']}({row['ticker']}) 4週変化: +{row['trend_change_4w']:.1%}")
        send_discord_notification(discord_webhook_url, "
".join(lines))
        print("Discord通知送信完了")

まとめ

試してみた感想として、pytrendsは無料で使えて実装も簡単ですが、シグナルとしては弱めです。テクニカル指標と組み合わせることで、注目度の高い銘柄を絞り込む補助として使うのが現実的だと思っています。ラグ相関で何週先行するかを定量的に確認してから使うといいかと思います。

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