computer_IT

(퀀트전략 파이썬으로 세워라) 재무제표 데이터 가져오기

LifenLight 2022. 8. 3. 21:17
반응형

기업의 재무제표 데이터를 가져오려면 아래 사이트에 접속한다.

https://comp.fnguide.com/

 

삼성전자(A005930) | Snapshot | 기업정보 | Company Guide

삼성전자 005930 | 12월 결산 | <!-- SamsungElec | --> 홈페이지 홈페이지http://www.samsung.com 전화번호 전화번호031-200-1114 | IR 담당자 031-200-1114 주소 주소경기도 수원시 영통구 삼성로 129 (매탄동) KSE  코스

comp.fnguide.com

접속 후 재무제표를 클릭 후 주소창을 보면, comp.fnguide.com/SVO2/ASP/SVD_Finance.asp?pGB=1&gicode=A005930&cID=&MenuYn=Y&ReportGB=&NewMenuID=103&stkGb=701 와 같은 URL인 것을 알 수 있다. 이 페이지에서 테이블들을 불러오자.

제무제표 테이블 가져오기

다음과 같이 [0]을 붙여 데이터프레임으로 받는 경우(첫번째 테이블), CSV 파일로 저장할 수 있다.

데이터프레임 csv 파일변환
csv파일을 열 때 delimiter를 comma로 설정한다.

실제로 table에는 6개의 테이블이 들어있는데 재무제표 탭의 포괄손익계산서, 재무상태표, 현금흐름표의 3개 테이블이 각각 연간, 분기로 있기 때문에 6개의 테이블이 되는 것이다. 교재에는 매출액, 영업이익, 당기순이익 3개만 남기려고 table=table.loc[['매출액','영업이익','당기순이익']] 으로 하는데, 나의 경우는 에러가 나서 다음과 같이 인덱스로 대신하였다.

매출액, 영업이익, 당기순이익 데이터만 table 변수에 저장

전치함수 T는 행과 열을 바꾸는 함수이다.

전치함수 T

재무상태표와 현금흐름표도 마찬가지로 데이터프레임으로 가져와서 같은 방식으로 실행한다. 이제 모든 종목에 대해 데이터를 가져오려면 상장된 모든 종목의 종목코드를 구해야 한다. 한국거래소 홈페이지에서 상장회사 상세검색에서 엑셀파일을 다운로드한다.

http://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC0201020501 

 

KRX 정보데이터시스템

증권·파생상품의 시장정보(Marketdata), 공매도정보, 투자분석정보(SMILE) 등 한국거래소의 정보데이터를 통합하여 제공 서비스

data.krx.co.kr

다운로드받은 엑셀파일을 현재 작업하는 폴더에 넣고 데이터를 불러와보자. import pandas as pd 로 판다스라이브러리를 임포트하고 code = pd.read_excel('파일이름.xslx') 로 엑셀파일을 불러온다. 

종목코드와 종목명

종목코드는 6자리가 되어야 하는데 앞에 0이 빠져서 나온다. 이 책에서는 apply 함수를 사용하는데, 여기선 map 함수를 사용한다. code['종목코드'] = code['종목코드'].map('{:06d}'.format) 으로 6자리로 바꾼다.

종목코드 6자리 숫자로 바꾸기

모든 종목의 제무제표 가져오기(연간)

import requests
import pandas as pd
import time

# 재무제표 데이터를 데이터프레임으로 만드는 함수
def make_fs_dataframe(code):
    url = 'https://comp.fnguide.com/SVO2/ASP/SVD_Finance.asp?pGB=1&gicode=A'+str(code)+'&cID=&MenuYn=Y&ReportGB=&NewMenuID=103&stkGb=701'
    # headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'} 
    page = requests.get(url)
    tables = pd.read_html(page.text)
    # 연간데이터만 사용
    temp_df = tables[0]
    # 매출액, 영업이익, 당기순이익만 저장
    temp_df = temp_df.loc[[0,4,15]]
    temp_df = temp_df.set_index(temp_df.columns[0])
    # 4번째 열까지만 저장
    temp_df = temp_df[temp_df.columns[:4]]

    temp_df2 = tables[2]
    # 자산, 부채, 자본
    temp_df2 = temp_df2.loc[[0,4,8]]
    temp_df2 = temp_df2.set_index(temp_df2.columns[0])
    
    temp_df3 = tables[4]
    # 영업활동으로 인한 현금 흐름
    temp_df3 = temp_df3.loc[[0]]
    temp_df3 = temp_df3.set_index(temp_df3.columns[0])

    # 데이터프레임을 아래로(행으로) 합치기
    df = pd.concat([temp_df,temp_df2,temp_df3])
    # print(df)
    return df

# 데이터프레임을 전치행렬로 바꾸는 함수
def change_df(code, dataframe):
    for num, col in enumerate(dataframe.columns):
        temp_df = pd.DataFrame({code:dataframe[col]})
        temp_df = temp_df.T
        temp_df.columns = [[col]*len(dataframe), temp_df.columns]
        if num ==0:
            total_df = temp_df
        else:
            # 데이터프레임을 옆으로(열추가) 붙이기
            total_df = pd.merge(total_df, temp_df, how='outer', left_index=True, right_index=True)
    # print(total_df)
    return total_df


code = pd.read_excel('complist.xlsx')[['종목코드','종목명']]
code['종목코드'] = code['종목코드'].map('{:06d}'.format)

for num, code in enumerate(code['종목코드']):
    try:
        print(num, code)
        time.sleep(1)
        try:
            df = make_fs_dataframe(code)
        except requests.exceptions.Timeout:
            time.sleep(60)
            df = make_fs_dataframe(code)
        fs_df_changed = change_df(code, df)
        if num == 0:
            total_fs = fs_df_changed
        else:
            total_fs = pd.concat([total_fs, fs_df_changed])
    except :
        continue

# 엑셀데이터로 저장한다
total_fs.to_excel('stock_table.xlsx')

가져와서 보니 빈 데이터가 많다. 대부분 12월 결산을 하는데 3월 결산을 하는 곳도 있어서 그렇다는데 아무튼 2019, 2020, 2021년 12월 결산에 대한 데이터는 거의 대부분 들어와있다.

stock_table.xlsx
1.58MB

 

반응형