GIL's LAB

Open DART를 이용한 기업공시 수집 (4) 전체 재무제표 수집 본문

퀀트 투자/데이터 수집

Open DART를 이용한 기업공시 수집 (4) 전체 재무제표 수집

GIL~ 2021. 12. 15. 16:14

이번 포스팅에서는 OpenDartReader를 이용하여 코스피/코스닥 전체 기업의 주요 재무지표를 수집하겠습니다.

보고서 제출 날짜 뿐만 아니라, 분기별 보고서까지 모두 포함시키겠습니다.

 

OpenDartReader의 설치와 사용 방법은 이전 포스팅을, finstate 메서드에 대한 설명은 이전 포스팅 2를 참고해주시기 바랍니다.

 

 

환경 설정

먼저, 필요한 패키지를 모두 불러옵니다.

import os
import OpenDartReader
import FinanceDataReader as fdr

다음으로 종목 목록을 다음과 같이 불러옵니다.

stock_list = fdr.StockListing("KRX").dropna()

결측을 제거한 이유는 선물이나 우선주는 지역 등의 정보가 결측이고 이들은 재무제표가 당연히 없기 때문입니다. 

 

필요 함수 정의

이제 재무제표에서 문자로 표시된 숫자를 숫자로 바꿔주는 함수를 작성하겠습니다.

# 숫자로 모두 변환
def convert_str_to_float(value):
    if type(value) == float: # nan의 자료형은 float임
        return value
    elif value == '-': # -로 되어 있으면 0으로 변환
        return 0
    else:
        return float(value.replace(',', ''))

마지막으로 데이터를 불러와서 저장하는 함수를 작성하겠습니다.

def extract_info_and_save(dart, path, year, name, code, report_type, report_type_code):
    report = dart.finstate(code, year, report_type_code)
    if report is None:
        pass
    else:
        submission_date = report['rcept_no'].iloc[0][:8]
        report = report[['fs_nm', 'account_nm', 'thstrm_dt', 'thstrm_amount', 'sj_nm']]
        report.rename({"fs_nm":"개별/연결",
                       "account_nm":"계정명",
                       "sj_nm":"재무제표명",
                       "thstrm_dt": "당기일자",
                       "thstrm_amount":"금액"}, axis = 1, inplace = True)
        report['금액'] = report['금액'].apply(convert_str_to_float)
        
        try:
            os.mkdir(path + "/" + name)
        except:
            pass
        report.to_csv(path + "/{}/{}_{}년_{}.csv".format(name, submission_date, year, report_type),
                      index = False, encoding = "euc-kr")

이 함수는 dart 객체의 finstate 메서드를 이용하여 보고서 데이터(report)를 불러와서, 보고서 데이터에서 필요한 부분만 가져와 저장하는 함수입니다. 

먼저, report가 None이라면 데이터가 없다는 뜻이므로, 특별한 작업을 하지 않습니다.

그렇지 않으면 report의 rcept_no 컬럼에서 제출일을 추출하고, 필요한 컬럼만 인덱싱합니다. 또, 나중에 관리하기 쉽도록 컬럼명을 한글로 바꿔줍니다. 금액 컬럼에는 실제로는 숫자인데 문자로 표현되어있으므로,  conver_str_to_float 함수를 이용하여 숫자로 바꿔줬습니다.

또, 입력한 path에서 종목명인 폴더명이 없으면 해당 폴더를 만든 뒤에 report를 저장합니다.

파일명은 종목명/제출일자_사업연도년_보고서구분.csv  양식으로 저장합니다.

 

 

메인

이제 이 코드를 전 종목에 적용합니다.

API는 일일 호출 가능 횟수가 1만회이므로, API가 한 개라면 하루에 아래 코드를 다 못돌립니다. 

전 꼼수로 여러 개의 아이디를 만들어서 돌아가며 호출했지만, 그 내용을 공유하기는 조심스러워서 안전한 코드를 공유합니다.

import time
path = '' # path 설정 필요
my_api = '' # api 설정 필요
dart = OpenDartReader(my_api)
for code, name in stock_list[['Symbol', 'Name']].values:
    for year in range(2016, 2022):
        for report_type, report_type_code in zip(["1분기보고서", "반기보고서", "3분기보고서", "사업보고서"],
                                                  ["11013", "11012", "11014", "11011"]):
            print(name, year, report_type)
            while True:
                try:
                    extract_info_and_save(dart = dart,
                                          path = r"qspy\data\재무제표",
                                          year = year,
                                          name = name,
                                          code = code,
                                          report_type = report_type,
                                          report_type_code = report_type_code)
                    time.sleep(0.5)
                    break
                    
                except:
                    time.sleep(60)

여기서 my_api는 OpenDART에서 받은 API 키(문자열)이며, path는 실제 데이터가 저장될 패스입니다.

 

데이터 다운로드

Open DART의 FAQ에 따르면, 아래와 같이 공공데이터법에 의해 이 데이터를 상업적으로 이용해도 무방하다고 합니다 (https://opendart.fss.or.kr/cop/bbs/selectArticleDetail.do).

 

그래서 쿨하게 데이터를 공유합니다.

파일 크기 때문에 직접 업로드는 어렵고, 제가 수집한 데이터는 아래 깃허브에서 확인할 수 있습니다. 

https://github.com/GilseungAhn/finance_data

 

또, 전체 소스 코드는 다음에서 다운로드받을 수 있습니다.

Open DART를 이용한 전체 재무제표 수집.ipynb
0.00MB

 

 

수집하고 싶은 금융 데이터나 실험하고 싶은 퀀트 관련 아이디어가 있으면 댓글로 남겨주세요! 
관련 포스팅을 준비하도록 하겠습니다!

 

Comments