목차
0. 관련 글 목록
- [python] FinanceDataReader로 주가 데이터 가져오기
- [python] pykrx로 주가 데이터 가져오기
- [ML4T] 미국 주식 데이터 수집하기 - 주가, 거래량, 재무 데이터
1. 들어가며
이번 글에서는 한국 주식의 주가 데이터를 수집할 때 사용할 수 있는 4개의 파이썬 패키지를 비교해보려고 한다.
패키지 간의 비교는 (1)종목 리스트 조회, (2)상장 종목의 주가 데이터 조회, (3)상장폐지 종목의 주가 데이터 조회를 기준으로 수행하였다.
import FinanceDataReader as fdr
from pykrx import stock
import pandas_datareader.data as pdr
import yfinance as yf
2. 종목 리스트 조회
생존편향(survivorship bias)을 고려하여 주가 데이터를 수집하려면 백테스트에 사용할 데이터에 상장폐지 종목도 포함되어 있어야 한다. 이를 위해서는 어떤 종목이 어떤 시점에 상장되어 있고, 어떤 종목이 어떤 시점에 상장폐지 되었는지 알 수 있어야 하기 때문에 상장종목의 리스트와 상장폐지 종목의 리스트의 조회가 가능해야 한다. 도입부에서 나열한 4개의 패키지 중 FinanceDataReader와 pykrx가 이 기능을 제공하고 있다. FinanceDataReader는 현재 시점에서 가장 가까운 영업일 기준의 상장종목과 상장폐지 종목 리스트 조회 기능을 제공하고 있고, pykrx는 특정일자의 상장종목 리스트 조회 기능을 제공하고 있다.
2.1. FinanceDataReader
- 현재 시점의 시장별 상장종목 리스트를 가져올 수 있음
- 종목코드, 시장, 종목명, 섹터, 산업군, 상장일, 결산월, 대표자, 홈페이지, 사업체 지역을 알 수 있음
- 과거 특정 시점의 상장종목 리스트는 알 수 없으나 상장폐지 종목을 조회할 수 있음
# 가장 최근 영업일의 시장별 종목리스트를 가져옴
stocks = fdr.StockListing('KRX') # 코스피, 코스닥, 코넥스 전체
stocks
stocks.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 7633 entries, 0 to 7632
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Symbol 7633 non-null object
1 Market 7633 non-null object
2 Name 7633 non-null object
3 Sector 2499 non-null object
4 Industry 2481 non-null object
5 ListingDate 2499 non-null datetime64[ns]
6 SettleMonth 2499 non-null object
7 Representative 2499 non-null object
8 HomePage 2348 non-null object
9 Region 2499 non-null object
dtypes: datetime64[ns](1), object(9)
memory usage: 656.0+ KB
# KRX stock delisting symbol list 상장폐지 종목 전체 리스트
krx_delisting = fdr.StockListing('KRX-DELISTING')
krx_delisting
krx_delisting.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3355 entries, 0 to 3354
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Symbol 3355 non-null object
1 Name 3355 non-null object
2 Market 3355 non-null object
3 SecuGroup 3355 non-null object
4 Kind 3355 non-null object
5 ListingDate 3355 non-null datetime64[ns]
6 DelistingDate 3355 non-null datetime64[ns]
7 Reason 3355 non-null object
8 ArrantEnforceDate 989 non-null datetime64[ns]
9 ArrantEndDate 989 non-null datetime64[ns]
10 Industry 3355 non-null object
11 ParValue 3124 non-null float64
12 ListingShares 3307 non-null float64
13 ToSymbol 3355 non-null object
14 ToName 3355 non-null object
dtypes: datetime64[ns](4), float64(2), object(9)
memory usage: 393.3+ KB
2.2. pykrx
- 특정 시점의 상장 종목코드 조회 가능
- 해당 종목코드의 종목명을 조회하는 함수가 별도로 존재
# 날짜를 명시해주지 않으면 가장 최근 영업일의 시장별 종목리스트를 가져옴
tickers = stock.get_market_ticker_list()
tickers[:6], tickers[-6:]
(['095570', '006840', '027410', '282330', '138930', '001460'],
['005010', '069260', '000540', '000547', '000545', '003280'])
tickers = stock.get_market_ticker_list('2010-01-01')
tickers[:6], tickers[-6:]
(['004560', '004565', '001460', '001465', '084680', '001040'],
['005010', '069260', '000540', '000547', '000545', '003280'])
stock.get_market_ticker_name('005930')
'삼성전자'
3. 상장종목의 주가 조회
이번에는 상장 종목의 주가 정보를 조회해보자. 주가 정보를 제공하는 패키지들은 보통 OHLCV(시가/고가/저가/종가/거래량) 형태로 데이터를 제공하며, 액면분할 등을 고려한 수정주가를 보여주는데 패키지에 따라 거래량은 보정이 안된 경우가 있다. 이번 글에서는 삼성전자(005930)의 주가 데이터 조회를 예시로 들어보려고 한다. 삼성전자의 상장일은 1975년 6월 11일인데 이 시점부터 데이터를 제공하는 패키지는 없었고, 패키지마다 데이터 제공 시작시점이 모두 달랐다.
3.1. FinanceDataReader
- 조회 시점에 따라 조회할 수 있는 최대 과거 시점이 변동됨
- 예를 들어, 2022-03-22에 조회했을 때는 1998-02-05부터 조회됐었는데, 2022-03-23에 조회했을 때는 1998-02-06부터 조회됨 - 네이버금융에서 데이터를 가져오는데 일자가 지날 때 마다 과거 데이터를 삭제하는 것으로 보임
- 액면분할을 반영한 수정주가가 조회되는데 거래량은 보정되지 않은 상태임
start_date = '1975-06-11'
end_date = '2022-03-23'
df_fdr = fdr.DataReader('005930', start=start_date, end=end_date)
df_fdr
3.2. pykrx
- 1990년 데이터부터 조회 가능
- 수정주가가 디폴트로 조회됨(adjusted 옵션으로 수정주가 여부 설정가능)
- adjusted=False로 조회하면 1995-05-02부터 조회되고, 거래대금과 등락률 칼럼이 추가됨
- 액면분할을 반영한 수정주가가 조회되는데 거래량은 보정되지 않은 상태임
df_pykrx = stock.get_market_ohlcv_by_date(fromdate=start_date,
todate=end_date,
ticker="005930")
df_pykrx
df_pykrx = stock.get_market_ohlcv_by_date(fromdate=start_date,
todate=end_date,
ticker="005930", adjusted=False)
df_pykrx
3.3. pandas_datareader
- 데이터소스를 naver로 지정하면 1990년 데이터부터 조회할 수 있고, yahoo로 지정하면 2000년 데이터부터 조회할 수 있음
- 액면분할이 고려된 수정주가로 조회됨
- yahoo finance를 데이터소스로 사용할 때는 종목코드 뒤에 코스피 종목인 경우 .KS, 코스닥 종목인 경우 .KQ를 붙여줘야 함
df_pdr = pdr.DataReader('005930', 'naver', start=start_date, end=end_date)
df_pdr
# yahoo finance를 데이터 소스로 사용할 때는 종목코드 뒤에 코스피 종목인 경우 .KS, 코스닥 종목인 경우 .KQ를 붙여줘야 함
df_pdr = pdr.DataReader('005930.KS', 'yahoo', start=start_date, end=end_date)
df_pdr
3.4. yfinance
- yahoo finance를 데이터 소스로 사용하는 패키지이기 때문에 위에서 설명한 바와 같이 코스피 종목에는 .KS, 코스닥 종목에는 .KQ를 붙여줘야 함
- 가장 다양한 정보 확인 가능 - 배당정보, 분할정보, 재무정보 등
- 2000년 데이터부터 조회 가능
- end에 설정한 일자의 전일자까지 조회되기 때문에 조회하고자 하는 종료일+1일을 end에 넣어줘야함
- 분단위 데이터도 조회 가능하지만 조회 가능한 기간에 제한이 있음
ticker = yf.Ticker('005930.KS')
ticker.history(
interval='1d',
start=start_date,
end='2022-03-24',
actions=True,
auto_adjust=True)
# 분단위 데이터 조회. 조회할 수 있는 기간에 제한이 있음
# 마지막행의 데이터는 당일 종가로 조회되는 듯?
df_minute = ticker.history(
interval='1m',
start='2022-03-20',
end='2022-03-22',
actions=True,
auto_adjust=True)
df_minute
# 재무정보도 조회가능
ticker.financials
4. 상장폐지 종목의 주가 조회
상장폐지 종목의 주가 조회는 FinanceDataReader, pykrx, pandas_datareader에서 데이터 소스를 naver로 설정했을 때만 가능하다. yahoo finance에서는 상장폐지 종목에 대한 정보를 제공하지 않고 있는 것 같다. 상장폐지 종목의 리스트는 앞에서 설명한 것처럼 FinanceDataReader를 통해 조회하면 된다.
4.1. FinanceDataReader
krx_delisting[krx_delisting.Symbol=='001047']
# KRX delisting stock data 상장폐지된 종목 가격 데이터 (상장일~상장폐지일)
df = fdr.DataReader('001047', exchange='KRX-DELISTING')
df
4.2. pykrx
stock.get_market_ohlcv_by_date(fromdate=start_date,
todate=end_date,
ticker="001047")
4.3. pandas_datareader
df_pdr = pdr.DataReader('001047', 'naver', start=start_date, end=end_date)
df_pdr
5. 패키지별 특정 기간의 값 비교
2000년 1월 4일 ~ 2000년 1월 7일의 삼성전자 데이터를 비교해보자.
start_date = '2000-01-01'
end_date = '2000-01-07'
# FinanceDataReader
df_fdr = fdr.DataReader('005930', start=start_date, end=end_date)
df_fdr
# pykrx
df_pykrx = stock.get_market_ohlcv_by_date(fromdate=start_date,
todate=end_date,
ticker="005930")
df_pykrx
# pandas_datareader - naver
df_pdr = pdr.DataReader('005930', 'naver', start=start_date, end=end_date)
df_pdr
# pandas_datareader - yahoo
df_pdr = pdr.DataReader('005930.KS', 'yahoo', start=start_date, end=end_date)
df_pdr
# yfinance
ticker = yf.Ticker('005930.KS')
ticker.history(
interval='1d',
start=start_date,
end='2000-01-08',
actions=True,
auto_adjust=False)
krx나 naver를 데이터 소스로 사용하는 경우에는 거래량이 액면분할을 고려하지 않은 상태로 조회되고, yahoo finance를 데이터 소스로 사용하는 경우에는 거래량이 액면분할을 고려한 상태로 조회된다(1483967*50=74198350).