※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。
Pythonで株価分析を始めると、最初は1銘柄ずつデータを取得して満足しがちです。
しかし、実際のトレードやポートフォリオ管理では「複数銘柄を同時に監視・比較する」ことが不可欠となります。
たとえば、日経225の主要銘柄を一括で取得してセクター別の強弱を比較したり、保有銘柄のパフォーマンスをまとめてCSVに出力したりといった作業は、手動では到底追いつきません。
この記事では、世界標準のオープンソースライブラリ「yfinance」を使い、複数銘柄の株価データを一括取得・保存・比較するための実践コードをすべてコピペ可能な形で提供します。
📘 外部参考:yfinance 公式GitHub / PyPI
for文によるループ処理から、yfinance組み込みの一括取得関数まで、用途に応じた3パターンの実装を網羅しています。
yfinanceで複数銘柄を扱う2つのアプローチ
yfinanceで複数銘柄のデータを取得する方法は大きく分けて2つあります。
それぞれの特徴を理解した上で、目的に合った方法を選択してください。
アプローチ①:for文で1銘柄ずつループ取得
最も直感的でカスタマイズしやすい方法です。
銘柄ごとに個別のCSVファイルを保存したい場合や、取得の途中でエラーが発生しても他の銘柄の処理を続行したい場合に適しています。
- 銘柄ごとに個別のDataFrameやCSVを管理できます
- エラーハンドリングを銘柄単位で制御できます
- 銘柄数が多い場合はYahoo Financeサーバーへの負荷に注意が必要です
アプローチ②:yf.download()で一括取得
yfinanceには、スペース区切りで複数のティッカーシンボルを渡すだけで一括取得できる yf.download() 関数が用意されています。
- 1回のリクエストで複数銘柄を取得できるため高速です
- 戻り値はマルチカラムのDataFrameとなり、pandasで横断比較しやすい構造です
- ただし、特定の銘柄だけ取得失敗した場合の個別制御がやや難しくなります
| 比較項目 | for文ループ | yf.download()一括取得 |
|---|---|---|
| 実装の簡単さ | やや手間がかかる | 非常にシンプル |
| 取得速度 | 銘柄数に比例して遅くなる | 高速(並列取得) |
| エラー制御 | 銘柄単位で細かく制御可能 | まとめてエラーになりやすい |
| CSV保存の柔軟性 | 銘柄別ファイルに最適 | 1ファイルにまとめるのに最適 |
| おすすめ用途 | 個別分析・個別保存 | 横断比較・ポートフォリオ分析 |
10銘柄以下の比較分析であれば
yf.download()が手軽です。50銘柄以上のスクリーニングや個別保存が必要な場合はfor文ループを選択してください。
【コピペOK】for文で複数銘柄を個別取得・CSV保存するコード
まずは、for文を使って1銘柄ずつ取得し、個別のCSVファイルに保存するパターンを紹介します。
実務で最も使用頻度が高い実装です。
事前準備:ライブラリのインストール
以下のコマンドで必要なライブラリをインストールしてください。
pip install yfinance pandas
【コピペOK】個別CSV保存コード
import yfinance as yf
import pandas as pd
import os
import time
# ==============================
# 設定エリア
# ==============================
# 取得したい銘柄のティッカーシンボル(日本株は末尾に .T を付与)
SYMBOLS = [
"7203.T", # トヨタ自動車
"6758.T", # ソニーグループ
"9984.T", # ソフトバンクグループ
"6861.T", # キーエンス
"8306.T", # 三菱UFJフィナンシャル・グループ
]
PERIOD = "1y" # 取得期間(1年間)
OUTPUT_DIR = "stock_data" # CSV保存先フォルダ
SLEEP_SEC = 1.0 # リクエスト間隔(秒)
# ==============================
# 保存先フォルダの作成
# ==============================
os.makedirs(OUTPUT_DIR, exist_ok=True)
# ==============================
# メイン処理:ループで1銘柄ずつ取得
# ==============================
def fetch_multiple_stocks():
""複数銘柄の株価データを1銘柄ずつ取得し、個別CSVに保存します。""
results = {}
failed = []
for i, symbol in enumerate(SYMBOLS, start=1):
print(f"[{i}/{len(SYMBOLS)}] {symbol} を取得中...")
try:
ticker = yf.Ticker(symbol)
df = ticker.history(period=PERIOD)
if df.empty:
print(f" ⚠ {symbol}: データが空です。スキップします。")
failed.append(symbol)
continue
# CSV保存
filepath = os.path.join(OUTPUT_DIR, f"{symbol.replace('.', '_')}.csv")
df.to_csv(filepath)
print(f" ✔ 保存完了: {filepath}({len(df)}行)")
results[symbol] = df
except Exception as e:
print(f" ✖ {symbol}: エラー発生 → {e}")
failed.append(symbol)
# サーバー負荷軽減のためスリープ
if i < len(SYMBOLS):
time.sleep(SLEEP_SEC)
# --- 結果サマリー ---
print("n========== 取得結果サマリー ==========")
print(f"成功: {len(results)} 銘柄")
print(f"失敗: {len(failed)} 銘柄 → {failed if failed else 'なし'}")
return results
if __name__ == "__main__":
stock_data = fetch_multiple_stocks()
このコードを実行すると、stock_data フォルダの中に銘柄ごとのCSVファイルが生成されます。
time.sleep(1.0) を入れることで、Yahoo Financeサーバーへの過剰アクセスを防止しています。
コードのカスタマイズポイント
用途に応じて以下の変数を変更してください。
SYMBOLS:取得したい銘柄のティッカーシンボルをリストで指定しますPERIOD:"1mo"(1ヶ月)、"6mo"(6ヶ月)、"2y"(2年)、"max"(全期間)などに変更可能ですSLEEP_SEC:50銘柄以上を取得する場合は2.0以上に設定することを推奨します
【コピペOK】yf.download()で一括取得・横断比較するコード
次に、yf.download() を使って複数銘柄を一括取得し、終値の比較チャートを描画するパターンです。
ポートフォリオの成績比較や、セクター間の強弱分析に最適な手法となります。
【コピペOK】一括取得+比較チャート描画コード
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
# ==============================
# 設定エリア
# ==============================
SYMBOLS = ["7203.T", "6758.T", "9984.T", "6861.T", "8306.T"]
SYMBOL_NAMES = {
"7203.T": "トヨタ",
"6758.T": "ソニー",
"9984.T": "SBG",
"6861.T": "キーエンス",
"8306.T": "三菱UFJ",
}
PERIOD = "6mo"
# ==============================
# 一括データ取得
# ==============================
def fetch_bulk_data(symbols: list, period: str) -> pd.DataFrame:
""yf.download()で複数銘柄の株価データを一括取得します。""
tickers_str = " ".join(symbols)
df = yf.download(tickers_str, period=period, group_by="ticker", auto_adjust=True)
if df.empty:
raise ValueError("データを取得できませんでした。ティッカーシンボルを確認してください。")
return df
# ==============================
# 終値を抽出してDataFrameにまとめる
# ==============================
def extract_close_prices(df: pd.DataFrame, symbols: list) -> pd.DataFrame:
""マルチカラムDataFrameから各銘柄のClose(終値)を抽出します。""
close_dict = {}
for symbol in symbols:
try:
close_dict[symbol] = df[symbol]["Close"]
except KeyError:
print(f"⚠ {symbol} の終値データが見つかりません。スキップします。")
return pd.DataFrame(close_dict)
# ==============================
# 基準日比パフォーマンスの計算
# ==============================
def calc_performance(close_df: pd.DataFrame) -> pd.DataFrame:
""各銘柄の終値を基準日=100として正規化します。""
return (close_df / close_df.iloc[0]) * 100
# ==============================
# メイン処理
# ==============================
if __name__ == "__main__":
print("=== 複数銘柄の株価データを一括取得中 ===")
raw_df = fetch_bulk_data(SYMBOLS, PERIOD)
close_df = extract_close_prices(raw_df, SYMBOLS)
print("n--- 終値データ(直近5日) ---")
print(close_df.tail())
# CSV保存(1ファイルにまとめる)
close_df.to_csv("multiple_stocks_close.csv")
print("n✔ 保存完了: multiple_stocks_close.csv")
# パフォーマンス比較
perf_df = calc_performance(close_df)
# --- グラフ描画 ---
plt.figure(figsize=(14, 7))
for symbol in perf_df.columns:
label = SYMBOL_NAMES.get(symbol, symbol)
plt.plot(perf_df.index, perf_df[symbol], label=label)
plt.axhline(100, color="gray", linestyle="--", alpha=0.5)
plt.title("Stock Performance Comparison (Base=100)")
plt.ylabel("Performance (%)")
plt.xlabel("Date")
plt.legend(fontsize=10)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
このコードを実行すると、5銘柄の過去6ヶ月間のパフォーマンスを「基準日=100」として正規化した比較チャートが表示されます。
株価の絶対値が異なる銘柄同士を同じスケールで比較できるため、どの銘柄が最も好調かを一目で判断できます。
yf.download()のgroup_byパラメータについて
yf.download() で複数銘柄を取得する場合、戻り値のDataFrame構造は group_by パラメータで変わります。
group_by="ticker"(推奨):df["7203.T"]["Close"]のように銘柄→項目の順でアクセスできますgroup_by="column"(デフォルト):df["Close"]["7203.T"]のように項目→銘柄の順になります
銘柄単位で処理することが多いため、group_by="ticker" を指定するほうがコードの可読性が高くなります。
【コピペOK】取得データの統計サマリーを自動生成するコード
複数銘柄を取得したら、次に必要になるのが「どの銘柄に注目すべきか」の判断材料です。
ここでは、各銘柄の基本統計量(リターン・ボラティリティ・最高値・最安値)を一覧表として自動生成するコードを紹介します。
【コピペOK】統計サマリー自動生成コード
import yfinance as yf
import pandas as pd
# ==============================
# 設定エリア
# ==============================
SYMBOLS = ["7203.T", "6758.T", "9984.T", "6861.T", "8306.T"]
SYMBOL_NAMES = {
"7203.T": "トヨタ",
"6758.T": "ソニー",
"9984.T": "SBG",
"6861.T": "キーエンス",
"8306.T": "三菱UFJ",
}
PERIOD = "6mo"
# ==============================
# データ取得+統計サマリー生成
# ==============================
def generate_summary(symbols: list, period: str) -> pd.DataFrame:
""複数銘柄の統計サマリーをDataFrameとして返します。""
summary_rows = []
for symbol in symbols:
try:
ticker = yf.Ticker(symbol)
df = ticker.history(period=period)
if df.empty:
continue
close = df["Close"]
daily_return = close.pct_change().dropna()
row = {
"銘柄コード": symbol,
"銘柄名": SYMBOL_NAMES.get(symbol, symbol),
"期間リターン(%)": round((close.iloc[-1] / close.iloc[0] - 1) * 100, 2),
"日次ボラティリティ(%)": round(daily_return.std() * 100, 2),
"最高値": round(close.max(), 1),
"最安値": round(close.min(), 1),
"直近終値": round(close.iloc[-1], 1),
"データ件数": len(df),
}
summary_rows.append(row)
except Exception as e:
print(f"⚠ {symbol}: {e}")
return pd.DataFrame(summary_rows)
# ==============================
# メイン処理
# ==============================
if __name__ == "__main__":
print("=== 統計サマリーを生成中 ===n")
summary_df = generate_summary(SYMBOLS, PERIOD)
print(summary_df.to_string(index=False))
summary_df.to_csv("stock_summary.csv", index=False, encoding="utf-8-sig")
print("n✔ 保存完了: stock_summary.csv")
実行すると、以下のような統計テーブルがコンソールに出力されます。
- 期間リターン:基準日から直近までの騰落率です
- 日次ボラティリティ:日次リターンの標準偏差で、値動きの荒さを示します
- 最高値・最安値:期間中のレンジを把握できます
encoding="utf-8-sig" を指定しているため、出力されたCSVファイルはExcelで開いても日本語が文字化けしません。
よくあるエラーと対処法
複数銘柄の一括取得では、1銘柄だけの場合には発生しないトラブルが起こりがちです。
ここでは頻出エラーとその対処法をまとめます。
一部の銘柄だけデータが取得できません
原因として最も多いのはティッカーシンボルの誤りです。
日本株の場合、以下のルールを守ってください。
- 証券コードの末尾に
.T(東証)を付けます(例:7203.T) - ETFも同様です(例:日経225連動型 →
1321.T) - 米国株は
.T不要です(例:Apple →AAPL)
上場廃止された銘柄や、Yahoo Financeに登録されていないマイナー銘柄もエラーの原因になります。
yf.download()で「KeyError」が発生します
group_by="ticker" を指定した場合、戻り値のカラム構造が2階層(マルチインデックス)になります。
df["Close"] ではなく df["7203.T"]["Close"] のようにアクセスしてください。
銘柄が1つしかない場合はマルチインデックスにならないため、条件分岐が必要になることがあります。
2銘柄以上のリストで使用するのが安全です。
大量銘柄を取得するとエラーや欠損が増えます
50銘柄以上を一度に取得しようとすると、Yahoo Finance側のレートリミット(アクセス制限)に引っかかる場合があります。
対処法は以下の通りです。
- for文ループの場合:
time.sleep(2.0)以上のインターバルを設定してください yf.download()の場合:threads=Falseを指定してシングルスレッドで実行してください- 100銘柄以上の場合:20〜30銘柄ごとにバッチ分割して取得することを推奨します
# シングルスレッドで安定取得する例
df = yf.download("7203.T 6758.T 9984.T", period="1y", threads=False)
Yahoo Financeは無料サービスであり、利用規約で過剰アクセスを禁止しています。大量取得を行う場合は、適切なインターバルを設けてサーバーに負荷をかけないように配慮してください。
CSVをExcelで開くと日本語が文字化けします
to_csv() 実行時に encoding="utf-8-sig" を指定してください。
utf-8-sig はBOM(Byte Order Mark)付きUTF-8であり、Excelがエンコーディングを正しく認識できます。
df.to_csv("output.csv", encoding="utf-8-sig")
まとめ
この記事では、yfinanceを使って複数銘柄の株価データを一括取得・保存・比較する方法を3パターンのコードで解説しました。
要点を整理します。
- for文ループは銘柄ごとの個別保存やエラーハンドリングに優れています
- yf.download()一括取得は高速で、横断比較やポートフォリオ分析に最適です
- 統計サマリー自動生成を組み合わせることで、注目銘柄の絞り込みが効率化されます
- 大量銘柄を取得する際は
time.sleep()やthreads=Falseでサーバー負荷に配慮してください
次のステップとして、今回取得したデータにRSIや移動平均線などのテクニカル指標を追加し、複数銘柄の売買シグナルを自動スクリーニングする仕組みの構築に挑戦してみてください。
📘 外部参考:RSI(Wikipedia 日本語) / RSI(Investopedia)
📘 外部参考:Moving Average(Investopedia)
📘 外部参考:移動平均(Wikipedia 日本語)
データ取得の自動化は、すべてのシステムトレードの土台となる最重要スキルです。
