日本株の検証を、実測で。

J-Quantsの分足は15:24の次が15:30|知らないと検証が静かに狂う時刻の癖

  • 2026年9月21日
  • 2026年9月21日
  • データ

J-Quants の分足は、東証の実際の取引時間に合わせた形で配られています。そのため「1分ごとに必ず1本ある」わけではありません。知らずに組むと、検証がエラーを出さずに狂います。

  • 15:24 の次は 15:30 です。間の5本はありません(10営業日で10日とも)
  • 11:30 と 15:30 は四本値が同じ値のバーになります(板寄せ)
  • 取引が無かった分には、そもそもレコードがありません
  • 公式は「最初のバーが必ず09:00とは限らない」としていますが、実測した10日は全部09:00でした。薄い銘柄では違うはずです

まず実物を見る

2026年9月18日の 86970(JPX)で、1日ぶんの分足を取ってみます。

look.py
import requests

r = requests.get(
    "https://api.jquants.com/v2/equities/bars/minute",
    params={"code": "86970", "date": "2026-09-18"},
    headers={"x-api-key": API_KEY},
)
rows = r.json()["data"]

times = [x["Time"] for x in rows]
print(len(rows), "本")
print("最初:", times[0], "最後:", times[-1])

# 15:24 の次が何か
i = times.index("15:24")
print("15:24 の次 →", times[i + 1])

結果は 327本。最初が 09:00、最後が 15:30。そして 15:24 の次は 15:30 でした。

なぜ 15:25〜15:29 が無いのか

東証はザラバ(通常の売買)が 15:25 で終わり、そこから 15:30 まではクロージング・オークション(板寄せ)です。この間は注文を受け付けますが、約定は成立しません。たまった注文は 15:30 にまとめて約定します。

だから分足も、15:25〜15:29 は存在しないのです。

ティックデータ側でも確かめました。15:25〜15:29 の約定は 0 件。「バーが返ってこない」のではなく「本当に約定が無い」ということです。

実測:10営業日で数えた

確かめたこと公式の記述実測(10営業日)
15:24 の次が 15:30 かザラバ終了(15:25)〜大引け(15:30)のバーは返らない10 / 10 日でそのとおり
最初のバーは 09:00 か当日最初のバーが必ず09:00になるわけではない10 / 10 日とも 09:00
11:30・15:30 が四本値同値か前引け・大引けの板寄せは同値のバーとして現れる10 / 10 日でそのとおり

「最初のバーが09:00とは限らない」は、どういう銘柄の話か

公式は「当日最初のバーが必ず『09:00』になるわけではありません」と書いていますが、JPX のような流動性の高い銘柄では10日とも09:00に寄っていました

その後、全銘柄で測りました。09:00ちょうどに寄るのは 89.48%14日とも09:00に寄った銘柄は 47.1% しかありません。しかも遅れる理由は薄い銘柄と厚い銘柄で逆でした(薄い=相手がいない/厚い=注文が片側に偏って板寄せが決まらない)。「板が薄いから遅れる」だけでは説明が付きません。別記事にまとめています。

取引が無い分は、レコードごとありません

公式の記述はこうです。

「当APIは取引のティックデータを1分単位で集約したデータを提供しており、その1分間に取引が存在しない時間帯のデータは返却値に含まれません」

つまり歯抜けになります。立会時間は 09:00〜11:30 が151分、12:30〜15:30 が181分で合計332分。ここから 15:25〜15:29 の5分を引くと 327分で、実測の327本とぴったり一致します。1本も欠けていない銘柄の上限が327本ということです。薄い銘柄では、ここから大きく減ります。

「約定のあった分の割合」を出すときは、分母を332ではなく327にしてください。332で割ると、どんなに出来ている銘柄でも5分ぶん足りないことになります。一日中ずっと約定していた大型株に「約定の無かった時間 5分」と出て気づきました。

移動平均やRSIを「直近N本」で計算しているコードは、ここで意味が変わります。歯抜けのある銘柄では「直近20本」が20分ぶんとは限りません。埋めるか埋めないかを決めて、どちらにしたかを結果と一緒に書くのが誠実です。

fill.py
# 歯抜けを埋めるかどうかは、自分で決めて記事や結果に書く
import pandas as pd

df = pd.DataFrame(rows).set_index("Time")

# 埋めない(既定。取引が無かった事実をそのまま残す)
# 埋める(終値で前に倣う。指標の計算を途切れさせたくないとき)
full = pd.date_range("09:00", "11:30", freq="1min").strftime("%H:%M")
df2 = df.reindex(full)
df2["C"] = df2["C"].ffill()
df2[["O", "H", "L"]] = df2[["O", "H", "L"]].fillna(df2["C"].values[:, None])
df2["Vo"] = df2["Vo"].fillna(0)

そのほか、知らないと困る仕様

  • 四本値は調整前です。株式分割をまたぐと値段が飛びます(調整済みは日足側にあります)
  • 立会内取引のみ。ToSTNeT などの立会外は含まれません
  • 後場寄りの板寄せ約定は、同一分の連続約定と合算されます。板寄せぶんだけを取り出すことはできません
  • 板寄せであることを示す項目はありません。時刻から判断するしかありません
  • 地方取引所の単独上場銘柄と PTS は対象外です
  • 先物・オプション・指数の分足は提供されていません

チェックリスト

自分の検証コードが、この癖に耐えられるか確かめてください。

  1. 15:25〜15:29 のバーを前提にしていないか。「引けの5分前から」という条件は、そのままでは書けません
  2. 「1日N本」を決め打ちしていないか。銘柄と日によって変わります
  3. 「直近N本」の N が、時間の長さのつもりになっていないか
  4. 11:30 と 15:30 の同値バーを、値動きが無かったと誤解していないか。板寄せなので、むしろ出来高が大きい分です
  5. 分割をまたぐ期間で、調整をしているか

まとめ

この手の仕様は、間違えてもエラーが出ません。動いて、それらしい数字が出て、ただ間違っているという壊れ方をします。

だから最初に、1銘柄1日ぶんを実際に表示して、自分の目で最初と最後と途切れを見ておくのがいちばん確実です。上のコードはそのためのものです。

この記事の出どころ

  • データ:J-Quants API「株価 分足・ティック」アドオン(ベースは Light プラン)
  • 対象:86970(JPX)/ 直近10営業日 /「15:25〜15:29の約定」は2026-09-18 の全銘柄ティック 4,313,905件で確認
  • 環境:Windows 11 / Python 3.12 / pandas 3.0
  • 測定日:2026年9月21日
  • 注意:掲載したのは集計結果です。取得したデータそのものは配布していません