S&P500構成銘柄を全自動で分析するPythonコード

Python実装・コード

S&P500は米国を代表する500銘柄で構成される株価指数です。この500銘柄を自動取得し、一括分析・スクリーニングするPythonコードを紹介します。

S&P500構成銘柄の自動取得

import pandas as pd
import yfinance as yf
import numpy as np
from bs4 import BeautifulSoup
import requests

def get_sp500_tickers():
    """WikipediaからS&P500構成銘柄を取得"""
    url = "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies"
    res = requests.get(url, headers={"User-Agent": "Mozilla/5.0"})
    soup = BeautifulSoup(res.text, "html.parser")
    table = soup.find("table", {"id": "constituents"})
    df = pd.read_html(str(table))[0]
    return df[["Symbol", "Security", "GICS Sector", "GICS Sub-Industry"]]

sp500_df = get_sp500_tickers()
print(f"S&P500銘柄数: {len(sp500_df)}")
print(sp500_df.head())

# セクター別集計
sector_counts = sp500_df["GICS Sector"].value_counts()
print("\nセクター別銘柄数:")
print(sector_counts)

セクター別パフォーマンス分析

def analyze_sector_performance(sp500_df, period="1y"):
    """セクター別ETFのパフォーマンスを比較"""
    sector_etfs = {
        "Technology": "XLK",
        "Health Care": "XLV",
        "Financials": "XLF",
        "Consumer Discretionary": "XLY",
        "Industrials": "XLI",
        "Communication Services": "XLC",
        "Consumer Staples": "XLP",
        "Energy": "XLE",
        "Utilities": "XLU",
        "Real Estate": "XLRE",
        "Materials": "XLB",
    }
    
    etf_tickers = list(sector_etfs.values()) + ["SPY"]
    data = yf.download(etf_tickers, period=period, progress=False)["Close"]
    returns = (data.iloc[-1] / data.iloc[0] - 1) * 100
    
    results = []
    for sector, etf in sector_etfs.items():
        if etf in returns:
            results.append({"Sector": sector, "ETF": etf, "Return(%)": round(returns[etf], 1)})
    
    df = pd.DataFrame(results).sort_values("Return(%)", ascending=False)
    spy_return = round(returns.get("SPY", 0), 1)
    print(f"SPY(S&P500): {spy_return}%")
    print(df.to_string(index=False))
    return df

analyze_sector_performance(sp500_df)

全銘柄の一括スクリーニング

def batch_screen_sp500(tickers, batch_size=50):
    """S&P500銘柄を一括スクリーニング(バッチ処理)"""
    all_results = []
    
    # バッチに分けて処理(yfinanceの負荷軽減)
    for i in range(0, len(tickers), batch_size):
        batch = tickers[i:i+batch_size]
        print(f"処理中: {i}/{len(tickers)} ({i/len(tickers)*100:.0f}%)")
        
        try:
            data = yf.download(batch, period="1y", progress=False)["Close"]
            returns_1y = (data.iloc[-1] / data.iloc[0] - 1) * 100
            returns_1m = (data.iloc[-1] / data.iloc[-22] - 1) * 100
            vol = data.pct_change().std() * np.sqrt(252) * 100
            
            for t in batch:
                if t in data.columns:
                    all_results.append({
                        "Ticker": t,
                        "1M騰落(%)": round(returns_1m.get(t, 0), 1),
                        "1Y騰落(%)": round(returns_1y.get(t, 0), 1),
                        "ボラ(%)": round(vol.get(t, 0), 1),
                    })
        except Exception as e:
            print(f"エラー: {e}")
    
    return pd.DataFrame(all_results).set_index("Ticker")

# 上位50銘柄でテスト
test_tickers = sp500_df["Symbol"].head(50).tolist()
results = batch_screen_sp500(test_tickers)

# 直近1ヶ月パフォーマンス上位10銘柄
print("\n1ヶ月パフォーマンス Top10:")
print(results.nlargest(10, "1M騰落(%)"))

S&P500ヒートマップ生成

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors

def create_sp500_heatmap(performance_df, sp500_info_df, top_n=100):
    """S&P500銘柄のパフォーマンスヒートマップを生成"""
    merged = sp500_info_df.merge(
        performance_df.reset_index(), 
        left_on="Symbol", right_on="Ticker", how="inner"
    )
    top = merged.nlargest(top_n, "1M騰落(%)")
    
    fig, ax = plt.subplots(figsize=(20, 12))
    
    for idx, (_, row) in enumerate(top.iterrows()):
        x = idx % 20
        y = idx // 20
        color = "green" if row["1M騰落(%)"] > 0 else "red"
        alpha = min(abs(row["1M騰落(%)"]) / 20 + 0.3, 1.0)
        rect = plt.Rectangle([x, y], 0.95, 0.95, color=color, alpha=alpha)
        ax.add_patch(rect)
        ax.text(x + 0.475, y + 0.6, row["Symbol"], ha="center", va="center",
                fontsize=8, fontweight="bold", color="white")
        ax.text(x + 0.475, y + 0.25, f"{row['1M騰落(%)']:.1f}%", ha="center",
                va="center", fontsize=7, color="white")
    
    ax.set_xlim(0, 20)
    ax.set_ylim(0, 5)
    ax.axis("off")
    ax.set_title(f"S&P500 パフォーマンスヒートマップ(上位{top_n}銘柄)", fontsize=16)
    plt.tight_layout()
    plt.show()

# create_sp500_heatmap(results, sp500_df)

まとめ

PythonでS&P500全銘柄を自動取得・分析することで、手動では不可能なスケールのスクリーニングが実現できます。セクター分析とモメンタムスクリーニングを組み合わせて、有望銘柄を効率的に発掘しましょう。

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