今回は、動画を撮っていません。撮っている最中に面倒くさくなってしまいました。
ただやったことを記録として残すため、このブログは書こうと思います。
今回、J-Quants APIから取得した過去5年分の株価を、銘柄ごとにSQLiteへ保存できるようにしました。
ただ保存するだけではなく、すでにDBに入っている期間を確認し、まだ保存されていない期間だけを取得します。
これにより、処理を途中で止めても続きから再開でき、今後は新しく増えた株価だけを追加できるようになりました。
今回実装した部分
株アプリでは、画面にNext.js、バックエンドにFastAPI、データの保存にSQLiteを使用しています。
今回はその中でも、J-Quantsから株価を取得し、FastAPIとSQLAlchemyを通してSQLiteへ保存する部分を実装しました。

処理の流れは、次のとおりです。
-
- DBに登録されている銘柄を取得する
- 銘柄ごとに、保存済み株価の最古日と最新日を調べる
- 5年前から昨日までのうち、まだ保存されていない期間を求める
- J-Quants APIから不足期間の株価を取得する
- 同じ銘柄・同じ日付のデータがないことを確認する
- 取得した株価をDBへ保存する
株価を保存するテーブル
株価の履歴は、stock_price_historiesというテーブルへ保存します。
このテーブルに保存する情報は、次のとおりです。
id
株価データを1件ずつ識別するための番号です。データを追加すると、自動で連番が付きます。
company_code
どの会社の株価なのかを表す証券コードです。
price_date
その株価が、いつのものなのかを表す日付です。
close_price
その日の終値です。
source
株価の取得元です。今回はJ-Quantsから取得しているため、「J-Quants」と記録します。
created_at・updated_at
データを登録した日時と、最後に更新した日時です。
また、同じ銘柄・同じ日付の株価が2件保存されないように、company_codeとprice_dateの組み合わせを重複禁止にしました。
同じ銘柄でも日付が違えば保存できますが、同じ銘柄の同じ日付は1件だけ保存できます。
保存されていない期間だけを取得する
APIへリクエストする前に、銘柄ごとに次の情報をDBから調べます。
- 保存されている最も古い株価の日付
- 保存されている最も新しい株価の日付
株価が1件も保存されていない銘柄は、5年前から昨日までをまとめて取得します。
すでに株価がある場合は、保存済み期間の前後を確認し、不足している部分だけを取得します。
過去側が不足していれば、5年前から「保存済みの最古日の前日」までを取得します。
最新側が不足していれば、「保存済みの最新日の翌日」から昨日までを取得します。

| DBの状態 | from | to | 取得する範囲 |
|---|---|---|---|
| 株価データなし | 5年前 | 昨日 | 5年分すべて |
| 過去側が不足 | 5年前 | DBの最古日 − 1日 | 保存済み期間より前 |
| 最新側が不足 | DBの最新日 + 1日 | 昨日 | 保存済み期間より後 |
| 不足なし | ― | ― | リクエストしない |
保存済みの日付を取得範囲から外すことで、同じデータを繰り返し取得しないようにしています。
また、処理を途中で止めても、次回はDBに保存されている最新日を確認し、その続きから再開できます。
J-Quants APIから株価を取得する
取得する期間が決まったら、J-Quants APIへ次の情報を送ります。
- 取得する銘柄の証券コード
- 取得開始日
- 取得終了日
APIから返ってきたJSONをPythonで扱える形へ変換し、その中から株価データの一覧を取り出します。
データが返ってきた場合だけ、DBへの保存処理を行います。

同じ株価を重複させずに保存する
APIから取得した株価を保存する前に、次の2点を確認します。
- Companyテーブルに対象の会社が登録されていること
- 同じ会社・同じ日付の株価が、まだ保存されていないこと
この2つの条件を満たした株価だけを、新しいデータとして追加します。

株価を1件追加するたびに保存を確定しているわけではありません。
APIから受け取った株価を順番に追加し、1回のリクエストで取得した分を最後にまとめて確定しています。
通常は、ほぼ1銘柄分ずつ保存を確定する形です。
この方法なら、全銘柄の処理が終わる前にエラーや手動停止が発生しても、それまでに処理した銘柄のデータはDBに残ります。
APIのアクセス制限でエラーが発生
全銘柄の株価を取得している途中で、「429 Too Many Requests」というエラーが発生しました。
これは、短時間にAPIへ何度もリクエストを送ったため、アクセス回数の制限にかかったことを表しています。
そこで、1回リクエストを送るたびに1.2秒待ってから、次のリクエストを送るようにしました。
取得には時間がかかりますが、アクセス制限にかかりにくい形で処理を続けられるようになりました。
保存結果
保存処理が終わったあとは、SQLを使って次の内容を確認しました。
- 保存されている株価の総件数
- 株価が保存されている銘柄数
- 保存されている最も古い日付
- 保存されている最も新しい日付
【ここにスライド8「全銘柄の株価をDBへ保存できた」を挿入】
確認結果は、次のとおりでした。
- 株価データ:4,408,179件
- 銘柄数:3,897銘柄
- 保存期間:2021年8月26日から2026年8月26日まで
これで、J-Quantsから取得した約5年分の株価を、銘柄ごとにDBへ保存できました。
今回実装して分かったこと
最初は「APIから株価を取得して保存するだけ」と考えていました。
しかし、今後も継続して使える仕組みにするには、保存済みの期間を確認すること、重複を防ぐこと、途中から再開できることも必要でした。
すべての株価を毎回取り直すのではなく、不足している部分だけを取得することで、今後のデータ更新にも対応できそうです。
次にやること
株価をDBへ保存できるようになったので、次は保存したデータをDBから取り出し、株アプリの画面へ表示する処理を作ります。
これまではデータを集めて保存する段階でしたが、次回からは保存した株価を実際にアプリで使う段階へ進みます。

コメント