"대신증권 파이썬 api"의 두 판 사이의 차이
DB CAFE
(→주식 미체결 조회 및 실시간 미체결 업데이트/취소주문/일괄 취소 예제...) |
(→주식 현재가(10차호가/시간대별/일자별) 구현하기 예제) |
||
8번째 줄: | 8번째 줄: | ||
=== 해외선물 현재가/5차 호가 조회(실시간 업데이트 포함) === | === 해외선물 현재가/5차 호가 조회(실시간 업데이트 포함) === | ||
=== 주식 현재가(10차호가/시간대별/일자별) 구현하기 예제 === | === 주식 현재가(10차호가/시간대별/일자별) 구현하기 예제 === | ||
+ | 주식 현재가 화면을 구성하는 10차 호가, 시간대별, 일자별 데이터를 구현한 파이썬 예제입니다 | ||
+ | |||
+ | 화면 UI 는 PYQT 를 이용하였고 첨부된 파일에서 소스와 UI 를 받아 확인 가능합니다. | ||
+ | <source lang=python> | ||
+ | import sys | ||
+ | |||
+ | import pandas | ||
+ | from PyQt5 import QtWidgets | ||
+ | from PyQt5.QtWidgets import * | ||
+ | from PyQt5 import uic | ||
+ | from PyQt5.QtCore import * | ||
+ | import win32com.client | ||
+ | from pandas import Series, DataFrame | ||
+ | import locale | ||
+ | |||
+ | |||
+ | # cp object | ||
+ | g_objCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr") | ||
+ | g_objCpStatus = win32com.client.Dispatch("CpUtil.CpCybos") | ||
+ | g_objCpTrade = win32com.client.Dispatch("CpTrade.CpTdUtil") | ||
+ | locale.setlocale(locale.LC_ALL, '') | ||
+ | |||
+ | |||
+ | # 현재가 정보 저장 구조체 | ||
+ | class stockPricedData: | ||
+ | def __init__(self): | ||
+ | self.dicEx = {ord('0'): "동시호가/장중 아님", ord('1'): "동시호가", ord('2'): "장중"} | ||
+ | self.code = "" | ||
+ | self.name = "" | ||
+ | self.cur = 0 # 현재가 | ||
+ | self.diff = 0 # 대비 | ||
+ | self.diffp = 0 # 대비율 | ||
+ | self.offer = [0 for _ in range(10)] # 매도호가 | ||
+ | self.bid = [0 for _ in range(10)] # 매수호가 | ||
+ | self.offervol = [0 for _ in range(10)] # 매도호가 잔량 | ||
+ | self.bidvol = [0 for _ in range(10)] # 매수호가 잔량 | ||
+ | self.totOffer = 0 # 총매도잔량 | ||
+ | self.totBid = 0 # 총매수 잔량 | ||
+ | self.vol = 0 # 거래량 | ||
+ | self.tvol = 0 # 순간 체결량 | ||
+ | self.baseprice = 0 # 기준가 | ||
+ | self.high = 0 | ||
+ | self.low = 0 | ||
+ | self.open = 0 | ||
+ | self.volFlag = ord('0') # 체결매도/체결 매수 여부 | ||
+ | self.time = 0 | ||
+ | self.sum_buyvol = 0 | ||
+ | self.sum_sellvol = 0 | ||
+ | self.vol_str = 0 | ||
+ | |||
+ | # 예상체결가 정보 | ||
+ | self.exFlag= ord('2') | ||
+ | self.expcur = 0 # 예상체결가 | ||
+ | self.expdiff = 0 # 예상 대비 | ||
+ | self.expdiffp = 0 # 예상 대비율 | ||
+ | self.expvol = 0 # 예상 거래량 | ||
+ | self.objCur = CpPBStockCur() | ||
+ | self.objOfferbid = CpPBStockBid() | ||
+ | |||
+ | def __del__(self): | ||
+ | self.objCur.Unsubscribe() | ||
+ | self.objOfferbid.Unsubscribe() | ||
+ | |||
+ | |||
+ | # 전일 대비 계산 | ||
+ | def makediffp(self): | ||
+ | lastday = 0 | ||
+ | if (self.exFlag == ord('1')): # 동시호가 시간 (예상체결) | ||
+ | if self.baseprice > 0 : | ||
+ | lastday = self.baseprice | ||
+ | else: | ||
+ | lastday = self.expcur - self.expdiff | ||
+ | if lastday: | ||
+ | self.expdiffp = (self.expdiff / lastday) * 100 | ||
+ | else: | ||
+ | self.expdiffp = 0 | ||
+ | else: | ||
+ | if self.baseprice > 0 : | ||
+ | lastday = self.baseprice | ||
+ | else: | ||
+ | lastday = self.cur - self.diff | ||
+ | if lastday: | ||
+ | self.diffp = (self.diff / lastday) * 100 | ||
+ | else: | ||
+ | self.diffp = 0 | ||
+ | |||
+ | def getCurColor(self): | ||
+ | diff = self.diff | ||
+ | if (self.exFlag == ord('1')): # 동시호가 시간 (예상체결) | ||
+ | diff = self.expdiff | ||
+ | if (diff > 0): | ||
+ | return 'color: red' | ||
+ | elif (diff == 0): | ||
+ | return 'color: black' | ||
+ | elif (diff < 0): | ||
+ | return 'color: blue' | ||
+ | |||
+ | |||
+ | # CpEvent: 실시간 이벤트 수신 클래스 | ||
+ | class CpEvent: | ||
+ | def set_params(self, client, name, rpMst, parent): | ||
+ | self.client = client # CP 실시간 통신 object | ||
+ | self.name = name # 서비스가 다른 이벤트를 구분하기 위한 이름 | ||
+ | self.parent = parent # callback 을 위해 보관 | ||
+ | self.rpMst = rpMst | ||
+ | |||
+ | |||
+ | |||
+ | # PLUS 로 부터 실제로 시세를 수신 받는 이벤트 핸들러 | ||
+ | def OnReceived(self): | ||
+ | if self.name == "stockcur": | ||
+ | # 현재가 체결 데이터 실시간 업데이트 | ||
+ | self.rpMst.exFlag = self.client.GetHeaderValue(19) # 예상체결 플래그 | ||
+ | code = self.client.GetHeaderValue(0) | ||
+ | diff = self.client.GetHeaderValue(2) | ||
+ | cur= self.client.GetHeaderValue(13) # 현재가 | ||
+ | vol = self.client.GetHeaderValue(9) # 거래량 | ||
+ | |||
+ | # 예제는 장중만 처리 함. | ||
+ | if (self.rpMst.exFlag == ord('1')): # 동시호가 시간 (예상체결) | ||
+ | # 예상체결가 정보 | ||
+ | self.rpMst.expcur = cur | ||
+ | self.rpMst.expdiff = diff | ||
+ | self.rpMst.expvol = vol | ||
+ | else: | ||
+ | self.rpMst.cur = cur | ||
+ | self.rpMst.diff = diff | ||
+ | self.rpMst.makediffp() | ||
+ | self.rpMst.vol = vol | ||
+ | self.rpMst.open = self.client.GetHeaderValue(4) | ||
+ | self.rpMst.high = self.client.GetHeaderValue(5) | ||
+ | self.rpMst.low = self.client.GetHeaderValue(6) | ||
+ | self.rpMst.tvol = self.client.GetHeaderValue(17) | ||
+ | self.rpMst.volFlag = self.client.GetHeaderValue(14) # '1' 매수 '2' 매도 | ||
+ | self.rpMst.time = self.client.GetHeaderValue(18) | ||
+ | self.rpMst.sum_buyvol = self.client.GetHeaderValue(16) #누적매수체결수량 (체결가방식) | ||
+ | self.rpMst.sum_sellvol = self.client.GetHeaderValue(15) #누적매도체결수량 (체결가방식) | ||
+ | if (self.rpMst.sum_sellvol) : | ||
+ | self.rpMst.volstr = self.rpMst.sum_buyvol / self.rpMst.sum_sellvol * 100 | ||
+ | else : | ||
+ | self.rpMst.volstr = 0 | ||
+ | |||
+ | self.rpMst.makediffp() | ||
+ | # 현재가 업데이트 | ||
+ | self.parent.monitorPriceChange() | ||
+ | |||
+ | return | ||
+ | |||
+ | elif self.name == "stockbid": | ||
+ | # 현재가 10차 호가 데이터 실시간 업데이c | ||
+ | code = self.client.GetHeaderValue(0) | ||
+ | dataindex = [3, 7, 11, 15, 19, 27, 31, 35, 39, 43] | ||
+ | obi = 0 | ||
+ | for i in range(10): | ||
+ | self.rpMst.offer[i] = self.client.GetHeaderValue(dataindex[i]) | ||
+ | self.rpMst.bid[i] = self.client.GetHeaderValue(dataindex[i] + 1) | ||
+ | self.rpMst.offervol[i] = self.client.GetHeaderValue(dataindex[i] + 2) | ||
+ | self.rpMst.bidvol[i] = self.client.GetHeaderValue(dataindex[i] + 3) | ||
+ | |||
+ | self.rpMst.totOffer = self.client.GetHeaderValue(23) | ||
+ | self.rpMst.totBid = self.client.GetHeaderValue(24) | ||
+ | # 10차 호가 변경 call back 함수 호출 | ||
+ | self.parent.monitorOfferbidChange() | ||
+ | return | ||
+ | |||
+ | # SB/PB 요청 ROOT 클래스 | ||
+ | class CpPublish: | ||
+ | def __init__(self, name, serviceID): | ||
+ | self.name = name | ||
+ | self.obj = win32com.client.Dispatch(serviceID) | ||
+ | self.bIsSB = False | ||
+ | |||
+ | def Subscribe(self, var, rpMst, parent): | ||
+ | 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, rpMst, parent) | ||
+ | self.obj.Subscribe() | ||
+ | self.bIsSB = True | ||
+ | |||
+ | def Unsubscribe(self): | ||
+ | if self.bIsSB: | ||
+ | self.obj.Unsubscribe() | ||
+ | self.bIsSB = False | ||
+ | |||
+ | # CpPBStockCur: 실시간 현재가 요청 클래스 | ||
+ | class CpPBStockCur(CpPublish): | ||
+ | def __init__(self): | ||
+ | super().__init__("stockcur", "DsCbo1.StockCur") | ||
+ | |||
+ | # CpPBStockBid: 실시간 10차 호가 요청 클래스 | ||
+ | class CpPBStockBid(CpPublish): | ||
+ | def __init__(self): | ||
+ | super().__init__("stockbid", "Dscbo1.StockJpBid") | ||
+ | |||
+ | |||
+ | # SB/PB 요청 ROOT 클래스 | ||
+ | class CpPBConnection: | ||
+ | def __init__(self): | ||
+ | self.obj = win32com.client.Dispatch("CpUtil.CpCybos") | ||
+ | handler = win32com.client.WithEvents(self.obj, CpEvent) | ||
+ | handler.set_params(self.obj, "connection", None) | ||
+ | |||
+ | |||
+ | # CpRPCurrentPrice: 현재가 기본 정보 조회 클래스 | ||
+ | class CpRPCurrentPrice: | ||
+ | def __init__(self): | ||
+ | if (g_objCpStatus.IsConnect == 0): | ||
+ | print("PLUS가 정상적으로 연결되지 않음. ") | ||
+ | return | ||
+ | self.objStockMst = win32com.client.Dispatch("DsCbo1.StockMst") | ||
+ | return | ||
+ | |||
+ | |||
+ | def Request(self, code, rtMst, callbackobj): | ||
+ | # 현재가 통신 | ||
+ | rtMst.objCur.Unsubscribe() | ||
+ | rtMst.objOfferbid.Unsubscribe() | ||
+ | |||
+ | self.objStockMst.SetInputValue(0, code) | ||
+ | ret = self.objStockMst.BlockRequest() | ||
+ | if self.objStockMst.GetDibStatus() != 0: | ||
+ | print("통신상태", self.objStockMst.GetDibStatus(), self.objStockMst.GetDibMsg1()) | ||
+ | return False | ||
+ | |||
+ | |||
+ | # 수신 받은 현재가 정보를 rtMst 에 저장 | ||
+ | rtMst.code = code | ||
+ | rtMst.name = g_objCodeMgr.CodeToName(code) | ||
+ | rtMst.cur = self.objStockMst.GetHeaderValue(11) # 종가 | ||
+ | rtMst.diff = self.objStockMst.GetHeaderValue(12) # 전일대비 | ||
+ | rtMst.baseprice = self.objStockMst.GetHeaderValue(27) # 기준가 | ||
+ | rtMst.vol = self.objStockMst.GetHeaderValue(18) # 거래량 | ||
+ | rtMst.exFlag = self.objStockMst.GetHeaderValue(58) # 예상플래그 | ||
+ | rtMst.expcur = self.objStockMst.GetHeaderValue(55) # 예상체결가 | ||
+ | rtMst.expdiff = self.objStockMst.GetHeaderValue(56) # 예상체결대비 | ||
+ | rtMst.makediffp() | ||
+ | |||
+ | rtMst.totOffer = self.objStockMst.GetHeaderValue(71) # 총매도잔량 | ||
+ | rtMst.totBid = self.objStockMst.GetHeaderValue(73) # 총매수잔량 | ||
+ | |||
+ | |||
+ | # 10차호가 | ||
+ | for i in range(10): | ||
+ | rtMst.offer[i] = (self.objStockMst.GetDataValue(0, i)) # 매도호가 | ||
+ | rtMst.bid[i] = (self.objStockMst.GetDataValue(1, i) ) # 매수호가 | ||
+ | rtMst.offervol[i] = (self.objStockMst.GetDataValue(2, i)) # 매도호가 잔량 | ||
+ | rtMst.bidvol[i] = (self.objStockMst.GetDataValue(3, i) ) # 매수호가 잔량 | ||
+ | |||
+ | |||
+ | rtMst.objCur.Subscribe(code,rtMst, callbackobj) | ||
+ | rtMst.objOfferbid.Subscribe(code,rtMst, callbackobj) | ||
+ | |||
+ | |||
+ | # CpWeekList: 일자별 리스트 구하기 | ||
+ | class CpWeekList: | ||
+ | def __init__(self): | ||
+ | self.objWeek = win32com.client.Dispatch("Dscbo1.StockWeek") | ||
+ | return | ||
+ | |||
+ | |||
+ | def Request(self, code, caller): | ||
+ | # 현재가 통신 | ||
+ | self.objWeek.SetInputValue(0, code) | ||
+ | # 데이터들 | ||
+ | dates = [] | ||
+ | opens = [] | ||
+ | highs = [] | ||
+ | lows = [] | ||
+ | closes = [] | ||
+ | diffs = [] | ||
+ | vols = [] | ||
+ | diffps = [] | ||
+ | foreign_vols = [] | ||
+ | foreign_diff = [] | ||
+ | foreign_p = [] | ||
+ | |||
+ | # 누적 개수 - 100 개까지만 하자 | ||
+ | sumCnt = 0 | ||
+ | while True: | ||
+ | ret = self.objWeek.BlockRequest() | ||
+ | if self.objWeek.GetDibStatus() != 0: | ||
+ | print("통신상태", self.objWeek.GetDibStatus(), self.objWeek.GetDibMsg1()) | ||
+ | return False | ||
+ | |||
+ | cnt = self.objWeek.GetHeaderValue(1) | ||
+ | sumCnt += cnt | ||
+ | if cnt == 0: | ||
+ | break | ||
+ | |||
+ | for i in range(cnt): | ||
+ | dates.append(self.objWeek.GetDataValue(0, i)) | ||
+ | opens.append(self.objWeek.GetDataValue(1, i)) | ||
+ | highs.append(self.objWeek.GetDataValue(2, i)) | ||
+ | lows.append(self.objWeek.GetDataValue(3, i)) | ||
+ | closes.append(self.objWeek.GetDataValue(4, i)) | ||
+ | |||
+ | temp = self.objWeek.GetDataValue(5, i) | ||
+ | diffs.append(temp) | ||
+ | vols.append(self.objWeek.GetDataValue(6, i)) | ||
+ | |||
+ | temp2 = self.objWeek.GetDataValue(10, i) | ||
+ | if (temp < 0): | ||
+ | temp2 *= -1 | ||
+ | diffps.append(temp2) | ||
+ | |||
+ | foreign_vols.append(self.objWeek.GetDataValue(7, i)) # 외인보유 | ||
+ | foreign_diff.append(self.objWeek.GetDataValue(8, i)) # 외인보유 전일대비 | ||
+ | foreign_p.append(self.objWeek.GetDataValue(9, i)) # 외인비중 | ||
+ | |||
+ | if (sumCnt > 100): | ||
+ | break | ||
+ | |||
+ | if self.objWeek.Continue == False: | ||
+ | break | ||
+ | |||
+ | if len(dates) == 0: | ||
+ | return False | ||
+ | |||
+ | caller.rpWeek = None | ||
+ | weekCol = {'close': closes, | ||
+ | 'diff': diffs, | ||
+ | 'diffp': diffps, | ||
+ | 'vol': vols, | ||
+ | 'open':opens, | ||
+ | 'high': highs, | ||
+ | 'low': lows, | ||
+ | 'for_v' : foreign_vols, | ||
+ | 'for_d': foreign_diff, | ||
+ | 'for_p': foreign_p, | ||
+ | } | ||
+ | caller.rpWeek = DataFrame(weekCol, index=dates) | ||
+ | return True | ||
+ | |||
+ | |||
+ | # CpStockBid: 시간대별 조회 | ||
+ | class CpStockBid: | ||
+ | def __init__(self): | ||
+ | self.objSBid = win32com.client.Dispatch("Dscbo1.StockBid") | ||
+ | return | ||
+ | |||
+ | |||
+ | def Request(self, code, caller): | ||
+ | # 현재가 통신 | ||
+ | self.objSBid.SetInputValue(0, code) | ||
+ | self.objSBid.SetInputValue(2, 80) # 요청개수 (최대 80) | ||
+ | self.objSBid.SetInputValue(3, ord('C')) # C 체결가 비교 방식 H 호가 비교방식 | ||
+ | |||
+ | times = [] | ||
+ | curs = [] | ||
+ | diffs = [] | ||
+ | tvols = [] | ||
+ | offers = [] | ||
+ | bids = [] | ||
+ | vols = [] | ||
+ | offerbidFlags = [] # 체결 상태 '1' 매수 '2' 매도 | ||
+ | volstrs = [] # 체결강도 | ||
+ | marketFlags = [] # 장구분 '1' 동시호가 예상체결' '2' 장중 | ||
+ | |||
+ | # 누적 개수 - 100 개까지만 하자 | ||
+ | sumCnt = 0 | ||
+ | while True: | ||
+ | ret = self.objSBid.BlockRequest() | ||
+ | if self.objSBid.GetDibStatus() != 0: | ||
+ | print("통신상태", self.objSBid.GetDibStatus(), self.objSBid.GetDibMsg1()) | ||
+ | return False | ||
+ | |||
+ | cnt = self.objSBid.GetHeaderValue(2) | ||
+ | sumCnt += cnt | ||
+ | if cnt == 0: | ||
+ | break | ||
+ | |||
+ | strcur = "" | ||
+ | strflag = "" | ||
+ | strflag2 = "" | ||
+ | for i in range(cnt): | ||
+ | cur = self.objSBid.GetDataValue(4, i) | ||
+ | times.append(self.objSBid.GetDataValue(9, i)) | ||
+ | diffs.append(self.objSBid.GetDataValue(1, i)) | ||
+ | vols.append(self.objSBid.GetDataValue(5, i)) | ||
+ | tvols.append(self.objSBid.GetDataValue(6, i)) | ||
+ | offers.append(self.objSBid.GetDataValue(2, i)) | ||
+ | bids.append(self.objSBid.GetDataValue(3, i)) | ||
+ | flag = self.objSBid.GetDataValue(7, i) | ||
+ | if (flag == ord('1')): | ||
+ | strflag = "체결매수" | ||
+ | else: | ||
+ | strflag = "체결매도" | ||
+ | offerbidFlags.append(strflag) | ||
+ | volstrs.append(self.objSBid.GetDataValue(8, i)) | ||
+ | flag = self.objSBid.GetDataValue(10, i) | ||
+ | if (flag == ord('1')): | ||
+ | strflag2 = "예상체결" | ||
+ | #strcur = '*' + str(cur) | ||
+ | else: | ||
+ | strflag2 = "장중" | ||
+ | #strcur = str(cur) | ||
+ | marketFlags.append(strflag2) | ||
+ | curs.append(cur) | ||
+ | |||
+ | |||
+ | if (sumCnt > 100): | ||
+ | break | ||
+ | |||
+ | if self.objSBid.Continue == False: | ||
+ | break | ||
+ | |||
+ | if len(times) == 0: | ||
+ | return False | ||
+ | |||
+ | caller.rpStockBid = None | ||
+ | sBidCol = {'time': times, | ||
+ | 'cur': curs, | ||
+ | 'diff': diffs, | ||
+ | 'vol': vols, | ||
+ | 'tvol':tvols, | ||
+ | 'offer': offers, | ||
+ | 'bid': bids, | ||
+ | 'flag': offerbidFlags, | ||
+ | 'market': marketFlags, | ||
+ | 'volstr': volstrs} | ||
+ | caller.rpStockBid = DataFrame(sBidCol) | ||
+ | print(caller.rpStockBid) | ||
+ | return True | ||
+ | |||
+ | class Form(QtWidgets.QDialog): | ||
+ | def __init__(self, parent=None): | ||
+ | QtWidgets.QDialog.__init__(self, parent) | ||
+ | self.ui = uic.loadUi("hoga.ui", self) | ||
+ | self.ui.show() | ||
+ | self.objMst = CpRPCurrentPrice() | ||
+ | self.item = stockPricedData() | ||
+ | |||
+ | # 일자별 | ||
+ | self.objWeek = CpWeekList() | ||
+ | self.rpWeek = DataFrame() # 일자별 데이터프레임 | ||
+ | |||
+ | |||
+ | # 시간대별 | ||
+ | self.rpStockBid = DataFrame() | ||
+ | self.objStockBid = CpStockBid() | ||
+ | self.todayIndex = 0 | ||
+ | |||
+ | self.setCode("000660") | ||
+ | |||
+ | |||
+ | @pyqtSlot() | ||
+ | def slot_codeupdate(self): | ||
+ | code = self.ui.editCode.toPlainText() | ||
+ | self.setCode(code) | ||
+ | |||
+ | def slot_codechanged(self): | ||
+ | code = self.ui.editCode.toPlainText() | ||
+ | self.setCode(code) | ||
+ | |||
+ | |||
+ | def monitorPriceChange(self): | ||
+ | self.displyHoga() | ||
+ | self.updateWeek() | ||
+ | self.updateStockBid() | ||
+ | |||
+ | def monitorOfferbidChange(self): | ||
+ | self.displyHoga() | ||
+ | |||
+ | def setCode(self, code): | ||
+ | if len(code) < 6 : | ||
+ | return | ||
+ | |||
+ | print(code) | ||
+ | if not (code[0] == "A"): | ||
+ | code = "A" + code | ||
+ | |||
+ | name = g_objCodeMgr.CodeToName(code) | ||
+ | if len(name) == 0: | ||
+ | print("종목코드 확인") | ||
+ | return | ||
+ | |||
+ | self.ui.label_name.setText(name) | ||
+ | |||
+ | if (self.objMst.Request(code, self.item, self) == False): | ||
+ | return | ||
+ | self.displyHoga() | ||
+ | |||
+ | |||
+ | # 일자별 | ||
+ | self.ui.tableWeek.clearContents() | ||
+ | if (self.objWeek.Request(code, self) == True): | ||
+ | print(self.rpWeek) | ||
+ | self.displyWeek() | ||
+ | |||
+ | # 시간대별 | ||
+ | self.ui.tableStockBid.clearContents() | ||
+ | if (self.objStockBid.Request(code, self) == True): | ||
+ | self.displyStockBid() | ||
+ | |||
+ | |||
+ | # 10차 호가 UI 채우기 | ||
+ | def displyHoga(self): | ||
+ | self.ui.label_offer10.setText(format(self.item.offer[9],',')) | ||
+ | self.ui.label_offer9.setText(format(self.item.offer[8],',')) | ||
+ | self.ui.label_offer8.setText(format(self.item.offer[7],',')) | ||
+ | self.ui.label_offer7.setText(format(self.item.offer[6],',')) | ||
+ | self.ui.label_offer6.setText(format(self.item.offer[5],',')) | ||
+ | self.ui.label_offer5.setText(format(self.item.offer[4],',')) | ||
+ | self.ui.label_offer4.setText(format(self.item.offer[3],',')) | ||
+ | self.ui.label_offer3.setText(format(self.item.offer[2],',')) | ||
+ | self.ui.label_offer2.setText(format(self.item.offer[1],',')) | ||
+ | self.ui.label_offer1.setText(format(self.item.offer[0],',')) | ||
+ | |||
+ | self.ui.label_offer_v10.setText(format(self.item.offervol[9],',')) | ||
+ | self.ui.label_offer_v9.setText(format(self.item.offervol[8],',')) | ||
+ | self.ui.label_offer_v8.setText(format(self.item.offervol[7],',')) | ||
+ | self.ui.label_offer_v7.setText(format(self.item.offervol[6],',')) | ||
+ | self.ui.label_offer_v6.setText(format(self.item.offervol[5],',')) | ||
+ | self.ui.label_offer_v5.setText(format(self.item.offervol[4],',')) | ||
+ | self.ui.label_offer_v4.setText(format(self.item.offervol[3],',')) | ||
+ | self.ui.label_offer_v3.setText(format(self.item.offervol[2],',')) | ||
+ | self.ui.label_offer_v2.setText(format(self.item.offervol[1],',')) | ||
+ | self.ui.label_offer_v1.setText(format(self.item.offervol[0],',')) | ||
+ | |||
+ | self.ui.label_bid10.setText(format(self.item.bid[9],',')) | ||
+ | self.ui.label_bid9.setText(format(self.item.bid[8],',')) | ||
+ | self.ui.label_bid8.setText(format(self.item.bid[7],',')) | ||
+ | self.ui.label_bid7.setText(format(self.item.bid[6],',')) | ||
+ | self.ui.label_bid6.setText(format(self.item.bid[5],',')) | ||
+ | self.ui.label_bid5.setText(format(self.item.bid[4],',')) | ||
+ | self.ui.label_bid4.setText(format(self.item.bid[3],',')) | ||
+ | self.ui.label_bid3.setText(format(self.item.bid[2],',')) | ||
+ | self.ui.label_bid2.setText(format(self.item.bid[1],',')) | ||
+ | self.ui.label_bid1.setText(format(self.item.bid[0],',')) | ||
+ | |||
+ | self.ui.label_bid_v10.setText(format(self.item.bidvol[9],',')) | ||
+ | self.ui.label_bid_v9.setText(format(self.item.bidvol[8],',')) | ||
+ | self.ui.label_bid_v8.setText(format(self.item.bidvol[7],',')) | ||
+ | self.ui.label_bid_v7.setText(format(self.item.bidvol[6],',')) | ||
+ | self.ui.label_bid_v6.setText(format(self.item.bidvol[5],',')) | ||
+ | self.ui.label_bid_v5.setText(format(self.item.bidvol[4],',')) | ||
+ | self.ui.label_bid_v4.setText(format(self.item.bidvol[3],',')) | ||
+ | self.ui.label_bid_v3.setText(format(self.item.bidvol[2],',')) | ||
+ | self.ui.label_bid_v2.setText(format(self.item.bidvol[1],',')) | ||
+ | self.ui.label_bid_v1.setText(format(self.item.bidvol[0],',')) | ||
+ | |||
+ | cur = self.item.cur | ||
+ | diff = self.item.diff | ||
+ | diffp = self.item.diffp | ||
+ | if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결) | ||
+ | cur = self.item.expcur | ||
+ | diff = self.item.expdiff | ||
+ | diffp = self.item.expdiffp | ||
+ | |||
+ | |||
+ | strcur = format(cur, ',') | ||
+ | if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결) | ||
+ | strcur = "*" + strcur | ||
+ | |||
+ | curcolor = self.item.getCurColor() | ||
+ | self.ui.label_cur.setStyleSheet(curcolor) | ||
+ | self.ui.label_cur.setText(strcur) | ||
+ | strdiff = str(diff) + " " + format(diffp, '.2f') | ||
+ | strdiff += "%" | ||
+ | self.ui.label_diff.setText(strdiff) | ||
+ | self.ui.label_diff.setStyleSheet(curcolor) | ||
+ | |||
+ | self.ui.label_totoffer.setText(format(self.item.totOffer,',')) | ||
+ | self.ui.label_totbid.setText(format(self.item.totBid,',')) | ||
+ | |||
+ | # 일자별 리스트 UI 채우기 | ||
+ | def displyWeek(self): | ||
+ | rowcnt = len(self.rpWeek.index) | ||
+ | if rowcnt == 0: | ||
+ | return | ||
+ | self.ui.tableWeek.setRowCount(rowcnt) | ||
+ | |||
+ | nRow = 0 | ||
+ | |||
+ | for index, row in self.rpWeek.iterrows(): | ||
+ | datas = [index, row['close'],row['diff'],row['diffp'],row['vol'],row['open'],row['high'],row['low'], | ||
+ | row['for_v'], row['for_d'], row['for_p']] | ||
+ | for col in range(len(datas)) : | ||
+ | val = '' | ||
+ | if (col == 0): # 일자 | ||
+ | # 20170929 ==> 2017/09/29 | ||
+ | yyyy = int(datas[col] / 10000) | ||
+ | mm = int(datas[col] - (yyyy * 10000)) | ||
+ | dd = mm % 100 | ||
+ | mm = mm / 100 | ||
+ | val = '%04d/%02d/%02d' %(yyyy, mm, dd) | ||
+ | elif (col == 3 or col == 10): # 대비율 | ||
+ | val = locale.format('%.2f', datas[col], 1) | ||
+ | val += "%" | ||
+ | |||
+ | else: | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | |||
+ | item = QTableWidgetItem(val) | ||
+ | item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight) | ||
+ | self.ui.tableWeek.setItem(nRow, col, item) | ||
+ | |||
+ | if (nRow == 0) : | ||
+ | self.todayIndex = index | ||
+ | nRow += 1 | ||
+ | |||
+ | self.tableWeek.resizeColumnsToContents() | ||
+ | return | ||
+ | |||
+ | # 일자별 리스트 UI 채우기 - 오늘 날짜 업데이트 | ||
+ | def updateWeek(self): | ||
+ | rowcnt = len(self.rpWeek.index) | ||
+ | if rowcnt == 0: | ||
+ | return | ||
+ | |||
+ | # 오늘 날짜 데이터 업데이트 | ||
+ | self.rpWeek.set_value(self.todayIndex, 'close', self.item.cur) | ||
+ | self.rpWeek.set_value(self.todayIndex, 'open', self.item.open) | ||
+ | self.rpWeek.set_value(self.todayIndex, 'high', self.item.high) | ||
+ | self.rpWeek.set_value(self.todayIndex, 'low', self.item.low) | ||
+ | self.rpWeek.set_value(self.todayIndex, 'vol', self.item.vol) | ||
+ | self.rpWeek.set_value(self.todayIndex, 'diff', self.item.diff) | ||
+ | self.rpWeek.set_value(self.todayIndex, 'diffp', self.item.diffp) | ||
+ | |||
+ | datas = [self.todayIndex, self.item.cur,self.item.diff, self.item.diffp, self.item.vol, | ||
+ | self.item.open, self.item.high, self.item.low] | ||
+ | for col in range(len(datas)) : | ||
+ | val = '' | ||
+ | if (col == 0): # 일자 | ||
+ | # 20170929 ==> 2017/09/29 | ||
+ | yyyy = int(datas[col] / 10000) | ||
+ | mm = int(datas[col] - (yyyy * 10000)) | ||
+ | dd = mm % 100 | ||
+ | mm = mm / 100 | ||
+ | val = '%04d/%02d/%02d' %(yyyy, mm, dd) | ||
+ | elif (col == 3): # 대비율 | ||
+ | val = locale.format('%.2f', datas[col], 1) | ||
+ | val += "%" | ||
+ | |||
+ | else: | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | |||
+ | item = QTableWidgetItem(val) | ||
+ | item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight) | ||
+ | self.ui.tableWeek.setItem(0, col, item) | ||
+ | |||
+ | return | ||
+ | |||
+ | |||
+ | |||
+ | # 시간대별 리스트 UI 채우기 | ||
+ | def displyStockBid(self): | ||
+ | rowcnt = len(self.rpStockBid.index) | ||
+ | if rowcnt == 0: | ||
+ | return | ||
+ | self.ui.tableStockBid.setRowCount(rowcnt) | ||
+ | |||
+ | nRow = 0 | ||
+ | |||
+ | for index, row in self.rpStockBid.iterrows(): | ||
+ | # 행 내에 표시할 데이터 - 컬럼 순 | ||
+ | datas = [row['time'], row['cur'], row['diff'], row['offer'], row['bid'], row['vol'], row['tvol'], | ||
+ | row['tvol'], row['volstr']] | ||
+ | market = row['market'] | ||
+ | for col in range(len(datas)): | ||
+ | val = '' | ||
+ | if col == 0: # 시각 | ||
+ | # 155925 ==> 15:59:25 | ||
+ | hh = int(datas[col] / 10000) | ||
+ | mm = int(datas[col] - (hh * 10000)) | ||
+ | ss = mm % 100 | ||
+ | mm = mm / 100 | ||
+ | val = '%02d:%02d:%02d' %(hh, mm, ss) | ||
+ | elif col == 6: # 체결매도 | ||
+ | market = row['flag'] | ||
+ | if (market == "체결매도") : | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | elif col == 7: # 체결매수 | ||
+ | market = row['flag'] | ||
+ | if (market == "체결매수"): | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | elif col == 8: # 체결강도 | ||
+ | val = locale.format('%.2f', datas[col], 1) | ||
+ | elif col == 1: # 현재가 | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | if (market == "예상체결"): | ||
+ | val = '*' + val | ||
+ | else: # 기타 | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | item = QTableWidgetItem(val) | ||
+ | item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight) | ||
+ | self.ui.tableStockBid.setItem(nRow, col, item) | ||
+ | nRow += 1 | ||
+ | |||
+ | self.tableStockBid.resizeColumnsToContents() | ||
+ | return | ||
+ | |||
+ | |||
+ | def updateStockBid(self): | ||
+ | rowcnt = len(self.rpStockBid.index) | ||
+ | if rowcnt == 0: | ||
+ | return | ||
+ | if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결) | ||
+ | return | ||
+ | |||
+ | buyvol = sellvol = 0 | ||
+ | if self.item.volFlag == ord('1') : | ||
+ | buyvol = self.item.tvol | ||
+ | if self.item.volFlag == ord('2') : | ||
+ | sellvol = self.item.tvol | ||
+ | line = DataFrame({"time": self.item.time, | ||
+ | "cur": self.item.cur, | ||
+ | "diff": self.item.diff, | ||
+ | "offer": self.item.offer[0], | ||
+ | "bid": self.item.bid[0], | ||
+ | "vol": self.item.vol, | ||
+ | "tvol": buyvol, | ||
+ | "tvol": sellvol, | ||
+ | "volstr": self.item.volstr}, | ||
+ | index=[0]) | ||
+ | |||
+ | self.rpStockBid = pandas.concat([line, self.rpStockBid.ix[:]]).reset_index(drop=True) | ||
+ | |||
+ | # 행 내에 표시할 데이터 - 컬럼 순 | ||
+ | datas = [self.item.time, self.item.cur, self.item.diff, self.item.offer[0], self.item.bid[0], | ||
+ | self.item.vol, sellvol, buyvol, self.item.volstr] | ||
+ | self.ui.tableStockBid.insertRow(0) | ||
+ | for col in range(len(datas)): | ||
+ | val = '' | ||
+ | if col == 0: # 시각 | ||
+ | # 155925 ==> 15:59:25 | ||
+ | hh = int(datas[col] / 10000) | ||
+ | mm = int(datas[col] - (hh * 10000)) | ||
+ | ss = mm % 100 | ||
+ | mm = mm / 100 | ||
+ | val = '%02d:%02d:%02d' %(hh, mm, ss) | ||
+ | elif col == 6: # 체결매도 | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | elif col == 7: # 체결매수 | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | elif col == 8: # 체결강도 | ||
+ | val = locale.format('%.2f', datas[col], 1) | ||
+ | else: # 기타 | ||
+ | val = locale.format('%d', datas[col], 1) | ||
+ | |||
+ | item = QTableWidgetItem(val) | ||
+ | item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight) | ||
+ | self.ui.tableStockBid.setItem(0, col, item) | ||
+ | |||
+ | |||
+ | return | ||
+ | |||
+ | |||
+ | if __name__ == '__main__': | ||
+ | app = QtWidgets.QApplication(sys.argv) | ||
+ | w = Form() | ||
+ | sys.exit(app.exec()) | ||
+ | </source> | ||
+ | |||
=== 주식 미체결 조회 및 실시간 미체결 업데이트/취소주문/일괄 취소 예제... === | === 주식 미체결 조회 및 실시간 미체결 업데이트/취소주문/일괄 취소 예제... === | ||
주식 미체결을 실시간으로 처리하는 파이썬 예제 입니다 | 주식 미체결을 실시간으로 처리하는 파이썬 예제 입니다 |
2020년 9월 8일 (화) 23:33 판
- DBA { Oracle DBA 명령어 > DBA 초급 과정 > DBA 고급 과정 }
- 튜닝 { 오라클 튜닝 목록 }
- 모델링 { 데이터 모델링 가이드 }
목차
- 1 주식 현재가 조회/실시간
- 2 주식 일자별 조회(다음)
- 3 주식 현재가 조회
- 4 종목정보 구하는 예제
- 5 주식차트 조회(일간/주간/월간/분간/틱) 예제
- 6 지수옵션 최근월물 시세 조회(실시간 포함)
- 7 매매입체분석(투자주체별현황) 예제
- 8 해외선물 현재가/5차 호가 조회(실시간 업데이트 포함)
- 9 주식 현재가(10차호가/시간대별/일자별) 구현하기 예제
- 10 주식 미체결 조회 및 실시간 미체결 업데이트/취소주문/일괄 취소 예제...
- 11 주식 현재가 10차 호가 화면 구현하기
- 12 주식 예약 매수/매도/취소/조회 예제
- 13 주식/ELW/선물/옵션/업종 전 종목 시세 조회 예제
- 14 시세 연속 조회 제한 확인용 예제
- 15 VI 발동 종목에 대한 현재가 변화 추이 감시 예제
- 16 주식 주문 체결 실시간 처리 예제
- 17 주식 잔고 종목 조회 및 실시간 현재가 업데이트
- 18 당일 상승률 상위 200 종목 실시간 통신 예제
- 19 MACD 차트지표 계산(실시간)
- 20 차트 데이터 구하는 예제
- 21 주식 현금 매도주문
- 22 주식 현금 매수주문
- 23 주식 복수종목 조회/실시간
- 24 주식 복수종목 실시간 등록/해지
- 25 ETF NAV , ETN IIV 실시간 수신 예제
- 26 데이터 요청 방법 2가지 BlockRequest 와 Request 방식 비교 예제
- 27 주식 5분 차트 MACD 신호
- 28 종목검색 조회 및 실시간 감시 예제
- 29 선물 현재가/시간대별/일자별/주문/잔고/미체결 예제
- 30 투자자별 매매 종합 예제
- 31 전종목 시가총액 구하기 예제
- 32 차트 지표 계산(MACD/RSI 등)
- 33 선물 분 차트 그리기(matplotlib 이용)
- 34 체결기준 주식 당일 매매 손익 예제
- 35 실시간 분차트 데이터 만들기
- 36 주식 잔고 실시간 조회(현재가 및 주문 체결 실시간 반영)
- 37 해외선물 주문 예제
- 38 특징주 포착(뉴스/공시/차트/외국인 신호) 예제
- 39 보유 주식 잔고 일괄 매도 예제
- 40 주식 IOC/FOK 주문 테스트 예제
- 41 종목검색 서비스를 이용하여 예제 전략 조건 조회하기 예제
- 42 종목별 투자자 매매동향 (잠정)데이터
- 43 주식 분할 주문 예제
- 44 해외선물 잔고(미결제약정)과 실시간 주문체결 처리 예제
1 주식 현재가 조회/실시간[편집]
2 주식 일자별 조회(다음)[편집]
3 주식 현재가 조회[편집]
4 종목정보 구하는 예제[편집]
5 주식차트 조회(일간/주간/월간/분간/틱) 예제[편집]
6 지수옵션 최근월물 시세 조회(실시간 포함)[편집]
7 매매입체분석(투자주체별현황) 예제[편집]
8 해외선물 현재가/5차 호가 조회(실시간 업데이트 포함)[편집]
9 주식 현재가(10차호가/시간대별/일자별) 구현하기 예제[편집]
주식 현재가 화면을 구성하는 10차 호가, 시간대별, 일자별 데이터를 구현한 파이썬 예제입니다
화면 UI 는 PYQT 를 이용하였고 첨부된 파일에서 소스와 UI 를 받아 확인 가능합니다.
import sys
import pandas
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *
import win32com.client
from pandas import Series, DataFrame
import locale
# cp object
g_objCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
g_objCpStatus = win32com.client.Dispatch("CpUtil.CpCybos")
g_objCpTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
locale.setlocale(locale.LC_ALL, '')
# 현재가 정보 저장 구조체
class stockPricedData:
def __init__(self):
self.dicEx = {ord('0'): "동시호가/장중 아님", ord('1'): "동시호가", ord('2'): "장중"}
self.code = ""
self.name = ""
self.cur = 0 # 현재가
self.diff = 0 # 대비
self.diffp = 0 # 대비율
self.offer = [0 for _ in range(10)] # 매도호가
self.bid = [0 for _ in range(10)] # 매수호가
self.offervol = [0 for _ in range(10)] # 매도호가 잔량
self.bidvol = [0 for _ in range(10)] # 매수호가 잔량
self.totOffer = 0 # 총매도잔량
self.totBid = 0 # 총매수 잔량
self.vol = 0 # 거래량
self.tvol = 0 # 순간 체결량
self.baseprice = 0 # 기준가
self.high = 0
self.low = 0
self.open = 0
self.volFlag = ord('0') # 체결매도/체결 매수 여부
self.time = 0
self.sum_buyvol = 0
self.sum_sellvol = 0
self.vol_str = 0
# 예상체결가 정보
self.exFlag= ord('2')
self.expcur = 0 # 예상체결가
self.expdiff = 0 # 예상 대비
self.expdiffp = 0 # 예상 대비율
self.expvol = 0 # 예상 거래량
self.objCur = CpPBStockCur()
self.objOfferbid = CpPBStockBid()
def __del__(self):
self.objCur.Unsubscribe()
self.objOfferbid.Unsubscribe()
# 전일 대비 계산
def makediffp(self):
lastday = 0
if (self.exFlag == ord('1')): # 동시호가 시간 (예상체결)
if self.baseprice > 0 :
lastday = self.baseprice
else:
lastday = self.expcur - self.expdiff
if lastday:
self.expdiffp = (self.expdiff / lastday) * 100
else:
self.expdiffp = 0
else:
if self.baseprice > 0 :
lastday = self.baseprice
else:
lastday = self.cur - self.diff
if lastday:
self.diffp = (self.diff / lastday) * 100
else:
self.diffp = 0
def getCurColor(self):
diff = self.diff
if (self.exFlag == ord('1')): # 동시호가 시간 (예상체결)
diff = self.expdiff
if (diff > 0):
return 'color: red'
elif (diff == 0):
return 'color: black'
elif (diff < 0):
return 'color: blue'
# CpEvent: 실시간 이벤트 수신 클래스
class CpEvent:
def set_params(self, client, name, rpMst, parent):
self.client = client # CP 실시간 통신 object
self.name = name # 서비스가 다른 이벤트를 구분하기 위한 이름
self.parent = parent # callback 을 위해 보관
self.rpMst = rpMst
# PLUS 로 부터 실제로 시세를 수신 받는 이벤트 핸들러
def OnReceived(self):
if self.name == "stockcur":
# 현재가 체결 데이터 실시간 업데이트
self.rpMst.exFlag = self.client.GetHeaderValue(19) # 예상체결 플래그
code = self.client.GetHeaderValue(0)
diff = self.client.GetHeaderValue(2)
cur= self.client.GetHeaderValue(13) # 현재가
vol = self.client.GetHeaderValue(9) # 거래량
# 예제는 장중만 처리 함.
if (self.rpMst.exFlag == ord('1')): # 동시호가 시간 (예상체결)
# 예상체결가 정보
self.rpMst.expcur = cur
self.rpMst.expdiff = diff
self.rpMst.expvol = vol
else:
self.rpMst.cur = cur
self.rpMst.diff = diff
self.rpMst.makediffp()
self.rpMst.vol = vol
self.rpMst.open = self.client.GetHeaderValue(4)
self.rpMst.high = self.client.GetHeaderValue(5)
self.rpMst.low = self.client.GetHeaderValue(6)
self.rpMst.tvol = self.client.GetHeaderValue(17)
self.rpMst.volFlag = self.client.GetHeaderValue(14) # '1' 매수 '2' 매도
self.rpMst.time = self.client.GetHeaderValue(18)
self.rpMst.sum_buyvol = self.client.GetHeaderValue(16) #누적매수체결수량 (체결가방식)
self.rpMst.sum_sellvol = self.client.GetHeaderValue(15) #누적매도체결수량 (체결가방식)
if (self.rpMst.sum_sellvol) :
self.rpMst.volstr = self.rpMst.sum_buyvol / self.rpMst.sum_sellvol * 100
else :
self.rpMst.volstr = 0
self.rpMst.makediffp()
# 현재가 업데이트
self.parent.monitorPriceChange()
return
elif self.name == "stockbid":
# 현재가 10차 호가 데이터 실시간 업데이c
code = self.client.GetHeaderValue(0)
dataindex = [3, 7, 11, 15, 19, 27, 31, 35, 39, 43]
obi = 0
for i in range(10):
self.rpMst.offer[i] = self.client.GetHeaderValue(dataindex[i])
self.rpMst.bid[i] = self.client.GetHeaderValue(dataindex[i] + 1)
self.rpMst.offervol[i] = self.client.GetHeaderValue(dataindex[i] + 2)
self.rpMst.bidvol[i] = self.client.GetHeaderValue(dataindex[i] + 3)
self.rpMst.totOffer = self.client.GetHeaderValue(23)
self.rpMst.totBid = self.client.GetHeaderValue(24)
# 10차 호가 변경 call back 함수 호출
self.parent.monitorOfferbidChange()
return
# SB/PB 요청 ROOT 클래스
class CpPublish:
def __init__(self, name, serviceID):
self.name = name
self.obj = win32com.client.Dispatch(serviceID)
self.bIsSB = False
def Subscribe(self, var, rpMst, parent):
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, rpMst, parent)
self.obj.Subscribe()
self.bIsSB = True
def Unsubscribe(self):
if self.bIsSB:
self.obj.Unsubscribe()
self.bIsSB = False
# CpPBStockCur: 실시간 현재가 요청 클래스
class CpPBStockCur(CpPublish):
def __init__(self):
super().__init__("stockcur", "DsCbo1.StockCur")
# CpPBStockBid: 실시간 10차 호가 요청 클래스
class CpPBStockBid(CpPublish):
def __init__(self):
super().__init__("stockbid", "Dscbo1.StockJpBid")
# SB/PB 요청 ROOT 클래스
class CpPBConnection:
def __init__(self):
self.obj = win32com.client.Dispatch("CpUtil.CpCybos")
handler = win32com.client.WithEvents(self.obj, CpEvent)
handler.set_params(self.obj, "connection", None)
# CpRPCurrentPrice: 현재가 기본 정보 조회 클래스
class CpRPCurrentPrice:
def __init__(self):
if (g_objCpStatus.IsConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
return
self.objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
return
def Request(self, code, rtMst, callbackobj):
# 현재가 통신
rtMst.objCur.Unsubscribe()
rtMst.objOfferbid.Unsubscribe()
self.objStockMst.SetInputValue(0, code)
ret = self.objStockMst.BlockRequest()
if self.objStockMst.GetDibStatus() != 0:
print("통신상태", self.objStockMst.GetDibStatus(), self.objStockMst.GetDibMsg1())
return False
# 수신 받은 현재가 정보를 rtMst 에 저장
rtMst.code = code
rtMst.name = g_objCodeMgr.CodeToName(code)
rtMst.cur = self.objStockMst.GetHeaderValue(11) # 종가
rtMst.diff = self.objStockMst.GetHeaderValue(12) # 전일대비
rtMst.baseprice = self.objStockMst.GetHeaderValue(27) # 기준가
rtMst.vol = self.objStockMst.GetHeaderValue(18) # 거래량
rtMst.exFlag = self.objStockMst.GetHeaderValue(58) # 예상플래그
rtMst.expcur = self.objStockMst.GetHeaderValue(55) # 예상체결가
rtMst.expdiff = self.objStockMst.GetHeaderValue(56) # 예상체결대비
rtMst.makediffp()
rtMst.totOffer = self.objStockMst.GetHeaderValue(71) # 총매도잔량
rtMst.totBid = self.objStockMst.GetHeaderValue(73) # 총매수잔량
# 10차호가
for i in range(10):
rtMst.offer[i] = (self.objStockMst.GetDataValue(0, i)) # 매도호가
rtMst.bid[i] = (self.objStockMst.GetDataValue(1, i) ) # 매수호가
rtMst.offervol[i] = (self.objStockMst.GetDataValue(2, i)) # 매도호가 잔량
rtMst.bidvol[i] = (self.objStockMst.GetDataValue(3, i) ) # 매수호가 잔량
rtMst.objCur.Subscribe(code,rtMst, callbackobj)
rtMst.objOfferbid.Subscribe(code,rtMst, callbackobj)
# CpWeekList: 일자별 리스트 구하기
class CpWeekList:
def __init__(self):
self.objWeek = win32com.client.Dispatch("Dscbo1.StockWeek")
return
def Request(self, code, caller):
# 현재가 통신
self.objWeek.SetInputValue(0, code)
# 데이터들
dates = []
opens = []
highs = []
lows = []
closes = []
diffs = []
vols = []
diffps = []
foreign_vols = []
foreign_diff = []
foreign_p = []
# 누적 개수 - 100 개까지만 하자
sumCnt = 0
while True:
ret = self.objWeek.BlockRequest()
if self.objWeek.GetDibStatus() != 0:
print("통신상태", self.objWeek.GetDibStatus(), self.objWeek.GetDibMsg1())
return False
cnt = self.objWeek.GetHeaderValue(1)
sumCnt += cnt
if cnt == 0:
break
for i in range(cnt):
dates.append(self.objWeek.GetDataValue(0, i))
opens.append(self.objWeek.GetDataValue(1, i))
highs.append(self.objWeek.GetDataValue(2, i))
lows.append(self.objWeek.GetDataValue(3, i))
closes.append(self.objWeek.GetDataValue(4, i))
temp = self.objWeek.GetDataValue(5, i)
diffs.append(temp)
vols.append(self.objWeek.GetDataValue(6, i))
temp2 = self.objWeek.GetDataValue(10, i)
if (temp < 0):
temp2 *= -1
diffps.append(temp2)
foreign_vols.append(self.objWeek.GetDataValue(7, i)) # 외인보유
foreign_diff.append(self.objWeek.GetDataValue(8, i)) # 외인보유 전일대비
foreign_p.append(self.objWeek.GetDataValue(9, i)) # 외인비중
if (sumCnt > 100):
break
if self.objWeek.Continue == False:
break
if len(dates) == 0:
return False
caller.rpWeek = None
weekCol = {'close': closes,
'diff': diffs,
'diffp': diffps,
'vol': vols,
'open':opens,
'high': highs,
'low': lows,
'for_v' : foreign_vols,
'for_d': foreign_diff,
'for_p': foreign_p,
}
caller.rpWeek = DataFrame(weekCol, index=dates)
return True
# CpStockBid: 시간대별 조회
class CpStockBid:
def __init__(self):
self.objSBid = win32com.client.Dispatch("Dscbo1.StockBid")
return
def Request(self, code, caller):
# 현재가 통신
self.objSBid.SetInputValue(0, code)
self.objSBid.SetInputValue(2, 80) # 요청개수 (최대 80)
self.objSBid.SetInputValue(3, ord('C')) # C 체결가 비교 방식 H 호가 비교방식
times = []
curs = []
diffs = []
tvols = []
offers = []
bids = []
vols = []
offerbidFlags = [] # 체결 상태 '1' 매수 '2' 매도
volstrs = [] # 체결강도
marketFlags = [] # 장구분 '1' 동시호가 예상체결' '2' 장중
# 누적 개수 - 100 개까지만 하자
sumCnt = 0
while True:
ret = self.objSBid.BlockRequest()
if self.objSBid.GetDibStatus() != 0:
print("통신상태", self.objSBid.GetDibStatus(), self.objSBid.GetDibMsg1())
return False
cnt = self.objSBid.GetHeaderValue(2)
sumCnt += cnt
if cnt == 0:
break
strcur = ""
strflag = ""
strflag2 = ""
for i in range(cnt):
cur = self.objSBid.GetDataValue(4, i)
times.append(self.objSBid.GetDataValue(9, i))
diffs.append(self.objSBid.GetDataValue(1, i))
vols.append(self.objSBid.GetDataValue(5, i))
tvols.append(self.objSBid.GetDataValue(6, i))
offers.append(self.objSBid.GetDataValue(2, i))
bids.append(self.objSBid.GetDataValue(3, i))
flag = self.objSBid.GetDataValue(7, i)
if (flag == ord('1')):
strflag = "체결매수"
else:
strflag = "체결매도"
offerbidFlags.append(strflag)
volstrs.append(self.objSBid.GetDataValue(8, i))
flag = self.objSBid.GetDataValue(10, i)
if (flag == ord('1')):
strflag2 = "예상체결"
#strcur = '*' + str(cur)
else:
strflag2 = "장중"
#strcur = str(cur)
marketFlags.append(strflag2)
curs.append(cur)
if (sumCnt > 100):
break
if self.objSBid.Continue == False:
break
if len(times) == 0:
return False
caller.rpStockBid = None
sBidCol = {'time': times,
'cur': curs,
'diff': diffs,
'vol': vols,
'tvol':tvols,
'offer': offers,
'bid': bids,
'flag': offerbidFlags,
'market': marketFlags,
'volstr': volstrs}
caller.rpStockBid = DataFrame(sBidCol)
print(caller.rpStockBid)
return True
class Form(QtWidgets.QDialog):
def __init__(self, parent=None):
QtWidgets.QDialog.__init__(self, parent)
self.ui = uic.loadUi("hoga.ui", self)
self.ui.show()
self.objMst = CpRPCurrentPrice()
self.item = stockPricedData()
# 일자별
self.objWeek = CpWeekList()
self.rpWeek = DataFrame() # 일자별 데이터프레임
# 시간대별
self.rpStockBid = DataFrame()
self.objStockBid = CpStockBid()
self.todayIndex = 0
self.setCode("000660")
@pyqtSlot()
def slot_codeupdate(self):
code = self.ui.editCode.toPlainText()
self.setCode(code)
def slot_codechanged(self):
code = self.ui.editCode.toPlainText()
self.setCode(code)
def monitorPriceChange(self):
self.displyHoga()
self.updateWeek()
self.updateStockBid()
def monitorOfferbidChange(self):
self.displyHoga()
def setCode(self, code):
if len(code) < 6 :
return
print(code)
if not (code[0] == "A"):
code = "A" + code
name = g_objCodeMgr.CodeToName(code)
if len(name) == 0:
print("종목코드 확인")
return
self.ui.label_name.setText(name)
if (self.objMst.Request(code, self.item, self) == False):
return
self.displyHoga()
# 일자별
self.ui.tableWeek.clearContents()
if (self.objWeek.Request(code, self) == True):
print(self.rpWeek)
self.displyWeek()
# 시간대별
self.ui.tableStockBid.clearContents()
if (self.objStockBid.Request(code, self) == True):
self.displyStockBid()
# 10차 호가 UI 채우기
def displyHoga(self):
self.ui.label_offer10.setText(format(self.item.offer[9],','))
self.ui.label_offer9.setText(format(self.item.offer[8],','))
self.ui.label_offer8.setText(format(self.item.offer[7],','))
self.ui.label_offer7.setText(format(self.item.offer[6],','))
self.ui.label_offer6.setText(format(self.item.offer[5],','))
self.ui.label_offer5.setText(format(self.item.offer[4],','))
self.ui.label_offer4.setText(format(self.item.offer[3],','))
self.ui.label_offer3.setText(format(self.item.offer[2],','))
self.ui.label_offer2.setText(format(self.item.offer[1],','))
self.ui.label_offer1.setText(format(self.item.offer[0],','))
self.ui.label_offer_v10.setText(format(self.item.offervol[9],','))
self.ui.label_offer_v9.setText(format(self.item.offervol[8],','))
self.ui.label_offer_v8.setText(format(self.item.offervol[7],','))
self.ui.label_offer_v7.setText(format(self.item.offervol[6],','))
self.ui.label_offer_v6.setText(format(self.item.offervol[5],','))
self.ui.label_offer_v5.setText(format(self.item.offervol[4],','))
self.ui.label_offer_v4.setText(format(self.item.offervol[3],','))
self.ui.label_offer_v3.setText(format(self.item.offervol[2],','))
self.ui.label_offer_v2.setText(format(self.item.offervol[1],','))
self.ui.label_offer_v1.setText(format(self.item.offervol[0],','))
self.ui.label_bid10.setText(format(self.item.bid[9],','))
self.ui.label_bid9.setText(format(self.item.bid[8],','))
self.ui.label_bid8.setText(format(self.item.bid[7],','))
self.ui.label_bid7.setText(format(self.item.bid[6],','))
self.ui.label_bid6.setText(format(self.item.bid[5],','))
self.ui.label_bid5.setText(format(self.item.bid[4],','))
self.ui.label_bid4.setText(format(self.item.bid[3],','))
self.ui.label_bid3.setText(format(self.item.bid[2],','))
self.ui.label_bid2.setText(format(self.item.bid[1],','))
self.ui.label_bid1.setText(format(self.item.bid[0],','))
self.ui.label_bid_v10.setText(format(self.item.bidvol[9],','))
self.ui.label_bid_v9.setText(format(self.item.bidvol[8],','))
self.ui.label_bid_v8.setText(format(self.item.bidvol[7],','))
self.ui.label_bid_v7.setText(format(self.item.bidvol[6],','))
self.ui.label_bid_v6.setText(format(self.item.bidvol[5],','))
self.ui.label_bid_v5.setText(format(self.item.bidvol[4],','))
self.ui.label_bid_v4.setText(format(self.item.bidvol[3],','))
self.ui.label_bid_v3.setText(format(self.item.bidvol[2],','))
self.ui.label_bid_v2.setText(format(self.item.bidvol[1],','))
self.ui.label_bid_v1.setText(format(self.item.bidvol[0],','))
cur = self.item.cur
diff = self.item.diff
diffp = self.item.diffp
if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결)
cur = self.item.expcur
diff = self.item.expdiff
diffp = self.item.expdiffp
strcur = format(cur, ',')
if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결)
strcur = "*" + strcur
curcolor = self.item.getCurColor()
self.ui.label_cur.setStyleSheet(curcolor)
self.ui.label_cur.setText(strcur)
strdiff = str(diff) + " " + format(diffp, '.2f')
strdiff += "%"
self.ui.label_diff.setText(strdiff)
self.ui.label_diff.setStyleSheet(curcolor)
self.ui.label_totoffer.setText(format(self.item.totOffer,','))
self.ui.label_totbid.setText(format(self.item.totBid,','))
# 일자별 리스트 UI 채우기
def displyWeek(self):
rowcnt = len(self.rpWeek.index)
if rowcnt == 0:
return
self.ui.tableWeek.setRowCount(rowcnt)
nRow = 0
for index, row in self.rpWeek.iterrows():
datas = [index, row['close'],row['diff'],row['diffp'],row['vol'],row['open'],row['high'],row['low'],
row['for_v'], row['for_d'], row['for_p']]
for col in range(len(datas)) :
val = ''
if (col == 0): # 일자
# 20170929 ==> 2017/09/29
yyyy = int(datas[col] / 10000)
mm = int(datas[col] - (yyyy * 10000))
dd = mm % 100
mm = mm / 100
val = '%04d/%02d/%02d' %(yyyy, mm, dd)
elif (col == 3 or col == 10): # 대비율
val = locale.format('%.2f', datas[col], 1)
val += "%"
else:
val = locale.format('%d', datas[col], 1)
item = QTableWidgetItem(val)
item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
self.ui.tableWeek.setItem(nRow, col, item)
if (nRow == 0) :
self.todayIndex = index
nRow += 1
self.tableWeek.resizeColumnsToContents()
return
# 일자별 리스트 UI 채우기 - 오늘 날짜 업데이트
def updateWeek(self):
rowcnt = len(self.rpWeek.index)
if rowcnt == 0:
return
# 오늘 날짜 데이터 업데이트
self.rpWeek.set_value(self.todayIndex, 'close', self.item.cur)
self.rpWeek.set_value(self.todayIndex, 'open', self.item.open)
self.rpWeek.set_value(self.todayIndex, 'high', self.item.high)
self.rpWeek.set_value(self.todayIndex, 'low', self.item.low)
self.rpWeek.set_value(self.todayIndex, 'vol', self.item.vol)
self.rpWeek.set_value(self.todayIndex, 'diff', self.item.diff)
self.rpWeek.set_value(self.todayIndex, 'diffp', self.item.diffp)
datas = [self.todayIndex, self.item.cur,self.item.diff, self.item.diffp, self.item.vol,
self.item.open, self.item.high, self.item.low]
for col in range(len(datas)) :
val = ''
if (col == 0): # 일자
# 20170929 ==> 2017/09/29
yyyy = int(datas[col] / 10000)
mm = int(datas[col] - (yyyy * 10000))
dd = mm % 100
mm = mm / 100
val = '%04d/%02d/%02d' %(yyyy, mm, dd)
elif (col == 3): # 대비율
val = locale.format('%.2f', datas[col], 1)
val += "%"
else:
val = locale.format('%d', datas[col], 1)
item = QTableWidgetItem(val)
item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
self.ui.tableWeek.setItem(0, col, item)
return
# 시간대별 리스트 UI 채우기
def displyStockBid(self):
rowcnt = len(self.rpStockBid.index)
if rowcnt == 0:
return
self.ui.tableStockBid.setRowCount(rowcnt)
nRow = 0
for index, row in self.rpStockBid.iterrows():
# 행 내에 표시할 데이터 - 컬럼 순
datas = [row['time'], row['cur'], row['diff'], row['offer'], row['bid'], row['vol'], row['tvol'],
row['tvol'], row['volstr']]
market = row['market']
for col in range(len(datas)):
val = ''
if col == 0: # 시각
# 155925 ==> 15:59:25
hh = int(datas[col] / 10000)
mm = int(datas[col] - (hh * 10000))
ss = mm % 100
mm = mm / 100
val = '%02d:%02d:%02d' %(hh, mm, ss)
elif col == 6: # 체결매도
market = row['flag']
if (market == "체결매도") :
val = locale.format('%d', datas[col], 1)
elif col == 7: # 체결매수
market = row['flag']
if (market == "체결매수"):
val = locale.format('%d', datas[col], 1)
elif col == 8: # 체결강도
val = locale.format('%.2f', datas[col], 1)
elif col == 1: # 현재가
val = locale.format('%d', datas[col], 1)
if (market == "예상체결"):
val = '*' + val
else: # 기타
val = locale.format('%d', datas[col], 1)
item = QTableWidgetItem(val)
item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
self.ui.tableStockBid.setItem(nRow, col, item)
nRow += 1
self.tableStockBid.resizeColumnsToContents()
return
def updateStockBid(self):
rowcnt = len(self.rpStockBid.index)
if rowcnt == 0:
return
if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결)
return
buyvol = sellvol = 0
if self.item.volFlag == ord('1') :
buyvol = self.item.tvol
if self.item.volFlag == ord('2') :
sellvol = self.item.tvol
line = DataFrame({"time": self.item.time,
"cur": self.item.cur,
"diff": self.item.diff,
"offer": self.item.offer[0],
"bid": self.item.bid[0],
"vol": self.item.vol,
"tvol": buyvol,
"tvol": sellvol,
"volstr": self.item.volstr},
index=[0])
self.rpStockBid = pandas.concat([line, self.rpStockBid.ix[:]]).reset_index(drop=True)
# 행 내에 표시할 데이터 - 컬럼 순
datas = [self.item.time, self.item.cur, self.item.diff, self.item.offer[0], self.item.bid[0],
self.item.vol, sellvol, buyvol, self.item.volstr]
self.ui.tableStockBid.insertRow(0)
for col in range(len(datas)):
val = ''
if col == 0: # 시각
# 155925 ==> 15:59:25
hh = int(datas[col] / 10000)
mm = int(datas[col] - (hh * 10000))
ss = mm % 100
mm = mm / 100
val = '%02d:%02d:%02d' %(hh, mm, ss)
elif col == 6: # 체결매도
val = locale.format('%d', datas[col], 1)
elif col == 7: # 체결매수
val = locale.format('%d', datas[col], 1)
elif col == 8: # 체결강도
val = locale.format('%.2f', datas[col], 1)
else: # 기타
val = locale.format('%d', datas[col], 1)
item = QTableWidgetItem(val)
item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
self.ui.tableStockBid.setItem(0, col, item)
return
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Form()
sys.exit(app.exec())
10 주식 미체결 조회 및 실시간 미체결 업데이트/취소주문/일괄 취소 예제...[편집]
주식 미체결을 실시간으로 처리하는 파이썬 예제 입니다
※ 제공된 예제는 PLUS API 학습을 위해 제공되는 예제로, 모든 예외 케이스와 상세 처리가 포함되어 있지 않습니다. 참고로만 이용하시기 바랍니다.
1. 미체결 (CpTrade.CpTd5339)
예제에서는 Cp5339 클래스에서 미체결을 조회 합니다 연속 조회를 통해 당일 발생한 모든 미체결을 조회 합니다.
2. 실시간 주문 체결 (DsCbo1.CpConclusion) 미체결을 실시간으로 감시하기 위해서는 "DsCbo1.CpConclusion" 에 이벤트를 등록하고 이벤트를 수신 받아 처리 해야 합니다 DsCbo1.CpConclusion 이벤트는 CpEvent::OnReceived 에서 수신 받아 처리 합니다.
기본적으로 실시간 주문 체결의 경우 아래 4가지 type 이 있습니다 ▶ 접수 - 주문에 대한 1차 수신 ▶ 확인(정정 또는 취소) - 정정이나 취소 주문에 대해 거래소로 부터 확인 응답을 받음 ▶ 체결 - 주문 내역 중 일부 또는 전체가 체결됨을 통보 받음 ▶ 거부 - 정정 또는 취소 주문 등이 거래소로 부터 거부 됨(이미 체결 된 경우)
3. 취소 주문 (CpTrade.CpTd0314)
클래스 CpRPOrder 에서는 CpTrade.CpTd0314 를 이용하여 취소주문을 냅니다
CpRPOrder 에서는 2가지 취소 방식을 제공하는데
RequestCancel 는 Request API 를 BlockRequestCancel 는 BlockRequest API 를 각각 이용하여 취소 주문을 냅니다
Request API 의 경우 수신이벤트를 등록하고 처리해야 함으로 이에 대한 예제로 참고 바랍니다.
4. 일괄 취소 일괄 취소는 미체결 된 전체 주문 리스트에 대해 BlockRequest 를 이용하여 취소 주문을 냅니다
5. 연속 주문에 대한 처리 PLUS 는 연속적으로 주문/계좌 조회가 발생 할 경우 서비스 보호를 위해 오류 코드 4를 리턴합니다 이 경우에는 CpUtil.CpCybos > LimitRequestRemainTime 를 이용하여 남은 대기 시간동안 대기 후 재 시도 또는 다른 방법을 찾아야 합니다 (신규 주문인 경우 대기 시간 동안 주문 가격이 달라질 수 있으니 이런 점에 유의가 필요 합니다) 예제에 취소 주문과 미체결 통신에 연속 조회 오류 코드를 참고 하시기 바랍니다.
import sys
from PyQt5.QtWidgets import *
import win32com.client
import time
g_objCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
g_objCpStatus = win32com.client.Dispatch("CpUtil.CpCybos")
g_objCpTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
# 미체결 주문 정보 저장 구조체
class orderData:
def __init__(self):
self.code = "" # 종목코드
self.name = "" # 종목명
self.orderNum = 0 # 주문번호
self.orderPrev = 0 # 원주문번호
self.orderDesc = "" # 주문구분내용
self.amount = 0 # 주문수량
self.price = 0 # 주문 단가
self.ContAmount = 0 # 체결수량
self.credit = "" # 신용 구분 "현금" "유통융자" "자기융자" "유통대주" "자기대주"
self.modAvali = 0 # 정정/취소 가능 수량
self.buysell = "" # 매매구분 코드 1 매도 2 매수
self.creditdate = "" # 대출일
self.orderFlag = "" # 주문호가 구분코드
self.orderFlagDesc = "" # 주문호가 구분 코드 내용
# 데이터 변환용
self.concdic = {"1": "체결", "2": "확인", "3": "거부", "4": "접수"}
self.buyselldic = {"1": "매도", "2": "매수"}
def debugPrint(self):
print("%s, %s, 주문번호 %d, 원주문 %d, %s, 주문수량 %d, 주문단가 %d, 체결수량 %d, %s, "
"정정가능수량 %d, 매수매도: %s, 대출일 %s, 주문호가구분 %s %s"
%(self.code, self.name, self.orderNum, self.orderPrev, self.orderDesc, self.amount, self.price,
self.ContAmount,self.credit,self.modAvali, self.buyselldic.get(self.buysell),
self.creditdate,self.orderFlag, self.orderFlagDesc))
# CpEvent: 실시간 이벤트 수신 클래스
class CpEvent:
def set_params(self, client, name, parent):
self.client = client # CP 실시간 통신 object
self.name = name # 서비스가 다른 이벤트를 구분하기 위한 이름
self.parent = parent # callback 을 위해 보관
self.concdic = {"1" : "체결", "2" : "확인", "3" : "거부", "4" : "접수"}
# PLUS 로 부터 실제로 이벤트(체결/주문 응답/시세 이벤트 등)를 수신 받아 처리하는 함수.
# 여러가지 이벤트가 이 클래스로 들어 오기 때문에 구분은 이벤트 등록 시 사용한 self.name 을 통해 구분한다.
def OnReceived(self):
# 주문 Request 에 대한 응답 처리
if self.name == "td0314" :
print("[CpEvent]주문응답")
self.parent.OrderReply()
return
# 주문 체결 PB 에 대한 처리
elif self.name == "conclusion" :
# 주문 체결 실시간 업데이트
i3 = self.client.GetHeaderValue(3) # 체결 수량
i4 = self.client.GetHeaderValue(4) # 가격
i5 = self.client.GetHeaderValue(5) # 주문번호
i6 = self.client.GetHeaderValue(6) # 원주문번호
i9 = self.client.GetHeaderValue(9) # 종목코드
i12 = self.client.GetHeaderValue(12) # 매수/매도 구분 1 매도 2매수
i14 = self.client.GetHeaderValue(14) # 체결 플래그 1 체결 2 확인...
i15 = self.client.GetHeaderValue(15) # 신용대출구분
i16 = self.client.GetHeaderValue(16) # 정정/취소 구분코드 (1 정상, 2 정정 3 취소)
i17 = self.client.GetHeaderValue(17) # 현금신용대용 구분
i18 = self.client.GetHeaderValue(18) # 주문호가구분코드
i19 = self.client.GetHeaderValue(19) # 주문조건구분코드
i20 = self.client.GetHeaderValue(20) # 대출일
i21 = self.client.GetHeaderValue(21) # 장부가
i22 = self.client.GetHeaderValue(22) # 매도가능수량
i23 = self.client.GetHeaderValue(23) # 체결기준잔고수량
# for debug
print("[CpEvent]%s, 수량 %d, 가격 %d, 주문번호 %d, 원주문 %d, 코드 %s, 매도매수 %s, 신용대출 %s 정정취소 %s,"
"현금신용대용 %s, 주문호가구분 %s, 주문조건구분 %s, 대출일 %s, 장부가 %d, 매도가능 %d, 체결기준잔고%d"
%(self.concdic.get(i14), i3, i4, i5, i6, i9, i12, i15, i16, i17, i18, i19, i20, i21, i22, i23) )
# 체결 에 대한 처리
# 미체결에서 체결이 발생한 주문번호를 찾아 주문 수량과 체결 수량을 비교한다
# 전부 체결이면 미체결을 지우고, 부분 체결일 경우 체결 된 수량만큼 주문 수량에서 제한다.
if (i14 == "1") : # 체결
if not (i5 in self.parent.diOrderList) :
print("[CpEvent]주문번호 찾기 실패", i5)
return
item = self.parent.diOrderList[i5]
if (item.amount - i3 > 0): # 일부 체결인경우
# 기존 데이터 업데이트
item.amount -= i3
item.modAvali = item.amount
item.ContAmount += i3
else: # 전체 체결인 경우
self.parent.deleteOrderNum(i5)
# for debug
#for i in range(len(self.parent.orderList)):
# self.parent.orderList[i].debugPrint()
print("[CpEvent]미체결 개수 ", len(self.parent.orderList))
# 확인 에 대한 처리
# 정정확인 - 정정주문이 발생한 원주문을 찾아
# 부분 정정인 경우 - 기존 주문은 수량을 업데이트, 새로운 정정에 의한 미체결 주문번호는 신규 추가
# 전체 정정인 경우 - 주문 리스트의 원주문/주문번호만 업데이트
# 취소 확인 - 취소주문이 발생한 원주문을 찾아 미체결 리스트에서 제거 한다.
elif (i14 == "2") : # 확인
# 원주문 번호로 찾는다.
if not (i6 in self.parent.diOrderList) :
print("[CpEvent]원주문번호 찾기 실패", i6)
# IOC/FOK 의 경우 취소 주문을 낸적이 없어도 자동으로 취소 확인이 들어 온다.
if i5 in self.parent.diOrderList and (i16 == "3") :
self.parent.deleteOrderNum(i5)
self.parent.ForwardPB("cancelpb", i5)
return
item = self.parent.diOrderList[i6]
if (i16 == "2") : # 정정 확인 ==> 미체결 업데이트 해야 함.
print("[CpEvent]정정확인", item.amount, i3)
if (item.amount - i3 > 0): # 일부 정정인 경우
# 기존 데이터 업데이트
item.amount -= i3
item.modAvali = item.amount
# 새로운 미체결 추가
item2 = orderData()
item2.code = i9
item2.name = g_objCodeMgr.CodeToName(i9)
item2.orderNum = i5
item2.orderPrev = i6
item2.buysell = i12
item2.modAvali = item2.amount = i3
item2.price = i4
item2.orderFlag = i18
item2.debugPrint()
self.parent.diOrderList[i5] = item2
self.parent.orderList.append(item2)
else: # 잔량 정정 인 경우 ==> 업데이트
item.orderNum = i5 # 주문번호 변경
item.orderPrev = i6 # 원주문번호 변경
item.modAvali = item.amount = i3
item.price = i4
item.orderFlag = i18
item.debugPrint()
# 주문번호가 변경 되어 기존 key 는 제거
self.parent.diOrderList[i5] = item
del self.parent.diOrderList[i6]
elif (i16 == "3") : # 취소 확인 ==> 미체결 찾아 지운다.
self.parent.deleteOrderNum(i6)
self.parent.ForwardPB("cancelpb", i6)
# for debug
#for i in range(len(self.parent.orderList)):
# self.parent.orderList[i].debugPrint()
print("[CpEvent]미체결 개수 ", len(self.parent.orderList))
elif (i14 == "3"): # 거부
print("[CpEvent]거부")
# 접수 - 신규 접수만 처리. 새로운 주문에 대한 접수는 미체결 리스트에 추가한다.
elif (i14 == "4"): # 접수
if not (i16 == "1") :
print("[CpEvent]정정이나 취소 접수는 일단 무시한다.")
return
item = orderData()
item.code = i9
item.name = g_objCodeMgr.CodeToName(i9)
item.orderNum = i5
item.buysell = i12
item.modAvali = item.amount = i3
item.price = i4
item.orderFlag = i18
item.debugPrint()
self.parent.diOrderList[i5] = item
self.parent.orderList.append(item)
print("[CpEvent]미체결 개수 ", len(self.parent.orderList))
return
# SB/PB 요청 ROOT 클래스
class CpPublish:
def __init__(self, name, serviceID):
self.name = name
self.obj = win32com.client.Dispatch(serviceID)
self.bIsSB = False
def __del__(self):
self.Unsubscribe()
def Subscribe(self, var, parent):
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, parent)
self.obj.Subscribe()
self.bIsSB = True
def Unsubscribe(self):
if self.bIsSB:
self.obj.Unsubscribe()
self.bIsSB = False
# CpPBStockCur: 실시간 현재가 요청 클래스
class CpConclution(CpPublish):
def __init__(self):
super().__init__("conclusion", "DsCbo1.CpConclusion")
# 취소 주문 요청에 대한 응답 이벤트 처리 클래스
class CpPB0314:
def __init__(self, obj) :
self.name = "td0314"
self.obj = obj
def Subscribe(self, parent):
handler = win32com.client.WithEvents(self.obj, CpEvent)
handler.set_params(self.obj, self.name, parent)
# 주식 주문 취소 클래스
class CpRPOrder:
def __init__(self):
self.acc = g_objCpTrade.AccountNumber[0] # 계좌번호
self.accFlag = g_objCpTrade.GoodsList(self.acc, 1) # 주식상품 구분
self.objCancelOrder = win32com.client.Dispatch("CpTrade.CpTd0314") # 취소
self.callback = None
self.bIsRq = False
self.RqOrderNum = 0 # 취소 주문 중인 주문 번호
# 주문 취소 통신 - Request 를 이용하여 취소 주문
# callback 은 취소 주문의 reply 이벤트를 전달하기 위해 필요
def RequestCancel(self, ordernum, code, amount, callback):
# 주식 취소 주문
if self.bIsRq:
print("RequestCancel - 통신 중이라 주문 불가 ")
return False
self.callback = callback
print("[CpRPOrder/RequestCancel]취소주문", ordernum, code,amount)
self.objCancelOrder.SetInputValue(1, ordernum) # 원주문 번호 - 정정을 하려는 주문 번호
self.objCancelOrder.SetInputValue(2, self.acc) # 상품구분 - 주식 상품 중 첫번째
self.objCancelOrder.SetInputValue(3, self.accFlag[0]) # 상품구분 - 주식 상품 중 첫번째
self.objCancelOrder.SetInputValue(4, code) # 종목코드
self.objCancelOrder.SetInputValue(5, amount) # 정정 수량, 0 이면 잔량 취소임
# 취소주문 요청
ret = 0
while True:
ret = self.objCancelOrder.Request()
if ret == 0:
break
print("[CpRPOrder/RequestCancel] 주문 요청 실패 ret : ", ret)
if ret == 4:
remainTime = g_objCpStatus.LimitRequestRemainTime
print("연속 통신 초과에 의해 재 통신처리 : ", remainTime / 1000, "초 대기")
time.sleep(remainTime / 1000)
continue
else: # 1 통신 요청 실패 3 그 외의 오류 4: 주문요청제한 개수 초과
return False;
self.bIsRq = True
self.RqOrderNum = ordernum
# 주문 응답(이벤트로 수신
self.objReply = CpPB0314(self.objCancelOrder)
self.objReply.Subscribe(self)
return True
# 취소 주문 - BloockReqeust 를 이용해서 취소 주문
def BlockRequestCancel(self, ordernum, code, amount, callback):
# 주식 취소 주문
self.callback = callback
print("[CpRPOrder/BlockRequestCancel]취소주문2", ordernum, code,amount)
self.objCancelOrder.SetInputValue(1, ordernum) # 원주문 번호 - 정정을 하려는 주문 번호
self.objCancelOrder.SetInputValue(2, self.acc) # 상품구분 - 주식 상품 중 첫번째
self.objCancelOrder.SetInputValue(3, self.accFlag[0]) # 상품구분 - 주식 상품 중 첫번째
self.objCancelOrder.SetInputValue(4, code) # 종목코드
self.objCancelOrder.SetInputValue(5, amount) # 정정 수량, 0 이면 잔량 취소임
# 취소주문 요청
ret = 0
while True:
ret = self.objCancelOrder.BlockRequest()
if ret == 0:
break;
print("[CpRPOrder/RequestCancel] 주문 요청 실패 ret : ", ret)
if ret == 4:
remainTime = g_objCpStatus.LimitRequestRemainTime
print("연속 통신 초과에 의해 재 통신처리 : ", remainTime / 1000, "초 대기")
time.sleep(remainTime / 1000)
continue
else: # 1 통신 요청 실패 3 그 외의 오류 4: 주문요청제한 개수 초과
return False;
print("[CpRPOrder/BlockRequestCancel] 주문결과", self.objCancelOrder.GetDibStatus(), self.objCancelOrder.GetDibMsg1())
if self.objCancelOrder.GetDibStatus() != 0:
return False
return True
# 주문 취소 Request 에 대한 응답 처리
def OrderReply(self):
self.bIsRq = False
if self.objCancelOrder.GetDibStatus() != 0:
print("[CpRPOrder/OrderReply]통신상태",
self.objCancelOrder.GetDibStatus(), self.objCancelOrder.GetDibMsg1())
self.callback.ForwardReply(-1, 0)
return False
orderPrev = self.objCancelOrder.GetHeaderValue(1)
code = self.objCancelOrder.GetHeaderValue(4)
orderNum = self.objCancelOrder.GetHeaderValue(6)
amount = self.objCancelOrder.GetHeaderValue(5)
print("[CpRPOrder/OrderReply] 주문 취소 reply, 취소한 주문:",orderPrev, code, orderNum, amount)
# 주문 취소를 요청한 클래스로 포워딩 한다.
if (self.callback != None) :
self.callback.ForwardReply(0, orderPrev)
# 미체결 조회 서비스
class Cp5339:
def __init__(self):
self.objRq = win32com.client.Dispatch("CpTrade.CpTd5339")
self.acc = g_objCpTrade.AccountNumber[0] # 계좌번호
self.accFlag = g_objCpTrade.GoodsList(self.acc, 1) # 주식상품 구분
def Request5339(self, dicOrderList, orderList):
self.objRq.SetInputValue(0, self.acc)
self.objRq.SetInputValue(1, self.accFlag[0])
self.objRq.SetInputValue(4, "0") # 전체
self.objRq.SetInputValue(5, "1") # 정렬 기준 - 역순
self.objRq.SetInputValue(6, "0") # 전체
self.objRq.SetInputValue(7, 20) # 요청 개수 - 최대 20개
print("[Cp5339] 미체결 데이터 조회 시작")
# 미체결 연속 조회를 위해 while 문 사용
while True :
ret = self.objRq.BlockRequest()
if self.objRq.GetDibStatus() != 0:
print("통신상태", self.objRq.GetDibStatus(), self.objRq.GetDibMsg1())
return False
if (ret == 2 or ret == 3):
print("통신 오류", ret)
return False;
# 통신 초과 요청 방지에 의한 요류 인 경우
while (ret == 4) : # 연속 주문 오류 임. 이 경우는 남은 시간동안 반드시 대기해야 함.
remainTime = g_objCpStatus.LimitRequestRemainTime
print("연속 통신 초과에 의해 재 통신처리 : ",remainTime/1000, "초 대기" )
time.sleep(remainTime / 1000)
ret = self.objRq.BlockRequest()
# 수신 개수
cnt = self.objRq.GetHeaderValue(5)
print("[Cp5339] 수신 개수 ", cnt)
if cnt == 0 :
break
for i in range(cnt):
item = orderData()
item.orderNum = self.objRq.GetDataValue(1, i)
item.orderPrev = self.objRq.GetDataValue(2, i)
item.code = self.objRq.GetDataValue(3, i) # 종목코드
item.name = self.objRq.GetDataValue(4, i) # 종목명
item.orderDesc = self.objRq.GetDataValue(5, i) # 주문구분내용
item.amount = self.objRq.GetDataValue(6, i) # 주문수량
item.price = self.objRq.GetDataValue(7, i) # 주문단가
item.ContAmount = self.objRq.GetDataValue(8, i) # 체결수량
item.credit = self.objRq.GetDataValue(9, i) # 신용구분
item.modAvali = self.objRq.GetDataValue(11, i) # 정정취소 가능수량
item.buysell = self.objRq.GetDataValue(13, i) # 매매구분코드
item.creditdate = self.objRq.GetDataValue(17, i) # 대출일
item.orderFlagDesc = self.objRq.GetDataValue(19, i) # 주문호가구분코드내용
item.orderFlag = self.objRq.GetDataValue(21, i) # 주문호가구분코드
# 사전과 배열에 미체결 item 을 추가
dicOrderList[item.orderNum] = item
orderList.append(item)
# 연속 처리 체크 - 다음 데이터가 없으면 중지
if self.objRq.Continue == False :
print("[Cp5339] 연속 조회 여부: 다음 데이터가 없음")
break
return True
# 샘플 코드 메인 클래스
class testMain():
def __init__(self):
self.bTradeInit = False
# 연결 여부 체크
if (g_objCpStatus.IsConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
return False
if (g_objCpTrade.TradeInit(0) != 0):
print("주문 초기화 실패")
return False
self.bTradeInit = True
# 미체결 리스트를 보관한 자료 구조체
self.diOrderList= dict() # 미체결 내역 딕셔너리 - key: 주문번호, value - 미체결 레코드
self.orderList = [] # 미체결 내역 리스트 - 순차 조회 등을 위한 미체결 리스트
# 미체결 통신 object
self.obj = Cp5339()
# 주문 취소 통신 object
self.objOrder = CpRPOrder()
# 실시간 주문 체결
self.contsb = CpConclution()
self.contsb.Subscribe("", self)
return
# 더 이상 미체결이 아닌 주문번호를 찾아 지운다.
def deleteOrderNum(self, orderNum):
print("미체결 주문 번호 삭제: ", orderNum)
del self.diOrderList[orderNum]
for i in range(len(self.orderList)):
if (self.orderList[i].orderNum == orderNum):
del self.orderList[i]
break
# 미체결 주문 조회
def Reqeust5339(self):
if self.bTradeInit == False :
print("TradeInit 실패")
return False
self.diOrderList = {}
self.orderList = []
self.obj.Request5339(self.diOrderList, self.orderList)
for item in self.orderList:
item.debugPrint()
print("[Reqeust5339]미체결 개수 ", len(self.orderList))
# 첫번째 미체결을 취소 한다.
# Request 함수 이용 - OnRecieved 이벤트를 통해 응답을 받는다.
def RequestCancel(self):
if len(self.orderList) > 0 :
item = self.orderList[0]
self.objOrder.RequestCancel(item.orderNum, item.code, item.amount, self)
# 첫번째 미체결을 취소 한다. - BlockReqest 이용
def BlockRequestCancel(self):
print(2)
if len(self.orderList) > 0:
item = self.orderList[0]
self.objOrder.BlockRequestCancel(item.orderNum, item.code, item.amount, self)
# 일괄 취소
def RequestCancelAll(self):
onums = []
codes = []
amounts = []
for item in self.orderList :
onums.append(item.orderNum)
codes.append(item.code)
amounts.append(item.amount)
for i in range(len(onums)):
self.objOrder.BlockRequestCancel(onums[i], codes[i], amounts[i],self)
# 주문 응답 받음.
def ForwardReply(self, ret, orderNum):
print("[testMain/ForwardReply] reply ret %d, 주문번호 %d" %(ret, orderNum))
# 주문 체결에 대한 실시간 업데이트
def ForwardPB(self,name, orderNum):
# 취소 확인을 받은 후 , 다음 취소 할 게 있음 취소 주문 전송
if (name == "cancelpb") :
print("[testMain/ForwardPB] 취소 확인 받음, 주문번호", orderNum)
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main = testMain()
self.setWindowTitle("PLUS API TEST")
nHeight = 20
btnNoContract = QPushButton("미체결 조회", self)
btnNoContract.move(20, nHeight)
btnNoContract.clicked.connect(self.btnNoContract_clicked)
nHeight += 50
btnCancel = QPushButton("취소 주문(Request)", self)
btnCancel.move(20, nHeight)
btnCancel.resize(200,30)
btnCancel.clicked.connect(self.btnCancel_clicked)
nHeight += 50
btnCancel2 = QPushButton("취소 주문(BlockRequest)", self)
btnCancel2.move(20, nHeight)
btnCancel2.resize(200, 30)
btnCancel2.clicked.connect(self.btnCancel2_clicked)
nHeight += 50
btnAllCancel = QPushButton("일괄 취소", self)
btnAllCancel.move(20, nHeight)
btnAllCancel.clicked.connect(self.btnAllCancel_clicked)
nHeight += 50
btnExit = QPushButton("종료", self)
btnExit.move(20, nHeight)
btnExit.clicked.connect(self.btnExit_clicked)
nHeight += 50
self.setGeometry(300, 500, 300, nHeight)
# 시작 부터 미체결 미리 조회 한다.
self.main.Reqeust5339()
# 미체결 조회
def btnNoContract_clicked(self):
self.main.Reqeust5339()
return
# 취소 주문- 주문 리스트에 최근 거 부터
def btnCancel_clicked(self):
self.main.RequestCancel()
return
# 취소 주문- 주문 리스트에 최근 거 부터
def btnCancel2_clicked(self):
self.main.BlockRequestCancel()
return
# 일괄 취소 - 미체결 전체 취소
def btnAllCancel_clicked(self):
self.main.RequestCancelAll()
return
def btnExit_clicked(self):
exit()
return
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
11 주식 현재가 10차 호가 화면 구현하기[편집]
import sys
from PyQt5 import QtWidgets
from PyQt5 import uic
from PyQt5.QtCore import pyqtSlot
import win32com.client
# cp object
g_objCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
g_objCpStatus = win32com.client.Dispatch("CpUtil.CpCybos")
g_objCpTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
# 현재가 정보 저장 구조체
class stockPricedData:
def __init__(self):
self.dicEx = {ord('0'): "동시호가/장중 아님", ord('1'): "동시호가", ord('2'): "장중"}
self.code = ""
self.name = ""
self.cur = 0 # 현재가
self.diff = 0 # 대비
self.diffp = 0 # 대비율
self.offer = [0 for _ in range(10)] # 매도호가
self.bid = [0 for _ in range(10)] # 매수호가
self.offervol = [0 for _ in range(10)] # 매도호가 잔량
self.bidvol = [0 for _ in range(10)] # 매수호가 잔량
self.totOffer = 0 # 총매도잔량
self.totBid = 0 # 총매수 잔량
self.vol = 0 # 거래량
self.baseprice = 0 # 기준가
# 예상체결가 정보
self.exFlag= ord('2')
self.expcur = 0 # 예상체결가
self.expdiff = 0 # 예상 대비
self.expdiffp = 0 # 예상 대비율
self.expvol = 0 # 예상 거래량
self.objCur = CpPBStockCur()
self.objOfferbid = CpPBStockBid()
def __del__(self):
self.objCur.Unsubscribe()
self.objOfferbid.Unsubscribe()
# 전일 대비 계산
def makediffp(self):
lastday = 0
if (self.exFlag == ord('1')): # 동시호가 시간 (예상체결)
if self.baseprice > 0 :
lastday = self.baseprice
else:
lastday = self.expcur - self.expdiff
if lastday:
self.expdiffp = (self.expdiff / lastday) * 100
else:
self.expdiffp = 0
else:
if self.baseprice > 0 :
lastday = self.baseprice
else:
lastday = self.cur - self.diff
if lastday:
self.diffp = (self.diff / lastday) * 100
else:
self.diffp = 0
def getCurColor(self):
diff = self.diff
if (self.exFlag == ord('1')): # 동시호가 시간 (예상체결)
diff = self.expdiff
if (diff > 0):
return 'color: red'
elif (diff == 0):
return 'color: black'
elif (diff < 0):
return 'color: blue'
# CpEvent: 실시간 이벤트 수신 클래스
class CpEvent:
def set_params(self, client, name, rpMst, parent):
self.client = client # CP 실시간 통신 object
self.name = name # 서비스가 다른 이벤트를 구분하기 위한 이름
self.parent = parent # callback 을 위해 보관
self.rpMst = rpMst
# PLUS 로 부터 실제로 시세를 수신 받는 이벤트 핸들러
def OnReceived(self):
if self.name == "stockcur":
# 현재가 체결 데이터 실시간 업데이트
self.rpMst.exFlag = self.client.GetHeaderValue(19) # 예상체결 플래그
code = self.client.GetHeaderValue(0)
diff = self.client.GetHeaderValue(2)
cur= self.client.GetHeaderValue(13) # 현재가
vol = self.client.GetHeaderValue(9) # 거래량
# 예제는 장중만 처리 함.
if (self.rpMst.exFlag == ord('1')): # 동시호가 시간 (예상체결)
# 예상체결가 정보
self.rpMst.expcur = cur
self.rpMst.expdiff = diff
self.rpMst.expvol = vol
else:
self.rpMst.cur = cur
self.rpMst.diff = diff
self.rpMst.makediffp()
self.vol = vol
self.rpMst.makediffp()
# 현재가 업데이트
self.parent.monitorPriceChange()
return
elif self.name == "stockbid":
# 현재가 10차 호가 데이터 실시간 업데이c
code = self.client.GetHeaderValue(0)
dataindex = [3, 7, 11, 15, 19, 27, 31, 35, 39, 43]
obi = 0
for i in range(10):
self.rpMst.offer[i] = self.client.GetHeaderValue(dataindex[i])
self.rpMst.bid[i] = self.client.GetHeaderValue(dataindex[i] + 1)
self.rpMst.offervol[i] = self.client.GetHeaderValue(dataindex[i] + 2)
self.rpMst.bidvol[i] = self.client.GetHeaderValue(dataindex[i] + 3)
self.rpMst.totOffer = self.client.GetHeaderValue(23)
self.rpMst.totBid = self.client.GetHeaderValue(24)
# 10차 호가 변경 call back 함수 호출
self.parent.monitorOfferbidChange()
return
# SB/PB 요청 ROOT 클래스
class CpPublish:
def __init__(self, name, serviceID):
self.name = name
self.obj = win32com.client.Dispatch(serviceID)
self.bIsSB = False
def Subscribe(self, var, rpMst, parent):
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, rpMst, parent)
self.obj.Subscribe()
self.bIsSB = True
def Unsubscribe(self):
if self.bIsSB:
self.obj.Unsubscribe()
self.bIsSB = False
# CpPBStockCur: 실시간 현재가 요청 클래스
class CpPBStockCur(CpPublish):
def __init__(self):
super().__init__("stockcur", "DsCbo1.StockCur")
# CpPBStockBid: 실시간 10차 호가 요청 클래스
class CpPBStockBid(CpPublish):
def __init__(self):
super().__init__("stockbid", "Dscbo1.StockJpBid")
# SB/PB 요청 ROOT 클래스
class CpPBConnection:
def __init__(self):
self.obj = win32com.client.Dispatch("CpUtil.CpCybos")
handler = win32com.client.WithEvents(self.obj, CpEvent)
handler.set_params(self.obj, "connection", None)
# CpRPCurrentPrice: 현재가 기본 정보 조회 클래스
class CpRPCurrentPrice:
def __init__(self):
if (g_objCpStatus.IsConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
return
self.objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
return
def Request(self, code, rtMst, callbackobj):
# 현재가 통신
rtMst.objCur.Unsubscribe()
rtMst.objOfferbid.Unsubscribe()
self.objStockMst.SetInputValue(0, code)
ret = self.objStockMst.BlockRequest()
if self.objStockMst.GetDibStatus() != 0:
print("통신상태", self.objStockMst.GetDibStatus(), self.objStockMst.GetDibMsg1())
return False
# 수신 받은 현재가 정보를 rtMst 에 저장
rtMst.code = code
rtMst.name = g_objCodeMgr.CodeToName(code)
rtMst.cur = self.objStockMst.GetHeaderValue(11) # 종가
rtMst.diff = self.objStockMst.GetHeaderValue(12) # 전일대비
rtMst.baseprice = self.objStockMst.GetHeaderValue(27) # 기준가
rtMst.vol = self.objStockMst.GetHeaderValue(18) # 거래량
rtMst.exFlag = self.objStockMst.GetHeaderValue(58) # 예상플래그
rtMst.expcur = self.objStockMst.GetHeaderValue(55) # 예상체결가
rtMst.expdiff = self.objStockMst.GetHeaderValue(56) # 예상체결대비
rtMst.makediffp()
rtMst.totOffer = self.objStockMst.GetHeaderValue(71) # 총매도잔량
rtMst.totBid = self.objStockMst.GetHeaderValue(73) # 총매수잔량
# 10차호가
for i in range(10):
rtMst.offer[i] = (self.objStockMst.GetDataValue(0, i)) # 매도호가
rtMst.bid[i] = (self.objStockMst.GetDataValue(1, i) ) # 매수호가
rtMst.offervol[i] = (self.objStockMst.GetDataValue(2, i)) # 매도호가 잔량
rtMst.bidvol[i] = (self.objStockMst.GetDataValue(3, i) ) # 매수호가 잔량
rtMst.objCur.Subscribe(code,rtMst, callbackobj)
rtMst.objOfferbid.Subscribe(code,rtMst, callbackobj)
class Form(QtWidgets.QDialog):
def __init__(self, parent=None):
QtWidgets.QDialog.__init__(self, parent)
self.ui = uic.loadUi("hoga.ui", self)
self.ui.show()
self.objMst = CpRPCurrentPrice()
self.item = stockPricedData()
self.setCode("000660")
@pyqtSlot()
def slot_codeupdate(self):
code = self.ui.editCode.toPlainText()
self.setCode(code)
def slot_codechanged(self):
code = self.ui.editCode.toPlainText()
self.setCode(code)
def monitorPriceChange(self):
self.displyHoga()
def monitorOfferbidChange(self):
self.displyHoga()
def setCode(self, code):
if len(code) < 6 :
return
print(code)
if not (code[0] == "A"):
code = "A" + code
name = g_objCodeMgr.CodeToName(code)
if len(name) == 0:
print("종목코드 확인")
return
self.ui.label_name.setText(name)
if (self.objMst.Request(code, self.item, self) == False):
return
self.displyHoga()
def displyHoga(self):
self.ui.label_offer10.setText(format(self.item.offer[9],','))
self.ui.label_offer9.setText(format(self.item.offer[8],','))
self.ui.label_offer8.setText(format(self.item.offer[7],','))
self.ui.label_offer7.setText(format(self.item.offer[6],','))
self.ui.label_offer6.setText(format(self.item.offer[5],','))
self.ui.label_offer5.setText(format(self.item.offer[4],','))
self.ui.label_offer4.setText(format(self.item.offer[3],','))
self.ui.label_offer3.setText(format(self.item.offer[2],','))
self.ui.label_offer2.setText(format(self.item.offer[1],','))
self.ui.label_offer1.setText(format(self.item.offer[0],','))
self.ui.label_offer_v10.setText(format(self.item.offervol[9],','))
self.ui.label_offer_v9.setText(format(self.item.offervol[8],','))
self.ui.label_offer_v8.setText(format(self.item.offervol[7],','))
self.ui.label_offer_v7.setText(format(self.item.offervol[6],','))
self.ui.label_offer_v6.setText(format(self.item.offervol[5],','))
self.ui.label_offer_v5.setText(format(self.item.offervol[4],','))
self.ui.label_offer_v4.setText(format(self.item.offervol[3],','))
self.ui.label_offer_v3.setText(format(self.item.offervol[2],','))
self.ui.label_offer_v2.setText(format(self.item.offervol[1],','))
self.ui.label_offer_v1.setText(format(self.item.offervol[0],','))
self.ui.label_bid10.setText(format(self.item.bid[9],','))
self.ui.label_bid9.setText(format(self.item.bid[8],','))
self.ui.label_bid8.setText(format(self.item.bid[7],','))
self.ui.label_bid7.setText(format(self.item.bid[6],','))
self.ui.label_bid6.setText(format(self.item.bid[5],','))
self.ui.label_bid5.setText(format(self.item.bid[4],','))
self.ui.label_bid4.setText(format(self.item.bid[3],','))
self.ui.label_bid3.setText(format(self.item.bid[2],','))
self.ui.label_bid2.setText(format(self.item.bid[1],','))
self.ui.label_bid1.setText(format(self.item.bid[0],','))
self.ui.label_bid_v10.setText(format(self.item.bidvol[9],','))
self.ui.label_bid_v9.setText(format(self.item.bidvol[8],','))
self.ui.label_bid_v8.setText(format(self.item.bidvol[7],','))
self.ui.label_bid_v7.setText(format(self.item.bidvol[6],','))
self.ui.label_bid_v6.setText(format(self.item.bidvol[5],','))
self.ui.label_bid_v5.setText(format(self.item.bidvol[4],','))
self.ui.label_bid_v4.setText(format(self.item.bidvol[3],','))
self.ui.label_bid_v3.setText(format(self.item.bidvol[2],','))
self.ui.label_bid_v2.setText(format(self.item.bidvol[1],','))
self.ui.label_bid_v1.setText(format(self.item.bidvol[0],','))
cur = self.item.cur
diff = self.item.diff
diffp = self.item.diffp
if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결)
cur = self.item.expcur
diff = self.item.expdiff
diffp = self.item.expdiffp
strcur = format(cur, ',')
if (self.item.exFlag == ord('1')): # 동시호가 시간 (예상체결)
strcur = "*" + strcur
curcolor = self.item.getCurColor()
self.ui.label_cur.setStyleSheet(curcolor)
self.ui.label_cur.setText(strcur)
strdiff = str(diff) + " " + format(diffp, '.2f')
strdiff += "%"
self.ui.label_diff.setText(strdiff)
self.ui.label_diff.setStyleSheet(curcolor)
self.ui.label_totoffer.setText(format(self.item.totOffer,','))
self.ui.label_totbid.setText(format(self.item.totBid,','))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Form()
sys.exit(app.exec())
12 주식 예약 매수/매도/취소/조회 예제[편집]
- 예약매수 전송 - 예약 매수(오늘 종가 기준) - 예약매도 전송 - 예약 매수(오늘 종가 기준) - 예약주문 취소 - 미체결 예약주문 리스트에서 첫번째 예약 주문 취소 - 예약내역 가져오기 - 예약주문 리스트 가져와 미체결 건만 리스트에 저장(취소 주문 할 수 있도록)
# 예약매수/매도/예약주문 내역 조회 예제
# 화면 설명
# 예약매수 전송 - 예약 매수(오늘 종가 기준)
# 예약매도 전송 - 예약 매수(오늘 종가 기준)
# 예약주문 취소 - 미체결 예약주문 리스트에서 첫번째 예약 주문 취소
# 예약내역 가져오기 - 예약주문 리스트 가져와 미체결 건만 리스트에 저장(취소 주문 할 수 있도록)
import sys
from PyQt5.QtWidgets import *
from enum import Enum
import win32com.client
import time
import pythoncom
g_objCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
g_objCpStatus = win32com.client.Dispatch("CpUtil.CpCybos")
g_objCpTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
# enum 주문 상태 세팅용
class EorderBS(Enum):
buy = 1 # 매수
sell= 2 # 매도
none =3
# 현재가 정보 저장 구조체
class stockPricedData:
def __init__(self):
self.dicEx = {ord('0'): "동시호가/장중 아님", ord('1'): "동시호가", ord('2'): "장중"}
self.code = ""
self.name = ""
self.cur = 0 # 현재가
self.open = self.high = self.low = 0 # 시/고/저
self.diff = 0
self.diffp = 0
self.objCur = None
self.objBid = None
self.vol = 0 # 거래량
self.offer = [0 for _ in range(10)] # 매도호가
self.bid = [0 for _ in range(10)] # 매수호가
self.offervol = [0 for _ in range(10)] # 매도호가 잔량
self.bidvol = [0 for _ in range(10)] # 매수호가 잔량
# 전일 대비 계산
def makediffp(self, baseprice):
lastday = 0
if baseprice :
lastday =baseprice
else:
lastday = self.cur - self.diff
if lastday:
self.diffp = (self.diff / lastday) * 100
else:
self.diffp = 0
def debugPrint(self, type):
if type == 0 :
print("%s, %s %s, 현재가 %d 대비 %d, (%.2f), 1차매도 %d(%d) 1차매수 %d(%d)"
%(self.dicEx.get(self.exFlag), self.code,
self.name, self.cur, self.diff, self.diffp,
self.offer[0], self.offervol[0],self.bid[0], self.bidvol[0] ) )
else :
print("%s %s, 현재가 %.2f 대비 %.2f, (%.2f), 1차매도 %.2f(%d) 1차매수 %.2f(%d)"
% (self.code,
self.name, self.cur, self.diff, self.diffp,
self.offer[0], self.offervol[0], self.bid[0], self.bidvol[0]))
# 주문 데이터
class orderData:
def __init__(self):
self.dicEx = {EorderBS.buy: "매수", EorderBS.sell: "매도", EorderBS.none: "없음"}
self.orderNum = 0
self.bs = EorderBS.none # 0 : buy 1: sell
self.code = ""
self.amount = 0
self.price = 0
def debugPrint(self):
print(self.dicEx.get(self.bs), self.code, self.orderNum, self.amount, self.price)
# CpRPCurrentPrice: 현재가 기본 정보 조회 클래스
class CpRPCurrentPrice:
def __init__(self):
if (g_objCpStatus.IsConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
return
self.objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
return
def Request(self, code, rtMst):
# 현재가 통신
rqtime = time.time()
self.objStockMst.SetInputValue(0, code)
ret = self.objStockMst.BlockRequest()
if self.objStockMst.GetDibStatus() != 0:
print("통신상태", self.objStockMst.GetDibStatus(), self.objStockMst.GetDibMsg1())
return False
# 수신 받은 현재가 정보를 rtMst 에 저장
rtMst.code = code
rtMst.name = g_objCodeMgr.CodeToName(code)
rtMst.cur = self.objStockMst.GetHeaderValue(11) # 종가
rtMst.diff = self.objStockMst.GetHeaderValue(12) # 전일대비
rtMst.baseprice = self.objStockMst.GetHeaderValue(27) # 기준가
rtMst.exFlag = self.objStockMst.GetHeaderValue(58) # 예상플래그
if rtMst.baseprice :
rtMst.diffp = (rtMst.diff / rtMst.baseprice) * 100
# 10차호가
for i in range(10):
rtMst.offer[i] = (self.objStockMst.GetDataValue(0, i)) # 매도호가
rtMst.bid[i] = (self.objStockMst.GetDataValue(1, i) ) # 매수호가
rtMst.offervol[i] = (self.objStockMst.GetDataValue(2, i)) # 매도호가 잔량
rtMst.bidvol[i] = (self.objStockMst.GetDataValue(3, i) ) # 매수호가 잔량
return True
# CpRPPreOrder - 예약 주문 매수/매도/취소/내역 조회 클래스
class CpRPPreOrder:
def __init__(self):
if (g_objCpStatus.IsConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
return
if (g_objCpTrade.TradeInit(0) != 0):
print("주문 초기화 실패")
exit
self.objOrder = win32com.client.Dispatch("CpTrade.CpTdNew9061")
self.objCancel = win32com.client.Dispatch("CpTrade.CpTdNew9064")
self.objResult = win32com.client.Dispatch("CpTrade.CpTd9065")
self.acc = g_objCpTrade.AccountNumber[0] # 계좌번호
self.accFlag = g_objCpTrade.GoodsList(self.acc, 1) # 주식상품 구분
return
# 예약 매수 또는 매도
def RequestOrder(self, bs, code, price, amount, data):
data.code = code
data.amount = amount
data.price = price;
rqBS = "2"
if bs == EorderBS.buy: # 매수
rqBS = "2"
data.bs = EorderBS.buy
elif bs == EorderBS.sell: # 매도
data.bs = EorderBS.sell
rqBS = "1"
# 예약 주문
print(self.acc, self.accFlag[0])
self.objOrder.SetInputValue(0, self.acc)
self.objOrder.SetInputValue(1, self.accFlag[0])
self.objOrder.SetInputValue(2, rqBS)
self.objOrder.SetInputValue(3, code)
self.objOrder.SetInputValue(4, amount)
self.objOrder.SetInputValue(5, "01") # 주문호가 구분 01: 보통
self.objOrder.SetInputValue(6, price)
# 예약 주문 요청
self.objOrder.BlockRequest()
if self.objOrder.GetDibStatus() != 0:
print("통신상태", self.objOrder.GetDibStatus(), self.objOrder.GetDibMsg1())
return False
data.orderNum = self.objOrder.GetHeaderValue(0) # 예약번호
print("예약주문 성공, 예약번호 #", data.orderNum)
# 예약 취소 주문
def RequestCancel(self, ordernum, code):
# 예약주문 취소
print(self.acc, self.accFlag[0])
self.objCancel.SetInputValue(0, ordernum)
self.objCancel.SetInputValue(1, self.acc)
self.objCancel.SetInputValue(2, self.accFlag[0])
self.objCancel.SetInputValue(3, code)
# 예약 취소 주문 요청
self.objCancel.BlockRequest()
if self.objCancel.GetDibStatus() != 0:
print("통신상태", self.objCancel.GetDibStatus(), self.objCancel.GetDibMsg1())
return False
print("예약주문 취소 ", ordernum, self.objCancel.GetDibMsg1() )
# 예약 주문 내역 조회 및 미체결 리스트 구하기
def RequestOrderList(self, orderList):
print(self.acc, self.accFlag[0])
self.objResult.SetInputValue(0, self.acc)
self.objResult.SetInputValue(1, self.accFlag[0])
self.objResult.SetInputValue(2, 20)
while True: # 연속 조회로 전체 예약 주문 가져온다.
self.objResult.BlockRequest()
if self.objResult.GetDibStatus() != 0:
print("통신상태", self.objResult.GetDibStatus(), self.objResult.GetDibMsg1())
return False
cnt = self.objResult.GetHeaderValue(4)
if cnt == 0 :
break
for i in range(cnt):
i1 = self.objResult.GetDataValue(1, i) # 주문구분(매수 또는 매도)
i2 = self.objResult.GetDataValue(2, i) # 코드
i3 = self.objResult.GetDataValue(3, i) # 주문 수량
i4 = self.objResult.GetDataValue(4, i) # 주문호가구분
i5 = self.objResult.GetDataValue(6, i) # 예약번호
i6 = self.objResult.GetDataValue(12, i) # 처리구분내용 - 주문취소 또는 주문예정
i7 = self.objResult.GetDataValue(9, i) # 주문단가
i8= self.objResult.GetDataValue(11, i) # 주문번호
i9 = self.objResult.GetDataValue(12, i) # 처리구분코드
i10= self.objResult.GetDataValue(13, i) # 거부코드
i11 = self.objResult.GetDataValue(14, i) # 거부내용
print(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11)
# 미체결
if (i6 == "주문예정") :
item = orderData()
item.orderNum = i5
if (i1 == "매수") :
item.bs = EorderBS.buy
else:
item.bs = EorderBS.sell
item.code = i2
item.amount = i3
item.price = i7
orderList.append(item)
# 연속 처리 체크 - 다음 데이터가 없으면 중지
if self.objResult.Continue == False :
break
# 샘플 코드 메인 클래스
class testMain():
def __init__(self):
self.orderList = []
self.objMst = CpRPCurrentPrice()
self.obj9061 = CpRPPreOrder()
# 미체결 된 예약 주문 처음부터 받아옴.
self.resultOrder()
return
def newBuyOrder(self, code, amount):
mstData = stockPricedData()
if self.objMst.Request(code, mstData) == False :
print("현재가 요청 실패")
return
item = orderData()
ret = self.obj9061.RequestOrder(EorderBS.buy, code, mstData.cur, amount, item )
if (ret == False):
return False
self.orderList.append(item)
item.debugPrint()
def newSellOrder(self, code, amount):
mstData = stockPricedData()
if self.objMst.Request(code, mstData) == False :
print("현재가 요청 실패")
return
item = orderData()
ret = self.obj9061.RequestOrder(EorderBS.sell, code, mstData.cur, amount, item )
if (ret == False):
return False
self.orderList.append(item)
item.debugPrint()
def cancelOrder(self):
if len(self.orderList) == 0:
print("취소 할 주문 확인하세요")
return
item = self.orderList[0]
ret = self.obj9061.RequestCancel(item.orderNum, item.code)
if (ret == False):
return False
del (self.orderList[0])
def resultOrder(self):
self.orderList = []
# 미체결 주문만 받아 보자
ret = self.obj9061.RequestOrderList(self.orderList)
if (ret == False):
return False
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main = testMain()
self.setWindowTitle("PLUS API TEST")
w = 200
h = 30
nHeight = 20
btnBuy = QPushButton("예약매수 전송", self)
btnBuy.move(20, nHeight)
btnBuy.resize(w, h)
btnBuy.clicked.connect(self.btnBuy_clicked)
nHeight += 50
btnSell = QPushButton("예약 매도 전송", self)
btnSell.move(20, nHeight)
btnSell.resize(w, h)
btnSell.clicked.connect(self.btnSell_clicked)
nHeight += 50
btnCancel = QPushButton("예약 주문 취소", self)
btnCancel.move(20, nHeight)
btnCancel.resize(w, h)
btnCancel.clicked.connect(self.btnCancel_clicked)
nHeight += 50
btnResult= QPushButton("예약 내역 가져오기", self)
btnResult.move(20, nHeight)
btnResult.resize(w, h)
btnResult.clicked.connect(self.btnResult_clicked)
nHeight += 50
btnExit = QPushButton("종료", self)
btnExit.move(20, nHeight)
btnExit.resize(w, h)
btnExit.clicked.connect(self.btnExit_clicked)
nHeight += 50
self.setGeometry(300, 500, 300, nHeight)
def btnBuy_clicked(self):
self.main.newBuyOrder("A003540", 10)
return
def btnSell_clicked(self):
self.main.newSellOrder("A003540", 10)
return
def btnCancel_clicked(self):
self.main.cancelOrder()
return
def btnResult_clicked(self):
self.main.resultOrder()
return
def btnExit_clicked(self):
exit()
return
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()
13 주식/ELW/선물/옵션/업종 전 종목 시세 조회 예제[편집]
import sys
from PyQt5.QtWidgets import *
from enum import Enum
import win32com.client
import time
import pythoncom
g_objCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
g_objCpStatus = win32com.client.Dispatch("CpUtil.CpCybos")
g_objElwMgr = win32com.client.Dispatch("CpUtil.CpElwCode")
g_objFutureMgr = win32com.client.Dispatch("CpUtil.CpFutureCode")
g_objOptionMgr = win32com.client.Dispatch("CpUtil.CpOptionCode")
=== 감시 중인 현재가 정보 저장 구조체===
class stockPricedData:
def __init__(self):
self.dicEx = {ord('0'): "동시호가/장중 아님", ord('1'): "동시호가", ord('2'): "장중"}
self.code = ""
self.name = ""
===elf.cur = 0 # 현재가===
===elf.open = self.high = self.low = 0 # 시/고/저===
self.diff = 0
self.diffp = 0
self.objCur = None
self.objBid = None
#self.Zoffer = 0
#self.ZodfferDate = 0
===elf.vol = 0 # 거래량===
===elf.offer = [0 for _ in range(10)] # 매도호가===
===elf.bid = [0 for _ in range(10)] # 매수호가===
===elf.offervol = [0 for _ in range(10)] # 매도호가 잔량===
===elf.bidvol = [0 for _ in range(10)] # 매수호가 잔량===
=== 전일 대비 계산===
def makediffp(self, baseprice):
lastday = 0
if baseprice :
lastday =baseprice
else:
lastday = self.cur - self.diff
if lastday:
self.diffp = (self.diff / lastday) * 100
else:
self.diffp = 0
def debugPrint(self, type):
if type == 0 :
print("%s, %s %s, 현재가 %d 대비 %d, (%.2f), 1차매도 %d(%d) 1차매수 %d(%d)"
%(self.dicEx.get(self.exFlag), self.code,
self.name, self.cur, self.diff, self.diffp,
self.offer[0], self.offervol[0],self.bid[0], self.bidvol[0] ) )
else :
print("%s %s, 현재가 %.2f 대비 %.2f, (%.2f), 1차매도 %.2f(%d) 1차매수 %.2f(%d)"
% (self.code,
self.name, self.cur, self.diff, self.diffp,
self.offer[0], self.offervol[0], self.bid[0], self.bidvol[0]))
class CpMarketEye:
def __init__(self):
if (g_objCpStatus.IsConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
return False
self.objRq = win32com.client.Dispatch("CpSysDib.MarketEye")
self.RpFiledIndex = 0
def Request(self, codes, dicCodes):
#rqField = [코드, 대비부호, 대비, 현재가, 시가, 고가, 저가, 매도호가, 매수호가, 거래량, 장구분, 매도잔량,매수잔량,
=== 공매도수량, 공매도날짜]===
=== rqField = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16, 127, 128] # 요청 필드===
===qField = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 16] # 요청 필드===
===elf.objRq.SetInputValue(0, rqField) # 요청 필드===
===elf.objRq.SetInputValue(1, codes) # 종목코드 or 종목코드 리스트===
self.objRq.BlockRequest()
=== 현재가 통신 및 통신 에러 처리===
rqStatus = self.objRq.GetDibStatus()
print("통신상태", rqStatus, self.objRq.GetDibMsg1())
if rqStatus != 0:
return False
cnt = self.objRq.GetHeaderValue(2)
for i in range(cnt):
===ode = self.objRq.GetDataValue(0, i) # 코드===
record = None
if code in dicCodes:
record = dicCodes.get(code)
else:
record = stockPricedData()
record.code = code
record.name = g_objCodeMgr.CodeToName(code)
===ecord.diff = self.objRq.GetDataValue(2, i) # 전일대비===
===ecord.cur = self.objRq.GetDataValue(3, i) # 현재가===
===ecord.open = self.objRq.GetDataValue(4, i) # 시가===
===ecord.high = self.objRq.GetDataValue(5, i) # 고가===
===ecord.low = self.objRq.GetDataValue(6, i) # 저가===
===ecord.offer[0] = self.objRq.GetDataValue(7, i) # 매도호가===
===ecord.bid[0] = self.objRq.GetDataValue(8, i) # 매수호가===
===ecord.vol = self.objRq.GetDataValue(9, i) # 거래량===
===ecord.exFlag = self.objRq.GetDataValue(10, i) # 장구분===
===ecord.offervol[0] = self.objRq.GetDataValue(11, i) # 매도잔량===
===ecord.bidvol[0] = self.objRq.GetDataValue(12, i) # 매수잔량===
===record.Zoffer = self.objRq.GetDataValue(13, i) # 공매도수량===
===record.ZofferDate = self.objRq.GetDataValue(14, i) # 공매도날짜===
record.makediffp(0)
dicCodes[code] = record
return True
=== 샘플 코드 메인 클래스===
class testMain():
def __init__(self):
===elf.dicStockCodes = dict() # 주식 전 종목 시세 ===
===elf.dicElwCodes = dict() # ELW 전종목 시세 ===
===elf.dicFutreCodes = dict() # 선물 전종목 시세 ===
===elf.dicOptionCodes = dict() # 옵션 전종목 시세 ===
===elf.dicUpjongCodes = dict() # 업종 전종목 시세 ===
self.obj = CpMarketEye()
return
def ReqeustStockMst(self):
===odeList = g_objCodeMgr.GetStockListByMarket(1) # 거래소===
===odeList2 = g_objCodeMgr.GetStockListByMarket(2) # 코스닥===
allcodelist = codeList + codeList2
print("전체 종목 코드 #", len(allcodelist))
rqCodeList = []
for i, code in enumerate(allcodelist):
rqCodeList.append(code)
if len(rqCodeList) == 200:
self.obj.Request(rqCodeList, self.dicStockCodes)
rqCodeList = []
continue
if len(rqCodeList) > 0 :
self.obj.Request(rqCodeList, self.dicStockCodes)
print("거래소 + 코스닥 전 종목 ", len(self.dicStockCodes))
for key in self.dicStockCodes :
self.dicStockCodes[key].debugPrint(0)
def ReqeustElwMst(self):
allcodelist = []
for i in range(g_objElwMgr.GetCount()) :
allcodelist.append(g_objElwMgr.GetData(0,i))
print("전체 종목 코드 #", len(allcodelist))
rqCodeList = []
for i, code in enumerate(allcodelist):
rqCodeList.append(code)
if len(rqCodeList) == 200:
self.obj.Request(rqCodeList, self.dicElwCodes)
rqCodeList = []
continue
if len(rqCodeList) > 0 :
self.obj.Request(rqCodeList, self.dicElwCodes)
print("ELW 전종목", len(self.dicElwCodes))
for key in self.dicElwCodes :
self.dicElwCodes[key].debugPrint(0)
def ReqeustFutreMst(self):
allcodelist = []
for i in range(g_objFutureMgr.GetCount()) :
allcodelist.append(g_objFutureMgr.GetData(0,i))
print("전체 종목 코드 #", len(allcodelist))
rqCodeList = []
for i, code in enumerate(allcodelist):
rqCodeList.append(code)
if len(rqCodeList) == 200:
self.obj.Request(rqCodeList, self.dicFutreCodes)
rqCodeList = []
continue
if len(rqCodeList) > 0 :
self.obj.Request(rqCodeList, self.dicFutreCodes)
print("선물 전종목 ", len(self.dicFutreCodes))
for key in self.dicFutreCodes :
self.dicFutreCodes[key].debugPrint(1)
def ReqeustOptionMst(self):
allcodelist = []
for i in range(g_objOptionMgr.GetCount()) :
allcodelist.append(g_objOptionMgr.GetData(0,i))
print("전체 종목 코드 #", len(allcodelist))
rqCodeList = []
for i, code in enumerate(allcodelist):
rqCodeList.append(code)
if len(rqCodeList) == 200:
self.obj.Request(rqCodeList, self.dicOptionCodes)
rqCodeList = []
continue
if len(rqCodeList) > 0 :
self.obj.Request(rqCodeList, self.dicOptionCodes)
print("옵션 전종목 ", len(self.dicOptionCodes))
for key in self.dicOptionCodes :
self.dicOptionCodes[key].debugPrint(1)
def ReqeustUpjongMst(self):
===odeList = g_objCodeMgr.GetIndustryList() # 증권 산업 업종 리스트===
allcodelist = codeList
print("전체 종목 코드 #", len(allcodelist))
rqCodeList = []
for i, code in enumerate(allcodelist):
code2 = "U" + code
rqCodeList.append(code2)
if len(rqCodeList) == 200:
self.obj.Request(rqCodeList, self.dicUpjongCodes)
rqCodeList = []
continue
if len(rqCodeList) > 0 :
self.obj.Request(rqCodeList, self.dicUpjongCodes)
print("증권산업업종 리스트", len(self.dicUpjongCodes))
for key in self.dicUpjongCodes :
self.dicUpjongCodes[key].debugPrint(1)
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main = testMain()
self.setWindowTitle("PLUS API TEST")
self.setGeometry(300, 500, 300, 500)
nHeight = 20
btnStock = QPushButton("주식 전 종목", self)
btnStock.move(20, nHeight)
btnStock.clicked.connect(self.btnStock_clicked)
nHeight += 50
btnElw = QPushButton("ELW 전 종목", self)
btnElw.move(20, nHeight)
btnElw.clicked.connect(self.btnElw_clicked)
nHeight += 50
btnFuture = QPushButton("선물 전 종목", self)
btnFuture.move(20, nHeight)
btnFuture.clicked.connect(self.btnFuture_clicked)
nHeight += 50
btnOption= QPushButton("옵션 전 종목", self)
btnOption.move(20, nHeight)
btnOption.clicked.connect(self.btnOption_clicked)
nHeight += 50
btnUpjong= QPushButton("업종 전 종목", self)
btnUpjong.move(20, nHeight)
btnUpjong.clicked.connect(self.btnUpjong_clicked)
nHeight += 50
btnExit = QPushButton("종료", self)
btnExit.move(20, nHeight)
btnExit.clicked.connect(self.btnExit_clicked)
def btnStock_clicked(self):
self.main.ReqeustStockMst()
return
def btnElw_clicked(self):
self.main.ReqeustElwMst()
return
def btnFuture_clicked(self):
self.main.ReqeustFutreMst()
return
def btnOption_clicked(self):
self.main.ReqeustOptionMst()
return
def btnUpjong_clicked(self):
self.main.ReqeustUpjongMst()
return
def btnExit_clicked(self):
exit()
return
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
myWindow.show()
app.exec_()