EDINET四半期データビューアの設計とデータパイプライン
昨日までに年次データの可視化ページが動いていた。今日は「四半期も見たい」から始まって、データの取り方・渡し方で3回方針が揺れ、最終的に計画書と指示書を書き上げるところまで進んだ。コードは1行も書いていない。設計だけで半日が溶けた日。
Turso Embedded Replicaの使い分けを整理した
朝一番の疑問は「edinet-apiディレクトリで取得したデータを、mdx-playgroundディレクトリでどう読むのか」だった。ローカルにSQLiteファイルがあり、Tursoのクラウドにもデータがある。turso-replicas というディレクトリも存在する。3つの場所にデータが散らばっている状態を整理するところから始めた。
確認した結果、構成は以下の通り。
- edinet-api: EDINET DB APIを叩いてデータを取得し、ローカルSQLiteに保存。
turso db pushでクラウドに同期 - turso-replicas: Embedded Replicaのローカルキャッシュ。クラウドDBのミラーとして各プロジェクトから読み取り用に使う
- mdx-playground: 表示側。クラウドのTursoDB(またはレプリカ)からデータを引いてJSONに変換し、フロントに渡す
プロジェクト間でデータを共有するには、クラウド側を経由するのが正解。edinet-api側でクラウドに同期した後、mdx-playground側でクラウドから sync すれば最新データがローカルレプリカに降りてくる。
四半期ビューアの計画を立てた
年次データは既に2社分(会計ソフトA、会計ソフトB)がチャート表示できている。四半期を追加する方針を固めるため、計画書を作った。
骨子は以下の通り。
- 右カラムに「年次 / 四半期」のタブ切替を追加
- 四半期タブには6つのチャートを2x3グリッドで並べる(売上高、営業利益+営業利益率、経常利益・純利益、BS、CF、純利益単独四半期)
- データは
data/edinet/E35325_quarterly.jsonのようなJSONファイルとして静的配置 - 既存の
BaseComboChartコンポーネントをそのまま再利用
Codexレビューで計画を修正した
Codexにプランを投げたところ、致命的な指摘が2つ返ってきた。
1つ目は累計→単独値変換のテスト不足。年次データでは113件のテストを書いたのに、四半期にはテストがない。「Q1+Q2+Q3+Q4の合計が年次PLに一致するか」を自動検証すべきだという指摘。これはそのまま計画に追加した。
2つ目は四半期EPSの扱い。四半期報告のEPSは累計値で、単純に差し引いても正しい単独四半期EPSにならない。加重平均株式数が四半期ごとに変わるからだ。この指摘を受けて、6つ目のチャートをEPSから「純利益(単独四半期)」に差し替えた。年次タブにEPSチャートがあるので、そちらで確認すれば足りる。
データパイプラインの設計で3回揺れた
この日一番時間を使ったのが、四半期データをフロントまでどう届けるかの方式選定だった。3つの案を行ったり来たりした。
案1: Turso sync → JSON生成スクリプト
最初に固まった案。edinet-api側でAPIデータをTursoに格納済みなので、mdx-playground側でTursoクラウドから sync し、Pythonスクリプトで累計→単独値変換してJSONを吐く。
edinet-api → Turso クラウドDB → mdx-playground側でsync → Python → JSON → Vue composable
データの一元管理ができる。ただし、Tursoトークンが .env にあるのでClaude Codeが直接スクリプトを実行できない。
案2: Python直接JSON生成(Turso不要)
途中で「確認しながら進めたい」と考え直した。Tursoを経由せず、EDINET DB APIを直接Pythonスクリプトで叩いてJSONを生成する案。ビルド不要で pnpm dev のホットリロードで即反映される点が魅力だった。
ただ冷静に考えると、edinet-api側に既にTursoへの格納パイプラインがある。同じAPIを二重に叩く意味がない。
案3(採用): edinet-api側でTurso格納 → mdx-playground側でJSON生成
結局、案1に戻った。ただし、mdx-playground側のClaude Codeが自力でTursoDB接続するのが手間だったので、edinet-api側のClaude Codeに指示書を渡してJSONを出力してもらう方式に落ち着いた。
edinet-api側Claude Code: Turso → 累計→単独値変換 → JSON出力
↓(JSONファイルをmdx-playground/apps/web/data/edinet/ に配置)
mdx-playground側Claude Code: JSONをimportしてVueで表示
揺れた原因を振り返ると、「どこでデータ変換するか」と「誰がスクリプトを実行するか」が別の問題なのに、一緒に考えていたからだった。データの一元管理はTurso、変換の実行はedinet-api側のセッション、表示はmdx-playground側のセッション。役割を分けたら迷いが消えた。
セッション間連携の指示書を書いた
edinet-api側のClaude Codeに渡す指示書を memo/2026-04-12/edinet-quarterly-data-export-instruction.md に作成した。盛り込んだ要素は以下の通り。
- 対象企業のEDINETコードと期末月
- APIエンドポイントのURL
- 出力JSON形式(年次JSONと同じ
{ "data": [...] }構造にquarterフィールドを追加) - 累計→単独値の変換ルール(P/L・CFは差し引き、BSはそのまま)
- フィールド一覧と優先度
- 検証ポイント(Q合計が年次に一致するか、BS貸借が合うか)
別セッションのClaude Codeに正確な仕事をしてもらうには、出力形式と検証条件を明示した指示書がいる。口頭で伝えると、フィールド名の揺れや変換ルールの曖昧さが入り込む。
銘柄追加の手順を整理した
現在Tursoに入っているのは会計ソフトA(E33390)と会計ソフトB(E35325)の2社のみ。今後銘柄を追加するときの手順も計画書に盛り込んだ。
- EDINET検索APIでEDINETコードを調べる(認証不要)
- edinet-api側の
store_to_turso.pyにコードを追加して6エンドポイント分を取得・格納 - mdx-playground側でJSON生成スクリプトを実行
types/edinet.tsのEDINET_COMPANIES配列に企業メタデータを追加
手順をドキュメント化しておくと、次に銘柄を追加するときに「何をやるんだっけ」と手が止まらない。
今日の学び
- データの一元管理と変換の実行場所は別の問題。Turso(一元管理)を使うかどうかと、どのセッションでスクリプトを走らせるかは独立した判断。混ぜて考えると方針が揺れる
- Codexレビューは設計段階で入れると効く。テスト不足とEPS問題は、実装後に気づいていたら手戻りが大きかった。コードを書く前に計画書をレビューに出したのは正解
- 別セッションへの指示書は「出力形式」と「検証条件」を書く。ロジックの説明より、期待する成果物の仕様を正確に伝える方が結果が安定する