본문 바로가기
미국 주식/주식 데이터 분석 (Quant Analysis)

[야후 파이낸스 데이터를 활용한 Quant Analysis - 3] 쓸 만한 데이터 정리하기 (2)

by Yamarae 2022. 7. 6.

 

 

 

지난 포스팅에 이어, yfinance를 통해 가져온 Ticker 객체에서 쓸 만한 정보가 뭐가 있는지 나머지를 정리해보고, pandas로 데이터를 보기좋게 정리하는 방법을 살펴보도록 하자.

 

 

 


 

[financials, balance_sheet 정보]

 

 

마찬가지로 종목코드를 입력하여 Ticker 객체를 가져오도록 하자.

 

import yfinance as yf

ticker = yf.Ticker("MSFT")

 

 

이번에는 info 변수가 아니라, financials와 balance_sheet을 출력해보자. 그럼 다음과 같은 출력 결과를 볼 수 있다.

 

 

 

기업의 재무제표, 현금 흐름과 관련된 세부 내용들을 이렇게 살펴볼 수 있다. 여기에서도 필요 이상으로 많은 정보가 있기 때문에, 실제 분석에서 사용될 법한 것들로만 한번 더 추려내보도록 하자.

 

 


 

[쓸 만한 정보들 추려내기]

 

 

1) 중요 비즈니스 금액정보

 

- Research Development : 기업이 해당 분기에 R&D에 투자한 비용을 의미한다.

- Net Income : 기업이 해당 분기에 올린 순이익을 의미한다.

- Gross Profit : 기업이 해당 분기에 올린 매출 총이익을 의미한다.

- Operating Income : 기업이 해당 분기에 올린 영업이익을 의미한다.

- Total Revenue : 기업이 해당 분기에 올린 총매출액을 의미한다.

- Cost Of Revenue : 기업이 해당 분기에 사용한 제품원가를 의미한다.

 

 

2) 재무제표 정보

 

- Total Liab : 기업이 가지고 있는 총 부채를 의미한다.

- Total Stockholder Equity : 기업이 가지고 있는 자기자본을 의미한다.

- Total Assets : 기업이 가지고 있는 총자산을 의미한다.

 

 


 

[데이터 크롤링]

 

지금까지의 내용을 pandas 형태로 만지기 쉽게 데이터를 정리해보자. yfinance 패키지의 응답 속도가 그렇게 시원치는 않기 때문에, 모든 종목을 하기는 힘들고, 하루 요청량도 정해져있어서 종목을 어느정도는 필터링을 한 뒤에 크롤링을 수행하는 것을 추천한다. 크롤링을 수행하기 전, 미리 column 정보를 다음과 같이 매핑해두도록 하자.

 

info_columns_mapper = {
    # 정보 관련
    'market': '상장종류',  # nasdaq, nyse, amex
    'sector': '섹터',
    'industry': '산업군',
    'recommendationKey': '종합매수의견',
    
    # 매매 정보 관련
    'sharesOutstanding': '발행주식수',
    'averageVolume10days': '종목평균거래량(10일)',
    'averageVolume': '종목평균거래량',
    'heldPercentInstitutions': '기관보유비율',
    'shortRatio': '일일공매도비율',
    'sharesPercentSharesOut': '발행주식대비공매도비율',
    'shortPercentOfFloat': '유동주식중공매도비율',
    
    # 가격 관련
    'marketCap': '시가총액',  # 200B:mega // 10B~200B:large // 2B-10B:medium // 300M~2B:small // 50M~300M:micro // ~50M:nano
    'currentPrice': '현재가',
    'fiftyDayAverage': '50일평균가',
    'twoHundredDayAverage': '200일평균가',
    'fiftyTwoWeekHigh': '52주최고가',
    'fiftyTwoWeekLow': '52주최저가',
    'SandP52WeekChange': 'S&P_52주변동성',
    '52WeekChange': '52주변동성',
    'ytdReturn': '연초대비수익률',
    'fiveYearAverageReturn': '5년연평균수익률',  # 5년연평균수익률
    'beta': '베타값',  # 5년 데이터, 개별주식의 변동률을 의미. 1에 가까울수록 시장과 가깝고, 1을 넘어가면 시장 대비 고변동, 0으로 가까우면 시장 대비 저변동 주식을 의미함.
    
    # 현금 창출, 매출 관련 (ttm)
    'totalRevenue': '총매출액',
    'grossProfits': '매출총이익',  # 매출이익(매출액 - 매출원가)
    'revenuePerShare': '주당매출액',
    'ebitda': 'EBITDA',  # 감가상각 등의 부가비용을 차감하기 전의 금액, 영업 활동을 통한 현금 창출 능력. 유형자산의 가치까지 포함하는 지표
    'ebitdaMargins': 'EBITDA마진',  # 유형자산의 유지비용을 고려한 기업의 현금 창출 능력
    
    # 재무 상태 관련 (mrq)
    'debtToEquity': '부채자본비율',
    'operatingCashflow': '영업현금흐름',  # 영업현금흐름 : 영업이익 - 법인세 - 이자비용 + 감가상각비
    'freeCashflow': '잉여현금흐름',  # 기업의 본원적 영업활동을 위해 현금을 창출하고, 영업자산에 투자하고도 남은 현금
    'totalCashPerShare': '주당현금흐름',
    'currentRatio': '유동비율',  # 회사가 가지고 있는 단기 부채 상환 능력
    'quickRatio': '당좌비율',  # 회사가 가지고 있는 단기 부채 상환 능력
    
    
    # 경영 효율 관련
    'returnOnAssets': '자기자본이익률',  # mrq : 간단히 말해, 얼마를 투자해서 얼마를 벌었냐
    'returnOnEquity': '총자산순이익률',  # mrq : ROE와 비교하여 기업이 가지고 있는 부채의 비중을 볼 때
    'grossMargins': '매출총이익률',  # ttm : 매출이익(매출액 - 매출원가) / 매출액 : 매출이익률, Gross Profit Margin (GPM)
    'operatingMargins': '영업이익률',  # ttm : 매출총이익 - 판관비 - 감가상각비
    'profitMargins': '순이익률',  # ttm : Net Income(순이익) / Revenue(총수익) : 순이익률, Net Profit Margin (NPM)
    
    # 기업 자산 관련
    'totalCash': '총현금액',
    'totalDebt': '총부채액',
    
    # 기업 가치 관련
    'priceToBook': 'PBR',  # 기업이 가진 순 자산에 비해 주가가 얼마나 비싼지
    'enterpriseValue': '기업가치',  # 기업가치 : 시가총액 + (총차입금 - 현금성 자산)
    'enterpriseToRevenue': 'EV/R',  # 매출액대비 기업가치 비율
    'enterpriseToEbitda': 'EV/EBITDA',  # EBITDA대비 기업가치 비율 : PER과 의미적으로 비슷한 지표
    'forwardEps': '선행1년EPS',  # 주당순이익, 보통 5년동안의 EPS를 관찰해서 추이를 봄
    'trailingEps': '1년EPS',  # 주당순이익 = 당기순이익 / 유통주식수
    'priceToSalesTrailing12Months': '1년PSR',  # 주가매출액비율 (1년 기준)
    'forwardPE': '선행1년PER',  # 향후 1년동안 예상되는 PER
    'trailingPE': '1년PER',  # 현재 PER. 기업이 한 주당 벌어들이는 순이익에 비해, 실제 주가가 몇 배가 되는 지 나타내는 지표. 고평가 저평가에 사용
    
    # 배당 관련
    'dividendYield': '배당수익률',  # 현재 기준 배당 수익률
    'payoutRatio': '배당성향',  # 20 ~ 60% 사이가 일반적.
    'trailingAnnualDividendYield': '1년배당수익률',  # 지난 1년간 배당 수익률
    'dividendRate': '주당수익달러',
    'trailingAnnualDividendRate': '1년주당수익달러',
    
    # 성장성 관련
    'revenueGrowth': 'mrq매출액증가율',
    'earningsGrowth': 'mrq수익상승률',
    'earningsQuarterlyGrowth': 'yoy수익상승률',  # yoy : 지난해 동일 분기 대비 최근 분기의 수익 상승률
    'revenueQuarterlyGrowth': 'yoy매출상승률',  # yoy : 지난해 동일 분기 대비 최근 분기의 매출 상승률
    'heldPercentInsiders': '직원보유비율',
}

financial_columns_mapper = {
    'Research Development': 'R&D비용',
    'Net Income': '순이익',
    'Gross Profit': '매출총이익',
    'Operating Income': '영업이익',
    'Total Revenue': '총매출',
    'Cost Of Revenue': '제품원가',
}

balance_sheet_columns_mapper = {
    'Total Liab': '총부채',
    'Total Stockholder Equity': '자기자본',
    'Total Assets': '총자산',
}

 

아래 코드는 나스닥 종목 중, 시가총액이 100,000,000불 이상인 종목들 중에, 20개만 잘라서 수행을 해 본 것이다. 이런식으로 보고싶은 종목의 규칙을 만들어서 사용해야 정상적인 크롤링을 수행할 수 있다.

 

df = pd.DataFrame()

temp_df = nasdaq_df[nasdaq_df['Market Cap']>100000000]
for index, row in temp_df.iloc[:20, ].iterrows():
    ticker_start_time = time.time()
    symbol = row['Symbol']
    ticker = yf.Ticker(symbol)
    raw_info = ticker.info
    try:
        if raw_info['quoteType'] == 'EQUITY':  # ETF를 제외한 개별 종목
            inner_dict = {}

            # 기본 정보 추가
            inner_dict['symbol'] = row['Symbol']
            inner_dict['name'] = row['Name']
            inner_dict['country'] = row['Country']
            inner_dict['origin_sector'] = row['Sector']
            inner_dict['industry'] = row['Industry']

            # info 정보 추가
            for info_column in info_columns_mapper:
                value = raw_info[info_column]
                inner_dict[info_columns_mapper[info_column]] = value

            # ticker.financials : 직전 4년 매출관련 데이터 추가
            financial_dict = ticker.financials.T.to_dict('list')
            for financial_column in financial_columns_mapper:
                value_list = list(reversed(financial_dict[financial_column]))
                inner_dict["list_financial_" + financial_columns_mapper[financial_column]] = value_list

            # ticker.balance_sheet : 직전 4년 재무상태 데이터 추가
            balance_sheet_dict = ticker.balance_sheet.T.to_dict('list')
            for balance_sheet_column in balance_sheet_columns_mapper:
                value_list = list(reversed(balance_sheet_dict[balance_sheet_column]))
                inner_dict["list_balancesheet_" + balance_sheet_columns_mapper[balance_sheet_column]] = value_list

            # append to df
            df = df.append(inner_dict, ignore_index=True)
            
            # time check
            print(symbol)
            print("--- %s seconds ---" % (time.time() - total_start_time))
    except Exception as e:
        print(symbol, 'Error:', e)

 

 

이를 실행해보면 다음과 같이 데이터를 pandas 형태로 정리할 수 있다. 이제 이 결과를 가지고 각자 분석 주제를 정해 분석을 수행해보도록 하자.