※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。
yfinanceなどのライブラリを使って株価データを取得するところまでは成功したものの、「取得したデータの中身がよく分からない」「必要な値だけを取り出す方法が分からない」という段階で手が止まる初心者は非常に多いです。
株価データはJSON形式やpandasのDataFrame形式で返されるのが一般的ですが、それぞれの構造を理解していなければ、始値・終値・出来高といった必要な情報を正確に抽出できません。
この記事では、JSON形式のデータ構造の基礎から、DataFrameの操作方法、そして実際にyfinanceで取得した株価データから必要な値だけを取り出す実践的なコードまで、ステップごとに解説します。
JSON形式の基礎知識
株価データを扱ううえで、まずJSON形式の基本構造を理解しておく必要があります。
JSONとは何か
JSON(JavaScript Object Notation)は、データを「キーと値のペア」で表現する軽量なテキスト形式です。Web APIのレスポンスとして最も広く使われているフォーマットであり、Pythonでは辞書型(dict)として扱います。
基本的な構造は以下のとおりです。
{
"symbol": "7203.T",
"name": "トヨタ自動車",
"price": 2850.0,
"volume": 12345678
}
JSONの主要なデータ型
JSONで使用できるデータ型は以下の6種類です。
| JSONデータ型 | Pythonでの対応型 | 例 |
|---|---|---|
| 文字列 | str | "トヨタ自動車" |
| 数値(整数) | int | 12345678 |
| 数値(小数) | float | 2850.0 |
| 真偽値 | bool | true → True |
| 配列 | list | [1, 2, 3] |
| オブジェクト | dict | {"key": "value"} |
PythonでのJSON読み込み
Pythonには標準ライブラリとして json モジュールが用意されています。外部ライブラリのインストールは不要です。
import json
# JSON文字列をPythonの辞書に変換
json_str = '{"symbol": "7203.T", "price": 2850.0}'
data = json.loads(json_str)
print(data["symbol"]) # 出力: 7203.T
print(data["price"]) # 出力: 2850.0
json.loads()はJSON文字列を辞書に変換します。JSONファイルを読み込む場合はjson.load()(sなし)を使用してください。
DataFrameの基礎知識
yfinanceで取得した株価データは、pandasのDataFrameという表形式のデータ構造で返されます。DataFrameの仕組みを理解することが、株価データ操作の核心です。
DataFrameの構造
DataFrameは「行(row)」と「列(column)」で構成される二次元のデータ構造です。Excelのスプレッドシートに近いイメージで理解してください。
yfinanceで取得した株価データのDataFrameは、以下のような構造になっています。
| Date | Open | High | Low | Close | Volume |
|---|---|---|---|---|---|
| 2025-01-06 | 2800.0 | 2850.0 | 2780.0 | 2830.0 | 15000000 |
| 2025-01-07 | 2835.0 | 2870.0 | 2820.0 | 2860.0 | 12000000 |
| 2025-01-08 | 2855.0 | 2890.0 | 2840.0 | 2875.0 | 13500000 |
各カラムの意味
株価データに含まれる各カラムの意味は以下のとおりです。
- Open(始値): その日の最初に成立した取引価格
- High(高値): その日の最も高い取引価格
- Low(安値): その日の最も安い取引価格
- Close(終値): その日の最後に成立した取引価格
- Volume(出来高): その日に取引された株数の合計
テクニカル分析では終値(Close)を基準にすることが最も一般的です。移動平均線やRSIなどの指標は、原則として終値をベースに計算されます。
インデックスとカラムの確認方法
DataFrameの構造を把握するために、以下の属性を確認する習慣をつけてください。
import pandas as pd
# dfはDataFrameオブジェクトとする
print(df.index) # 行ラベル(日付など)の一覧
print(df.columns) # 列名の一覧
print(df.shape) # (行数, 列数) のタプル
print(df.dtypes) # 各列のデータ型
【コピペOK】yfinanceで株価データを取得して構造を確認する
ここからは実際にyfinanceでデータを取得し、その中身を確認していきます。
データ取得と基本情報の表示
以下のスクリプトを inspect_data.py として保存・実行してください。
import yfinance as yf
import pandas as pd
# ==============================
# 設定エリア
# ==============================
SYMBOL = "7203.T" # トヨタ自動車
PERIOD = "1mo" # 直近1ヶ月
# ==============================
# データ取得と構造確認
# ==============================
def inspect_stock_data():
print(f"=== {SYMBOL} のデータ構造を確認 ===n")
ticker = yf.Ticker(SYMBOL)
df = ticker.history(period=PERIOD)
if df.empty:
print("データが取得できませんでした。")
return
# 基本情報
print(f"【データ型】 {type(df)}")
print(f"【行数×列数】 {df.shape}")
print(f"【カラム一覧】 {list(df.columns)}")
print(f"【インデックス型】 {type(df.index)}")
print()
# 各列のデータ型
print("【各列のデータ型】")
print(df.dtypes)
print()
# 先頭5行
print("【先頭5行】")
print(df.head())
print()
# 末尾5行
print("【末尾5行】")
print(df.tail())
print()
# 基本統計量
print("【基本統計量】")
print(df.describe())
if __name__ == "__main__":
inspect_stock_data()
出力結果の読み方
このスクリプトを実行すると、以下の情報が順番に表示されます。
| 表示項目 | 確認すべきポイント |
|---|---|
| データ型 | pandas.core.frame.DataFrame であること |
| 行数×列数 | 取得期間に対して妥当な行数か |
| カラム一覧 | Open, High, Low, Close, Volume が含まれているか |
| インデックス型 | DatetimeIndex であること(日付で索引されている) |
| 基本統計量 | 平均値や最大値に異常な値がないか |
describe()メソッドは、各列の件数・平均値・標準偏差・最小値・四分位数・最大値を一括表示します。データの概要を素早く把握するための最も効率的な方法です。
【コピペOK】必要な値だけを取り出すテクニック
DataFrameの全体像を把握したら、次は必要なデータだけを抽出する操作を習得します。
特定のカラムを取り出す
終値だけを取り出す場合は、以下のように記述します。
import yfinance as yf
# ==============================
# 特定カラムの抽出
# ==============================
ticker = yf.Ticker("7203.T")
df = ticker.history(period="1mo")
# 終値のみ取得(Series型)
close_prices = df["Close"]
print("【終値データ】")
print(close_prices)
print()
# 複数カラムを同時に取得(DataFrame型)
ohlc = df[["Open", "High", "Low", "Close"]]
print("【OHLC(4本値)データ】")
print(ohlc)
単一カラムを df["Close"] で取り出した場合、戻り値はSeries型(1次元データ)になります。複数カラムを df[["Open", "Close"]] で取り出した場合はDataFrame型(2次元データ)が返されます。
特定の日付範囲でフィルタリングする
日付でデータを絞り込むには、インデックスに対してスライスを適用します。
import yfinance as yf
# ==============================
# 日付範囲でフィルタリング
# ==============================
ticker = yf.Ticker("7203.T")
df = ticker.history(period="3mo")
# 2025年1月のデータだけを抽出
df_jan = df["2025-01"]
print("【2025年1月のデータ】")
print(df_jan)
print()
# 特定の日付範囲を指定
df_range = df["2025-01-10":"2025-01-20"]
print("【2025/1/10〜1/20のデータ】")
print(df_range)
DatetimeIndexを持つDataFrameでは、
df["2025-01"]のように年月だけでスライスできます。日付範囲の指定は非常に頻繁に使用するため、この記法は必ず覚えてください。
条件を指定して行を抽出する
出来高が一定以上の日だけを抽出するなど、条件付きフィルタリングも可能です。
import yfinance as yf
# ==============================
# 条件付きフィルタリング
# ==============================
ticker = yf.Ticker("7203.T")
df = ticker.history(period="3mo")
# 出来高が1500万株以上の日だけ抽出
high_volume = df[df["Volume"] >= 15000000]
print("【出来高1500万株以上の日】")
print(high_volume[["Close", "Volume"]])
print()
# 終値が前日比プラスの日だけ抽出
df["Change"] = df["Close"].diff()
positive_days = df[df["Change"] > 0]
print(f"【上昇日数】 {len(positive_days)}日 / 全{len(df)}日")
最新の終値だけを1つ取得する
自動売買の判定ロジックなどでは、最新の終値1つだけが必要になるケースがあります。
import yfinance as yf
# ==============================
# 最新値の取得
# ==============================
ticker = yf.Ticker("7203.T")
df = ticker.history(period="5d")
latest_close = df["Close"].iloc[-1]
latest_date = df.index[-1].strftime("%Y-%m-%d")
print(f"最新日付: {latest_date}")
print(f"最新終値: {latest_close:,.1f}円")
iloc[-1] は「最後の行」を意味するインデックス指定です。iloc[0] なら最初の行、iloc[-2] なら最後から2番目の行を取得できます。
【コピペOK】JSON形式のファイルを読み込んで解析する
外部APIのレスポンスや保存済みデータがJSON形式の場合の読み込み方法も確認しておきます。
JSONファイルからDataFrameへの変換
以下のスクリプトは、JSON形式の株価データをDataFrameに変換するサンプルです。
import json
import pandas as pd
# ==============================
# JSONデータの解析サンプル
# ==============================
# サンプルJSON(API応答を模したデータ)
sample_json = """
{
"symbol": "7203.T",
"currency": "JPY",
"history": [
{"date": "2025-01-06", "open": 2800, "high": 2850, "low": 2780, "close": 2830, "volume": 15000000},
{"date": "2025-01-07", "open": 2835, "high": 2870, "low": 2820, "close": 2860, "volume": 12000000},
{"date": "2025-01-08", "open": 2855, "high": 2890, "low": 2840, "close": 2875, "volume": 13500000}
]
}
"""
def parse_json_data():
# JSON文字列を辞書に変換
data = json.loads(sample_json)
print(f"銘柄コード: {data['symbol']}")
print(f"通貨: {data['currency']}")
print()
# historyリストをDataFrameに変換
df = pd.DataFrame(data["history"])
df["date"] = pd.to_datetime(df["date"])
df = df.set_index("date")
print("【DataFrameに変換後】")
print(df)
print()
# 終値の平均を計算
avg_close = df["close"].mean()
print(f"終値の平均: {avg_close:,.1f}円")
if __name__ == "__main__":
parse_json_data()
ネストされたJSONの展開
実際のAPIレスポンスは、JSONが複数階層にネスト(入れ子)されていることが多いです。pd.json_normalize() を使えば、ネストされた構造をフラットなDataFrameに展開できます。
import pandas as pd
# ネストされたJSON
nested_data = [
{
"date": "2025-01-06",
"prices": {"open": 2800, "close": 2830},
"meta": {"exchange": "TSE", "currency": "JPY"}
},
{
"date": "2025-01-07",
"prices": {"open": 2835, "close": 2860},
"meta": {"exchange": "TSE", "currency": "JPY"}
}
]
df = pd.json_normalize(nested_data)
print(df)
出力では prices.open、prices.close、meta.exchange のようにドット区切りでフラット化されたカラム名が自動生成されます。
よくあるエラーと対処法
「KeyError: ‘Close’」と表示される
DataFrameのカラム名が想定と異なる場合に発生します。yfinanceのバージョンによってカラム名の大文字・小文字が変わることがあります。
確認方法:
print(df.columns.tolist())
カラム名が close(小文字)になっている場合は、df["close"] でアクセスしてください。
「IndexError: single positional indexer is out-of-bounds」と表示される
iloc で存在しない行番号を指定した場合に発生します。データが空(取得失敗)でないか、以下のように事前チェックを行ってください。
if df.empty:
print("データが空です。")
else:
latest = df["Close"].iloc[-1]
DataFrameの日付インデックスにタイムゾーン情報が含まれている
yfinanceで取得したデータには、タイムゾーン情報が付与されていることがあります。日付の比較やスライスで不具合が生じる場合は、以下のコードでタイムゾーンを除去してください。
df.index = df.index.tz_localize(None)
タイムゾーンの除去は、CSVに保存する前やグラフ描画の前に実行しておくと、後続処理でのトラブルを防止できます。
まとめ
株価データの解析に必要な基礎知識を整理すると、以下のとおりです。
- JSON形式はWeb APIの標準的なレスポンス形式であり、Pythonでは辞書型として扱う
- DataFrameはpandasの二次元データ構造であり、yfinanceの株価データはこの形式で返される
- 特定カラムの抽出は
df["Close"]、複数カラムはdf[["Open", "Close"]]で行う - 日付範囲のフィルタリングは
df["2025-01"]のようなスライスで行う - 最新の値は
df["Close"].iloc[-1]で取得する - カラム名のエラーが出た場合は
df.columns.tolist()で実際のカラム名を確認する
データの「取得」と「解析」は別のスキルです。この記事で解説したDataFrameの操作方法を身につけることで、移動平均線の計算やシグナル判定ロジックの実装など、次のステップにスムーズに進むことができます。

