-
(파이썬 증권데이터 분석) 일별시세 DB구축 및 시세 조회 API 개발computer_IT 2022. 7. 22. 14:52반응형
2022.07.17 - [computer_IT] - (파이썬 증권데이터 분석) 상장법인 정보 불러오기, 주가 스크레이핑
소스코드는 아래 링크
https://github.com/Investar/StockAnalysisInPython
"파이썬 증권데이터 분석" 책을 계속 실습하는 중이다. 삼성전자가 2018년 5월 초에 액면분할을 시행해서 액면 분할 이전의 종가는 250만원대, 수정종가가 5만원대로 표시되어야 맞다고 한다. 야후 파이낸스를 2018년 5월 이전의 데이터가 제대로 반영되어 있지 않다.
from pandas_datareader import data as pdr import yfinance as yf yf.pdr_override() import matplotlib.pyplot as plt df = pdr.get_data_yahoo('005930.KS', '2017-01-01') # ① plt.figure(figsize=(9, 6)) plt.subplot(2, 1, 1) # ② plt.title('Samsung Electronics (Yahoo Finance)') plt.plot(df.index, df['Close'], 'c', label='Close') # ③ plt.plot(df.index, df['Adj Close'], 'b--', label='Adj Close') # ④ plt.legend(loc='best') plt.subplot(2, 1, 2) # ⑤ plt.bar(df.index, df['Volume'], color='g', label='Volume') # ⑥ plt.legend(loc='best') plt.savefig('test1.png')
결과 그래프
따라서 네이버 금융의 주식데이터를 스크레이핑해서 데이터베이스를 구축한 뒤, 언제든지 조회할 수 있도록 시세 조회 API를 만들어본다.
MariaDB 설치하기
해당 os별로 mariadb를 설치한다. 필자는 Arch 리눅스 계열 OS이므로 관련 링크는 아래에 있다.
https://www.itzgeek.com/how-tos/linux/arch-linux/how-to-install-mariadb-on-arch-linux.html
설치 후 mysql -u root -p 명령어를 입력하고 설치시 설정한 비밀번호를 입력한다. database 생성, 테이블정보확인, database 삭제를 해보자.
mariaDB에서 create database Investar;를 실행하여 데이터베이스를 생성한 후, 소스코드의 05폴더 > Investar폴더로 가면 DBUpdater.py파일과 DBUpdaterEx.py 파일을 볼 수 있다. 차이는 지난번에 언급한 headers 관련 설정인데, 네이버에서 headers를 체크하므로 headers 설정 여부 차이이다. DBUpdaterEx.py파일을 열어 비밀번호와 database를 Investar 로 수정한다. 그리고 config.json 파일을 열어 숫자가 100인지 확인하고 저장한다. (100페이지씩 스크레이핑 한다는 것)
책에서는 2500여개 종목별 100페이지를 가져오는데 약 5시간이 걸렸다고 한다. 직접해보니 5시간까진 아니었던 것 같고 약3~4시간 소요된 것 같다.
데이터를 스크레이핑 후 분석을 해보자.
일별 시세 조회 API (Analyzer.py)
import pandas as pd import pymysql from datetime import datetime from datetime import timedelta import re class MarketDB: def __init__(self): """생성자: MariaDB 연결 및 종목코드 딕셔너리 생성""" self.conn = pymysql.connect(host='localhost', user='root', password='testdb', db='Investar', charset='utf8') self.codes = {} self.get_comp_info() def __del__(self): """소멸자: MariaDB 연결 해제""" self.conn.close() def get_comp_info(self): """company_info 테이블에서 읽어와서 codes에 저장""" sql = "SELECT * FROM company_info" krx = pd.read_sql(sql, self.conn) for idx in range(len(krx)): self.codes[krx['code'].values[idx]] = krx['company'].values[idx] def get_daily_price(self, code, start_date=None, end_date=None): """KRX 종목의 일별 시세를 데이터프레임 형태로 반환 - code : KRX 종목코드('005930') 또는 상장기업명('삼성전자') - start_date : 조회 시작일('2020-01-01'), 미입력 시 1년 전 오늘 - end_date : 조회 종료일('2020-12-31'), 미입력 시 오늘 날짜 """ if start_date is None: # 인수값이 없을 때 기본값(1년전 오늘로 설정) one_year_ago = datetime.today() - timedelta(days=365) start_date = one_year_ago.strftime('%Y-%m-%d') print("start_date is initialized to '{}'".format(start_date)) else: # 정규식 \D는 숫자가 아닌 문자, \d는 숫자, +는 한번 또는 한번이상 start_lst = re.split('\D+', start_date) if start_lst[0] == '': start_lst = start_lst[1:] start_year = int(start_lst[0]) start_month = int(start_lst[1]) start_day = int(start_lst[2]) if start_year < 1900 or start_year > 2200: print(f"ValueError: start_year({start_year:d}) is wrong.") return if start_month < 1 or start_month > 12: print(f"ValueError: start_month({start_month:d}) is wrong.") return if start_day < 1 or start_day > 31: print(f"ValueError: start_day({start_day:d}) is wrong.") return start_date=f"{start_year:04d}-{start_month:02d}-{start_day:02d}" if end_date is None: end_date = datetime.today().strftime('%Y-%m-%d') print("end_date is initialized to '{}'".format(end_date)) else: end_lst = re.split('\D+', end_date) if end_lst[0] == '': end_lst = end_lst[1:] end_year = int(end_lst[0]) end_month = int(end_lst[1]) end_day = int(end_lst[2]) if end_year < 1800 or end_year > 2200: print(f"ValueError: end_year({end_year:d}) is wrong.") return if end_month < 1 or end_month > 12: print(f"ValueError: end_month({end_month:d}) is wrong.") return if end_day < 1 or end_day > 31: print(f"ValueError: end_day({end_day:d}) is wrong.") return end_date = f"{end_year:04d}-{end_month:02d}-{end_day:02d}" codes_keys = list(self.codes.keys()) # code딕셔너리에서 키를 추출하여 리스트 생성 codes_values = list(self.codes.values()) if code in codes_keys: pass elif code in codes_values: idx = codes_values.index(code) code = codes_keys[idx] else: print(f"ValueError: Code({code}) doesn't exist.") sql = f"SELECT * FROM daily_price WHERE code = '{code}'"\ f" and date >= '{start_date}' and date <= '{end_date}'" # pandas의 read_sql()함수로 sql결과를 데이터프레임으로 가져오면 정수형 인덱스가 별도로 생성됨 df = pd.read_sql(sql, self.conn) # 정수형 인데스이므로 인덱스를 date 컬럼으로 새로 설정함 df.index = df['date'] return df
Investar 폴더에 Analyzer.py 파일이 있으므로, cd .. 명령으로 Investart 상위 폴더로 이동한다. 가상환경을 실행 후 python을 입력한다.
네이버증권에서 수집한 주가 종목 데이터베이스(Investar)에서 해당 내역을 조회하였다. SQLAlchemy 를 사용하라는 내용이 나온다. 일단 책 내용대로 해도 무리가 없으니 패스.
다음에는 볼린저밴드와 관련된 내용을 다루어보겠다.
2022.07.23 - [computer_IT] - (파이썬 증권데이터 분석) 볼린저 밴드 지표
반응형'computer_IT' 카테고리의 다른 글
(파이썬 증권데이터 분석) 삼중창 매매, 듀얼 모멘텀 투자 (0) 2022.07.24 (파이썬 증권데이터 분석) 볼린저 밴드 지표 (0) 2022.07.23 (파이썬 증권데이터 분석) 상장법인 정보 불러오기, 주가 스크레이핑 (0) 2022.07.17 [파이썬 증권데이터분석] 최대손실낙폭(MDD), 회귀분석과 상관관계 (0) 2022.07.16 (파이썬 증권데이터 분석) 일간 변동률 누적합 그래프 그리기 (0) 2022.07.13