투자자/알고리즘

개발첫걸음_ 파이썬에서 모든 주식의 차트데이터 저장하기

나그네_즈브즈 2021. 5. 15. 21:34

지난 포스팅에서 모든 종목의 이름과 코드를 확보해 저장해 두었다. 이 파일을 데이터프레임으로 불러와서, 코드를 하나하나 인자로 넘기면 그걸 받아 해당하는 차트를 만들어주는 함수를 설계해 보자. 이번에도 완성된 최종 코드부터 적어놓고 설명을 이어나가도록 하겠다.

 

from dateutil.parser import parse as p
from pandas import Series, DataFrame
import win32com.client
import pandas as pd
import numpy as np

instStockChart = win32com.client.Dispatch('CpSysDib.StockChart')
tgt = pd.read_excel(경로+파일이름, engine='openpyxl')

def gen_raw (code, bgn=19000101, end=0) :
    instStockChart.SetInputValue(0, code)
    instStockChart.SetInputValue(1, ord('1'))  # 기간 입력 옵션
    instStockChart.SetInputValue(2, end)
    instStockChart.SetInputValue(3, bgn)
    instStockChart.SetInputValue(5, (0, 2, 3, 4, 5, 8))  # 날짜(0), 시가(2), 고가(3), 저가(4), 종가(5), 거래량(8)
    instStockChart.SetInputValue(6, ord('D'))  # 일 차트
    instStockChart.SetInputValue(7, 1)  # 1개 캔들 주기로, 즉 일봉
    instStockChart.SetInputValue(9, ord('1'))  # 수정주가 적용
    ### 붕어빵틀에 재료준비 끝
    
    base = DataFrame({'date':[], 'open':[], 'high':[], 'low':[], 'close':[], 'volume':[]}, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
    ### 붕어빵 완성되면 담아갈 빈 봉투 준비 완료
    
    ans = 1
    while ans==1 :
        instStockChart.BlockRequest()
        ans = instStockChart.Continue ### 이거 없으면 과거 데이터 포기함
        num = instStockChart.GetHeaderValue(3)  # 불러온 데이터 개수
        raw = DataFrame(np.arange(num), columns=['index'])
        
        ### 지금부터 붕어빵 대량생산 시작
        raw['date'] = raw['index'].apply(lambda i: p(str(instStockChart.GetDataValue(0, num - 1 - i))))
        raw['open'] = raw['index'].apply(lambda i: instStockChart.GetDataValue(1, num - 1 - i))
        raw['high'] = raw['index'].apply(lambda i: instStockChart.GetDataValue(2, num - 1 - i))
        raw['low'] = raw['index'].apply(lambda i: instStockChart.GetDataValue(3, num - 1 - i))
        raw['close'] = raw['index'].apply(lambda i: instStockChart.GetDataValue(4, num - 1 - i))
        raw['volume'] = raw['index'].apply(lambda i: instStockChart.GetDataValue(5, num - 1 - i))
        raw.drop(['index'], axis=1, inplace=True)
        base = pd.concat([base, raw], ignore_index=True)
    base = base.sort_values(by='date').reset_index(drop=True)
    return base
    
    for code in list(tgt['code']) :
    	gen_raw(code).to_csv(경로+code+'.csv')

길어보이지만 그렇게 복잡한 구조는 아니니까 차근차근 뜯어보자. 

 

함수를 시작하기 전에 준비할 것들은 지난 번과 비슷하다. 필요한 패키지들을 임포트하고, 이번에는 CpSysDib의 .StockChart 클래스가 필요하니까 붕어빵 틀을 만들어준다(대신증권 고마워). 그리고 미리 만들어 두었던 종목리스트 '타겟(=tgt)'을 불러오도록 하자. 불러온 이 목록에서 종목코드를 순차적으로 활용할 계획이다.

 

종목코드가 있다 치면, 그걸 가지고 차트를 불러오는 작업을 지시해야 한다. 붕어빵틀에다가 필요한 여러가지 재료를 넣어주고, 준비가 되면 붕어빵을 똑같이 찍어내면 된다. 재료를 넣어줄 때에는 붕어빵틀이 가진 기능 중에서 SetInputValue 함수를 이용한다. 이름 그대로, 입력값을 설정해주는 기능이 있다. 괄호 안에는 옵션번호와 설정내용을 입력해준다. 코드, 차트범위를 정하는 방식(기간으로 할지, 개수로 할지), 시작하고 끝나는 날을 각각 입력하고, 그 범위 안에서 실제 필요한 내용들을 주문하고, 캔들이 나타낼 기간을 알려준 뒤, 캔들을 얼마나 자세하게 쪼개어 나타낼지 등등을 미리 정하자.

 

이렇게 준비가 됐다면, 나중에 완성된 붕어빵을 각각 담아줄 봉투(=빈 데이터프레임)도 미리 준비해준다.

 

InputValue를 Set 해주는 작업이 끝났으니, 이제는 DataValue를 Get할 차례다. 이 작업을 하기전에 .BlockRequest()를 해줘야 한다고 한다. 이유는 까먹었다. 붕어빵 틀 안에 이미 저장된 차트 길이를 측정한 다음에(시작날짜~종료날짜를 지정해주면 길이가 자연스럽게 생길 테니까), 그 길이 안에서 캔들 정보를 raw 데이터프레임에 차례차례 담아주도록 한다. 

 

예를 들어, raw['close'] = raw['index'].apply(lambda i: instStockChart.GetDataValue(4, num - 1 - i)) 라는 작업은 i번째 캔들의 붕어빵 틀에 저장된 종가를 차례대로 'close'라는 열에 넣어주라는 뜻이다. GetDataValue의 첫번째 인자에는 캔들이 가진 데이터의 종류를 넣고, 다음에는 인덱스를 달아주면 된다. 0은 날짜, 1은 시가, 2는 고가, 3은 저가, 4는 종가, 5는 거래량이다. 인덱스에 i를 쓰지 않고 길이-인덱스-1 처럼 해준 것은 캔들순서를 과거에서 현재 순으로 정렬해주기 위해서다. 나중에 sort_values()를 사용해도 똑같지만, 이러든 저러든 중요한 건 아니다.

 

그러니까 내가 짠 걸 보면 날짜부터 만들어주고, 뒤이어 시가/고가/저가/종가/거래량을 같은 순서로 주르륵 연결해줘서 하나의 차트를 완성한 로직이다. 그런데 이렇게만 하면, 이유는 알 수 없지만, 특정 시점 이후의 캔들 데이터만 출력된다. 대신증권에 전화해서 문의해보니, StockChart 붕어빵 틀의 .Continue() 기능을 활용해보라는 조언을 받았다.

 

이 함수는 불러오지 않은 남은 차트가 있는지를 True/False로 알려주는 기능을 한다. 이 값이 True이면 나는 앞서 설계한 붕어빵 만들기 알고리즘을 더 반복해야 한다는 뜻이 된다. 이러면 여러 개의 raw 데이터프레임들이 생성될 텐데, 그것들을 base 데이터프레임에다가 몽땅 합쳐주면 된다. 그래서 이 참/거짓 결과를 ans(=answer의 축약)에 저장해서 조건형 반복문인 while을 적용했다. 더이상 읽어들이지 못한 캔들 데이터가 남지 않아서 .Continue()가 거짓이 될 때까지 반복문이 다 돌고나면, 어떤 종목은 1980년부터 기록된 캔들 데이터까지도 출력된다. 

 

함수가 완성됐으면, 종목코드가 반복문을 돌면서 차트를 만들어 저장하기만 하면 된다. 그런데 마지막 반복문은 아직 실행하지 말자. 다음 포스팅에서 보다 세련된 형태로, 이 차트생성 함수를 활용하는 팁에 대해 소개할까 한다.

반응형