ふくふくHukuhuku Inc.
EP.21Data Fetch 9分公開: 2026-09-02

債券利回りを取る ── 価格ではなく利回りが動く世界

株価と同じつもりで扱うと混乱します。債券は価格ではなく利回りで語られ、しかも同じ発行体でも残存期間ごとに別の数字が並びます。

#債券#Python#金融データ
執筆 / 監修
松尾 亮合同会社ふくふく 代表社員

データ基盤・データパイプライン構築 / BI / 生成 AI 活用支援を専門とするエンジニア (28 年)。 本記事は AI 利用ポリシーに基づき、生成 AI の補助で執筆 → 人間が監修・編集して公開しています。

プロフィール詳細
シェア

株価であれば、1つの銘柄に対して1つの数字が対応します。債券はそうなりません。同じ発行体でも、償還までの期間が違えば別の債券で、それぞれ違う利回りが付きます。2年、5年、10年、30年。これらを並べたものがです。

配信元によっては、価格と利回りの両方を返してくれます。どちらを使うかを決めずに列を選ぶと、意味の違う数字が混ざります。そして債券の世界では、価格ではなく利回りで語るのが普通です。価格と利回りは逆に動くので、「利回りが上がった」は「価格が下がった」を意味します。株価の感覚で「上がった=良かった」と読むと、逆の解釈になります。

取得の経路はのこともあれば の配布のこともあります。この回では、利回りのデータを取得するときに何を確認しておくべきかを扱います。数字そのものは単純ですが、その数字が何を指しているかの確認を怠ると、まったく違うものを比較することになります。

同じ「10年金利」でも中身が違う

10年国債の利回り、という言い方をしますが、実際に配信されている数字にはいくつか種類があります。実在する特定の銘柄の利回りなのか、残存10年ちょうどに補間した理論値なのか。前者は銘柄が入れ替わるたびに段差が出ますが、後者は滑らかに繋がります。

長期の系列を作るなら補間された値のほうが扱いやすく、実際の取引を追うなら実在銘柄のほうが正確です。ここはと同じで、揃えるべきものを揃えないまま並べると比較が成立しません。提供元がどちらを配信しているかを確認せずに繋ぐと、段差の意味が分からなくなります。

利回りのデータで確認すること
確認項目違いが出ること
実在銘柄か、補間値か銘柄入替時に段差が出るかどうか
単位(% か 小数か)0.5 なのか 0.005 なのかで 100 倍ずれる
年率の計算方法複利か単利かで数字が変わる
営業日の定義国ごとに休日が違う
公表の時点終値ベースか、日中の特定時刻か
単位の取り違えが最も多い

利回りは「0.5」と書いて 0.5% を意味することも、「0.005」と書いて同じ 0.5% を意味することもあります。100 倍の違いが、パッと見では判別できません。取得直後に値の範囲を確認して、想定と桁が合っているかを見てください。

取得直後に桁を確かめる。想定と違えば止める
Python
import pandas as pd

def check_yield_scale(s: pd.Series, expect: str = "percent") -> None:    """利回りの単位が想定どおりかを、値の範囲で判定する。
    percent : 0.5 が 0.5% を意味する(絶対値はおおむね 10 未満)    decimal : 0.005 が 0.5% を意味する(絶対値はおおむね 0.2 未満)    """    v = s.dropna().abs()    if v.empty:        raise ValueError("値が1つも無い")
    hi = v.quantile(0.99)    if expect == "percent" and hi < 0.2:        raise ValueError(f"percent のはずが小数のようだ(99%点 {hi:.4f})")    if expect == "decimal" and hi > 1.0:        raise ValueError(f"decimal のはずが百分率のようだ(99%点 {hi:.4f})")

曲線として持つか、時系列として持つか

イールドカーブは、日付 × 残存期間の2次元のデータです。持ち方には2通りあり、後の使い方で選びます。日付を行・期間を列にした横長の形は、ある日の曲線を見るのに向きます。日付と期間と値を1行ずつ並べた縦長の形は、期間を増やしても列が増えないので保存に向きます。

保存は縦長、分析は横長に変換して使うのが扱いやすいです。縦長なら、提供元が配信する期間の種類が変わっても、保存の形を変えずに済みます。横長で保存していると、期間が1つ増えるたびに列を足すことになります。

縦長で保存し、使うときに横長へ変える
Python
import pandas as pd

def to_wide(long_df: pd.DataFrame) -> pd.DataFrame:    """date / tenor_years / yield の縦長を、日付 × 期間の表に変える。"""    wide = long_df.pivot(index="date", columns="tenor_years", values="yield")    # 列(期間)を数値として昇順に並べる。文字列のままだと 10 が 2 より前に来る    wide = wide.reindex(sorted(wide.columns, key=float), axis=1)    return wide.sort_index()

def curve_slope(wide: pd.DataFrame, short: float = 2, long: float = 10) -> pd.Series:    """長短の差。マイナスなら逆イールド。"""    if short not in wide.columns or long not in wide.columns:        raise KeyError(f"必要な期間が無い: {short}, {long}")    return wide[long] - wide[short]

上のコードで列を数値として並べ替えているのは、文字列のまま並べると 10 が 2 より前に来るからです。期間を文字列で持っていると、曲線を描いたときに順序が狂います。地味ですが、気づきにくい部類の間違いです。

欠けている期間をどう埋めるか

利回りのデータは、期間によっては配信されていないことがあります。30年債が存在しなかった時期、発行が止まっていた時期。その期間は「値がゼロ」ではなく「存在しない」ので、ゼロで埋めると曲線が地面まで落ちます。

埋めるとしても、隣の期間から補間するのか、直前の日から持ち越すのかで意味が変わります。前者は曲線の形を保ちますが実在しない値を作り、後者は日々の変化がゼロになります。どちらも情報を作り出しているという自覚が要ります。

扱いを決めたら、埋めた場所が分かるように印を残してください。なら、値の列とは別に「補間したかどうか」の列を持たせます。後から見た人が、どこが実測でどこが推定かを判別できます。

埋めた場所に印を残す。あとから実測と区別できるように
Python
import pandas as pd

def fill_with_flag(s: pd.Series, method: str = "ffill") -> pd.DataFrame:    """埋めた値と、それが埋めたものかどうかを並べて返す。"""    if method not in ("ffill", "interpolate"):        raise ValueError("ffill か interpolate を指定してください")
    was_missing = s.isna()    filled = s.ffill() if method == "ffill" else s.interpolate(method="linear")    return pd.DataFrame({"value": filled, "imputed": was_missing & filled.notna()})

為替や商品のデータについては データの宝石箱 EP.16 で扱っています。次回は、ここまで何度か触れてきた識別子の問題を正面から扱います。

利回りのデータは、金額のデータほど直感が働きません。桁が合っているか、符号が想定どおりか、期間の並びが正しいか。取得のたびに機械的に確かめる仕組みを入れておくのが確実です。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp