본문 바로가기
python/메모장

[Python] 야후파이낸스에서 주가 데이터 불러오기 및 엑셀 저장

by GJ999 2023. 1. 14.

파이썬으로 야후파이낸스에서 주가 데이터를 불러오는 방법을 검색해보니 pandas_datareader 패키지를 이용하는 방법이 주로 검색되었다. 

그러나 직접해보니 아래와 같은 에러가 발생하고, 아무리 에러 해결법을 찾아보려고 해도 고쳐지지가 않았다....

>>> import pandas_datareader as pdr
>>> from datetime import datetime

>>> print(pdr.__version__)
0.10.0

>>> start_date = datetime(2022,1,1)
>>> end_date = datetime(2022,12,31)

>>> df1 = pdr.DataReader('AAPL', 'yahoo' , start_date, end_date)
Traceback (most recent call last):
		~~~
	data = j["context"]["dispatcher"]["stores"]["HistoricalPriceStore"]
TypeError: string indices must be integers

위의 string indices must be integers라는 에러에 대한 해결법들을 실행해봐도 이상하게 난 고쳐지지가 않았다....

그래서 찾은 방법이 아래와 같다.

1. yahoo_fin 패키지 설치

yahoo_fin 설치

2. ticker 찾기

위 코드에서 첫번째 인수로 들어가는 '^GSPC' 가 어디서 온 값인지 궁금할 수 있다.

일반적으로 해당 종목별 고유코드라고 할 수 있는 티커(ticker)가 존재하며, 야후파이낸스에서는 아래와 같이 찾을 수 있다.

야후 파이낸스에서 S&P 500 검색
종목이름 옆에 ticker가 존재

3. 해당 종목의 주가 데이터 불러오기( yahoo_fin.stock_info.get_data )

야후파이낸스에서 S&P 500 지수의 2006년~2007년 정보 가져온 결과는 아래와 같다.

>>> import yahoo_fin.stock_info as si
>>> df = si.get_data('^GSPC', start_date='01/01/2006', end_date='12/31/2007')

>>> df.head()
                   open         high          low        close     adjclose      volume ticker
2006-01-03  1248.290039  1270.219971  1245.739990  1268.800049  1268.800049  2554570000  ^GSPC
2006-01-04  1268.800049  1275.369995  1267.739990  1273.459961  1273.459961  2515330000  ^GSPC
2006-01-05  1273.459961  1276.910034  1270.300049  1273.479980  1273.479980  2433340000  ^GSPC
2006-01-06  1273.479980  1286.089966  1273.479980  1285.449951  1285.449951  2446560000  ^GSPC
2006-01-09  1285.449951  1290.780029  1284.819946  1290.150024  1290.150024  2301490000  ^GSPC

>>> df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 501 entries, 2006-01-03 to 2007-12-28
Data columns (total 7 columns):
---  ------    --------------  -----
 0   open      501 non-null    float64
 1   high      501 non-null    float64
 2   low       501 non-null    float64
 3   close     501 non-null    float64
 4   adjclose  501 non-null    float64
 5   volume    501 non-null    int64
 6   ticker    501 non-null    object
dtypes: float64(5), int64(1), object(1)
memory usage: 29.4+ KB

데이터를 조회할 때, get_data 함수 내 start_dateend_date 인수 값의 형식은 아래 4가지 모두 가능하다.

① 문자열 : 'MM/DD/YYYY'
② 문자열 : 'YYYYMMDD'
③ 문자열 : 'YYYY-MM-DD'
④ 시간형 : datetime.datetime(YYYY, MM, DD)

실제로 아래 예시들을 봤을 때, 잘 작동하는 것을 볼 수 있다.

>>> df = si.get_data('^GSPC', start_date='20060101', end_date='20071231')
>>> df.head()
                   open         high          low        close     adjclose      volume ticker
2006-01-03  1248.290039  1270.219971  1245.739990  1268.800049  1268.800049  2554570000  ^GSPC
2006-01-04  1268.800049  1275.369995  1267.739990  1273.459961  1273.459961  2515330000  ^GSPC
2006-01-05  1273.459961  1276.910034  1270.300049  1273.479980  1273.479980  2433340000  ^GSPC
2006-01-06  1273.479980  1286.089966  1273.479980  1285.449951  1285.449951  2446560000  ^GSPC
2006-01-09  1285.449951  1290.780029  1284.819946  1290.150024  1290.150024  2301490000  ^GSPC
>>> df = si.get_data('^GSPC', start_date='2006-01-01', end_date='2007-12-31')
>>> df.head()
                   open         high          low        close     adjclose      volume ticker
2006-01-03  1248.290039  1270.219971  1245.739990  1268.800049  1268.800049  2554570000  ^GSPC
2006-01-04  1268.800049  1275.369995  1267.739990  1273.459961  1273.459961  2515330000  ^GSPC
2006-01-05  1273.459961  1276.910034  1270.300049  1273.479980  1273.479980  2433340000  ^GSPC
2006-01-06  1273.479980  1286.089966  1273.479980  1285.449951  1285.449951  2446560000  ^GSPC
2006-01-09  1285.449951  1290.780029  1284.819946  1290.150024  1290.150024  2301490000  ^GSPC
>>> from datetime import datetime
>>> start = datetime(2006,1,1)
>>> end = datetime(2007,12,31)
>>> df = si.get_data('^GSPC', start_date=start, end_date=end)
>>> df.head()
                   open         high          low        close     adjclose      volume ticker
2006-01-03  1248.290039  1270.219971  1245.739990  1268.800049  1268.800049  2554570000  ^GSPC
2006-01-04  1268.800049  1275.369995  1267.739990  1273.459961  1273.459961  2515330000  ^GSPC
2006-01-05  1273.459961  1276.910034  1270.300049  1273.479980  1273.479980  2433340000  ^GSPC
2006-01-06  1273.479980  1286.089966  1273.479980  1285.449951  1285.449951  2446560000  ^GSPC
2006-01-09  1285.449951  1290.780029  1284.819946  1290.150024  1290.150024  2301490000  ^GSPC

4. 전처리 및 엑셀 저장

>>> df.to_excel('S&P.xlsx')

저장 후 엑셀 데이터를 확인해보면 다음과 같다.

인덱스가 시간 데이터이다보니 엑셀 데이터의 A열이 시/분/초까지 기재된 것을 볼 수 있다.

그래서 년월일 까지만 따로 추출해서 저장할 필요가 있으며, 가공 순서는 다음과 같다.

 ① 인덱스를 별도의 컬럼으로 전환 : reset_index()

 ② 컬럼명 index 를 date로 변경 : rename(columns = {'index' : 'date'})

 ③ date 컬럼의 데이터 형식이 datetime이므로 문자열로 변환 : apply(lambda x : x.strftime('%Y-%m-%d'))

 ④ 엑셀 저장시 index는 제외 : to_excel( 'df.xlsx', index = False )

>>> df = si.get_data('^GSPC', start_date='2006-01-01', end_date='2007-12-31')
>>> df = df.reset_index().rename(columns={'index':'date'})
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 501 entries, 0 to 500
Data columns (total 8 columns):
 #   Column    Non-Null Count  Dtype
---  ------    --------------  -----
 0   date      501 non-null    datetime64[ns]
 1   open      501 non-null    float64
 2   high      501 non-null    float64
 3   low       501 non-null    float64
 4   close     501 non-null    float64
 5   adjclose  501 non-null    float64
 6   volume    501 non-null    int64
 7   ticker    501 non-null    object
 
>>> df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))

>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 501 entries, 0 to 500
Data columns (total 8 columns):
 #   Column    Non-Null Count  Dtype
---  ------    --------------  -----
 0   date      501 non-null    object
 1   open      501 non-null    float64
 2   high      501 non-null    float64
 3   low       501 non-null    float64
 4   close     501 non-null    float64
 5   adjclose  501 non-null    float64
 6   volume    501 non-null    int64
 7   ticker    501 non-null    object
dtypes: float64(5), int64(1), object(2)
memory usage: 27.5+ KB

>>> df.to_excel('S&P.xlsx', index = False)

반응형

댓글