Skip to content

creon

4 posts with the tag “creon”

대신증권 크레온 API로 매수/매도 주문 넣고 확인하기

이번 포스트에서는 대신증권 크레온 API로 주식 주문을 내고 실시간으로 체결을 확인하고 주문 내역을 조회하는 방법을 다룹니다.

먼저 매수 또는 매도 주문을 내는 방법을 알아보겠습니다. 주문은 크레온 API의 CpTrade.CpTd0311 모듈을 사용하면 됩니다.

다음과 같이 order() 함수를 선언하고, action, code, amount를 매수/매도 구분, 주문할 종목 코드, 주식 수로 각각 입력 받도록 했습니다. 물론 더 다양한 입력을 받을 수 있게 이 함수를 수정할 수 있습니다.

import win32com.client
class Creon:
def __init__(self):
self.orderevent_handler = None
def order(self, action, code, amount):
if not code.startswith('A'):
code = 'A' + code
account_no, account_gflags = self.init_trade()
self.obj_CpTrade_CpTd0311.SetInputValue(0, action) # 1: 매도, 2: 매수
self.obj_CpTrade_CpTd0311.SetInputValue(1, account_no) # 계좌번호
self.obj_CpTrade_CpTd0311.SetInputValue(2, account_gflags[0]) # 상품구분
self.obj_CpTrade_CpTd0311.SetInputValue(3, code) # 종목코드
self.obj_CpTrade_CpTd0311.SetInputValue(4, amount) # 매수수량
self.obj_CpTrade_CpTd0311.SetInputValue(8, '03') # 시장가
result = self.obj_CpTrade_CpTd0311.BlockRequest()
if result != 0:
print('order request failed.', file=sys.stderr)
status = self.obj_CpTrade_CpTd0311.GetDibStatus()
msg = self.obj_CpTrade_CpTd0311.GetDibMsg1()
if status != 0:
print('order failed. {}'.format(msg), file=sys.stderr)
def buy(self, code, amount):
return self.order('2', code, amount)
def sell(self, code, amount):
return self.order('1', code, amount)

매수할 때는 buy() 함수를 호출해서 action2로 지정하고, 매도할 때는 sell() 함수를 호출해서 action1로 지정하도록 했습니다.

여기서는 시장가로 매수/매도를 하도록 했는데 지정가, 최유리지정가, 최우선지정가 등으로 변경할 수 있습니다. 이 부분은 CpTrade.CpTd0311 문서에서 SetInputValue8 - (string) 주문호가구분코드 항목을 함고하시기 바랍니다.

이렇게 매수 또는 매도 주문을 넣고 체결 되었을 때 다음과 같이 이벤트를 받을 수 있습니다.

class Creon:
def subscribe_orderevent(self, cb):
obj = win32com.client.Dispatch('Dscbo1.CpConclusion')
handler = win32com.client.WithEvents(obj, OrderEventHandler)
handler.set_attrs(obj, cb)
self.orderevent_handler = obj
obj.Subscribe()
def unsubscribe_orderevent(self):
if self.orderevent_handler is not None:
self.orderevent_handler.Unsubscribe()
self.orderevent_handler = None
class OrderEventHandler(EventHandler):
def OnReceived(self):
item = {
'계좌명': self.obj.GetHeaderValue(1),
'name': self.obj.GetHeaderValue(2),
'체결수량': self.obj.GetHeaderValue(3),
'체결가격': self.obj.GetHeaderValue(4),
'주문번호': self.obj.GetHeaderValue(5),
'원주문번호': self.obj.GetHeaderValue(6),
'계좌번호': self.obj.GetHeaderValue(7),
'상품관리구분코드': self.obj.GetHeaderValue(8),
'종목코드': self.obj.GetHeaderValue(9),
'매매구분코드': self.obj.GetHeaderValue(12),
'체결구분코드': self.obj.GetHeaderValue(14),
'체결구분코드': self.obj.GetHeaderValue(14),
'체결구분코드': self.obj.GetHeaderValue(14),
'현금신용대용구분코드': self.obj.GetHeaderValue(17),
}
self.cb(item)

subscribe_orderevent() 함수를 호출해서 체결 이벤트를 실시간으로 받아올 수 있습니다. 매수/매도 주문이 체결되면 지정된 콜백 함수 cb로 체결 정보를 전송합니다. 이를 위해서 OrderEventHandler 클래스를 선언했고, 이 클래스의 OnReceived() 함수에서 체결 정보를 cb에 전송합니다.

다음과 같이 지금까지 주문한 내역을 확인할 수도 있습니다.

class Creon:
def __init__(self, account_no=''):
self.obj_CpTrade_CpTd5341 = win32com.client.Dispatch('CpTrade.CpTd5341')
def get_trade_history(self):
account_no, account_gflags = self.init_trade()
self.obj_CpTrade_CpTd5341.SetInputValue(0, account_no)
self.obj_CpTrade_CpTd5341.SetInputValue(1, account_gflags[0]) # 상품구분
_fields = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 22, 24]
_keys = [
'상품관리구분코드', '주문번호', '원주문번호', '종목코드', '종목이름',
'주문내용', '주문호가구분코드내용', '주문수량', '주문단가', '총체결수량',
'체결수량', '체결단가', '확인수량', '정정취소구분내용 ', '거부사유내용',
'채권매수일', '거래세과세구분내용', '현금신용대용구분내용', '주문입력매체코드내용',
'정정취소가능수량', '매매구분',
]
result = self.request(self.obj_CpTrade_CpTd5341, dict(zip(_fields, _keys)), cntidx=6)
return result

주문 이후에 get_trade_history() 함수를 호출하면 다음과 같이 매수/매도 주문에 대한 정보들을 받아올 수 있습니다. 여기서는 삼성전자를 10주씩 매수->매도->매수한 다음 get_trade_history() 함수를 호출한 결과 입니다.

{'data': [{'상품관리구분코드': '10', '주문번호': 6095, '원주문번호': 0, '종목코드': 'A005930', '종목이름': '삼성전자', '주문내용': '정규장현금매수', '주문호가구분코드내용': '시장가', '주문수량': 10, '주문단가': 0, '총체결수량': 10, '체결수량': 10, '체결단가': 82430, '확인수량': 0, '정정취소구분내용 ': '정상주문', '거부사유내용': '', '채권매수일': '', '거래세과세구분내용': '', '현금신용대용구분내용': '', '주문입력매체코드내용': 'C8', '정정취소가능수량': 0, '매매구분': '매수'}, {'상품관리구분코드': '10', '주문번호': 6099, '원주문번호': 0, '종목코드': 'A005930', '종목이름': '삼성전자', '주문내용': '정규장현금매도', '주문호가구분코드내용': '시장가', '주문수량': 10, '주문단가': 0, '총체결수량': 10, '체결수량': 10, '체결단가': 82500, '확인수량': 0, '정정취소구분내용 ': '정상주문', '거부사유내용': '', '채권매수일': '', '거래세과세구분내용': '', '현금신용대용구분내용': '', '주문입력매체코드내용': 'C8', '정정취소가능수량': 0, '매매구분': '매도'}, {'상품관리구분코드': '10', '주문번호': 6121, '원주문번호': 0, '종목코드': 'A005930', '종목이름': '삼성전자', '주문내용': '정규장현금매수', '주문호가구분코드내용': '시장가', '주문수량': 10, '주문단가': 0, '총체결수량': 10, '체결수량': 10, '체결단가': 82500, '확인수량': 0, '정정취소구분내용 ': '정상주문', '거부사유내용': '', '채권매수일': '', '거래세과세구분내용': '', '현금신용대용구분내용': '', '주문입력매체코드내용': 'C8', '정정취소가능수량': 0, '매매구분': '매수'}]}

퀀티랩 systrader 프로젝트에서 전반적인 시스템 트레이딩 코드를 공개하고 있습니다. 앞으로 시스템 트레이딩에 필요한 주요 기능들을 퀀티랩 Github systrader 리포지토리에서 오픈소스로 개발해 나갈 예정입니다.

SysTrader의 주요 TODO 태스크는 다음과 같습니다.

  • 주요 시스템 트레이딩 기능 구현
  • 딥러닝 모델 기반 자동 매매
  • PyQt5 기반의 GUI 개발
  • 매매 현황 리포팅

관심 있으신 모든 분들께서 이 프로젝트에 참여해 주시면 감사하겠습니다. SysTrader는 모든 개미들을 위한 견고한 시스템 트레이딩 솔루션이 되는 것을 목표로 합니다.

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

이번 포스트에서는 대신증권 크레온 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 리포지토리에서 전체 코드를 확인할 수 있습니다. 문의는 이 리포지토리 이슈로 또는 네이버 카페로 주세요.

대신증권 크레온(Creon) API를 사용하여 파이썬에서 주식 차트 데이터 받아오기

최근 개인 투자자들의 프로그램 매매에 대한 관심이 높아지고 있습니다. 이에 따라 여러 증권사들이 API를 선보이고 있습니다. 대표적인 증권사 API로 키움증권 OpenAPI+, 이베스트투자증권 Xing API, 그리고 이번 포스트에서 다룰 대신증권 크레온 Plus API를 들 수 있습니다.

세 가지 API를 모두 사용해 봤지만, 크레온 Plus API를 가장 직관적으로 쉽게 사용할 수 있었습니다. 여기서는 크레온 Plus API로 분봉 차트 데이터를 받아오는 파이썬 소스코드를 다룹니다.

크레온 Plus API를 설치하고 파이썬 스크립트를 관리자 권한으로 실행해야 합니다.

크레온 Plus API는 다음 페이지에서 다운 받을 수 있습니다.

https://www.creontrade.com/

이 페이지 하단에 있는 다운로드센터 링크를 클릭합니다.

여기서 CREON Plus 영역의 다운로드 버튼을 클릭합니다. 그러면 팝업 메시지가 하나 뜨고 다운로드를 시작합니다. 실제로는 CREON HTS를 다운받습니다.

CREON HTS를 설치하고 실행하면 다음과 같은 창이 뜹니다.

creon

이 창의 상단에 보면 creon plus 버튼이 있습니다. 크레온 API 사용을 위해서는 이 버튼을 누른 후 로그인을 해야 합니다.

로그인이 제대로 완료되면 작업표시줄에 다음과 같이 두 아이콘이 뜹니다. creon

이제 파이선에서 크레온 Plus API를 사용하기 위해 다음 두 라이브러리를 설치합니다.

  • conda install -c anaconda pywin32
  • pip install pywinauto

이렇게 크레온 Plus API를 사용할 준비를 마친 후 파이썬 코드를 작성합니다.

import time
import logging
from logging.handlers import TimedRotatingFileHandler
import win32com.client
import pandas as pd
# 로그 파일 핸들러
fh_log = TimedRotatingFileHandler("logs/log", when="midnight", encoding="utf-8", backupCount=120)
fh_log.setLevel(logging.DEBUG)
# 콘솔 핸들러
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
# 로깅 포멧 설정
formatter = logging.Formatter("[%(asctime)s][%(levelname)s] %(message)s")
fh_log.setFormatter(formatter)
sh.setFormatter(formatter)
# 로거 생성
logger = logging.getLogger("creon")
logger.setLevel(logging.DEBUG)
logger.addHandler(fh_log)
logger.addHandler(sh)
class Creon:
def __init__(self):
self.obj_CpCodeMgr = win32com.client.Dispatch('CpUtil.CpCodeMgr')
self.obj_CpCybos = win32com.client.Dispatch('CpUtil.CpCybos')
self.obj_StockChart = win32com.client.Dispatch("CpSysDib.StockChart")
def creon_7400_주식차트조회(self, code, date_from, date_to):
"""
http://money2.creontrade.com/e5/mboard/ptype_basic/HTS_Plus_Helper/DW_Basic_Read_Page.aspx?boardseq=284&seq=102&page=1&searchString=StockChart&p=8841&v=8643&m=9505
:return:
"""
b_connected = self.obj_CpCybos.IsConnect
if b_connected == 0:
logger.debug("연결 실패")
return None
list_field_key = [0, 1, 2, 3, 4, 5, 8]
list_field_name = ['date', 'time', 'open', 'high', 'low', 'close', 'volume']
dict_chart = {name: [] for name in list_field_name}
while True:
self.obj_StockChart.SetInputValue(0, 'A'+code)
self.obj_StockChart.SetInputValue(1, ord('1')) # 0: 개수, 1: 기간
self.obj_StockChart.SetInputValue(2, date_to) # 종료일
self.obj_StockChart.SetInputValue(3, date_from) # 시작일
self.obj_StockChart.SetInputValue(4, 100) # 요청 개수
self.obj_StockChart.SetInputValue(5, list_field_key) # 필드
self.obj_StockChart.SetInputValue(6, ord('m')) # 'D', 'W', 'M', 'm', 'T'
self.obj_StockChart.BlockRequest()
status = self.obj_StockChart.GetDibStatus()
msg = self.obj_StockChart.GetDibMsg1()
logger.debug("통신상태: {} {}".format(status, msg))
if status != 0:
return None
cnt = self.obj_StockChart.GetHeaderValue(3) # 수신개수
for i in range(cnt):
dict_item = {name: self.obj_StockChart.GetDataValue(pos, i) for pos, name in zip(range(len(list_field_name)), list_field_name)}
for k, v in dict_item.items():
dict_chart[k].append(v)
if not self.obj_StockChart.Continue:
break
self._wait()
logger.debug("차트: {} {}".format(cnt, dict_chart))
return pd.DataFrame(dict_chart, columns=list_field_name)
def _wait(self):
time_remained = self.obj_CpCybos.LimitRequestRemainTime
cnt_remained = self.obj_CpCybos.GetLimitRemainCount(1) # 0: 주문 관련, 1: 시세 요청 관련, 2: 실시간 요청 관련
if cnt_remained <= 0:
timeStart = time.time()
while cnt_remained <= 0:
time.sleep(time_remained / 1000)
time_remained = self.obj_CpCybos.LimitRequestRemainTime
cnt_remained = self.obj_CpCybos.GetLimitRemainCount(1)
if __name__ == '__main__':
creon = Creon()
print(creon.creon_7400_주식차트조회('035420', 20180101, 20180109))

이 파이썬 스크립트를 실행하면 다음과 같이 NAVER 종목의 20180101부터 20180109까지의 분봉 차트 데이터를 받아올 수 있습니다.

분봉차트데이터

크레온 Plus API를 설치하고 파이썬 스크립트를 관리자 권한으로 실행할 것을 권장합니다.

파이썬에서 크레온 API 사용을 위한 준비사항

최근 개인 투자자들의 프로그램 매매에 대한 관심이 높아지고 있습니다. 이에 따라 여러 증권사들이 API를 선보이고 있습니다. 대표적인 증권사 API로 키움증권 OpenAPI+, 이베스트투자증권 Xing API, 그리고 이번 포스트에서 다룰 대신증권 크레온 Plus API를 들 수 있습니다.

세 가지 API를 모두 사용해 봤지만, 크레온 Plus API를 가장 직관적으로 쉽게 사용할 수 있었습니다. 이번 포스트에서 크레온 Plus API를 사용하기 위한 준비사항을 정리합니다.

우선 크레온 Plus API를 설치해야 합니다. 대부분의 HTS API는 윈도우 환경에서만 사용 가능합니다. 크레온 Plus API 또한 그렇습니다.

크레온 Plus API는 다음 페이지에서 다운로드할 수 있습니다. https://www.creontrade.com/

여기서 CREON Plus 영역의 다운로드 버튼을 클릭합니다. 그러면 팝업 메시지가 하나 뜨고 다운로드를 시작합니다. 실제로는 CREON HTS를 다운로드합니다.

CREON HTS를 설치하고 실행하면 다음과 같은 창이 뜹니다. 1

이 창의 상단에 보면 creon plus 버튼이 있습니다. 크레온 API 사용을 위해서는 이 버튼을 누른 후 로그인을 해야 합니다.

로그인이 제대로 완료되면 작업표시줄에 다음과 같이 두 아이콘이 뜹니다.

2

대부분의 HTS API는 사용을 위해서 윈도우 운영체제와 32비트 파이썬이 필요합니다. 여기서는 32비트 아나콘다 설치를 권장합니다. 아나콘다는 파이썬과 주요 라이브러리를 동시에 설치하는 오픈소스입니다.

다음 경로에서 아나콘다를 다운받을 수 있습니다.

https://www.anaconda.com/products/individual

상단에 있는 Download 버튼을 누르면 64비트 아나콘다를 다운받습니다. 그러므로 이 버튼을 누르지 말고 페이지의 하단부분에 있는 다음 영역에서 32비트 아나콘다 설치파일을 다운로드 받아야 합니다.

3

기존에 아나콘다 64비트를 설치한 상태에서도 별도로 아나콘다 32비트를 설치하시면 됩니다. 이 때 설치 경로를 다음과 같이 다르게 주는 것이 좋습니다.

  • 아나콘다 64비트 경로 예: C:\Users\USER\anaconda3
  • 아나콘다 32비트 경로 예: C:\Users\USER\anaconda3x86

이제 파이선에서 크레온 Plus API를 사용하기 위해 다음 두 라이브러리를 설치합니다.

conda install -c anaconda pywin32
pip install pywinauto

위에서 설치한 32비트 아나콘다에서 라이브러리를 설치해야 함을 주의해야 합니다.

크레온 Plus API를 설치하고 파이썬 스크립트를 관리자 권한으로 실행해야 합니다. 아나콘다 프롬프트의 경우 다음과 같이 아이콘을 우클릭하고 관리자 권한으로 실행을 누르면 됩니다.

4

VSCode를 사용하는 경우도 같은 방식으로 관리자 권한으로 실행할 수 있습니다. 만약 VSCode를 앞으로도 계속 관리자 권한으로 실행하고 싶으면 먼저 다음과 같이 속성 메뉴로 들어갑니다.

5

다음으로 호환성 탭에서 관리자 권한으로 이 프로그램 실행을 체크하고 적용합니다.

6

이제 크레온 API를 사용할 준비가 됐습니다. 이어지는 시스템 트레이딩 관련 콘텐츠를 확인해 주세요. 시스템 트레이딩 카테고리에서 크레온 API를 이용한 차트 수집, 투자자별 매매내역 수집, 주문내기 등의 콘텐츠를 다룹니다.