株式会社ホクソエムのブログ

R, Python, データ分析, 機械学習

有価証券報告テキストマイニング入門

はじめに

こんにちは, ホクソエムサポーターのKAZYです。 先日猫カフェデビューをして, 猫アレルギーであることがわかりました🐈。 次はフクロウカフェに挑戦してみようかなと思っています🦉。

ところで皆様, 有価証券報告書は読んでますか? 私は読んでいません。 読めません。 眺めていると眠くなります💤。

私は眠くなるんですが, 有価証券報告書ってテキストマイニングするのに向いているんです。企業の事業や財務情報が詳細に書かれています。 XBRL形式で構造化されています。 数千社分のテキストが手に入ります。 おまけに無料です。

どうです?興味湧いてきませんか?

本記事ではPythonを使って有価証券報告書をテキストマイニングする方法を紹介します。 有価証券報告書をダウンロードするところからご紹介するのでご安心を。

こんな方が見たら役に立つかも

  • 企業分析をプログラミングでやりたいが何していいか何もわからん方
  • プログラミングできるけど有価証券報告書何もわからん方
  • 自然言語処理をするのに丁度いいテキストを探している方

やること

  • 有価証券報告書についての説明
  • 有価証券報告書のダウンロード方法紹介
  • XBRLファイルについての説明
  • Pythonで有価証券報告書からテキスト抽出
  • 抽出したテキストから簡単なテキストマイニング

有価証券報告書とは

有価証券報告書, 通称「有報」👽🛸は企業の状況を外部へ開示するための資料です。 企業が自ら毎年作成しています。 企業分析をする際などによく利用されます。

提出企業

日本にうん100万社ある企業すべてが有報は提出をしている訳ではありません。

以下の条件を満たす企業だけが各事業年度毎に国へ提出を義務付けられています。

  • 金融商品取引所(証券取引所)に株式公開している会社
  • 店頭登録している株式の発行会社
  • 有価証券届出書提出会社
  • 過去5年間において、事業年度末日時点の株券もしくは優先出資証券の保有者数が1000人以上となったことがある会社(ただし、資本金5億円未満の会社を除く)

雰囲気としては上場企業+α が提出している感じです。 *1

記載内容

企業の沿革, 事業内容, 財務状況, 研究開発状況, 抱える課題, 経営方針, キャッシュフロー, 役員状況... などの情報がとても詳細に記述されています。

情報量

PDFで100ページを越えるような報告書が多いです。 例えば日本マクドナルドホールディングス株式会社の第49期の有価証券報告94ページです。 (100ページ越えてない...)

取得方法

有価証券報告の取得方法は大きく分けて以下の2つあります。

  1. ブラウザからダウンロード
  2. APIからダウンロード

今回は1.のブラウザからダウンロードする方法を紹介します。

有価証券報告書は金融庁が運営するEDINETと呼ばれるWEBサイトから自由にダウンロードができます。

皆さんご存知の日本を代表する企業, 株式会社ホクソエムの有価証券を検索してダウンロードしてみます。

該当するデータが存在しません。

と出てしまいました。

株式会社ホクソエムは有報の提出が義務付けられている会社ではありませんでした。

つぎに私が学生時代にお世話になった日本マクドナルドホールディングス株式会社を検索してみます🍔。
4件ヒットしました。 そのなかに平成27年~令和2年の有価証券報告書がありますね。 *2

XBRLと書かれたアイコンをクリックして見ましょう。 zipで圧縮されたファイルがダウンロードできます(PDFをクリックするとpdfの書類がダウンロードできます)。

ダウンロードしたzipファイルの中身

ダウンロードしたデータを展開すると以下のようなファイルが入っています。

Xbrl_Search_20200909_221659
├── S100ICBO
│   └── XBRL
│       ├── AuditDoc
│       │   ├── jpaud-aai-cc-001_E03366-000_2019-12-31_01_2020-03-30.xbrl
│       │   ├── jpaud-aai-cc-001_E03366-000_2019-12-31_01_2020-03-30.xsd
│       │   ├── jpaud-aai-cc-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│       │   ├── jpaud-aai-cc-001_E03366-000_2019-12-31_01_2020-03-30_pre.xml
│       │   ├── jpaud-aar-cn-001_E03366-000_2019-12-31_01_2020-03-30.xbrl
│       │   ├── jpaud-aar-cn-001_E03366-000_2019-12-31_01_2020-03-30.xsd
│       │   ├── jpaud-aar-cn-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│       │   ├── jpaud-aar-cn-001_E03366-000_2019-12-31_01_2020-03-30_pre.xml
│       │   └── manifest_AuditDoc.xml
│       └── PublicDoc
│           ├── 0000000_header_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0101010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0102010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0103010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0104010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0105010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0105020_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0106010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0107010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── 0200010_honbun_jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_ixbrl.htm
│           ├── images
│           │   ├── 0101010_001.png
│           │   ├── 0101010_002.png
│           │   └── 0104010_001.png
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30.xbrl ←これ
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30.xsd
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_cal.xml
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_def.xml
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_lab-en.xml
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_lab.xml
│           ├── jpcrp030000-asr-001_E03366-000_2019-12-31_01_2020-03-30_pre.xml
│           └── manifest_PublicDoc.xml
└── XbrlSearchDlInfo.csv

XML, HTML, CSV, XBRLファイルが入っていますね。

今回テキストマイニングに使用するのはxbrlの拡張子がついたファイルです。

XBRLファイルはAuditDoc,PublicDocの2つのディレクトリ内に入っています。 それぞれ有価証券報告書内の監査に関する報告, それ以外の報告が記載されています。

XBRLファイルとは

XBRLファイルについて, テキストマイニングに必要最低限の説明します。 XBRLファイルとはXMLをベース に事業報告用に拡張したマークアップ言語です。*3

実際にXBRLファイルを覗いてみると,

<?xml version="1.0" encoding="UTF-8"?>
<xbrli:xbrl>
︙~中略~
</xbrli:xbrl>

と記述されています。 一行目に思いっきりxmlと書いてあることが確認できると思います。 そういうことです。

また, 有報に記述する基本的な名前空間とタグは定義されており, タクソノミ要素リストで確認できます(リンクは2020年版)。

タグが統一されているので様々な企業が提出するXBRLファイルを一度にプログラムで処理しやすいのです。 素敵です。

具体例として, 有報表紙の企業名部分の名前空間とタグはそれぞれjpcrp_cor,CompanyNameCoverPageで書きましょうと決められております。

実際にマクドナルドとモスバーガーのXBRLファイル内の対象部分を見ると,

<jpcrp_cor:CompanyNameCoverPage contextRef="FilingDateInstant">日本マクドナルドホールディングス株式会社</jpcrp_cor:CompanyNameCoverPage>

<jpcrp_cor:CompanyNameCoverPage contextRef="FilingDateInstant">株式会社モスフードサービス</jpcrp_cor:CompanyNameCoverPage>

とどちらも同じタグの中に会社名が囲まれていますね。

これでどんな情報がどんなタグで表現されているかがわかるので早速プログラムを書いてテキスト抽出していきましょう。

XBRLファイルについてもっと詳しく知りたいという方用にオススメ記事リンク貼っておくので読んでみてください。

👇👇👇👇👇👇👇👇👇👇👇👇

note.com

note.com

note.com

Pythonを使って任意の項目を抽出する

次に, Pythonを用いてXBRLファイルから任意の項目のテキストを抽出します。 今回はlxmlというライブラリを使います。 *4

【会社名】項目の抽出

会社名をXBRLファイルから抽出してみます。 会社名は有価証券報告書の表紙に書いてあります。 以下のスクリプトで抽出きます。

from lxml import etree
mcdonalds_xbrl = "./Xbrl_Search_20200914_000607/S100IW0P/XBRL/PublicDoc/jpcrp030000-asr-001_E02675-000_2020-03-31_01_2020-06-25.xbrl"

# xbrlファイルを指定してパース
tree = etree.parse(mosuburger_xbrl)
root = tree.getroot()
# 名前空間とタグを指定して検索
company_name = root.find("jpcrp_cor:CompanyNameCoverPage",root.nsmap).text

>> 日本マクドナルドホールディングス株式会社

簡単ですね。 XBRLファイルをモスフードサービスのものに変更すると,

from lxml import etree
mosuburger_xbrl = "./Xbrl_Search_20200914_000607/S100IW0P/XBRL/PublicDoc/jpcrp030000-asr-001_E02675-000_2020-03-31_01_2020-06-25.xbrl"

# xbrlファイルを指定してパース
tree = etree.parse(mosuburger_xbrl)
root = tree.getroot()
# 名前空間とタグを指定して検索
company_name = root.find("jpcrp_cor:CompanyNameCoverPage",root.nsmap).text

>> 株式会社モスフードサービス

同じコードで会社名が取り出せました。

【事業の内容】項目を抽出

次に事業の内容が記載された項目の抽出を行ってみます(上図)。

タクソノミ要素リストから事業の内容のタグを調べます。jpcrp_cor:DescriptionOfBusinessTextBlockのタグでできると書いてあります。 検索するタグを変更してスクリプトを実行します。

from lxml import etree
mcdonalds_xbrl = "./Xbrl_Search_20200914_000607/S100IW0P/XBRL/PublicDoc/jpcrp030000-asr-001_E02675-000_2020-03-31_01_2020-06-25.xbrl"

# xbrlファイルを指定してパース
tree = etree.parse(mosuburger_xbrl)
root = tree.getroot()
# 名前空間とタグを指定して検索
bussiness_block = root.find("jpcrp_cor:DescriptionOfBusinessTextBlock",root.nsmap).text

>> '\n<h3>3【事業の内容】</h3>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">\u3000当社グループの事業はハンバーガーレストラン事業単一であるため、セグメント情報に関連付けた記載を行っていません。</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">(当社の事業内容)</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">\u3000当社は、日本マクドナルド株式会社の持株会社として、グループ企業の連結経営戦略の策定業務と実行業務及び不動産賃貸業務を主たる事業としております。</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">\u3000なお、当社は特定上場会社等であります。特定上場会社等に該当することにより、インサイダー取引規制の重要事実の軽微基準については連結ベースの数値に基づいて判断することとなります。</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">(関係会社の事業内容)</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">\u3000日本マクドナルド株式会社(当社出資比率100%)は、直営店方式による店舗運営とともにフランチャイズ方式による店舗展開を通じハンバーガーレストラン事業を展開しております。同社は、米国マクドナルド・コーポレーションから許諾されるライセンスに対するロイヤルティーを支払っております。日本国内においては、フランチャイズ店舗を経営するフランチャイジーに対してノウハウ及び商標等のサブ・ライセンスを許諾し、フランチャイジーからロイヤルティーを収受しております。</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px; font-weight: normal">\u3000当社と関係会社との当連結会計年度における資本関係及び取引関係の概要は、以下のとおりであります。</span>\n</p>\n<p style="margin-left: 24px; text-align: left">\n<span style="font-family: &apos;MS Mincho&apos;; font-size: 12px">[事業系統図]</span>\n</p>\n<p style="text-align: center">\xa0</p>\n<p style="text-align: left">\n<img style="height: 441px; width: 566.195739746094px" src="images/0101010_002.png" alt="0101010_002.png"/>\n</p>\n<p style="text-align: left">\xa0</p>\n<p style="text-align: left">\xa0</p>\n'

html形式の文字列が抽出されました。 XBRLの各タグの要素をhtml形式で表現しているものが多く存在します。 表形式の情報などはhtml形式としてパースを行って目的の情報を抽出できます。 今回はhtmlタグを取り除く処理を行います(ついでに改行コードも除く)。

# 正規表現操作のライブラリ
import re
# 改行や空白文字を削除する
bussiness_block = re.('\s','',bussiness_block)
# htmlタグを削除する
bussiness_block = re.('<.*?>','',bussiness_block)

>>'3【事業の内容】当社グループの事業はハンバーガーレストラン事業単一であるため、セグメント情報に関連付けた記載を行っていません。(当社の事業内容)当社は、日本マクドナルド株式会社の持株会社として、グループ企業の連結経営戦略の策定業務と実行業務及び不動産賃貸業務を主たる事業としております。なお、当社は特定上場会社等であります。特定上場会社等に該当することにより、インサイダー取引規制の重要事実の軽微基準については連結ベースの数値に基づいて判断することとなります。(関係会社の事業内容)日本マクドナルド株式会社(当社出資比率100%)は、直営店方式による店舗運営とともにフランチャイズ方式による店舗展開を通じハンバーガーレストラン事業を展開しております。同社は、米国マクドナルド・コーポレーションから許諾されるライセンスに対するロイヤルティーを支払っております。日本国内においては、フランチャイズ店舗を経営するフランチャイジーに対してノウハウ及び商標等のサブ・ライセンスを許諾し、フランチャイジーからロイヤルティーを収受しております。当社と関係会社との当連結会計年度における資本関係及び取引関係の概要は、以下のとおりであります。[事業系統図]'

事業の内容項目をきれいに抽出することができました。 ファイルをモスフードサービスに変更しても,

"3【事業の内容】当社グループは、㈱モスフードサービス(当社)及び子会社12社、関連会社14社により構成されており、主にフランチャイズシステムによる飲食店の展開を事業としております。事業は大きく「モスバーガー」等の商標を使用した飲食店を展開する「モスバーガー事業」、「マザーリーフ」「MOSDO」「ミアクッチーナ」「あえん」「chef'sV」「GREENGRILL」等の商標を使用した飲食店を展開する「その他飲食事業」、これらの飲食事業を衛生、金融、保険等で支援する「その他の事業」に分けることができます。事業内容と当社及び関係会社等の当該事業における位置付け及びセグメントとの関連は、次のとおりであります。セグメントの名称主要製品主要な会社モスバーガー事業「モスバーガー」等の運営ハンバーガー、ライスバーガー、モスチキン、スープ、ドリンク等及びパティ、バンズ、ポテト等の食材並びにカップ、パッケージ等の包装資材[国内]㈱モスフードサービス㈱モスストアカンパニー[台湾]安心食品服務(股)[シンガポール]モスフード・シンガポール社安心フードサービスシンガポール社[香港]モスフード香港社香港モスバーガーインベストメント社[中国]広東摩斯貝格餐飲管理有限公司[タイ]モスバーガー・タイランド社[オーストラリア]モスバーガー・オーストラリア社[インドネシア]モグインドネシア社[韓国]モスバーガーコリア社[フィリピン]モスバーガー・フィリピン社食品製造、食材販売事業パティ、ソース類等[国内]紅梅食品工業㈱タミー食品工業㈱[台湾]魔術食品工業(股)[フィリピン]モスサプライ・フィリピン社アグリ事業トマト、レタス等[国内]㈱モスファーム熊本㈱モス・サンファームむかわ㈱モスファームすずなり㈱モスファームマルミツ㈱モスファーム信州㈱モスファーム千葉その他飲食事業喫茶紅茶、ワッフル、パスタ、スイーツ等[国内]㈱モスフードサービス㈱モスストアカンパニーレストラン和風旬菜料理、洋風旬菜料理等[国内]㈱モスフードサービス㈱モスダイニングその他の事業食品衛生検査業ハンバーガー等の衛生検査、衛生関連商品の販売[国内]㈱エム・エイチ・エス金銭貸付業フランチャイジー(加盟店)への事業資金貸付[国内]㈱モスクレジット保険代理業生命保険、損害保険[国内]㈱モスクレジットレンタル業POSレジスター、看板等[国内]㈱モスクレジットグループ内アウトソーシング事業グループ内アウトソーシング事業[国内]㈱モスシャイン以上の企業集団等について事業系統図を図示すると次のとおりであります。(注)海外における事業は「モスバーガー事業」であります。子会社及び関連会社の連結の範囲は、次のとおりであります。子会社関連会社㈱エム・エイチ・エス※紅梅食品工業㈱㈱モスクレジット※タミー食品工業㈱㈱モスストアカンパニー※安心食品服務(股)㈱モスダイニング※モスバーガー・オーストラリア社㈱モスシャイン※モスバーガーコリア社モスフード・シンガポール社※モスバーガー・タイランド社魔術食品工業(股)※モスバーガー・フィリピン社モスフード香港社㈱モスファーム熊本モスサプライ・フィリピン社㈱モス・サンファームむかわ※(モグインドネシア社)㈱モスファームすずなり※(香港モスバーガーインベストメント社)㈱モスファームマルミツ※(広東摩斯貝格餐飲管理有限公司)㈱モスファーム信州㈱モスファーム千葉安心フードサービスシンガポール社計12社計14社(注)1.()内は非連結子会社であります。2.※印は持分法適用会社であります。"

この通りきれいに内容を抽出することができました。

これでテキストの抽出ができるようになりました。

企業の課題を用いてワードクラウドを作ってみる

簡単なテキストマイニングをやってみます。 異なる2つの業界の企業から有価証券報告書の【経営方針、経営環境及び対処すべき課題等】の項目を抽出して頻出ワードを抽出してワードクラウドを作ります。

各業界のおかれている状況の違いみたいなのが見えたらいいなぁというお気持ちです。

まず,

  • SaaS企業売上の高そうな10社
  • “ゴルフクラブ”と名のついた企業10社

の有価証券報告書を用意します。

【経営方針、経営環境及び対処すべき課題等】項目のテキストを抽出します。

1文中の将来に関する事項は、当事業年度末現在において当社が判断したものであります。(1)経営方針①ゴルフ場は会員様(株主)の財産であるとの意識を高く持ち、そのハード・…略

形態素解析して名詞だけ抽出します(mecab-python3を使用)。

1文中 将来 事項 事業年度末現在 当社 判断 もの * 経営方針*ゴルフ場 会員様 株主 財産 意識 ハード …略

そこからを用いてワードクラウドを作ります(wordcloudを使用)。

SaaS企業

ゴルフ場経営企業

ワードクラウドが作成できました。 売上のあるSaaS経営企業とゴルフ場経営企業では頻出するワードの雰囲気がぜんぜん違いますね。

名詞ではなくて形容詞を用いて同様にワードクラウドを作ってみました。

SaaS企業

ゴルフ場経営企業

ところゴルフ場経営企業の厳しさが伝わってきました。

👇ソースコードはこちら👇 github.com

おわりに

今回は有価証券報告書からテキストを抽出して単なテキストマイニングを紹介しました。 次のステップとして有価証券報告書から財務情報を抽出がオススメです。 html形式から情報抽出する技術が身につけられます。

*1:ちなみに日本の上場企業数は4000社程度です

*2:ちなみに有価証券報告書の電子提出が義務付けられたのは2004年6月からですがEDINETでは直近5年間の有価証券報告書しかダウンロードできません。 全人類が思いつくであろうある企業の過去15年分の有価証券報告書を使って分析というのができないのは少し残念です。 実はこんなサイトには直近5年以上前の情報もあったりします。

*3:そもそもXMLを知らない方はこことかを読んで見るといいかもしれません。

*4:標準ライブラリに入っているxmlではなくlxmlを使用した理由は名前空間のURIマップをライブラリで取得することができるからです。