본문 바로가기

API

[전자공시 Dart API] PER 계산 및 PER 낮은 회사 순으로 정렬하기

반응형

전자공시 Dart API의 전체 재무제표와 주식수를 가져와 PER을 계산해보고,

PER이 낮은 순으로 정렬해서 리스트를 구해보겠습니다.

 

PER은 아래의 항목으로 계산됩니다.(출처 나무 위키)

  •   시가총액/당기순이익

 

당기순이익 : 재무제표상 지배기업의 소유주에게 귀속되는 당기순이익(손실) 사용

시가총액 : 주가 * 발행주식수

 

1. 가입 및 인증키 확인(Skip 가능)

2. 전체 회사 리스트 수집(Skip 가능)

3. 전체 재무제표에서 당기순이익 수집

4. 회사별 발행주식수 수집

5. 회사별 주가 수집 및 PER 계산

 

 

1. 가입 및 인증키 확인(Skip 가능)

https://yenpa.tistory.com/23

 

[전자공시 Dart API] 가입 및 인증키(API Key) 확인하기

1. 사이트 가입 2. 인증키(API Key) 확인하기 1. 사이트 가입 사이트에 접속합니다. https://opendart.fss.or.kr/ 전자공시 OPENDART 시스템 --> 시스템 점검으로 모든 서비스 이용이 일시적으로 중단되어니 양

yenpa.tistory.com

 

 

2. 전체 회사 리스트 수집(Skip 가능)

전체  회사 리스트 csv 파일이 필요한데 아래의 포스팅에서 만드셔도 되고,

첨부해드린 파일로 사용하셔도 됩니다.

https://yenpa.tistory.com/49

 

[전자공시 Dart API] 전체 상장 회사의 상세정보(기업개황) 수집 및 저장

전자공시 Dart API를 이용해서 상장회사의 리스트를 가져와서 저장해보도록 하겠습니다. 공시정보 > 고유번호에서 제공되는 데이터는 기본 정보(회사코드, 회사명, 주식코드)만 있어, 법인구분(코

yenpa.tistory.com

회사상세정보.csv
0.88MB

 

 

3. 전체 재무제표에서 당기순이익 수집

요청 parameter는 사업연도(bsns_year) 2021년, 보고서 종류(reprt_code) 사업보고서,

fs_div 연결 재무제표를 설정했습니다.

재무제표의 지배기업의 소유주에게 귀속되는 당기순이익(손실) 따로 저장하겠습니다.

crtfc_key는 본인의 데이터가 필요합니다.

# 회사별 전체재무제표 확인
result_all = pd.DataFrame()

#crtfc_key='YOUR_API_KEY'
bsns_year='2021'
reprt_code='11011' #1분기보고서: 11013 반기보고서: 11012 3분기보고서: 11014 사업보고서: 11011
fs_div='CFS'  #CFS:연결재무제표, OFS:재무제표

for i, r in corp_list.iterrows():
    #전체재무제표 요청인자
    crtfc_key=crtfc_key
    corp_code=str(r['corp_code']).zfill(8)
    
    #if i == 100:
    #    break
    
    time.sleep(0.3)
    
    print(i)
    
    url = 'https://opendart.fss.or.kr/api/fnlttSinglAcntAll.json'
    params = {
        'crtfc_key': crtfc_key,
        'corp_code' : corp_code,
        'bsns_year' : bsns_year,
        'reprt_code' : reprt_code,
        'fs_div' : fs_div,
    }
    
    #결과를 json형태로 저장
    results = requests.get(url, params=params).json()
    
    if results['status'] == '000':
        result_df = pd.DataFrame(results['list'])
        result_all = pd.concat([result_all,result_df])
    

profit=result_all.loc[(result_all['account_id']=='ifrs-full_ProfitLossAttributableToOwnersOfParent')]
profit = profit[['corp_code','thstrm_nm','thstrm_amount','frmtrm_nm', \
                 'frmtrm_amount','bfefrmtrm_nm','bfefrmtrm_amount','currency']]
profit.columns = ['corp_code','2021년','2021_당기순이익','2020년','2020_당기순이익', \
                  '2019년','2019_당기순이익','currency']
profit

요청 인자 설정하는 부분입니다.

#crtfc_key='YOUR_API_KEY'
bsns_year='2021'
reprt_code='11011' #1분기보고서: 11013 반기보고서: 11012 3분기보고서: 11014 사업보고서: 11011
fs_div='OFS'  #CFS:연결재무제표, OFS:재무제표

 

반응형

 

2번에서 수집한 전체 회사에 대해 for문을 실행합니다.

for i, r in corp_list.iterrows():

API를 호출해서 status가 '000' 정상일 경우에만 결과를 result_df, result_all에 저장합니다.

url = 'https://opendart.fss.or.kr/api/fnlttSinglAcntAll.json'
params = {
    'crtfc_key': crtfc_key,
    'corp_code' : corp_code,
    'bsns_year' : bsns_year,
    'reprt_code' : reprt_code,
    'fs_div' : fs_div,
}

#결과를 json형태로 저장
results = requests.get(url, params=params).json()

if results['status'] == '000':
    result_df = pd.DataFrame(results['list'])
    result_all = pd.concat([result_all,result_df])

재무제표의 손익계산서의 지배기업의 소유주에게 귀속되는 당기순이익(손실)

(ifrs_ProfitLossAttributableToOwnersOfParent)만 따로 저장했습니다.

그리고 필요 column 정보인 corp_code와 2021년, 2020년, 2019년의 자본총계 정보, currency(통화) 정보만

가져왔습니다

profit=result_all.loc[(result_all['account_id']=='ifrs-full_ProfitLossAttributableToOwnersOfParent')]
profit = profit[['corp_code','thstrm_nm','thstrm_amount','frmtrm_nm', \
                 'frmtrm_amount','bfefrmtrm_nm','bfefrmtrm_amount','currency']]
profit.columns = ['corp_code','2021년','2021_당기순이익','2020년','2020_당기순이익', \
                  '2019년','2019_당기순이익','currency']
profit

 

 

4. 회사별 발행주식수 수집

2번에서 구한 회사별로 사업보고서 주요 정보 > 주식의 총수의 정보를 가져와서

그중 필요한 정보인 발행주식의 총수와 회사 정보 등을 따로 저장합니다.

#전체결과저장
result_stocks=[]

print('총 회사수는 : ' + str(corp_list.shape[0]))

# 수집한 회사에 대해서 for문.
for i, r in corp_list.iterrows():
    #if i == 100:
    #    break
    
    #없으면 어느 시점에서 에러발생
    time.sleep(0.1)
    
    print('i = ' + str(i))
    corp_code=str(r['corp_code']).zfill(8)
    corp_name=r['corp_name']
    stock_code=str(r['stock_code'])
    bsns_year=2021
    reprt_code='11011' 
    #1분기보고서 : 11013, 반기보고서 : 11012, 3분기보고서 : 11014, 사업보고서 : 11011

    #print(corp_code)
    url = 'https://opendart.fss.or.kr/api/stockTotqySttus.json'
    params = {
        'crtfc_key': crtfc_key,
        'corp_code' : corp_code,
        'bsns_year' : str(bsns_year),
        'reprt_code' : reprt_code,
    }

    results = requests.get(url, params=params).json()
    # 응답이 정상 '000' 일 경우에만 데이터 수집
    if results['status'] == '000':
        for result in results['list']:
            if result['se'] in ['보통주','우선주','합계']:
                result_dic={}
                result_dic['se']=result['se']
                result_dic['istc_totqy']=result['istc_totqy']
                result_dic['corp_code']=corp_code
                result_dic['corp_name']=corp_name
                result_dic['stock_code']=stock_code
                result_stocks.append(result_dic)    

stocks=pd.DataFrame(result_stocks)
stocks

API를 호출하는 부분이 되겠습니다.

print('i = ' + str(i))
corp_code=str(r['corp_code'])
corp_name=r['corp_name']
stock_code=str(r['stock_code'])
bsns_year=2021
reprt_code='11011' 
#1분기보고서 : 11013, 반기보고서 : 11012, 3분기보고서 : 11014, 사업보고서 : 11011

url = 'https://opendart.fss.or.kr/api/stockTotqySttus.json'
params = {
    'crtfc_key': crtfc_key,
    'corp_code' : corp_code,
    'bsns_year' : str(bsns_year),
    'reprt_code' : reprt_code,
}

results = requests.get(url, params=params).json()

결과 중에서 보통주, 우선주 구분 및 corp_code(재무제표 데이터와 결합 시 key), stock_code(주가 정보) 등을 저장합니다.

# 응답이 정상 '000' 일 경우에만 데이터 수집
if results['status'] == '000':
    for result in results['list']:
        if result['se'] in ['보통주','우선주','합계']:
            result_dic={}
            result_dic['se']=result['se']
            result_dic['istc_totqy']=result['istc_totqy']
            result_dic['corp_code']=corp_code
            result_dic['corp_name']=corp_name
            result_dic['stock_code']=stock_code
            result_stocks.append(result_dic)
            
stocks=pd.DataFrame(result_stocks)
stocks

 

 

반응형

 

5. 회사별 주가 수집 및 PER 계산

재무제표 데이터와 회사 발행주식 정보를 병합합니다.

발행주식수에서 보통주의 정보만을 가져왔고, 통화를 원화(KRW)를 사용하는 회사 정보만을 저장합니다.

df=pd.merge(left=profit,right=stocks,how='left',on='corp_code')
df1=df.loc[(df['se']=='보통주') & (df['currency']=='KRW')]
df1['stock_code']=df1['stock_code'].str.zfill(6)
df1

 

회사별 오늘 날짜의 주가 정보를 수집합니다.

import matplotlib.pyplot as plt
import FinanceDataReader as fdr
import datetime
plt.rc('font', family='NanumGothic') 

price_all=pd.DataFrame()
for i, r in df1.iterrows():
    
    stock_code = r['stock_code']
    
    
    #주가정보
    code=stock_code
    today=datetime.datetime.now().strftime('%Y%m%d')
    price=fdr.DataReader(code,today,today)[['Close']]
    price['stock_code']=stock_code
    price_all = pd.concat([price_all,price])
    
price_all

 

df1에 주가 데이터를 추가해서 df2를 만듭니다.

df2=pd.merge(left=df1,right=price_all,how='left',on='stock_code')
df2

 

이제 df2에 저장된 정보로 PER을 계산해볼까요.

PER = 시가총액 / 당기순이익

PER = Close * istc_totqy / 2021_당기순이익

 

object를 int로 변경하고 당기순이익의 데이터가 없는 회사는 제외했습니다.

그다음 계산식을 넣어서 PER을 구합니다.

df2['istc_totqy']=df2['istc_totqy'].str.replace(',','').astype('int64')
df2=df2.loc[df2['2021_당기순이익']!='',]
df2=df2.astype({'2021_당기순이익':'int64'})
df2['PER'] = df2['Close'] * df2['istc_totqy'] / df2['2021_당기순이익']
df2

 

PER이 0보다 큰 회사 중에서 PER이 낮은 순으로 정렬 후에 20개의 회사를 구했습니다.

df2.loc[df2['PER']>0].sort_values('PER')[['corp_name','PER','Close']].iloc[:20,]

 

 

이상으로 전자공시 Dart API의 재무제표와 FinanceDataReader를 이용해서

PER이 낮은 회사 리스트를 구해봤습니다.

반응형