Claude Media
日銀の時系列統計APIをClaude Codeで呼ぶ — 系列コードを確かめて金利・為替・物価を取得

日銀の時系列統計APIをClaude Codeで呼ぶ — 系列コードを確かめて金利・為替・物価を取得

日本銀行の時系列統計データ検索サイトのAPIで、メタデータAPIから系列コードを確かめ、コードAPIで金利・為替・物価を取る手順。取得上限、続きの取り方、公開時の条件も書きます。

日本銀行の時系列統計データ検索サイトには、金利・為替・物価などの時系列をJSONやCSVで取得できるAPIがあります。利用にユーザー登録もAPIキーも要りません。Claude Codeに取得スクリプトを書かせれば、検索画面でCSVを落とす作業は置き換えられます。

ただし、取得の成否を分けるのは系列コードです。「ドル円の日次」を指すコードは名前から推測できず、同じDBの中に日次と月次が混ざっています。この記事は、系列コードを自分で確かめる手順を軸に、取得スクリプト、上限の越え方、Claudeに守らせる規約までを順に扱います。

日銀の時系列統計APIでできること

APIは3種類あり、指定する条件が違います。

API取得するもの
コードAPI取得するもの時系列統計データ
階層API取得するもの時系列統計データ
メタデータAPI取得するもの系列の属性情報

メタ情報とは、系列コードや系列名称などの属性です。メタデータAPIの結果は、コードAPIと階層APIのパラメータを作る材料になります。エンドポイントは https://www.stat-search.boj.or.jp/api/v1/ の下に getDataCode、getDataLayer、getMetadata を置く形で、大文字小文字を区別します。

取得できる範囲は、検索画面と同じ全データです。一括ダウンロードファイルが物価統計・資金循環統計・短観・国際収支統計・BIS関連統計に限られるのに対し、APIにはその制限がありません。出力形式はJSON(既定)とCSVで、言語は日本語(既定)と英語です。

データの更新は、原則として8時50分頃です。業務の都合で遅れることがあるため、毎朝の定時取得は9時台以降に置くと取りこぼしを避けられます。

系列コードは名前から推測できない

系列コードは、時系列の系列を特定する固有のコードです。公式の例は MADR1Z@D で、検索画面のデータコード検索では、先頭にDB名を付けた IR01'MADR1Z@D の形が出てきます。

APIに渡すのは、DB名を除いた系列コードだけです。データコードのまま渡すとエラーになり、STATUSは400、MESSAGEIDは M181001E(Invalid input parameters)が返ります。検索画面からコピーしたコードがそのまま通らない、というつまずきです。

Claudeに「ドル円の系列コードを教えて」と聞いても、答えは信用できません。日銀の系列コードは記憶から再現できる規則的な文字列ではないからです。実在しないコードを渡すと M181013E(指定した系列コードは存在しません)で止まりますが、実在するが別物のコードを渡すと、エラーなしで別の系列が返ります。止まらない取り違えのほうが厄介です。

メタデータAPIで系列コードを確かめる

コードを確かめる正式な経路が、メタデータAPIです。DB名を渡すと、そのDBの全系列の系列コード、系列名称、単位、期種、収録開始期・終了期、最終更新日などが返ります。

主なDB名は次のとおりです。分野ごとにDBが分かれているので、まず「どのDBか」を決めます。

知りたいものDB名
無担保コールO/NレートDB名FM01
短期市場の金利DB名FM02
基準割引率・基準貸付利率DB名IR01
貸出の平均金利DB名IR04
外国為替DB名FM08
実効為替レートDB名FM09
企業物価指数DB名PR01
企業向けサービス価格指数DB名PR02
マネタリーベースDB名MD01
短観DB名CO

メタデータAPIのCSVを日本語で取ると、先頭に処理結果の行(STATUS、MESSAGEID、MESSAGE、DATE、DB)があり、その後ろに SERIES_CODE から始まる見出し行が続きます。文字コードは日本語がShift-JIS、英語がUTF-8です。JSONで取れば文字コードに悩まずに済みますが、メタ情報は表形式のCSVのほうが検索しやすい場面が多くあります。

curl -s --compressed -H "Accept-Encoding: gzip" \
  "https://www.stat-search.boj.or.jp/api/v1/getMetadata?format=csv&lang=jp&db=fm08" \
  | iconv -f SHIFT_JIS -t UTF-8 > fm08_meta.csv

外国為替市況(FM08)のメタ情報を見ると、同じDBに日次と月次が同居しているとわかります。たとえば FXERD04(東京市場 ドル・円 スポット17時時点)の収録開始期は 19980105 で日次、FXERM06(同 月末)は 197301 で月次です。名前が似ていて期種が違う系列が並ぶので、コードを選ぶときは名称だけでなく、期種・単位・収録期間も一緒に見ます。

物価のPR01は、メタ情報だけで3万行を超えます。全体をClaudeに読ませると文脈を無駄に使うため、スクリプトで名称を絞り込んでから、候補だけを見せる形にします。メタ情報の行には、系列コードが空欄で階層の見出しだけを示す行も混ざります。

コードAPIで金利・為替・物価を取る

系列コードが決まったら、コードAPIでデータを取ります。必須のパラメータは db と code の2つで、ほかは任意です。

パラメータ内容備考
format内容json または csv備考省略時はJSON
lang内容jp または en備考省略時は日本語
db内容DB名備考必須
code内容系列コード備考必須
startDate内容開始期備考任意
endDate内容終了期備考任意
startPosition内容検索開始位置備考任意。続きを取るときに指定

開始期と終了期の書式は、系列の期種で変わります。暦年・年度は YYYY、半期は YYYYHH(HHは01か02)、四半期は YYYYQQ(QQは01〜04)、月次は YYYYMM です。週次と日次の系列でも、パラメータは月次形式の YYYYMM で渡します。日次の系列に 20250901 のような日単位の書式を渡すと、開始期の形式が期種と合わないとして M181015E が返ります。

公式の例には、無担保コールO/Nレートを取るURLが載っています。

https://www.stat-search.boj.or.jp/api/v1/getDataCode?db=FM01&code=STRDCLUCON,STRDCLUCONH,STRDCLUCONL&startDate=202501

出力のJSONでは、系列ごとに SERIES_CODE、系列名称、単位、期種、最終更新日があり、VALUES の中に時期の配列 SURVEY_DATES と値の配列 VALUES が並びます。2つの配列は位置で対応します。データがない時期は null です。検索画面の結果で出る「NA」「ND」とは表記が違います。

期種は、出力では DAILY、MONTHLY のような正式名称で表示されます。ところが階層APIの frequency パラメータには、D、M、Q などの略称しか使えません。出力に出た正式名称をそのまま入力に使うとエラーになります。

取得上限と、続きの取り方

コードAPIには、1回のリクエストで取れる量に上限があります。

上限値超えたとき
1回の系列数(コードAPI・階層API)値250件超えたとき上限まで出力し、NEXTPOSITION に続きの位置が入る
1回のデータ数(系列数×期数)値60,000件超えたとき同上
階層APIで絞り込まれる系列数値1,250件超えたときエラーで、出力ファイルは作られない

データ数には、欠損で null になる時期も含まれます。系列数かデータ数のどちらかが上限を超えると、上限までのデータが出力され、続きの位置が NEXTPOSITION に入ります。NEXTPOSITION がJSONで null(CSVではブランク)なら、全部取れています。

続きを取るには、同じパラメータに startPosition を足して再リクエストします。コードAPIでは、指定した系列コードの並び順がそのまま位置になります。たとえば200件の系列を指定し、160番目のコードから続けたいなら、startPosition=160 です。

250件を超える系列は、250件ずつに分けて、それぞれで NEXTPOSITION が消えるまで繰り返します。連続リクエストでは、必ず間隔を空けます。公式は高頻度のアクセスを避けるよう求めており、遮断される可能性があると明記しています。

Claude Codeに渡す前提を置く

ここまでの仕様のうち、Claudeが勝手に省きやすい点は、推測で動かれると困ります。次の内容をプロジェクトの CLAUDE.md に書いておきます。

## 日銀時系列統計APIの扱い
- 系列コードはメタデータAPI(getMetadata)の結果から選ぶ。記憶や推測で書かない
- 系列コードにDB名は付けない(IR01'MADR1Z@D ではなく MADR1Z@D)
- 1回のcodeには同じ期種の系列だけを入れる。250件を超えたら分割する
- NEXTPOSITIONが空になるまで続きを取る。リクエスト間は2秒以上空ける
- 数値を報告するときは、DB名・系列コード・系列名称・単位・期間を併記する
- STATUSが200以外なら、条件を変えずに止めてMESSAGEIDを報告する

実行権限も絞れます。公式のpermissionsでは、WebFetch(domain:example.com) の形でドメインを指定でき、ほかに Bash(...) で実行するコマンドも許可できます。日銀のAPIに触れるのは取得スクリプトだけにして、許可もスクリプトに限ると、Claudeが任意のURLを叩く余地が減ります。

{
  "permissions": {
    "allow": [
      "Bash(python3 scripts/boj_fetch.py *)",
      "WebFetch(domain:www.stat-search.boj.or.jp)"
    ]
  }
}

権限ルールの管理は、/permissionsコマンドの記事にまとまっています。

取得スクリプトの例

次のスクリプトは、標準ライブラリだけで動く最小形です。メタデータAPIから系列名で候補を絞り込み、コードAPIで NEXTPOSITION を追いかけます。エラー時のJSONはHTTPの400や503の本文に入って返るため、HTTPError を捕まえて本文を読んでいます。Accept-Encoding: gzip を付けて通信量を減らし、リクエストごとに2秒空けます。日次の外国為替と月次の企業物価指数に対して、手元で実行して動作を確認した形です。

import csv, gzip, io, json, sys, time
from urllib.parse import urlencode
from urllib.error import HTTPError
from urllib.request import Request, urlopen
 
BASE = "https://www.stat-search.boj.or.jp/api/v1"
HEADERS = {"Accept-Encoding": "gzip"}
PAUSE = 2  # 連続リクエストの間隔(秒)
 
 
def get(path, **params):
    time.sleep(PAUSE)
    req = Request(f"{BASE}/{path}?{urlencode(params, safe=',*')}",
                  headers=HEADERS)
    try:
        res = urlopen(req, timeout=60)
    except HTTPError as e:  # エラー内容は本文(JSON)に入る
        res = e
    raw = res.read()
    if res.headers.get("Content-Encoding") == "gzip":
        raw = gzip.decompress(raw)
    return raw
 
 
def search_series(db, keyword):
    """メタデータAPIから系列名で絞り込む"""
    r = get("getMetadata", format="csv", lang="jp", db=db)
    text = r.decode("shift_jis", errors="replace")
    rows = list(csv.reader(io.StringIO(text)))
    head = next(i for i, x in enumerate(rows) if x[:1] == ["SERIES_CODE"])
    cols = rows[head]
    for row in rows[head + 1:]:
        d = dict(zip(cols, row))
        if d.get("SERIES_CODE") and keyword in d["NAME_OF_TIME_SERIES_J"]:
            yield d
 
 
def fetch(db, codes, start=None, end=None):
    """コードAPI。NEXTPOSITIONが出る間は続きを取る"""
    pos, out = 1, []
    while pos:
        params = dict(db=db, code=",".join(codes))
        if start: params["startDate"] = start
        if end: params["endDate"] = end
        if pos > 1: params["startPosition"] = pos
        body = json.loads(get("getDataCode", **params))
        if body["STATUS"] != 200:
            sys.exit(f'{body["MESSAGEID"]}: {body["MESSAGE"]}')
        out += body["RESULTSET"]
        pos = body["NEXTPOSITION"]
    return out
 
 
if __name__ == "__main__":
    cmd, db, arg = sys.argv[1:4]
    if cmd == "search":  # python3 boj_fetch.py search FM08 17時時点
        for d in search_series(db, arg):
            print(d["SERIES_CODE"], d["NAME_OF_TIME_SERIES_J"], d["UNIT_J"],
                  d["START_OF_THE_TIME_SERIES"], d["END_OF_THE_TIME_SERIES"])
    else:  # python3 boj_fetch.py get FM08 FXERD04 202509
        for s in fetch(db, arg.split(","), *sys.argv[4:6]):
            v = s["VALUES"]
            print(s["SERIES_CODE"], s["UNIT_J"], s["FREQUENCY"],
                  list(zip(v["SURVEY_DATES"], v["VALUES"]))[:3])

呼び出し側では、まず候補を一覧にしてから取得します。

python3 scripts/boj_fetch.py search FM08 "17時時点"
python3 scripts/boj_fetch.py get FM08 FXERD04 202509 202509

手元でこの絞り込みを実行すると、FXERD04(ドル・円17時時点、日次)、FXERD34(ユーロ・ドル17時時点、日次)、FXERM06(ドル・円17時時点/月末、月次)、FXERM07(同 月中平均、月次)の4件が出ました。日次と月次が混ざっているので、日次を選ぶならこの時点で FXERD04 と決めます。そのコードで2025年9月を取ると、SURVEY_DATES は 20250901 から日付の配列になり、今回の取得では土日の値が null でした。営業日にだけ値が入る系列なので、休日はデータがない時期として null になるとみられます。

企業物価指数のほうは、PR01 の PRCG20_2200000000(国内の企業物価指数 総平均、2020年=100)を指定します。期種は月次で、startDate=202507&endDate=202509 なら SURVEY_DATES は 202507、202508、202509 の3件です。

取り違えを防ぐ確認手順

e-Statのような統計系APIと同じく、「取れた」と「正しいものが取れた」は別の話です。Claudeに取得させたあと、結果を報告させる前に次の確認を挟みます。

系列コードは名称と単位で突き合わせる

取得結果の NAME_OF_TIME_SERIES_J と UNIT_J を、依頼した内容と照らします。ドル円の日次を頼んだのに単位が 百万ドル なら、出来高の系列を引いています。FM08には、為替レートのほかにスポット出来高やスワップ出来高の系列も並んでいます。

期種と期間を取得後に検証させる

返ってきた FREQUENCY が想定の期種か、SURVEY_DATES の先頭と末尾が依頼した期間に収まっているかを確認させます。収録期間と合わない指定は、エラーにならず空で返ることがあります。指定した系列・時期がすべて収録期間外、または全系列のデータが欠損のときは、STATUSが200のまま M181030I(正常に終了しましたが、該当データはありませんでした)です。エラーにならないぶん、空のまま分析へ進みやすい箇所です。

欠損値の扱いを先に決める

為替の日次は、休日が null になります。そのまま平均を取ると、null を除く計算になるのか、0として入るのかが処理系で変わります。pandasで読み込む場合は、null を欠損のまま保持し、営業日だけにするのか、前の営業日の値で埋めるのかを、集計の前に決めます。扱いの詳しい書き方は、Claude Codeでpandasのデータ処理を書く記事が参考になります。

最終更新日を成果物に残す

出力の LAST_UPDATE は、系列のメタ情報やデータが更新されたときに変わります。成果物のCSVや集計表には、取得日時と一緒に残しておくと、あとから数値が食い違ったときに、改定か取り違えかを切り分けられます。

階層APIで一括取得する

DBの中の系列を丸ごと取りたいときは、階層APIが向いています。系列コードを並べる代わりに、DB内の階層構造(5階層の番号)で範囲を指定します。階層1は必須、階層2〜5は任意で、カンマ区切りです。* は「その階層をすべて」を意味します。

国際収支統計(BP01)の月次を、階層1〜3がすべて「1」の範囲で取る公式の例は次のとおりです。

https://www.stat-search.boj.or.jp/api/v1/getDataLayer?format=csv&db=BP01&frequency=M&startDate=202504&endDate=202509&layer=1,1,1

階層APIは frequency が必須で、略称(M、Q など)で指定します。気をつけたいのは、系列数の数え方です。絞り込み条件に合う系列は、期種で絞る前に数えられます。そのため、指定した階層に月次と四半期が混ざっている場合、欲しいのは月次だけでも、四半期の系列まで1,250件の上限に含まれます。

階層APIの startPosition は、コードAPIと意味が違います。コードAPIでは指定したコードの並び順ですが、階層APIでは階層1〜5で並べたDB内の全系列に付いた順序番号を使います。絞り込んだ結果の何番目、ではありません。続きを取るときは、返ってきた NEXTPOSITION の値をそのまま渡します。

結果を公開するときの条件

取得した結果を使ったサービスを公開する場合、日本銀行は「API機能利用時の留意点」で次を求めています。

  • サービスを公開したら、日本銀行の調査統計局に連絡する
  • 次のクレジットを、利用者が見られる場所に表示する

このサービスは、日本銀行時系列統計データ検索サイトのAPI機能を使用しています。サービスの内容は日本銀行によって保証されたものではありません。

禁止されているのは、本機能の運用を妨害する行為と、短時間の高頻度アクセスです。違反または違反のおそれがあると判断された場合、利用が停止されることがあります。機能の停止や仕様変更は予告なく行われる場合があり、利用に伴う損害について日本銀行は責任を負わないと定められています。留意点自体も、事前の通知なしに変更される場合があります。

個人の分析にとどまる取得なら、公開の連絡もクレジットも関係しません。ブログやダッシュボードに数値を載せる段階になったら、この2点を足すだけで済みます。ほかの統計系APIの扱いは、e-Stat APIの記事やEDINET APIの記事と並べると違いが見えます。

エラーが出たときの読み方

エラー時は、CSVを指定していてもJSON形式で内容が返ります。まず STATUS と MESSAGEID を見ます。400はパラメータの誤りで、直してから再実行します。500と503は、時間をおいてやり直す種類です。

MESSAGEID内容対処
M181001E内容Invalid input parameters対処使えない記号・全角文字、またはDB名付きのデータコードを直す
M181005E内容DB名が正しくありません対処DB名を確かめて直す
M181007E内容系列コードの数が1250を超えている対処系列を分けて取り直す
M181013E内容指定した系列コードは存在しない対処メタ情報で系列コードを確かめ直す
M181014E内容指定した系列コードの期種が一致しない対処同じ期種の系列ごとに分けて指定する
M181015E内容開始期の設定形式が期種と一致しない対処開始期の書式を期種に合わせる
M181090S内容予期しないエラー(500)対処時間をおいてやり直す
M181091S内容データベースアクセスエラー(503)対処時間をおいてやり直す

M181014E と M181013E は、メッセージに「何番目のコードか」が出ます。Claudeにエラーを読ませるときは、番号をもとに該当コードをメタ情報へ戻って確認させると、修正が早くなります。

週次の系列にも癖があります。週次の期種には W0 から W6 の7種類があり、パラメータ設定時は全部 W と書きます。ただしコードAPIでは異なる曜日の週次を1回のリクエストに混ぜられず、W1 と W4 の系列を取るなら2回に分けます。

まとめ

日銀の時系列統計APIは、登録なしで使えるぶん、系列コードの確かめ方が成否を決めます。メタデータAPIで名称・単位・期種・収録期間を見てコードを選び、コードAPIで250件以内・同じ期種で取り、NEXTPOSITION が消えるまで間隔を空けて続けます。

Claude Codeには、コードを推測させない規約を CLAUDE.md に置き、実行を取得スクリプトに絞り、取得後に名称・単位・期種・期間を突き合わせさせます。止まらない取り違えを検証で止める、という組み方です。結果を外に出すときは、連絡とクレジット表示の2点が加わります。

この記事を共有:XはてブLinkedIn