CREON PLUS API 를 이용해서 종목검색 예제 조건을 조회 하고, 해당 조건의 실시간 감시(서버에서 감시)를 등록해서 실시간으로 해당 조건에 만족하는 종목을 받아 오는 코드입니다
서버에서 실시간 감시를 해 주기 때문에, 당연하게도 등록 가능한 실시간 감시 조건은 제한되어 있어 감시를 마친 후에는 반드시 감시 중단 처리가 필요 합니다.
종목검색 프로세스는 아래 글을 참조
import sys
from PyQt5.QtWidgets import *
import win32com.client
import pandas as pd
import os
g_objCodeMgr = win32com.client.Dispatch('CpUtil.CpStockCode')
g_objCpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
g_objCpTrade = win32com.client.Dispatch('CpTrade.CpTdUtil')
# CpEvent: 실시간 이벤트 수신 클래스
class CpEvent:
def set_params(self, client, name, caller):
self.client = client # CP 실시간 통신 object
self.name = name # 서비스가 다른 이벤트를 구분하기 위한 이름
self.caller = caller # callback 을 위해 보관
def OnReceived(self):
pbData = {}
# 실시간 종목검색 감시 처리
if self.name == 'cssalert':
pbData['전략ID'] = self.client.GetHeaderValue(0)
pbData['감시일련번호'] = self.client.GetHeaderValue(1)
code = pbData['code'] = self.client.GetHeaderValue(2)
pbData['종목명'] = name = g_objCodeMgr.CodeToName(code)
inoutflag = self.client.GetHeaderValue(3)
if (ord('1') == inoutflag):
pbData['INOUT'] = '진입'
elif (ord('2') == inoutflag):
pbData['INOUT'] = '퇴출'
pbData['시각'] = self.client.GetHeaderValue(4)
pbData['현재가'] = self.client.GetHeaderValue(5)
self.caller.checkRealtimeStg(pbData)
class CpPublish:
def __init__(self, name, serviceID):
self.name = name
self.obj = win32com.client.Dispatch(serviceID)
self.bIsSB = False
def Subscribe(self, var, caller):
if self.bIsSB:
self.Unsubscribe()
if (len(var) > 0):
self.obj.SetInputValue(0, var)
handler = win32com.client.WithEvents(self.obj, CpEvent)
handler.set_params(self.obj, self.name, caller)
self.obj.Subscribe()
self.bIsSB = True
def Unsubscribe(self):
if self.bIsSB:
self.obj.Unsubscribe()
self.bIsSB = False
# CpPBCssAlert: 종목검색 실시간 PB 클래스
class CpPBCssAlert(CpPublish):
def __init__(self):
super().__init__('cssalert', 'CpSysDib.CssAlert')
# Cp8537 : 종목검색 전략 조회
class Cp8537:
def __init__(self):
self.objpb = CpPBCssAlert()
self.bisSB = False
self.monList = {}
def __del__(self):
self.Clear()
def Clear(self):
self.stopAllStgControl()
if self.bisSB:
self.objpb.Unsubscribe()
self.bisSB = False
def requestList(self, sel):
retStgList = {}
objRq = win32com.client.Dispatch("CpSysDib.CssStgList")
# 예제 전략에서 전략 리스트를 가져옵니다.
if (sel == '예제'):
objRq.SetInputValue(0, ord('0')) # '0' : 예제전략, '1': 나의전략
else:
objRq.SetInputValue(0, ord('1')) # '0' : 예제전략, '1': 나의전략
objRq.BlockRequest()
# 통신 및 통신 에러 처리
rqStatus = objRq.GetDibStatus()
if rqStatus != 0:
rqRet = objRq.GetDibMsg1()
print("통신상태", rqStatus, rqRet)
return (False, retStgList)
cnt = objRq.GetHeaderValue(0) # 0 - (long) 전략 목록 수
flag = objRq.GetHeaderValue(1) # 1 - (char) 요청구분
print('종목검색 전략수:', cnt)
for i in range(cnt):
item = {}
item['전략명'] = objRq.GetDataValue(0, i)
item['ID'] = objRq.GetDataValue(1, i)
item['전략등록일시'] = objRq.GetDataValue(2, i)
item['작성자필명'] = objRq.GetDataValue(3, i)
item['평균종목수'] = objRq.GetDataValue(4, i)
item['평균승률'] = objRq.GetDataValue(5, i)
item['평균수익'] = objRq.GetDataValue(6, i)
retStgList[item['전략명']] = item
print(item)
return (True, retStgList)
def requestStgID(self, id):
retStgList = []
objRq = None
objRq = win32com.client.Dispatch("CpSysDib.CssStgFind")
objRq.SetInputValue(0, id) # 전략 id 요청
objRq.BlockRequest()
# 통신 및 통신 에러 처리
rqStatus = objRq.GetDibStatus()
if rqStatus != 0:
rqRet = objRq.GetDibMsg1()
print("통신상태", rqStatus, rqRet)
return (False, retStgList)
cnt = objRq.GetHeaderValue(0) # 0 - (long) 검색된 결과 종목 수
totcnt = objRq.GetHeaderValue(1) # 1 - (long) 총 검색 종목 수
stime = objRq.GetHeaderValue(2) # 2 - (string) 검색시간
print('검색된 종목수:', cnt, '전체종목수:', totcnt, '검색시간:', stime)
for i in range(cnt):
item = {}
item['code'] = objRq.GetDataValue(0, i)
item['종목명'] = g_objCodeMgr.CodeToName(item['code'])
retStgList.append(item)
return (True, retStgList)
def requestMonitorID(self, id):
objRq = win32com.client.Dispatch("CpSysDib.CssWatchStgSubscribe")
objRq.SetInputValue(0, id) # 전략 id 요청
objRq.BlockRequest()
# 통신 및 통신 에러 처리
rqStatus = objRq.GetDibStatus()
if rqStatus != 0:
rqRet = objRq.GetDibMsg1()
print("통신상태", rqStatus, rqRet)
return (False, 0)
monID = objRq.GetHeaderValue(0)
if monID == 0:
print('감시 일련번호 구하기 실패')
return (False, 0)
# monID - 전략 감시를 위한 일련번호를 구해온다.
# 현재 감시되는 전략이 없다면 감시일련번호로 1을 리턴하고,
# 현재 감시되는 전략이 있다면 각 통신 ID에 대응되는 새로운 일련번호를 리턴한다.
return (True, monID)
def requestStgControl(self, id, monID, bStart):
objRq = win32com.client.Dispatch("CpSysDib.CssWatchStgControl")
objRq.SetInputValue(0, id) # 전략 id 요청
objRq.SetInputValue(1, monID) # 감시일련번호
if bStart == True:
objRq.SetInputValue(2, ord('1')) # 감시시작
print('전략감시 시작 요청 ', '전략 ID:', id, '감시일련번호', monID)
else:
objRq.SetInputValue(2, ord('3')) # 감시취소
print('전략감시 취소 요청 ', '전략 ID:', id, '감시일련번호', monID)
objRq.BlockRequest()
# 통신 및 통신 에러 처리
rqStatus = objRq.GetDibStatus()
if rqStatus != 0:
rqRet = objRq.GetDibMsg1()
print("통신상태", rqStatus, rqRet)
return (False, '')
status = objRq.GetHeaderValue(0)
if status == 0:
print('전략감시상태: 초기상태')
elif status == 1:
print('전략감시상태: 감시중')
elif status == 2:
print('전략감시상태: 감시중단')
elif status == 3:
print('전략감시상태: 등록취소')
# event 수신 요청 - 요청 중이 아닌 경우에만 요청
if self.bisSB == False:
self.objpb.Subscribe('', self)
self.bisSB = True
# 진행 중인 전략들 저장
if bStart == True:
self.monList[id] = monID
else:
if id in self.monList:
del self.monList[id]
return (True, status)
def stopAllStgControl(self):
delitem = []
for id, monId in self.monList.items():
delitem.append((id, monId))
for item in delitem:
self.requestStgControl(item[0], item[1], False)
print(len(self.monList))
def checkRealtimeStg(self, pbData):
# 감시중인 전략인 경우만 체크
id = pbData['전략ID']
monid = pbData['감시일련번호']
if not (id in self.monList):
return
if (monid != self.monList[id]):
return
print(pbData)
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("종목검색 예제")
self.setGeometry(300, 300, 500, 180)
self.obj8537 = Cp8537()
self.dataStg = []
nH = 20
self.comboStg = QComboBox(self)
self.comboStg.move(20, nH)
self.comboStg.currentIndexChanged.connect(self.comboChanged)
self.comboStg.resize(400, 30)
nH += 50
btnExit = QPushButton('종료', self)
btnExit.move(20, nH)
btnExit.clicked.connect(self.btnExit_clicked)
nH += 50
self.setGeometry(300, 300, 500, nH)
self.listAllStrategy()
def __del__(self):
self.obj8537.Clear()
# 전략리스트 조회
def listAllStrategy(self):
self.comboStg.addItem('전략선택없음')
self.data8537 = {}
ret, self.data8537 = self.obj8537.requestList('예제')
for k, v in self.data8537.items():
self.comboStg.addItem(k)
return
def comboChanged(self):
stgName = self.comboStg.currentText()
print(stgName)
if (stgName == '전략선택없음'):
return
# 1: 기존 감시 중단 (중요)
# 종목검색 실시간 감시 개수 제한이 있어, 불필요한 감시는 중단이 필요
self.obj8537.Clear()
# 2 - 종목검색 조회: CpSysDib.CssStgFind
item = self.data8537[stgName]
id = item['ID']
name = item['전략명']
ret, self.dataStg = self.obj8537.requestStgID(id)
if ret == False:
return
for item in self.dataStg:
print(item)
print('검색전략:', id, '전략명:', name, '검색종목수:', len(self.dataStg))
if (len(self.dataStg) >= 200):
print('검색종목이 200 을 초과할 경우 실시간 감시 불가 ')
return
#####################################################
# 실시간 요청
# 3 - 전략의 감시 일련번호 요청 : CssWatchStgSubscribe
ret, monid = self.obj8537.requestMonitorID(id)
if (False == ret):
return
print('감시일련번호', monid)
# 4 - 전략 감시 시작 요청 - CpSysDib.CssWatchStgControl
ret, status = self.obj8537.requestStgControl(id, monid, True)
if (False == ret):
return
return
def btnExit_clicked(self):
self.obj8537.Clear()
exit()
return
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
'개발 > 파이썬' 카테고리의 다른 글
[파이썬] 파일 다루기(유니코드, 파일 읽기 등) (0) | 2018.10.21 |
---|---|
[파이썬] 문자열 다루기 (0) | 2018.10.17 |
[CREON PLUS API 활용] 종목별 기관/외국인/개인 매수 수량/금액 조회 (0) | 2018.09.29 |
[CREON PLUS API 활용] 전 종목 시가총액 구하기 (0) | 2018.06.06 |
[CREON PLUS API 활용] 차트 지표 계산 하기 (0) | 2018.06.06 |
[파이썬] 선물 분 차트 그리기(matplotlib) (4) | 2018.02.18 |
댓글