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

