LoginSignup
77
102

More than 5 years have passed since last update.

投資するための財務分析step2「XBRLファイルをDBに取り込む」

Last updated at Posted at 2015-07-27

◆はじめに

ここでは、財務情報を取得するためのSTEPを紹介します。
今後は取得した財務情報を解析するまでに道筋を追って紹介していく予定です。
最終的には、公開企業の倒産確率を求めたり、独自ファクターを用いた株価予測モデルの構築などを考えています。
関連記事:

前step:

◆XBRL

◇XBRLファイルとは

WikipediaよりXBRLファイルとは、eXtensible Business Reporting Language(拡張可能な事業報告言語)の略称です。財務諸表などのビジネスレポートを電子文書化することでそれらの作成の効率化や比較・分析などの二次利用を目的として、XMLの規格をベースに作られた言語を表します。

◇会計にも共通化が必要に。XBRLが社会的に必要になった背景

XBRLファイルという形式で財務諸表を表しはじめた理由は、

のうちの1つの取り組みになります
平たくいえば、「日本独自の会計基準にならず、国際統一していこうよ」という施策により始まっているものです

◇XBRLファイルの読み方は次章

これは、次章で細かく細分化していきたいと思います
ひとまず、データを広いあげて何ができるかを本投稿では考えていきます

◆XBRLをDBロードできる形(CSV)へ変換する

◇EDINETが提供しているCSV変換アプリ

以下、でedinetにてXBRLをCSVに変換するアプリケーションを提供している。
ただし今回は、それを利用するとつまらないのと、CUIの口があるかわからなかったため、pythonで実装しました
https://disclosure.edinet-fsa.go.jp/download/ESE140131.pdf

◇事前準備

python にpython-xbrlというpackageをインストールする。
※私はここでやたらと詰まったので、本投稿の最下部にメモしておきます。

事前準備
pip install python-xbrl

◇PythonでCSVへデータ変換

以下の記事を参考にPythonでデータを取得するプログラムを作り直しました。

上記はPython2系で動くようなアプリですが、3系で動くように変更しています。
その他にも、IRデータベースが作成できるように一括で取得するような定義に変更しています。
主な変更点は以下になります

  • 前章で取得したXBRLファイルの全データをCSVへparseするようにロジックを変更
  • ラベル情報の取得などは別途マスタ化を行うものとして、XBRLのみをparseするように変更
  • ラベル定義は外出しして、取得したいラベルのみ情報を取得できるように変換
  • 結果をすべて1ファイルのCSV形式で出力(DBロードしやすくするため)

以下コードでは、前ステップで取得したXBRLファイルを一括でCSVファイルへ変換します。

XBRLファイルをCSVファイルへ変換する
# coding: utf-8
from xbrl import XBRLParser
import os, re, csv
from collections import defaultdict

default_tag = ['file_nm','element_id','amount']
custom_tag = ['unit_ref','decimals','contextref']
encode_type = 'utf-8'

class XbrlParser(XBRLParser):
    def __init__(self, xbrl_filepath):
        self.xbrl_filepath = xbrl_filepath

    def parse_xbrl(self):
        # parse xbrl file
        with open(self.xbrl_filepath,'r',encoding='utf-8') as of:
            xbrl = XBRLParser.parse(of) # beautiful soup type object
        result_dicts = defaultdict(list)
        _idx = 0

        #print xbrl
        name_space = 'jp*'
        for node in xbrl.find_all(name=re.compile(name_space+':*')):
            if self.ignore_pattern(node):
                continue

            row_dict = defaultdict(list)
            #default tag
            row_dict['file_nm'] = self.xbrl_filepath.rsplit('\\' or '/', 1)[1]
            row_dict['element_id'] = node.name
            row_dict['amount'] = node.string

            #cutom tag
            for tag in custom_tag:
                row_dict[tag] = self.get_attrib_value(node,tag)

            result_dicts[_idx] = row_dict
            _idx += 1
        return result_dicts

    def ignore_pattern(self, node):
        if 'xsi:nil' in node.attrs:
            if node.attrs['xsi:nil']=='true':
                return True
        #結果が空の場合は対象外にする
        if not isinstance(node.string, str):
            return True
        # 改行コードが結果にある場合対象外にする
        if str(node.string).find(u'\n') > -1:
            return True
        #text文字列は解析に利用できないため、対象外
        if u'textblock' in str(node.name):
            return True
        return False

    def get_attrib_value(self, node, attrib):
        if attrib in node.attrs.keys():
            return node.attrs[attrib]
        else:
            return None

#ディレクトリ配下のファイルのうちis_xbrl_fileがTrueのもののみ取得する
def fild_all_files(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            if not is_xbrl_file(root,file):
                continue
            yield os.path.join(root, file)

def is_xbrl_file(root_path,file_name):
    #xbrlファイルでなければ対象外
    if not file_name.endswith('.xbrl'):
        return False
    #AuditDocは対象外
    if u'AuditDoc' in str(root_path):
        return False
    return True

def dump_file(writer,info_dicts):
    _idx = 0
    while _idx < len(info_dicts):
        row_dict = info_dicts[_idx]
        writer.writerow(row_dict)
        _idx += 1

def main():
    base_path = os.getcwd()+'/xbrl_files'

    #writerオブジェクト生成
    resultCsvWriter = csv.DictWriter(
                            open('eggs.csv', 'w',encoding=encode_type)
                        ,   default_tag + custom_tag
                        ,   lineterminator="\n")
    resultCsvWriter.writeheader()

    #対象ファイルを抽出
    xbrl_files = fild_all_files(base_path)
    count = 0
    for xbrl_file in xbrl_files:
        count += 1
        print ('getting data...'+xbrl_file)
        xp = XbrlParser(xbrl_file)
        info_dicts = xp.parse_xbrl()
        dump_file(resultCsvWriter,info_dicts)

if __name__=='__main__':
    main()

◆次回予定:XBRLファイルの中身を解読する(&タグのマスタ作成)

次回、更新またはソースをリファクタリングした際はストックした方に通知するように致します。

☆【参考】事前準備でつまった方へ

Windows環境でインストール時に詰まったので、そのメモになります。
もし、以下のエラーがでるようであれば、追加でMicrosoft Visual C++のdownloadが必要

Microsoft Visual C++ 10.0 is required(Unable to find vcvarsall.bat).

加えて、それでもなお以下のようなエラーがでるようであれば、

lxml\includes\etree_defs.h(14) : fatal error C1083: include ファイルを開けません。'libxml/xmlversion.h': No such file or directory

事前準備でエラーのとき
pip install lxml

私の場合は、それでも同じエラーでダメだったので、以下で実行しました
※参考

事前準備のエラーが解消しないとき
set STATICBUILD=true && pip install lxml

上記を実施することで、なんとか私はpython-xbrlのインストールができました。

77
102
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
77
102