※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。
yfinanceで株価データを取得する環境はすでに構築できている段階でしょう。しかし、ある日突然データが取れなくなった経験はないでしょうか。
yfinanceはYahoo Finance の非公式APIに依存しており、仕様変更やアクセス制限で突然動かなくなるリスクがあります。データ取得手段を1つに依存することは、分析パイプライン全体の停止を意味します。
pandas-datareaderは、Stooq・FRED・Tiingo など複数のデータソース(Data Source)に対応したライブラリです。yfinanceが使えない状況でもデータ取得を継続でき、バックアップ手段として非常に有効です。
しかし、pandas-datareaderは公式ドキュメントが分散しており、どのデータソースが現在も動作するのか判断しにくい状態です。過去に動いていたGoogle FinanceやMorningstarのリーダーはすでに廃止されています。
本記事では、2025年時点で実際に動作するデータソースに絞り、pandas-datareaderのインストールから実践的なデータ取得コード、yfinanceとの自動フォールバック(Fallback:代替切り替え)機構の構築までを解説します。
コードはすべてコピペで動く構成です。自分の分析パイプラインにそのまま組み込み、データ取得の冗長性を確保してください。
pandas-datareaderの概要と対応データソース
pandas-datareaderとは何か
pandas-datareaderは、外部のWebAPIやデータベースから金融・経済データを取得し、pandasのDataFrame形式で返すライブラリです。pandas本体から分離された経緯を持ち、独立パッケージとして開発が続いています。
最大の特徴は、データソースごとに専用のリーダー(Reader)クラスが用意されている点です。リーダーを切り替えるだけで、同じインターフェースで異なるソースからデータを取得できます。
現在も動作するデータソース一覧
すべてのリーダーが動作するわけではありません。以下の表は動作確認済みのデータソースです。
| データソース | 取得対象 | APIキー | 主な用途 |
|---|---|---|---|
| Stooq | 株価(日本株・米国株) | 不要 | yfinanceの代替として最有力 |
| FRED | 米国経済指標(GDP・CPI・金利等) | 不要 | マクロ分析・ファンダメンタルズ |
| Tiingo | 米国株価・暗号資産 | 必要(無料枠あり) | 高品質な米国株データ |
| Alpha Vantage | 株価・為替・暗号資産 | 必要(無料枠あり) | グローバル対応 |
Google Finance・Morningstar・Yahoo Finance(datareader経由)のリーダーは廃止済みです。これらを使おうとしてもImmediateDeprecationErrorが発生するので注意してください。
yfinanceとの使い分け方針
yfinanceをメイン、pandas-datareader(Stooq等)をバックアップとする二重構成を推奨します。日本株のデータ取得にはStooqリーダーが最も手軽です。
米国の経済指標(金利・インフレ率等)を取得する場合はFREDリーダー一択です。yfinanceではカバーできない領域なので、補完関係として併用してください。
【コピペOK】pandas-datareaderによるデータ取得コード
まず必要なライブラリをインストールしてください。
pip install pandas-datareader pandas numpy matplotlib yfinance
以下がメインコードです。
import datetime
import numpy as np
import pandas as pd
import pandas_datareader.data as web
import yfinance as yf
import matplotlib.pyplot as plt
from typing import Optional
# ==============================
# 設定エリア
# ==============================
TICKER_JP: str = "7203.JP" # Stooq用 日本株コード(トヨタ自動車)
TICKER_US: str = "AAPL" # Stooq/Tiingo用 米国株コード
TICKER_YF: str = "7203.T" # yfinance用 日本株コード
FRED_SERIES: str = "DFF" # FRED系列ID(FF金利)
START_DATE: str = "2023-01-01" # データ取得開始日
END_DATE: str = "2024-12-31" # データ取得終了日
TIINGO_API_KEY: str = ' # Tiingo APIキー(使用時に設定)
# ==============================
# Stooqからの取得(APIキー不要)
# ==============================
def fetch_from_stooq(ticker: str, start: str, end: str) -> Optional[pd.DataFrame]:
'Stooqから株価データを取得する'
try:
df: pd.DataFrame = web.DataReader(
ticker,
"stooq",
start=start,
end=end,
)
df = df.sort_index()
df.columns = [c.lower() for c in df.columns]
print(f"[Stooq] {ticker} : {len(df)}行 取得成功")
return df
except Exception as e:
print(f"[Stooq] {ticker} : 取得失敗 - {e}")
return None
# ==============================
# FREDからの取得(APIキー不要)
# ==============================
def fetch_from_fred(series_id: str, start: str, end: str) -> Optional[pd.DataFrame]:
'FREDから経済指標データを取得する'
try:
df: pd.DataFrame = web.DataReader(
series_id,
"fred",
start=start,
end=end,
)
print(f"[FRED] {series_id} : {len(df)}行 取得成功")
return df
except Exception as e:
print(f"[FRED] {series_id} : 取得失敗 - {e}")
return None
# ==============================
# Tiingoからの取得(APIキー必要)
# ==============================
def fetch_from_tiingo(
ticker: str, start: str, end: str, api_key: str,
) -> Optional[pd.DataFrame]:
'Tiingoから米国株データを取得する'
if not api_key:
print("[Tiingo] APIキーが未設定です。スキップします。")
return None
try:
df: pd.DataFrame = web.DataReader(
ticker,
"tiingo",
start=start,
end=end,
api_key=api_key,
)
df.index = df.index.droplevel("symbol") if isinstance(df.index, pd.MultiIndex) else df.index
df.columns = [c.lower() for c in df.columns]
print(f"[Tiingo] {ticker} : {len(df)}行 取得成功")
return df
except Exception as e:
print(f"[Tiingo] {ticker} : 取得失敗 - {e}")
return None
# ==============================
# yfinanceからの取得(フォールバック用)
# ==============================
def fetch_from_yfinance(ticker: str, start: str, end: str) -> Optional[pd.DataFrame]:
'yfinanceから株価データを取得する'
try:
df: pd.DataFrame = yf.download(
ticker, start=start, end=end, auto_adjust=True,
)
df = df.droplevel("Ticker", axis=1) if isinstance(df.columns, pd.MultiIndex) else df
df.columns = [c.lower() for c in df.columns]
if len(df) == 0:
raise ValueError("データが0行です")
print(f"[yfinance] {ticker} : {len(df)}行 取得成功")
return df
except Exception as e:
print(f"[yfinance] {ticker} : 取得失敗 - {e}")
return None
# ==============================
# フォールバック付き統合取得関数
# ==============================
def fetch_with_fallback(
ticker_stooq: str,
ticker_yf: str,
start: str,
end: str,
) -> Optional[pd.DataFrame]:
'Stooq → yfinance の順にフォールバックしてデータを取得する'
print("n--- フォールバック取得開始 ---")
# 第1候補: Stooq
df: Optional[pd.DataFrame] = fetch_from_stooq(ticker_stooq, start, end)
if df is not None and len(df) > 0:
print("→ Stooq をデータソースとして採用")
return df
# 第2候補: yfinance
df = fetch_from_yfinance(ticker_yf, start, end)
if df is not None and len(df) > 0:
print("→ yfinance をデータソースとして採用")
return df
print("→ すべてのデータソースで取得に失敗しました")
return None
# ==============================
# データ比較(Stooq vs yfinance)
# ==============================
def compare_sources(
df_a: pd.DataFrame,
df_b: pd.DataFrame,
label_a: str,
label_b: str,
) -> None:
'2つのデータソースの終値を比較してグラフ表示する'
merged: pd.DataFrame = pd.DataFrame({
label_a: df_a["close"],
label_b: df_b["close"],
}).dropna()
if len(merged) == 0:
print("共通する日付がありません。比較をスキップします。")
return
diff: pd.Series = (merged[label_a] - merged[label_b]).abs()
print(f"n--- 終値の差分統計 ({label_a} vs {label_b}) ---")
print(f" 平均差分 : {diff.mean():>10.2f}")
print(f" 最大差分 : {diff.max():>10.2f}")
print(f" 一致率 : {(diff < 0.01).mean() * 100:>10.2f} %")
fig, axes = plt.subplots(2, 1, figsize=(14, 8))
axes[0].plot(merged.index, merged[label_a], label=label_a, linewidth=1.2)
axes[0].plot(merged.index, merged[label_b], label=label_b, linewidth=1.2, linestyle="--")
axes[0].set_title("Close Price Comparison")
axes[0].set_ylabel("Price")
axes[0].legend()
axes[0].grid(alpha=0.3)
axes[1].bar(merged.index, diff, color="tomato", width=1.5, alpha=0.7)
axes[1].set_title("Absolute Difference")
axes[1].set_ylabel("Diff")
axes[1].grid(alpha=0.3)
plt.tight_layout()
plt.show()
# ==============================
# メイン処理
# ==============================
if __name__ == "__main__":
# 1. Stooqで日本株を取得
df_stooq: Optional[pd.DataFrame] = fetch_from_stooq(
TICKER_JP, START_DATE, END_DATE,
)
# 2. FREDで経済指標を取得
df_fred: Optional[pd.DataFrame] = fetch_from_fred(
FRED_SERIES, START_DATE, END_DATE,
)
# 3. Tiingoで米国株を取得(APIキー設定時のみ)
df_tiingo: Optional[pd.DataFrame] = fetch_from_tiingo(
TICKER_US, START_DATE, END_DATE, TIINGO_API_KEY,
)
# 4. フォールバック付き取得
df_main: Optional[pd.DataFrame] = fetch_with_fallback(
TICKER_JP, TICKER_YF, START_DATE, END_DATE,
)
# 5. Stooq vs yfinance の比較
df_yf: Optional[pd.DataFrame] = fetch_from_yfinance(
TICKER_YF, START_DATE, END_DATE,
)
if df_stooq is not None and df_yf is not None:
compare_sources(df_stooq, df_yf, "Stooq", "yfinance")
# 6. FRED取得結果の表示
if df_fred is not None:
print(f"n--- FRED ({FRED_SERIES}) 先頭5行 ---")
print(df_fred.head())
コードの処理フロー解説
上記のコードは、以下の6ステップで構成されています。
* ステップ1(Stooq取得):web.DataReaderにソース名"stooq"を指定し、日本株の日足データを取得する。Stooqは日付が降順で返るためsort_index()で昇順に整列する
* ステップ2(FRED取得):ソース名"fred"で米国の経済指標(ここではFF金利)を取得する。APIキーは不要で、系列ID(Series ID)を指定するだけで取得できる
* ステップ3(Tiingo取得):ソース名"tiingo"で米国株データを取得する。無料APIキーの取得が必要だが、データ品質が高くAdjusted Closeも含まれる
* ステップ4(フォールバック取得):fetch_with_fallback関数がStooq→yfinanceの順に試行し、最初に成功したソースのデータを返す
* ステップ5(ソース比較):StooqとyfinanceのClose値を日付で結合し、差分の統計と比較グラフを出力する
* ステップ6(FRED結果表示):経済指標データの先頭5行をコンソールに出力する
fetch_with_fallback関数の候補リストにTiingoやAlpha Vantageを追加すれば、3段階・4段階のフォールバック構成も容易に構築できます。
データソースごとの特徴と使い分け
Stooq:日本株バックアップの最有力
Stooqはポーランドの金融データサイトですが、日本株の日足データを無料・APIキー不要で提供しています。銘柄コードは7203.JPのように末尾に.JPを付けます。
注意点として、1リクエストで取得できる期間が約5年に制限される場合があります。10年分のデータが必要な場合は期間を分割して取得し、結合してください。
FRED:マクロ経済分析に不可欠
FRED(Federal Reserve Economic Data)は米国セントルイス連邦準備銀行が提供するデータベースです。80万以上の経済時系列を無料で取得できます。
よく使う系列IDを以下にまとめます。
| 系列ID | 内容 |
|---|---|
| DFF | フェデラルファンド実効金利 |
| CPIAUCSL | 消費者物価指数(CPI) |
| UNRATE | 失業率 |
| DGS10 | 米国10年国債利回り |
| DEXJPUS | 米ドル/円 為替レート |
株価との相関分析やレジーム分析に活用してください。
よくあるエラーと対処法
ImmediateDeprecationError が発生する
廃止済みのデータソース("google"、"yahoo"、"morningstar"等)を指定しています。pandas-datareader経由のYahoo Financeリーダーはすでに削除されています。
以下を試してください。
* データソース名を"stooq"や"fred"に変更する
* Yahoo Financeのデータが必要な場合はyfinanceライブラリを直接使う
* pandas-datareaderを最新版にアップデートする(pip install -U pandas-datareader)
RemoteDataError: Unable to read URL
データソースのサーバーが一時的に応答していないか、銘柄コードが間違っています。Stooqの場合、日本株は.JP、米国株はシンボルそのまま(AAPL等)で指定する必要があります。
以下を試してください。
* インターネット接続を確認する
* Stooqの銘柄コード形式(.JP付き)を確認する
* 数分待ってから再実行する(レートリミットの可能性がある)
Stooqで取得したデータにVolume列がない
Stooqの一部銘柄・一部期間ではVolume(出来高)が0またはNaNで返ることがあります。これはStooq側のデータ欠損です。
出来高データが必要な場合はyfinanceをメインソースとし、Stooqは価格データのバックアップ用途に限定してください。compare_sources関数で終値の整合性だけ確認しておけば、価格データとしての信頼性は担保できます。
まとめ
この記事では、pandas-datareaderを使ってyfinance以外のデータソースから金融データを取得する方法を解説しました。
要点を整理します。
* pandas-datareaderはStooq・FRED・Tiingo等の複数データソースに対応し、yfinanceの代替・補完として機能する
* Stooqは日本株の日足データをAPIキー不要で取得でき、yfinance障害時のバックアップとして最有力である
* FREDは80万以上の米国経済指標を無料で提供しており、マクロ分析には不可欠なデータソースである
* 廃止済みリーダー(Google Finance・Morningstar等)を使うとImmediateDeprecationErrorが発生するため、動作確認済みのソースのみ使用する
* fetch_with_fallback関数でStooq→yfinanceの自動切り替え機構を構築し、データ取得の冗長性を確保する
次のステップとして、フォールバック関数をcronやタスクスケジューラで定期実行し、CSVやデータベースに自動保存するパイプラインを構築してください。ローカルにデータを蓄積しておけば、外部APIの障害に左右されない分析環境が完成します。
さらに、FREDの金利データと株価データを組み合わせたレジーム分析を行えば、「利上げ局面では自分の戦略が機能するか」といった条件付きバックテストにも発展できます。
