ChatGPTを使ってEDINETのCSVファイルから財務諸表を機械的に解析する方法

:::note warn
警告
以下プログラムの利用に伴って発生した不利益や問題について、原因のいかんを問わず、一切の責任を負わないものとします。
:::

# はじめに

現在、個人で「Financial Lens（ファイナンシャルレンズ）」というWebサービスを開発しています。

### **Financial Lensとは？**

「Financial Lens」は、上場企業の財務情報や適時開示を簡単に閲覧できるWebサービスで、Web APIの提供も予定していて、過去10年分の企業業績をプログラムから取得できます。企業の財務状況を素早く分析したい個人投資家や研究者にとって、強力なツールとなることを目指しています。

現在、β版のリリース準備を進めていて、事前登録を受け付けています。興味のある方は、ぜひ以下のリンクから事前登録をよろしくお願いします🙇

👉 **[Financial Lens 事前登録ページ](https://lp.financial-lens.jp/)**

![financial-lens-hs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/7c05ec7f-3cbf-2b16-249b-5a59f70f839a.png)


## 記事の目的
Financial LensはEDINET（Electronic Disclosure for Investors' NETwork）という金融庁が運営する有価証券報告書などの開示書類を電子的に閲覧できるシステムからデータを取得しています。

EDINETは公式のEDINET API（Version2）を提供していて、開示書類をXBRL形式、または2024年4月1日からはCSV形式でも取得可能となりました。

上記サービスを開発する過程で現在も上場していて、会計基準がかつて米国基準だった企業（トヨタ自動車、NTT等）の財務諸表の連結決算のデータがCSVファイルになく、苦戦しました。

例えば、連結損益計算書の場合、`ConsolidatedStatementOfIncomeUSGAAPTextBlock`に以下のようにテキストブロックとして格納していて、前年度と今年度で金額が連結しているので以下のままでは機械的な処理ができません。

```
②【連結損益計算書】(単位：百万円)  前連結会計年度（2016年4月 1日から2017年3月31日まで）当連結会計年度（2017年4月 1日から2018年3月31日まで） 営業収益 (注4,20)   固定音声関連収入1,233,8851,146,901 移動音声関連収入865,293942,183 IP系・パケット通信収入3,808,9723,801,771 通信端末機器販売収入806,493843,548 システムインテグレーション収入3,041,5873,443,147 その他の営業収入1,634,7861,622,037 営業収益合計11,391,01611,799,587 営業費用 (注4,22)   サービス原価（以下に個別掲記する科目を除く）2,487,5882,348,541 通信端末機器原価（以下に個別掲記する科目を除く）879,725915,540 システムインテグレーション原価（以下に個別掲記する科目を除く）2,161,0072,471,347 減価償却費 (注13,20)1,462,2351,339,423 減損損失 (注20)   営業権 (注12)53,29418,864 メタルケーブル関連 (注9)－124,800 その他20,55818,505 販売費及び一般管理費 (注22)2,786,8202,919,724 営業費用合計9,851,22710,156,744 営業利益 (注20)1,539,7891,642,843 営業外損益   支払利息、社債発行差金償却及び社債発行費△37,761△32,188 受取利息17,75319,094 仲裁裁定金収入 (注10)－147,646 その他、純額 (注10,11,23,24)7,988△21,771 営業外損益合計△12,020112,781 税引前当期純利益1,527,7691,755,624 法人税等 (注16)468,370541,864 当年度分472,711532,525 繰延税額△4,3419,339 持分法による投資利益（△損失）調整前利益1,059,3991,213,760 持分法による投資利益（△損失）(注10,20)△215,551 当期純利益1,059,3781,219,311 控除：非支配持分に帰属する当期純利益259,249309,616 当社に帰属する当期純利益800,129909,695  1株当たり情報 （注18）：   期中平均発行済株式数（自己株式を除く）(株)2,046,678,1441,995,912,757 当社に帰属する当期純利益（円）390.94455.78 配当金（円）120.00150.00
```

![スクリーンショット 2025-02-05 22.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/1d9da74f-7496-1bad-5b89-e8919b6663e3.png)

しかし、130件程のCSVファイルを手動で解析するのは面倒だったのと、いくつかの代表的な開示項目（売上高、営業利益等）だけが欲しかったので、生成AIを使えば自動で取得できるかもしれないと思いChatGPT APIを使って検証しました。Financial LensはPythonとDjangoを使って実装しているので、検証プログラムもDjangoのコマンドとして実装しました。

抽出したい対象年度の開示項目を指定しつつ期待する出力形式を入力テキストと一緒にChatGPTへ送信します。

```python:python
import json
import logging
import traceback

from django.core.management.base import BaseCommand
from django.db import connection
from openai import OpenAI
from slack_sdk import WebClient

import config.settings as settings
from common.models import ManualEdinetFinancialStatement


class Command(BaseCommand):
    help = ''

    def get_records(self):
        # DBからレコードを取得（省略）

    def fetch_openai_response(self, content):
        client = OpenAI(api_key=settings.OPENAI_API_KEY)
        completion = client.chat.completions.create(
            model="gpt-4o-2024-11-20",
            messages=[{"role": "user", "content": content}]
        )
        text = completion.choices[0].message.content
        text = text.replace('```json', '')
        text = text.replace('```', '')
        return json.loads(text)

    def get_balance_sheet(self, row):
        answer_format = json.dumps({'現金及び預金': 1000000}, ensure_ascii=False)
        content = f"以下のテキストから当期({row['jpdei_cor_CurrentPeriodEndDateDEI']}時点)の損益計算書のデータを抽出して。抽出して欲しいのは、現金及び預金、有価証券、売掛金、棚卸資産、流動資産、有形固定資産、無形固定資産、固定資産、資産、流動負債、短期借入金、社債、1年以内返済予定の長期借入金、固定負債、負債、資本金、資本剰余金、利益剰余金、自己株式、株主資本、非支配株主持分、純資産、負債純資産になります。データがない場合もあるのでない場合はnull(文字列ではない)にしてください。回答はJSON文字列だけにして。回答結果としては{answer_format}であることを期待します。JSONのkeyは日本語で記述して。\n{row['jpcrp_cor_ConsolidatedBalanceSheetUSGAAPTextBlock']}"
        return self.fetch_openai_response(content)

    def get_income_statement(self, row):
        answer_format = json.dumps({'売上高': 1000000}, ensure_ascii=False)
        content = f"以下のテキストから当期({row['jpdei_cor_CurrentPeriodEndDateDEI']}時点)の損益計算書のデータを抽出して。抽出して欲しいのは、売上高、売上原価、売上総利益又は売上総損失、販売費及び一般管理費、研究開発費、営業利益又は営業損失、支払利息、経常利益又は経常損失、特別利益、特別損失、税引前当期純利益又は税引前当期純損失、法人税等、当期純利益又は当期純損失、1株当たり当期純利益、潜在株式調整後1株当たり当期純利益になります。データがない場合もあるのでない場合はnull(文字列ではない)にしてください。回答はJSON文字列だけにして。回答結果としては{answer_format}であることを期待します。JSONのkeyは日本語で記述して。\n{row['jpcrp_cor_ConsolidatedStatementOfIncomeUSGAAPTextBlock']}"
        return self.fetch_openai_response(content)

    def get_cash_flow_statement(self, row):
        answer_format = json.dumps({'営業活動によるキャッシュ・フロー': 1000000}, ensure_ascii=False)
        content = f"以下のテキストから当期({row['jpdei_cor_CurrentPeriodEndDateDEI']}時点)の損益計算書のデータを抽出して。抽出して欲しいのは、営業活動によるキャッシュ・フロー、減価償却費、支払利息、投資活動によるキャッシュ・フロー、財務活動によるキャッシュ・フロー、現金及び現金同等物の残高になります。データがない場合もあるのでない場合はnull(文字列ではない)にしてください。回答はJSON文字列だけにして。回答結果としては{answer_format}であることを期待します。JSONのkeyは日本語で記述して。\n{row['jpcrp_cor_ConsolidatedStatementOfCashFlowsUSGAAPTextBlock']}"
        return self.fetch_openai_response(content)

    def remove_chars(self, text):
        if isinstance(text, str):
            return text.replace(',', '').replace('円', '').replace('△', '-')
        return text

    def handle(self, *args, **options):
        statements = self.get_records()
        for statement in statements:
            balance_sheet = self.get_balance_sheet(statement)
            income_statement = self.get_income_statement(statement)
            cash_flow_statement = self.get_cash_flow_statement(statement)

        # DBへの保存処理（省略）

```

# 検証結果

今回NTTの2018年3月期の有価証券報告書を使って検証しました。

## 貸借対照表

![スクリーンショット 2025-02-06 0.43.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/7b265f1b-8103-ff90-c2d6-1d7b21218637.png)

![スクリーンショット 2025-02-06 0.43.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/a6b9318f-6acd-daf9-b0a0-2785496797b0.png)

```text:入力テキスト
①【連結貸借対照表】(単位：百万円)  前連結会計年度(2017年3月31日)当連結会計年度(2018年3月31日)  資産の部 (注20)   流動資産   現預金及び現金同等物 (注6,7)925,213780,300 短期投資63,84431,641 受取手形及び売掛金 (注4,7,24)2,699,7082,976,467 貸倒引当金(注25)△48,626△52,332 未収入金505,145662,190 棚卸資産 (注8)365,379393,582 前払費用及びその他の流動資産 (注24)573,170575,704 繰延税金資産 (注16)228,590－ 流動資産合計5,312,4235,367,552 有形固定資産 (注21)   電気通信機械設備11,046,11510,917,851 電気通信線路設備 (注9)16,064,73214,217,566 建物及び構築物6,147,8696,280,584 機械、工具及び備品2,032,3892,127,201 土地1,292,6851,307,985 建設仮勘定421,819438,604 小計37,005,60935,289,791 減価償却累計額△27,286,588△25,468,698 有形固定資産合計9,719,0219,821,093 投資及びその他の資産   関連会社投資 (注10)484,596502,936 市場性のある有価証券及びその他の投資 (注11)495,290525,170 営業権 (注12,27)1,314,6451,329,275 ソフトウェア(注13)1,209,4851,223,985 その他の無形資産 (注13)453,918394,489 その他の資産 (注15,24)1,492,0761,590,636 繰延税金資産 (注16)768,871920,634 投資及びその他の資産合計6,218,8816,487,125 資産合計21,250,32521,675,770   (単位：百万円)  前連結会計年度(2017年3月31日)当連結会計年度(2018年3月31日)  負債及び資本の部   流動負債   短期借入金 (注14)227,207270,743 1年以内の返済予定長期借入債務 (注14,24)681,904624,385 買掛金 (注4)1,612,9961,613,516 短期リース債務 (注21)14,43012,567 未払人件費443,308460,357 未払法人税等239,755245,326 未払消費税等75,08388,420 前受金324,342374,444 その他の流動負債 (注16,24)512,368549,263 流動負債合計4,131,3934,239,021 固定負債   長期借入債務 (注14,24)3,168,4782,947,945 長期リース債務 (注21)25,56822,587 未払退職年金費用 (注15)1,599,3811,619,907 ポイントプログラム引当金103,047105,037 繰延税金負債 (注16)166,751128,833 その他の固定負債 (注24)497,132529,959 固定負債合計5,560,3575,354,268 償還可能非支配持分 (注17)50,81949,930 資本 (注18)   株主資本   資本金937,950937,950 資本剰余金2,862,0352,853,613 利益剰余金 (注10)5,626,1556,260,631 その他の包括利益（△損失）累積額(注11,15,24)1,56244,529 自己株式△375,223△610,742 株主資本合計9,052,4799,485,981 非支配持分2,455,2772,546,570 資本合計11,507,75612,032,551 負債及び資本合計21,250,32521,675,770  (単位：円)  前連結会計年度(2017年3月31日)当連結会計年度(2018年3月31日)  1株当たり情報 （注18）：   株主資本4,491.734,812.59
```

```json:出力結果
{
  "現金及び預金": 780300,
  "有価証券": 31641,
  "売掛金": 2976467,
  "棚卸資産": 393582,
  "流動資産": 5367552,
  "有形固定資産": 9821093,
  "無形固定資産": null,
  "固定資産": null,
  "資産": 21675770,
  "流動負債": 4239021,
  "短期借入金": 270743,
  "社債": null,
  "1年以内返済予定の長期借入金": 624385,
  "固定負債": 5354268,
  "負債": 9593289,
  "資本金": 937950,
  "資本剰余金": 2853613,
  "利益剰余金": 6260631,
  "自己株式": -610742,
  "株主資本": 9485981,
  "非支配株主持分": 2546570,
  "純資産": 12032551,
  "負債純資産": 21675770
}
```

貸借対照表の金額と出力結果を照合する限り、主要な開示項目は正しく抽出できていることが確認できます。負債合計の金額は貸借対照表にはありませんが、流動負債と固定負債の金額を自動で合計して適切に抽出できています。固定資産の合計金額は`null`になっていますが、ほかの開示項目を利用すれば算出できそうなので、ChatGPTへの指示を変更すれば改善できるかもしれません。

## 損益計算書

![スクリーンショット 2025-02-05 22.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/1d9da74f-7496-1bad-5b89-e8919b6663e3.png)

```text:入力テキスト
②【連結損益計算書】(単位：百万円)  前連結会計年度（2016年4月 1日から2017年3月31日まで）当連結会計年度（2017年4月 1日から2018年3月31日まで） 営業収益 (注4,20)   固定音声関連収入1,233,8851,146,901 移動音声関連収入865,293942,183 IP系・パケット通信収入3,808,9723,801,771 通信端末機器販売収入806,493843,548 システムインテグレーション収入3,041,5873,443,147 その他の営業収入1,634,7861,622,037 営業収益合計11,391,01611,799,587 営業費用 (注4,22)   サービス原価（以下に個別掲記する科目を除く）2,487,5882,348,541 通信端末機器原価（以下に個別掲記する科目を除く）879,725915,540 システムインテグレーション原価（以下に個別掲記する科目を除く）2,161,0072,471,347 減価償却費 (注13,20)1,462,2351,339,423 減損損失 (注20)   営業権 (注12)53,29418,864 メタルケーブル関連 (注9)－124,800 その他20,55818,505 販売費及び一般管理費 (注22)2,786,8202,919,724 営業費用合計9,851,22710,156,744 営業利益 (注20)1,539,7891,642,843 営業外損益   支払利息、社債発行差金償却及び社債発行費△37,761△32,188 受取利息17,75319,094 仲裁裁定金収入 (注10)－147,646 その他、純額 (注10,11,23,24)7,988△21,771 営業外損益合計△12,020112,781 税引前当期純利益1,527,7691,755,624 法人税等 (注16)468,370541,864 当年度分472,711532,525 繰延税額△4,3419,339 持分法による投資利益（△損失）調整前利益1,059,3991,213,760 持分法による投資利益（△損失）(注10,20)△215,551 当期純利益1,059,3781,219,311 控除：非支配持分に帰属する当期純利益259,249309,616 当社に帰属する当期純利益800,129909,695  1株当たり情報 （注18）：   期中平均発行済株式数（自己株式を除く）(株)2,046,678,1441,995,912,757 当社に帰属する当期純利益（円）390.94455.78 配当金（円）120.00150.00
```

```json:出力結果
{
  "売上高": 11799587,
  "売上原価": 10156744,
  "売上総利益又は売上総損失": 162843,
  "販売費及び一般管理費": 2919724,
  "研究開発費": null,
  "営業利益又は営業損失": 1642843,
  "支払利息": -32188,
  "経常利益又は経常損失": null,
  "特別利益": null,
  "特別損失": null,
  "税引前当期純利益又は税引前当期純損失": 1755624,
  "法人税等": 541864,
  "当期純利益又は当期純損失": 1219311,
  "1株当たり当期純利益": 455.78,
  "潜在株式調整後1株当たり当期純利益": null
}
```

損益計算書と出力結果を照合すると、「売上原価」として営業費用合計 (10,156,744 百万円)を抽出しているのは誤りで、売上原価は、営業費用のうち「サービス原価」「通信端末機器原価」「システムインテグレーション原価」などに該当する部分であり、営業費用合計を売上原価とするのは適切ではないと考えます。しかし、売上原価以外の主要な開示項目は正しく抽出できていることが確認できます。

## キャッシュフロー計算書

![スクリーンショット 2025-02-06 0.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/fa30308d-9983-bec1-77c2-1cfae4d6fcef.png)

![スクリーンショット 2025-02-06 0.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76958/9f3440c2-0e83-6f94-fdf4-d4e277e033fa.png)


```text:入力テキスト
⑤【連結キャッシュ・フロー計算書】 (単位：百万円)  前連結会計年度（2016年4月 1日から2017年3月31日まで）当連結会計年度（2017年4月 1日から2018年3月31日まで） 営業活動によるキャッシュ・フロー   当期純利益1,059,3781,219,311 当期純利益から営業活動によるキャッシュ・フローへの調整：   減価償却費 (注13,20)1,462,2351,339,423 減損損失 (注9,12,20)73,852162,169 繰延税額 (注16)△4,3419,339 固定資産除却損105,79069,585 固定資産売却益△15,633△9,201 持分法による投資（△利益）損失 (注10)21△5,551 受取手形及び売掛金の（△増加）減少額 (注7)63,842△231,845 棚卸資産の（△増加）減少額 (注8)△731△44,491 その他の流動資産の（△増加）減少額△30,143△139,684 買掛金及び未払人件費の増加（△減少）額52,87212,437 未払消費税等の増加（△減少）額△7,25812,918 前受金の増加（△減少）額36,92552,790 未払法人税等の増加（△減少）額△8,9317,516 その他の流動負債の増加（△減少）額8,93472,822 未払退職年金費用の増加（△減少）額7,13335,930 その他の固定負債の増加（△減少）額41,78521,703 その他71,62752,376 営業活動によるキャッシュ・フロー2,917,3572,637,547   (単位：百万円)  前連結会計年度（2016年4月 1日から2017年3月31日まで）当連結会計年度（2017年4月 1日から2018年3月31日まで）   投資活動によるキャッシュ・フロー   有形固定資産の取得による支出△1,301,697△1,308,727 無形固定資産の取得による支出△400,110△401,995 有形固定資産の売却による収入24,92015,842 長期投資による支出△40,344△53,843 長期投資の売却及び償還による収入58,83527,018 新規連結子会社の取得による支出（取得現金控除後） (注27)△329,005△19,614 短期投資による支出△178,939△208,043 短期投資の償還による収入146,132249,987 その他△69,103△142,402 投資活動によるキャッシュ・フロー△2,089,311△1,841,777 財務活動によるキャッシュ・フロー   長期借入債務の増加による収入 (注14)320,464440,903 長期借入債務の返済による支出 (注14)△485,612△635,900 短期借入債務の増加による収入 (注14)4,987,7956,810,893 短期借入債務の返済による支出 (注14)△4,897,024△6,769,488 配当金の支払額△247,994△271,405 自己株式の売却及び取得（純額）(注18)△374,436△235,570 非支配持分からの子会社株式取得による支出△155,905△132,466 その他△128,799△138,625 財務活動によるキャッシュ・フロー△981,511△931,658 現預金及び現金同等物に係る換算差額△6,959△3,106 現預金及び現金同等物の増加（△減少）額△160,424△138,994 現預金及び現金同等物の期首残高1,088,275925,213 連結子会社の決算期変更に伴う現預金及び現金同等物の増加（△減少）額 (注3)△2,638△5,919 現預金及び現金同等物の期末残高 (注6,7)925,213780,300  補足情報 (単位：百万円)   前連結会計年度（2016年4月 1日から2017年3月31日まで）当連結会計年度（2017年4月 1日から2018年3月31日まで） 各連結会計年度の現預金支払額：   支払利息37,33932,262 法人税等（純額）468,357575,943 現金支出を伴わない投資及び財務活動：   キャピタル・リース債務発生額16,80913,594
```


```json:出力結果
{
  "営業活動によるキャッシュ・フロー": 2637547,
  "減価償却費": 1339423,
  "支払利息": 32262,
  "投資活動によるキャッシュ・フロー": -1841777,
  "財務活動によるキャッシュ・フロー": -931658,
  "現金及び現金同等物の残高": 780300
}
```

損益計算書と出力結果を照合する限り、全ての取得しようとした開示項目は正しく抽出できていて、抽出の精度は高いと考えます。

# まとめ
以上、EDINETのCSVファイルから財務諸表を機械的に解析する方法を紹介しました。EDINETの財務諸表のデータは、テキストブロックで格納しているため、従来の方法では機械的な処理が困難でしたが、ChatGPT（OpenAI API）を活用し、特定の開示項目を自動抽出する仕組みを構築できました。

まだ完璧ではないので最終的な人間の確認は必要ですが、機械的に財務情報を抽出し、多くの人間による作業を削減できると思います。

EDINETのデータを活用したい方は、是非上記の方法を参考に色々試してみて下さい。Google Geminiの抽出精度を比較するのも面白いかもと思いました。

# 最後に
「Financial Lens」では、 現在、β版のリリース準備を進めていて、事前登録を受け付けています。EDINETの開示情報をより便利に活用したい方は、ぜひチェックしてみて下さい！

**[Financial Lens 事前登録ページ](https://lp.financial-lens.jp/)**