국내주식에 대한 일봉/주봉/월봉, 분봉 데이터를 뽑아보자.
mojito2 모듈에서는 fetch-ohlcv 메서드를 통해서 데이터를 얻을 수 있는데, 리턴되는 값의 형식은 output2에 dictionary 타입으로 출력된다.

0. 객체 생성

import mojito
import pprint

key = "PStmW7....t"
secret = "7gPSHO....="
acc_no = "12345678-0"

# 객체 생성
broker = mojito.KoreaInvestment(
    api_key=key,
    api_secret=secret,
    acc_no=acc_no # 모의투자계좌라면 mock=True 추가
)

1. 분봉 조회

result = broker.fetch_today_1m_ohlcv("005930")

df = pd.DataFrame(result['output2'])
dt = pd.to_datetime(df['stck_bsop_date'] + ' ' + df['stck_cntg_hour'], format="%Y%m%d %H%M%S")
df.set_index(dt, inplace=True)
df = df[['stck_oprc', 'stck_hgpr', 'stck_lwpr', 'stck_prpr', 'cntg_vol']]
df.columns = ['open', 'high', 'low', 'close', 'volume']
df.index.name = "datetime"
df = df[::-1]
print(df)

위에 있는 코드는 현재 https://wikidocs.net/178242 에 있는 코드로, 파이썬에서 해당 코드를 그대로 실행해보면 Keyerror가 발생한다…

문제를 찾기 위해서 fetch_today_1m_ohlcv의 코드 일부분을 수정해서 원인을 찾을 수 있었다. while loop를 통해서 _fetch_today_1m_ohlcv에서 api로 분봉 데이터를 계속해서 polling을 하는데, 신한투자증권의 해당 API의 경우에는 가상투자계좌(Mock)의 경우에는 초당 5건으로 제한이 되어있다.

        while last_hour > "090100":
            # last minute
            dt1 = datetime.datetime(
                year=now.year,
                month=now.month,
                day=now.day,
                hour=int(last_hour[:2]),
                minute=int(last_hour[2:4])
            )
            delta = datetime.timedelta(minutes=1)

            # 1 minute ago
            dt2 = dt1 - delta
            to = dt2.strftime("%H%M%S")

            # request 1minute ohlcv
            output = self._fetch_today_1m_ohlcv(symbol, to)
            # 코드 수정한 부분 ###########################################
            if 'output2' in output:
                print(output['output2'])
                output2 = output['output2']
                last_hour = output2[-1]['stck_cntg_hour']
                result['output2'].extend(output2)
            else:
                print("output2가 응답에 없습니다.")
            # 코드 수정한 부분 ###########################################
            # output2 = output['output2']
            # last_hour = output2[-1]['stck_cntg_hour']

            # result['output2'].extend(output2)

        return result

** fetch_today_1m_ohlcv **

    def fetch_today_1m_ohlcv(self, symbol: str, to: str=""):
        """국내주식시세/주식당일분봉조회
        Args:
            symbol (str): 6자리 종목코드
            to (str, optional): "HH:MM:00". Defaults to "".
        """
        result = {}
        now = datetime.datetime.now()

        if to == "":
            to = now.strftime("%H%M%S")
            # kospi market end time
            if to > "153000":
                to = "153000"

        output = self._fetch_today_1m_ohlcv(symbol, to)
        output2 = output['output2']
        last_hour = output2[-1]['stck_cntg_hour']

        result['output1'] = output['output1']
        result['output2'] = output2

        while last_hour > "090100":
            # last minute
            dt1 = datetime.datetime(
                year=now.year,
                month=now.month,
                day=now.day,
                hour=int(last_hour[:2]),
                minute=int(last_hour[2:4])
            )
            delta = datetime.timedelta(minutes=1)

            # 1 minute ago
            dt2 = dt1 - delta
            to = dt2.strftime("%H%M%S")

            # request 1minute ohlcv
            output = self._fetch_today_1m_ohlcv(symbol, to)
            if 'output2' in output:
                print(output['output2'])
                output2 = output['output2']
                last_hour = output2[-1]['stck_cntg_hour']
                result['output2'].extend(output2)
            else:
                print("output2가 응답에 없습니다.")

            # output2 = output['output2']
            # last_hour = output2[-1]['stck_cntg_hour']

            # result['output2'].extend(output2)

        return result

    def _fetch_today_1m_ohlcv(self, symbol: str, to: str):
        """국내주식시세/주식당일분봉조회

        Args:
            symbol (str): 6자리 종목코드
            to (str): "HH:MM:SS"
        """
        path = "/uapi/domestic-stock/v1/quotations/inquire-time-itemchartprice"
        url = f"{self.base_url}/{path}"
        headers = {
           "content-type": "application/json; charset=utf-8",
           "authorization": self.access_token,
           "appKey": self.api_key,
           "appSecret": self.api_secret,
           "tr_id": "FHKST03010200",
           "tr_cont": "",
        }

        params = {
            "fid_etc_cls_code": "",
            "fid_cond_mrkt_div_code": "J",
            "fid_input_iscd": symbol,
            "fid_input_hour_1": to,
            "fid_pw_data_incu_yn": "Y"
        }
        res = requests.get(url, headers=headers, params=params)
        return res.json()

2. API 직접 분봉 데이터 호출해보기

import pickle
import requests
import pprint
url = "https://openapivts.koreainvestment.com:29443//uapi/domestic-stock/v1/quotations/inquire-time-itemchartprice"

with open("token.dat", "rb") as f:
    data = pickle.load(f)
    access_token = f'Bearer {data["access_token"]}'

headers = {
    "content-type": "application/json; charset=utf-8",
    "authorization": access_token,
    "appKey": key,
    "appSecret": secret,
    "tr_id": "FHKST03010200",
    "tr_cont": "",
}

params = {
    "fid_etc_cls_code": "",
    "fid_cond_mrkt_div_code": "J",
    "fid_input_iscd": "005930",
    "fid_input_hour_1": "",
    "fid_pw_data_incu_yn": "Y"
}
res = requests.get(url, headers=headers, params=params)
data = res.json()
pprint.pprint(data)

Reference