※本記事には広告・アフィリエイトリンクが含まれます。掲載内容は筆者の調査・検証に基づき、読者の判断を助ける目的で作成しています。
動作確認環境:Python 3.11 / pandas 2.x / yfinance 0.2.x / matplotlib 3.x
結論から言うと
- yfinanceで取得した株価データは
df.to_csv()の1行でCSVに保存できます - 保存したCSVを読み込む際は
parse_dates=Trueとindex_col=0の指定が必須です - 複数銘柄の一括保存はforループで回すだけで実現でき、APIの呼び出し回数を抑えられます
CSVに保存する理由(API制限・高速化)
yfinanceは無料で使えますが、短時間に大量のリクエストを送るとAPI制限やタイムアウトが発生することがあります。率直に言うと、分析や検証の度に毎回APIから取得するのは非効率という仕組みです。
CSVに保存しておくメリットは3つあります。また、オフライン環境でも分析できるという点も実務では重要です。
- 速度:ローカルファイルの読み込みはAPI経由より数十倍高速
- 安定性:API障害やレート制限の影響を受けない
- 再現性:同じデータで何度でも検証を繰り返せる
株価データをCSVに保存するコード
import yfinance as yf
import pandas as pd
# 取得して保存
df = yf.download("7203.T", period="1y", auto_adjust=True)
# マルチレベルカラム対策
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.droplevel(1)
df.to_csv("7203T_stock.csv")
print(f"保存完了: {len(df)}行")
デフォルトでは日付がインデックスとして保存されます。encoding="utf-8-sig"を追加するとExcelで開いたときに文字化けしません。
# Excel対応版(BOM付きUTF-8)
df.to_csv("7203T_stock.csv", encoding="utf-8-sig")
# 特定カラムのみ保存
df[["Close", "Volume"]].to_csv("7203T_close_volume.csv")
保存したCSVを読み込む方法
import pandas as pd
# 読み込み(日付インデックスを復元)
df_loaded = pd.read_csv(
"7203T_stock.csv",
index_col=0, # 最初の列をインデックスに
parse_dates=True # 日付文字列をdatetimeに変換
)
print(df_loaded.dtypes)
print(df_loaded.tail())
index_col=0とparse_dates=Trueを忘れると、日付が文字列として読み込まれてしまいます。また、読み込んだデータのインデックスがtimezone情報を持っているかどうかも確認が必要です。
# タイムゾーン確認
print(df_loaded.index.tz) # Asia/Tokyo または UTC
print(type(df_loaded.index)) # DatetimeIndex であることを確認
複数銘柄を一括保存する方法
import yfinance as yf
import pandas as pd
# 複数銘柄を一括保存
tickers = ["7203.T", "6758.T", "9984.T"]
for ticker in tickers:
df = yf.download(ticker, period="1y", auto_adjust=True)
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.droplevel(1)
# ファイル名のドットをアンダースコアに変換
filename = f"{ticker.replace('.', '_')}_stock.csv"
df.to_csv(filename)
print(f"{ticker}: {len(df)}行保存 → {filename}")
また、保存先ディレクトリを指定する場合はos.makedirs()で事前にフォルダを作成しておくと安全です。
import os
save_dir = "stock_data"
os.makedirs(save_dir, exist_ok=True)
for ticker in tickers:
df = yf.download(ticker, period="1y", auto_adjust=True)
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.droplevel(1)
df.to_csv(f"{save_dir}/{ticker.replace('.', '_')}_stock.csv")
print(f"{ticker}: 保存完了")
日付インデックスの注意点
yfinanceで取得したデータは日本株の場合Asia/Tokyoタイムゾーンが付与されることがあります。CSVに保存するとタイムゾーン情報が失われるため、読み込み時に必要であれば再設定が必要です。
# タイムゾーン再設定
df_loaded.index = pd.to_datetime(df_loaded.index)
df_loaded.index = df_loaded.index.tz_localize("Asia/Tokyo")
# 日付範囲でフィルタリング
df_2024 = df_loaded["2024-01-01":"2024-12-31"]
print(f"2024年のデータ: {len(df_2024)}行")
筆者の検証メモ
トヨタ(7203.T)、ソニー(6758.T)、ソフトバンクG(9984.T)の3銘柄でCSV保存・読み込みを確認しました。
- トヨタ(7203.T):1年分で約250行。ファイルサイズは約30KB。
parse_dates=Trueなしで読み込むと日付が文字列になり、グラフが崩れる現象が発生しました - ソニー(6758.T):
auto_adjust=Trueで取得したデータをCSV保存後に読み込み、移動平均計算まで問題なく動作。APIから再取得したデータとの差異もゼロでした - ソフトバンクG(9984.T):yfinanceのバージョンによってカラム名が変わることがあり、
MultiIndex対策のコードを入れておくと複数バージョンで安定動作しました
率直に言うと、CSVへの保存は「分析の再現性を確保する」という意味でも重要です。同じデータで検証を繰り返す前提があれば、最初にCSV化しておくのが合理的という仕組みです。
※当サイトの内容は投資判断を推奨するものではありません。掲載しているコード・分析例は学習・検証目的であり、実際の投資はご自身の責任で行ってください。

