대신증권 크레온 API로 실시간 주가 데이터 받기

2021-04-23 • quantpython, creon, 크레온, realtime, 실시간, 주가 • 2 min read

이번 포스트에서는 대신증권 크레온 API를 이용한 실시간 주가를 획득하는 방법을 다룹니다. 여느 때와 같이 언어는 파이썬으로 진행합니다.

크레온 API는 문서화가 비교적 잘되어 있고 사용성이 좋습니다. [증권사 API 장단점 비교][/htsapi.html] 포스트에서 주요 증권사 API의 장단점을 비교해 놓았으니 참고하시기 바랍니다.

실시간 주가를 얻어오기 위한 모듈은 Dscbo1.StockCur이며 이에 대한 문서는 여기에서 확인할 수 있습니다.

실시간 데이터는 Publish/Subscribe 방식으로 데이터를 획득합니다. 크레온에서 실시간 주가 데이터를 발행(Publish)하고 사용자는 실시간 주가를 원하는 종목을 구독(Subscribe)합니다. 사용자는 크레온이 발행한 데이터를 콜백(callback)을 통해 받습니다.

그럼 파이썬으로 실시간 주가 데이터를 구독하는 함수와 데이터를 획득하는 콜백 함수를 구현해 보겠습니다.

import win32com.client


class Creon:
    def __init__(self):
        self.stockcur_handlers = {}  # 주식/업종/ELW시세 subscribe event handlers

    def subscribe_stockcur(self, code, cb):
        if not code.startswith('A'):
            code = 'A' + code
        if code in self.stockcur_handlers:
            return
        obj = win32com.client.Dispatch('DsCbo1.StockCur')
        obj.SetInputValue(0, code)
        handler = win32com.client.WithEvents(obj, StockCurEventHandler)
        handler.set_attrs(obj, cb)
        self.stockcur_handlers[code] = obj
        obj.Subscribe()

    def unsubscribe_stockcur(self, code=None):
        lst_code = []
        if code is not None:
            if not code.startswith('A'):
                code = 'A' + code
            if code not in self.stockcur_handlers:
                return
            lst_code.append(code)
        else:
            lst_code = list(self.stockcur_handlers.keys()).copy()
        for code in lst_code:
            obj = self.stockcur_handlers[code]
            obj.Unsubscribe()
            del self.stockcur_handlers[code]


class StockCurEventHandler:
    def set_attrs(self, obj, cb):
        self.obj = obj
        self.cb = cb

    def OnReceived(self):
        item = {
            'code': self.obj.GetHeaderValue(0),
            'name': self.obj.GetHeaderValue(1),
            'diffratio': self.obj.GetHeaderValue(2),
            'timestamp': self.obj.GetHeaderValue(3),
            'price_open': self.obj.GetHeaderValue(4),
            'price_high': self.obj.GetHeaderValue(5),
            'price_low': self.obj.GetHeaderValue(6),
            'bid_sell': self.obj.GetHeaderValue(7),
            'bid_buy': self.obj.GetHeaderValue(8),
            'cum_volume': self.obj.GetHeaderValue(9),  # 주, 거래소지수: 천주
            'cum_trans': self.obj.GetHeaderValue(10),
            'price': self.obj.GetHeaderValue(13),
            'contract_type': self.obj.GetHeaderValue(14),
            'cum_sellamount': self.obj.GetHeaderValue(15),
            'buy_sellamount': self.obj.GetHeaderValue(16),
            'contract_amount': self.obj.GetHeaderValue(17),
            'second': self.obj.GetHeaderValue(18),
            'price_type': chr(self.obj.GetHeaderValue(19)),  # 1: 동시호가시간 예상체결가, 2: 장중 체결가
            'market_flag': chr(self.obj.GetHeaderValue(20)),  # '1': 장전예상체결, '2': 장중, '4': 장후시간외, '5': 장후예상체결
            'premarket_volume': self.obj.GetHeaderValue(21),
            'diffsign': chr(self.obj.GetHeaderValue(22)),
            'LP보유수량':self.obj.GetHeaderValue(23),
            'LP보유수량대비':self.obj.GetHeaderValue(24),
            'LP보유율':self.obj.GetHeaderValue(25),
            '체결상태(호가방식)':self.obj.GetHeaderValue(26),
            '누적매도체결수량(호가방식)':self.obj.GetHeaderValue(27),
            '누적매수체결수량(호가방식)':self.obj.GetHeaderValue(28),
        }
        self.cb(item)

이렇게 Creon 클래스에 실시간 주가를 구독하는 함수인 subscribe_stockcur와 구독을 취소하는 unsubscribe_stockcur 함수를 구현했습니다. subscribe_stockcur 함수에서 발행되는 주가 데이터를 처리하기 위한 StockCurEventHandler 클래스를 이어서 정의하였습니다.

subscribe_stockcur 함수에서 구독하는 종목마다 StockCurEventHandler를 할당해 주었습니다. 크레온이 주식 데이터를 발행하면 StockCurEventHandlerOnReceived 함수가 호출됩니다.

여기서 필요한 데이터를 획득할 수 있습니다. 여기서는 이렇게 획득한 데이터를 StockCurEventHandler 객체를 생성할 때 인자로 넘겨준 cb 함수로 전달하고 있습니다.

다음과 같이 종목명과 가격을 출력하는 간단한 cb 함수를 선언하고 NAVER와 미래에셋증권 두 종목의 실시간 주가를 구독해 보았습니다.

from quantylab.systrader.creon import Creon

c = Creon()

def cb(item):
    print(item['name'], item['price'])

c.subscribe_stockcur('035420', cb)
c.subscribe_stockcur('006800', cb)

# ...

c.unsubscribe_stockcur()

그러면 이런식으로 종목명과 주가가 출력되는 것을 볼 수 있습니다.

NAVER 389500
미래에셋증권 9990
미래에셋증권 10000
NAVER 390000
NAVER 389500
NAVER 389500
미래에셋증권 9990
NAVER 389500
NAVER 389500
미래에셋증권 9990
미래에셋증권 9990
미래에셋증권 9990
미래에셋증권 10000
미래에셋증권 9990
NAVER 390000
NAVER 389500
NAVER 389500
미래에셋증권 9990

퀀티랩 systrader 프로젝트에서 실시간 주가 확인 외에도 다양한 크레온 API 기능을 연결하고 있습니다. 퀀티랩 Github systrader 리포지토리에서 전체 코드를 확인할 수 있습니다. 문의는 이 리포지토리 이슈로 또는 네이버 카페로 주세요.