yfinanceで株価データを取得する完全ガイド
Python経験者向けの投資分析シリーズ第1回。yfinance で日本株・米国株・ETFの株価データを取得する方法を、最小コードから複数銘柄の一括取得・実務でハマる落とし穴まで実コードで解説します。この回で作る「価格取得」は、連載のゴールであるポートフォリオ管理アプリの土台になります。
1. この記事のゴールと連載の位置づけ
本記事は「Python経験者が、自分の投資ポートフォリオを管理・可視化するアプリを作る」連載の第1回です。最終的には保有銘柄の評価損益・資産配分・配当までを扱う Streamlit アプリを目指しますが、そのすべての土台が「株価データを取得する」こと。ここを最初に固めます。
株価取得の定番ライブラリが yfinance です。Yahoo! Finance のデータを pandas の DataFrame として手軽に取得でき、日本株・米国株・ETFを同じインターフェースで扱えます。無料で API キーも不要なので、個人の分析用途には十分です。ライブラリ全体の位置づけはよく使うPythonライブラリ50選でも触れています。
なぜ yfinance なのか、という点も先に押さえておきましょう。株価取得には証券会社の公式 API や有料データサービスもありますが、口座開設や申請、利用料が必要で、個人の分析を始めるにはハードルが高めです。yfinance は導入が pip 一発で、株・ETF・為替・指数を同じ書き方で扱えるため、まず手を動かして分析の型を作るのに最適です。一方で非公式ライブラリゆえの限界もあります。データ元(Yahoo! Finance)の仕様変更である日突然動かなくなる、取得が不安定なことがある、リアルタイム性は保証されない——この3点は前提として受け入れ、「壊れても自分で直せる薄い作り」にしておくのが、長く使うコツです。本記事の最後で示す取得関数も、その思想で書きます。
この回のゴールは、「任意の銘柄リストの最新価格と過去データを、エラーに強い形で取得する関数」を書けるようになることです。連載の全体像は投資×Python シリーズ一覧を参照してください。
2. インストールと最小コード
インストールは pip で一発です(Python環境がまだの方はPythonのインストールから)。
pip install yfinance pandas
まずは1銘柄の最新価格を取得する最小コードです。トヨタ自動車(証券コード 7203)を例にします。
import yfinance as yf
# 日本株は証券コードに「.T」を付ける
ticker = yf.Ticker("7203.T")
# 直近の終値を1行で取得
hist = ticker.history(period="5d")
print(hist["Close"].iloc[-1]) # 直近の終値
yf.Ticker(...) で銘柄オブジェクトを作り、history() で時系列データ(pandas DataFrame)を取得します。列は Open / High / Low / Close / Volume(OHLCV)。「直近の終値」は Close 列の末尾(iloc[-1])です。
3. 日本株・米国株・ETFのティッカー指定
yfinance で最初に迷うのがティッカー(銘柄記号)の書き方です。市場ごとにルールが違います。
| 対象 | 書き方 | 例 |
|---|---|---|
| 日本株 | 証券コード + .T | トヨタ → 7203.T |
| 米国株 | ティッカーそのまま | アップル → AAPL |
| 国内ETF | 証券コード + .T | TOPIX連動 → 1306.T |
| 米国ETF | ティッカーそのまま | S&P500 → VOO |
| 為替 | 通貨ペア + =X | ドル円 → USDJPY=X |
米国株を保有している場合、評価額を円換算するために為替が必要です。ドル円も同じ history() で取得できます。
usdjpy = yf.Ticker("USDJPY=X").history(period="5d")["Close"].iloc[-1]
print(f"1ドル = {usdjpy:.2f}円")
yfinance が扱えるのは市場で値が付く銘柄(株・ETF・為替など)です。日本の非上場の投資信託(基準価額)は対象外のことがほとんど。本連載では投信は手入力で割り切る方針にします(自動取得はETFに寄せる)。「全部自動化」にこだわると沼にハマるので、ここは早めに割り切るのが正解です。
4. OHLCVと期間・間隔の指定(history)
history() は period(期間)と interval(間隔)で取得範囲を制御します。ポートフォリオの資産推移を描くなら日足、デイトレ的な分析なら分足、と用途で変えます。
# 過去1年の日足
df = yf.Ticker("AAPL").history(period="1y", interval="1d")
# 期間を日付で明示することもできる
df = yf.Ticker("AAPL").history(start="2025-01-01", end="2025-12-31")
print(df.tail()) # 末尾5行
print(df.columns.tolist()) # ['Open','High','Low','Close','Volume','Dividends','Stock Splits']
period は 1d / 5d / 1mo / 3mo / 6mo / 1y / 5y / max など、interval は 1m / 5m / 1h / 1d / 1wk / 1mo などが使えます。注意点として、分足(1m等)は直近30日ぶんしか取れない制限があります。長期×細かい間隔は取得できないと覚えておきましょう。
取得後は普通の pandas として扱えます。たとえば月次リターンは次の通りです。
monthly = df["Close"].resample("ME").last()
returns = monthly.pct_change().dropna()
print(returns)
調整後終値(auto_adjust)に注意
リターンや資産推移を正しく分析するうえで必ず知っておくべきのが「調整後終値」です。配当の支払いや株式分割があると、その前後で株価は不連続に動きます。たとえば1株を2株に分割すれば、株価は理論上半分になります。素の Close をそのまま使うと、この「見かけの下落」をリターンと誤認してしまいます。
yfinance の history() は既定で auto_adjust=True(分割・配当を調整した連続的な価格)を返します。生の終値が必要なときだけ明示的に切り替えます。長期のリターン分析では調整後を使うのが原則です。
# 既定(auto_adjust=True): 分割・配当調整済みの連続価格 → リターン分析向き
adj = yf.Ticker("AAPL").history(period="5y")["Close"]
# 生の終値が必要なときだけ False(その日の実際の約定価格に近い)
raw = yf.Ticker("AAPL").history(period="5y", auto_adjust=False)["Close"]
ポートフォリオの「現在の評価額」を出すだけなら直近価格でよいので差は出ませんが、「過去からの値上がり率」や「資産推移グラフ」を描くときは調整後を使う、と覚えておきましょう。ここを取り違えると、後の分析がすべて狂います。
5. 複数銘柄を一括取得する
ポートフォリオは複数銘柄の集合なので、1銘柄ずつ Ticker を回すより一括取得が効率的です。yf.download() に銘柄をスペース区切りで渡します。
import yfinance as yf
tickers = ["7203.T", "6758.T", "AAPL", "VOO"]
data = yf.download(tickers, period="6mo", interval="1d", group_by="ticker")
# 銘柄ごとの終値だけ取り出す
closes = {t: data[t]["Close"] for t in tickers}
ここで列が銘柄×項目の MultiIndex(階層列)になるのが最初の関門です。group_by="ticker" を付けると data["AAPL"]["Close"] のように銘柄起点でアクセスできて扱いやすくなります。逆に項目起点でまとめたいなら、終値だけを横並びにする書き方が便利です。
# 全銘柄の終値を1枚のDataFrameに(列=銘柄)
close_df = yf.download(tickers, period="6mo")["Close"]
print(close_df.tail())
6. 実務でハマる落とし穴と対策
yfinance は手軽な反面、非公式ライブラリゆえの癖があります。アプリに組み込む前に知っておくべき落とし穴を4つ挙げます。
| 症状 | 原因 | 対策 |
|---|---|---|
| 空の DataFrame が返る | ティッカー誤り(.T 付け忘れ等)/ 一時的な取得失敗 | if df.empty: で都度分岐し、リトライ or スキップ |
YFRateLimitError 等で落ちる | 短時間に大量リクエスト(レート制限) | 銘柄数を絞る・取得間隔を空ける・結果をキャッシュ |
| 列が MultiIndex で扱いにくい | 複数銘柄取得時の仕様 | group_by="ticker" か ["Close"] で平坦化 |
| 過去データに欠損・ばらつき | 休場日・上場前・データソース都合 | dropna() / 取得後に件数を検証 |
これらを踏まえ、「失敗しても全体が止まらない」取得関数にまとめます。アプリに組み込む実用形はこの形です。
import yfinance as yf
def fetch_latest_price(ticker: str):
"""最新終値を返す。取得できなければ None。"""
try:
df = yf.Ticker(ticker).history(period="5d")
if df.empty:
return None
return float(df["Close"].iloc[-1])
except Exception as e:
print(f"[warn] {ticker}: {e}")
return None
prices = {t: fetch_latest_price(t) for t in ["7203.T", "AAPL", "VOO"]}
print(prices) # 取得失敗した銘柄は None
ポイントは 例外を握りつぶさずログに残しつつ、戻り値は None に揃えること。こうしておくと、1銘柄の取得失敗でアプリ全体がクラッシュするのを防げます。レート制限が気になる場合は、取得結果を SQLite にキャッシュして「当日ぶんは再取得しない」設計にすると安定します(この保存設計は連載の後半で扱います)。
7. ポートフォリオ管理アプリへの接続
ここまでで「銘柄リスト → 最新価格の辞書」を、エラーに強い形で得られるようになりました。これがポートフォリオ管理アプリの心臓部です。次の式が成り立てば、評価額が出せます。
# 保有: 銘柄, 数量, 取得単価(実際はCSV取込や手入力で用意)
holdings = [
{"ticker": "7203.T", "qty": 100, "avg_cost": 2500},
{"ticker": "AAPL", "qty": 10, "avg_cost": 180}, # ドル建て
]
usdjpy = fetch_latest_price("USDJPY=X") or 150.0
for h in holdings:
price = fetch_latest_price(h["ticker"])
if price is None:
continue
# 米国株は円換算(簡易判定: .T が付かない=ドル建てとみなす例)
rate = 1 if h["ticker"].endswith(".T") else usdjpy
value_jpy = price * h["qty"] * rate
cost_jpy = h["avg_cost"] * h["qty"] * rate
print(f'{h["ticker"]}: 評価額 {value_jpy:,.0f}円 / 損益 {value_jpy - cost_jpy:+,.0f}円')
この「評価額・評価損益の計算」を表とグラフにすれば、もう立派なポートフォリオ管理の最小版です。次回以降で、保有データの持ち方(証券会社のCSV取込)、損益計算の整備、資産配分の可視化…と部品を足していきます。Pythonで何が作れるかの全体像はPythonで作れるもの一覧も参考にどうぞ。
8. よくある質問(FAQ)
yfinanceでの株価取得でよくいただく質問をまとめました。
Q. yfinanceは無料ですか?商用利用できますか?
ライブラリ自体は無料・オープンソースです。ただしデータ元は Yahoo! Finance であり、その利用は Yahoo の規約に従います。個人の分析・学習用途が基本で、再配布や商用サービスへの組み込みは各規約の確認が必要です。本連載は「自分の資産を自分で管理する」ローカル用途を想定しています。
Q. 日本株が取得できません。
証券コードに .T を付けているか確認してください(トヨタなら 7203.T)。付け忘れると空の DataFrame が返ります。それでも取れない場合は、一時的な取得失敗の可能性があるのでリトライしてみてください。
Q. 投資信託の基準価額は取得できますか?
非上場の投資信託は基本的に取得できません。yfinanceが扱えるのは市場で値が付く株・ETF・為替などです。本連載では投信は手入力、自動取得は上場ETFに寄せる方針です。
Q. 大量の銘柄を取得するとエラーになります。
短時間の大量リクエストでレート制限に当たることがあります。銘柄数を絞る・取得間隔を空ける・取得結果をキャッシュ(SQLite等)する、で回避します。アプリ化するときは「当日ぶんは再取得しない」設計が安定します。
Q. リアルタイムの株価ですか?
厳密なリアルタイムではなく、数十分の遅延があることがあります。長期の資産管理・分析用途では十分ですが、秒単位の取引判断には向きません。本連載の目的(保有資産の評価・可視化)には問題ありません。
本記事は、生成AIを活用して下書きし、運営者が内容を確認・編集したうえで公開しています。本記事は情報提供を目的としたもので、特定の銘柄の売買や投資手法を推奨するものではありません。投資判断はご自身の責任で行ってください。AIの利用方針は免責事項をご覧ください。