행위

"대신증권 파이썬 api"의 두 판 사이의 차이

DB CAFE

(주식차트 조회(일간/주간/월간/분간/틱) 예제)
(종목별 투자자 매매동향 (잠정)데이터)
2,951번째 줄: 2,951번째 줄:
  
 
=== 종목별 투자자 매매동향 (잠정)데이터 ===
 
=== 종목별 투자자 매매동향 (잠정)데이터 ===
 +
CpSysDib.CpSvr7210d 를 통해 "종목별 투자자 매매동향(잠정)데이터" 를 조회 합니다.
 +
 +
■ 사용된 PLUS OBJECT
 +
 +
  - CpSysDib.CpSvr7210d - 투자자 매매 동향(잠정) 데이터 조회
 +
 +
■ 화면 설명
 +
 +
- 기관계 상위 :  기간계 상위 순으로 조회
 +
 +
- 외국인상위 :  외국인상위 순으로 조회
 +
 +
- print : 조회 내용 print
 +
 +
- 엑셀 내보내기 : 조회 내용 엑셀로 내보내기
 +
 +
<source lang=python>
 +
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')
 +
 +
 +
# Cp7210 : 종목별 투자자 매매동향(잠정)데이터
 +
class Cp7210:
 +
    def __init__(self):
 +
        self.objRq = None
 +
        return
 +
 +
    def request(self, investFlag, caller):
 +
        maxRqCont = 1
 +
        rqCnt = 0
 +
        caller.data7210 = []
 +
        self.objRq = None
 +
        self.objRq = win32com.client.Dispatch("CpSysDib.CpSvr7210d")
 +
 +
        while True:
 +
            self.objRq.SetInputValue(0, '0')  # 0 전체 1 거래소 2 코스닥 3 업종 4 관심종목
 +
            self.objRq.SetInputValue(1, ord('0')) # 0 수량 1 금액
 +
            self.objRq.SetInputValue(2, investFlag) # 0 종목 1 외국인 2 기관계 3 보험기타 4 투신..
 +
            self.objRq.SetInputValue(3, ord('0')) # 0 상위순 1 하위순
 +
 +
            self.objRq.BlockRequest()
 +
            rqCnt += 1
 +
 +
            # 통신 및 통신 에러 처리
 +
            rqStatus = self.objRq.GetDibStatus()
 +
            rqRet = self.objRq.GetDibMsg1()
 +
            print("통신상태", rqStatus, rqRet)
 +
            if rqStatus != 0:
 +
                return False
 +
 +
            cnt = self.objRq.GetHeaderValue(0)
 +
            date = self.objRq.GetHeaderValue(1) # 집계날짜
 +
            time = self.objRq.GetHeaderValue(2)  # 집계시간
 +
            print(cnt)
 +
 +
            for i in range(cnt):
 +
                item = {}
 +
                item['code'] = self.objRq.GetDataValue(0, i)
 +
                item['종목명'] = self.objRq.GetDataValue(1, i)
 +
                item['현재가'] = self.objRq.GetDataValue(2, i)
 +
                item['대비'] = self.objRq.GetDataValue(3, i)
 +
                item['대비율'] = self.objRq.GetDataValue(4, i)
 +
                item['거래량'] = self.objRq.GetDataValue(5, i)
 +
                item['외국인'] = self.objRq.GetDataValue(6, i)
 +
                item['기관계'] = self.objRq.GetDataValue(7, i)
 +
                item['보험기타금융'] = self.objRq.GetDataValue(8, i)
 +
                item['투신'] = self.objRq.GetDataValue(9, i)
 +
                item['은행'] = self.objRq.GetDataValue(10, i)
 +
                item['연기금'] = self.objRq.GetDataValue(11, i)
 +
                item['국가지자체'] = self.objRq.GetDataValue(12, i)
 +
                item['기타법인'] = self.objRq.GetDataValue(13, i)
 +
 +
                caller.data7210.append(item)
 +
 +
            if rqCnt >= maxRqCont:
 +
                break
 +
 +
            if self.objRq.Continue == False:
 +
                break
 +
        return True
 +
 +
 +
 +
 +
 +
 +
class MyWindow(QMainWindow):
 +
    def __init__(self):
 +
        super().__init__()
 +
 +
        self.setWindowTitle("종목별 투자자 매매동향(잠정)")
 +
        self.setGeometry(300, 300, 300, 180)
 +
 +
        self.obj7210 = Cp7210()
 +
        self.data7210 = []
 +
 +
        nH = 20
 +
        btnOpt1 = QPushButton('기관계 상위', self)
 +
        btnOpt1.move(20, nH)
 +
        btnOpt1.clicked.connect(self.btnOpt1_clicked)
 +
        nH += 50
 +
 +
        btnOpt2 = QPushButton('외국인 상위', self)
 +
        btnOpt2.move(20, nH)
 +
        btnOpt2.clicked.connect(self.btnOpt2_clicked)
 +
        nH += 50
 +
 +
        btnPrint = QPushButton('print', self)
 +
        btnPrint.move(20, nH)
 +
        btnPrint.clicked.connect(self.btnPrint_clicked)
 +
        nH += 50
 +
 +
        btnExcel = QPushButton('엑셀 내보내기', self)
 +
        btnExcel.move(20, nH)
 +
        btnExcel.clicked.connect(self.btnExcel_clicked)
 +
        nH += 50
 +
 +
 +
        btnExit = QPushButton('종료', self)
 +
        btnExit.move(20, nH)
 +
        btnExit.clicked.connect(self.btnExit_clicked)
 +
        nH += 50
 +
        self.setGeometry(300, 300, 300, nH)
 +
 +
 +
    # 기관계 상위
 +
    def btnOpt1_clicked(self):
 +
        self.obj7210.request(2, self)
 +
        return
 +
 +
    # 외국인 상위
 +
    def btnOpt2_clicked(self):
 +
        self.obj7210.request(1, self)
 +
        return
 +
 +
 +
    def btnPrint_clicked(self):
 +
        for item in self.data7210:
 +
            print(item)
 +
        return
 +
 +
    # 엑셀 내보내기
 +
    def btnExcel_clicked(self):
 +
        excelfile = '7210.xlsx'
 +
        df = pd.DataFrame(columns=['code','종목명', '현재가', '대비', '대비율', '거래량', '외국인', '기관계',
 +
                                              '보험기타금융', '투신','은행','연기금','국가지자체','기타법인'])
 +
 +
        for item in self.data7210:
 +
            df.loc[(len(df))] = item
 +
 +
        # create a Pandas Excel writer using XlsxWriter as the engine.
 +
        writer = pd.ExcelWriter(excelfile, engine='xlsxwriter')
 +
        # Convert the dataframe to an XlsxWriter Excel object.
 +
        df.to_excel(writer, sheet_name='Sheet1')
 +
        # Close the Pandas Excel writer and output the Excel file.
 +
        writer.save()
 +
        os.startfile(excelfile)
 +
        return
 +
 +
    def btnExit_clicked(self):
 +
        exit()
 +
        return
 +
 +
 +
 +
if __name__ == "__main__":
 +
    app = QApplication(sys.argv)
 +
    myWindow = MyWindow()
 +
    myWindow.show()
 +
    app.exec_()
 +
</python>
 +
 
=== 주식 분할 주문 예제 ===
 
=== 주식 분할 주문 예제 ===
 
=== 해외선물 잔고(미결제약정)과 실시간 주문체결 처리 예제===
 
=== 해외선물 잔고(미결제약정)과 실시간 주문체결 처리 예제===

2020년 9월 8일 (화) 23:36 판

thumb_up 추천메뉴 바로가기


목차

1 주식 현재가 조회/실시간[편집]

2 주식 일자별 조회(다음)[편집]

3 주식 현재가 조회[편집]

4 종목정보 구하는 예제[편집]

5 주식차트 조회(일간/주간/월간/분간/틱) 예제[편집]

주식 차트 정보를 구하는 파이썬 예제입니다


사용된 PLUS OBJECT

■ CpSysDib.StockChart - 차트 조회 OBJECT


주요 기능

■ 기간(일간) - 일간 차트를 특정 기간을 주어 조회

■ 개수(일간) - 최근일 부터 개수만큼 조회

■ 분차트 조회

■ 틱차트 조회

■ 주간 차트 조회

■ 월간 차트 조회

■ 엑셀로 저장 - 수신 받은 데이터를 엑셀로 내보내기 하여 데이터 확인

import sys
from PyQt5.QtWidgets import *
import win32com.client
import pandas as pd
import os
 
g_objCodeMgr = win32com.client.Dispatch('CpUtil.CpCodeMgr')
g_objCpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
 
 
class CpStockChart:
    def __init__(self):
        self.objStockChart = win32com.client.Dispatch("CpSysDib.StockChart")
 
    # 차트 요청 - 기간 기준으로
    def RequestFromTo(self, code, fromDate, toDate, caller):
        print(code, fromDate, toDate)
        # 연결 여부 체크
        bConnect = g_objCpStatus.IsConnect
        if (bConnect == 0):
            print("PLUS가 정상적으로 연결되지 않음. ")
            return False
 
        self.objStockChart.SetInputValue(0, code)  # 종목코드
        self.objStockChart.SetInputValue(1, ord('1'))  # 기간으로 받기
        self.objStockChart.SetInputValue(2, toDate)  # To 날짜
        self.objStockChart.SetInputValue(3, fromDate)  # From 날짜
        #self.objStockChart.SetInputValue(4, 500)  # 최근 500일치
        self.objStockChart.SetInputValue(5, [0, 2, 3, 4, 5, 8])  # 날짜,시가,고가,저가,종가,거래량
        self.objStockChart.SetInputValue(6, ord('D'))  # '차트 주기 - 일간 차트 요청
        self.objStockChart.SetInputValue(9, ord('1'))  # 수정주가 사용
        self.objStockChart.BlockRequest()
 
        rqStatus = self.objStockChart.GetDibStatus()
        rqRet = self.objStockChart.GetDibMsg1()
        print("통신상태", rqStatus, rqRet)
        if rqStatus != 0:
            exit()
 
        len = self.objStockChart.GetHeaderValue(3)
 
        caller.dates = []
        caller.opens = []
        caller.highs = []
        caller.lows = []
        caller.closes = []
        caller.vols = []
        for i in range(len):
            caller.dates.append(self.objStockChart.GetDataValue(0,i))
            caller.opens.append(self.objStockChart.GetDataValue(1, i))
            caller.highs.append(self.objStockChart.GetDataValue(2, i))
            caller.lows.append(self.objStockChart.GetDataValue(3, i))
            caller.closes.append(self.objStockChart.GetDataValue(4, i))
            caller.vols.append(self.objStockChart.GetDataValue(5, i))
 
        print(len)
 
    # 차트 요청 - 최근일 부터 개수 기준
    def RequestDWM(self, code, dwm, count, caller):
        # 연결 여부 체크
        bConnect = g_objCpStatus.IsConnect
        if (bConnect == 0):
            print("PLUS가 정상적으로 연결되지 않음. ")
            return False
 
        self.objStockChart.SetInputValue(0, code)  # 종목코드
        self.objStockChart.SetInputValue(1, ord('2'))  # 개수로 받기
        self.objStockChart.SetInputValue(4, count)  # 최근 500일치
        self.objStockChart.SetInputValue(5, [0, 2, 3, 4, 5, 8])  # 요청항목 - 날짜,시가,고가,저가,종가,거래량
        self.objStockChart.SetInputValue(6, dwm)  # '차트 주기 - 일/주/월
        self.objStockChart.SetInputValue(9, ord('1'))  # 수정주가 사용
        self.objStockChart.BlockRequest()
 
        rqStatus = self.objStockChart.GetDibStatus()
        rqRet = self.objStockChart.GetDibMsg1()
        print("통신상태", rqStatus, rqRet)
        if rqStatus != 0:
            exit()
 
        len = self.objStockChart.GetHeaderValue(3)
 
        caller.dates = []
        caller.opens = []
        caller.highs = []
        caller.lows = []
        caller.closes = []
        caller.vols = []
        caller.times = []
        for i in range(len):
            caller.dates.append(self.objStockChart.GetDataValue(0, i))
            caller.opens.append(self.objStockChart.GetDataValue(1, i))
            caller.highs.append(self.objStockChart.GetDataValue(2, i))
            caller.lows.append(self.objStockChart.GetDataValue(3, i))
            caller.closes.append(self.objStockChart.GetDataValue(4, i))
            caller.vols.append(self.objStockChart.GetDataValue(5, i))
 
        print(len)
 
        return
 
    # 차트 요청 - 분간, 틱 차트
    def RequestMT(self, code, dwm, count, caller):
        # 연결 여부 체크
        bConnect = g_objCpStatus.IsConnect
        if (bConnect == 0):
            print("PLUS가 정상적으로 연결되지 않음. ")
            return False
 
        self.objStockChart.SetInputValue(0, code)  # 종목코드
        self.objStockChart.SetInputValue(1, ord('2'))  # 개수로 받기
        self.objStockChart.SetInputValue(4, count)  # 조회 개수
        self.objStockChart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8])  # 요청항목 - 날짜, 시간,시가,고가,저가,종가,거래량
        self.objStockChart.SetInputValue(6, dwm)  # '차트 주기 - 분/틱
        self.objStockChart.SetInputValue(7, 1)  # 분틱차트 주기
        self.objStockChart.SetInputValue(9, ord('1'))  # 수정주가 사용
        self.objStockChart.BlockRequest()
 
        rqStatus = self.objStockChart.GetDibStatus()
        rqRet = self.objStockChart.GetDibMsg1()
        print("통신상태", rqStatus, rqRet)
        if rqStatus != 0:
            exit()
 
        len = self.objStockChart.GetHeaderValue(3)
 
        caller.dates = []
        caller.opens = []
        caller.highs = []
        caller.lows = []
        caller.closes = []
        caller.vols = []
        caller.times = []
        for i in range(len):
            caller.dates.append(self.objStockChart.GetDataValue(0, i))
            caller.times.append(self.objStockChart.GetDataValue(1, i))
            caller.opens.append(self.objStockChart.GetDataValue(2, i))
            caller.highs.append(self.objStockChart.GetDataValue(3, i))
            caller.lows.append(self.objStockChart.GetDataValue(4, i))
            caller.closes.append(self.objStockChart.GetDataValue(5, i))
            caller.vols.append(self.objStockChart.GetDataValue(6, i))
 
        print(len)
 
        return
 
 
 
class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
 
        # 기본 변수들
        self.dates = []
        self.opens = []
        self.highs = []
        self.lows = []
        self.closes = []
        self.vols = []
        self.times = []
 
        self.objChart = CpStockChart()
 
 
        # 윈도우 버튼 배치
        self.setWindowTitle("PLUS API TEST")
        nH = 20
 
        self.codeEdit = QLineEdit("", self)
        self.codeEdit.move(20, nH)
        self.codeEdit.textChanged.connect(self.codeEditChanged)
        self.codeEdit.setText('00660')
        self.label = QLabel('종목코드', self)
        self.label.move(140, nH)
        nH += 50
 
        btchart1= QPushButton("기간(일간) 요청", self)
        btchart1.move(20, nH)
        btchart1.clicked.connect(self.btchart1_clicked)
        nH += 50
 
        btchart2 = QPushButton("개수(일간) 요청", self)
        btchart2.move(20, nH)
        btchart2.clicked.connect(self.btchart2_clicked)
        nH += 50
 
        btchart3 = QPushButton("분차트 요청", self)
        btchart3.move(20, nH)
        btchart3.clicked.connect(self.btchart3_clicked)
        nH += 50
 
        btchart4 = QPushButton("틱차트 요청", self)
        btchart4.move(20, nH)
        btchart4.clicked.connect(self.btchart4_clicked)
        nH += 50
 
        btchart5 = QPushButton("주간차트 요청", self)
        btchart5.move(20, nH)
        btchart5.clicked.connect(self.btchart5_clicked)
        nH += 50
 
        btchart6 = QPushButton("월간차트 요청", self)
        btchart6.move(20, nH)
        btchart6.clicked.connect(self.btchart6_clicked)
        nH += 50
 
        btchart7 = QPushButton("엑셀로 저장", self)
        btchart7.move(20, nH)
        btchart7.clicked.connect(self.btchart7_clicked)
        nH += 50
 
        btnExit = QPushButton("종료", self)
        btnExit.move(20, nH)
        btnExit.clicked.connect(self.btnExit_clicked)
        nH += 50
 
        self.setGeometry(300, 300, 300, nH)
        self.setCode('A000660')
 
    # 기간(일간) 으로 받기
    def btchart1_clicked(self):
        if self.objChart.RequestFromTo(self.code, 20160102, 20171025, self) == False:
            exit()
 
    # 개수(일간) 으로 받기
    def btchart2_clicked(self):
        if self.objChart.RequestDWM(self.code, ord('D'), 500, self) == False:
            exit()
 
    # 분차트 받기
    def btchart3_clicked(self):
        if self.objChart.RequestMT(self.code, ord('m'), 500, self) == False:
            exit()
 
 
    # 틱차트 받기
    def btchart4_clicked(self):
        if self.objChart.RequestMT(self.code, ord('T'), 500, self) == False:
            exit()
 
    # 주간차트
    def btchart5_clicked(self):
        if self.objChart.RequestDWM(self.code, ord('W'), 100, self) == False:
            exit()
 
    # 월간차트
    def btchart6_clicked(self):
        if self.objChart.RequestDWM(self.code, ord('M'), 100, self) == False:
            exit()
 
 
    def btchart7_clicked(self):
        charfile = 'chart.xlsx'
        if (len(self.times) == 0):
            chartData = {'일자' : self.dates,
                       '시가' : self.opens,
                       '고가' : self.highs,
                       '저가' : self.lows,
                       '종가' : self.closes,
                       '거래량' : self.vols,
                       }
            df =pd.DataFrame(chartData, columns=['일자','시가','고가','저가','종가','거래량'])
        else:
            chartData = {'일자' : self.dates,
                       '시간' : self.times,
                       '시가' : self.opens,
                       '고가' : self.highs,
                       '저가' : self.lows,
                       '종가' : self.closes,
                       '거래량' : self.vols,
                       }
            df =pd.DataFrame(chartData, columns=['일자','시간','시가','고가','저가','종가','거래량'])
 
        df = df.set_index('일자')
 
        # create a Pandas Excel writer using XlsxWriter as the engine.
        writer = pd.ExcelWriter(charfile, engine='xlsxwriter')
        # Convert the dataframe to an XlsxWriter Excel object.
        df.to_excel(writer, sheet_name='Sheet1')
        # Close the Pandas Excel writer and output the Excel file.
        writer.save()
        os.startfile(charfile)
        return
 
    def codeEditChanged(self):
        code = self.codeEdit.text()
        self.setCode(code)
 
    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.label.setText(name)
        self.code = code
 
 
    def btnExit_clicked(self):
        exit()
 
 
 
if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    app.exec_()

6 지수옵션 최근월물 시세 조회(실시간 포함)[편집]

7 매매입체분석(투자주체별현황) 예제[편집]

매매입체분석(CpSysDib.CpSvr7254) 서비스를 이용하여 데이터를 조회하는 파이썬 예제입니다 조회 후 엑셀 내보내기를 통해 엑셀 파일로 데이터 확인 가능합니다.

import sys
from PyQt5.QtWidgets import *
import win32com.client
from pandas import Series, DataFrame
import pandas as pd
import locale
import os
import time
 
locale.setlocale(locale.LC_ALL, '')
# cp object
g_objCodeMgr = win32com.client.Dispatch('CpUtil.CpCodeMgr')
g_objCpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
g_objCpTrade = win32com.client.Dispatch('CpTrade.CpTdUtil')
 
gExcelFile = '7254.xlsx'
 
 
class CpRp7354:
    def Request(self, code, caller):
        # 연결 여부 체크
        objCpCybos = win32com.client.Dispatch('CpUtil.CpCybos')
        bConnect = objCpCybos.IsConnect
        if (bConnect == 0):
            print('PLUS가 정상적으로 연결되지 않음. ')
            return False
 
        # 관심종목 객체 구하기
        objRq = win32com.client.Dispatch('CpSysDib.CpSvr7254')
        objRq.SetInputValue(0, code)
        objRq.SetInputValue(1, 6)  # 일자별
        objRq.SetInputValue(4, ord('0'))  # '0' 순매수 '1' 매매비중
        objRq.SetInputValue(5, 0)  # '전체
        objRq.SetInputValue(6, ord('1'))  # '1' 순매수량 '2' 추정금액(백만)
 
        sumcnt = 0
        caller.data7254 = None
        caller.data7254 = pd.DataFrame(columns=('date', 'close', '개인', '외국인', '기관계',
                                                '금융투자', '보험', '투신', '은행', '기타금융', '연기금', '국가,지자체',
                                                '기타법인', '기타외인'))
 
        while True:
            remainCount = g_objCpStatus.GetLimitRemainCount(1)  # 1 시세 제한
            if remainCount <= 0:
                print('시세 연속 조회 제한 회피를 위해 sleep', g_objCpStatus.LimitRequestRemainTime)
                time.sleep(g_objCpStatus.LimitRequestRemainTime / 1000)
 
            objRq.BlockRequest()
 
            # 현재가 통신 및 통신 에러 처리
            rqStatus = objRq.GetDibStatus()
            print('통신상태', rqStatus, objRq.GetDibMsg1())
            if rqStatus != 0:
                return False
 
            cnt = objRq.GetHeaderValue(1)
            sumcnt += cnt
 
            for i in range(cnt):
                item = {}
                item['date'] = objRq.GetDataValue(0, i)
                item['close'] = objRq.GetDataValue(14, i)
                item['개인'] = 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)
                item['은행'] = objRq.GetDataValue(7, i)
                item['기타금융'] = objRq.GetDataValue(8, i)
                item['연기금'] = objRq.GetDataValue(9, i)
                item['국가,지자체'] = objRq.GetDataValue(13, i)
                item['기타법인'] = objRq.GetDataValue(10, i)
                item['기타외인'] = objRq.GetDataValue(11, i)
 
                caller.data7254.loc[len(caller.data7254)] = item
 
            # 1000 개 정도만 처리
            if sumcnt > 1000:
                break;
            # 연속 처리
            if objRq.Continue != True:
                break
 
        caller.data7254 = caller.data7254.set_index('date')
        # 인덱스 이름 제거
        caller.data7254.index.name = None
        print(caller.data7254)
        return True
 
 
class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('PLUS API TEST')
        self.setGeometry(300, 300, 300, 240)
        self.isSB = False
        self.objCur = []
 
        self.data7254 = DataFrame()
 
        btnStart = QPushButton('요청 시작', self)
        btnStart.move(20, 20)
        btnStart.clicked.connect(self.btnStart_clicked)
 
        btnExcel = QPushButton('Excel 내보내기', self)
        btnExcel.move(20, 70)
        btnExcel.clicked.connect(self.btnExcel_clicked)
 
        btnPrint = QPushButton('DF Print', self)
        btnPrint.move(20, 120)
        btnPrint.clicked.connect(self.btnPrint_clicked)
 
        btnExit = QPushButton('종료', self)
        btnExit.move(20, 190)
        btnExit.clicked.connect(self.btnExit_clicked)
 
 
 
    def btnStart_clicked(self):
        # 요청 필드 배열 - 종목코드, 시간, 대비부호 대비, 현재가, 거래량, 종목명
        obj7254 = CpRp7354()
        obj7254.Request('A000660',self)
 
 
    def btnExcel_clicked(self):
        print(len(self.data7254.index))
        # create a Pandas Excel writer using XlsxWriter as the engine.
        writer = pd.ExcelWriter(gExcelFile, engine='xlsxwriter')
        # Convert the dataframe to an XlsxWriter Excel object.
        self.data7254.to_excel(writer, sheet_name='Sheet1')
        # Close the Pandas Excel writer and output the Excel file.
        writer.save()
        os.startfile(gExcelFile)
        return
 
    def btnPrint_clicked(self):
        print(self.data7254)
 
    def btnExit_clicked(self):
        exit()
 
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()
    app.exec_()

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_()

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 종목별 투자자 매매동향 (잠정)데이터[편집]

CpSysDib.CpSvr7210d 를 통해 "종목별 투자자 매매동향(잠정)데이터" 를 조회 합니다.

■ 사용된 PLUS OBJECT

  - CpSysDib.CpSvr7210d - 투자자 매매 동향(잠정) 데이터 조회 

■ 화면 설명

- 기관계 상위 : 기간계 상위 순으로 조회

- 외국인상위 : 외국인상위 순으로 조회

- print : 조회 내용 print

- 엑셀 내보내기 : 조회 내용 엑셀로 내보내기

<source lang=python> 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')


  1. Cp7210 : 종목별 투자자 매매동향(잠정)데이터

class Cp7210:

   def __init__(self):
       self.objRq = None
       return

   def request(self, investFlag, caller):
       maxRqCont = 1
       rqCnt = 0
       caller.data7210 = []
       self.objRq = None
       self.objRq = win32com.client.Dispatch("CpSysDib.CpSvr7210d")

       while True:
           self.objRq.SetInputValue(0, '0')  # 0 전체 1 거래소 2 코스닥 3 업종 4 관심종목
           self.objRq.SetInputValue(1, ord('0')) # 0 수량 1 금액
           self.objRq.SetInputValue(2, investFlag) # 0 종목 1 외국인 2 기관계 3 보험기타 4 투신..
           self.objRq.SetInputValue(3, ord('0')) # 0 상위순 1 하위순

           self.objRq.BlockRequest()
           rqCnt += 1

           # 통신 및 통신 에러 처리
           rqStatus = self.objRq.GetDibStatus()
           rqRet = self.objRq.GetDibMsg1()
           print("통신상태", rqStatus, rqRet)
           if rqStatus != 0:
               return False

           cnt = self.objRq.GetHeaderValue(0)
           date = self.objRq.GetHeaderValue(1) # 집계날짜
           time = self.objRq.GetHeaderValue(2)  # 집계시간
           print(cnt)

           for i in range(cnt):
               item = {}
               item['code'] = self.objRq.GetDataValue(0, i)
               item['종목명'] = self.objRq.GetDataValue(1, i)
               item['현재가'] = self.objRq.GetDataValue(2, i)
               item['대비'] = self.objRq.GetDataValue(3, i)
               item['대비율'] = self.objRq.GetDataValue(4, i)
               item['거래량'] = self.objRq.GetDataValue(5, i)
               item['외국인'] = self.objRq.GetDataValue(6, i)
               item['기관계'] = self.objRq.GetDataValue(7, i)
               item['보험기타금융'] = self.objRq.GetDataValue(8, i)
               item['투신'] = self.objRq.GetDataValue(9, i)
               item['은행'] = self.objRq.GetDataValue(10, i)
               item['연기금'] = self.objRq.GetDataValue(11, i)
               item['국가지자체'] = self.objRq.GetDataValue(12, i)
               item['기타법인'] = self.objRq.GetDataValue(13, i)

               caller.data7210.append(item)

           if rqCnt >= maxRqCont:
               break

           if self.objRq.Continue == False:
               break
       return True






class MyWindow(QMainWindow):

   def __init__(self):
       super().__init__()

       self.setWindowTitle("종목별 투자자 매매동향(잠정)")
       self.setGeometry(300, 300, 300, 180)

       self.obj7210 = Cp7210()
       self.data7210 = []

       nH = 20
       btnOpt1 = QPushButton('기관계 상위', self)
       btnOpt1.move(20, nH)
       btnOpt1.clicked.connect(self.btnOpt1_clicked)
       nH += 50

       btnOpt2 = QPushButton('외국인 상위', self)
       btnOpt2.move(20, nH)
       btnOpt2.clicked.connect(self.btnOpt2_clicked)
       nH += 50

       btnPrint = QPushButton('print', self)
       btnPrint.move(20, nH)
       btnPrint.clicked.connect(self.btnPrint_clicked)
       nH += 50

       btnExcel = QPushButton('엑셀 내보내기', self)
       btnExcel.move(20, nH)
       btnExcel.clicked.connect(self.btnExcel_clicked)
       nH += 50


       btnExit = QPushButton('종료', self)
       btnExit.move(20, nH)
       btnExit.clicked.connect(self.btnExit_clicked)
       nH += 50
       self.setGeometry(300, 300, 300, nH)


   # 기관계 상위
   def btnOpt1_clicked(self):
       self.obj7210.request(2, self)
       return

   # 외국인 상위
   def btnOpt2_clicked(self):
       self.obj7210.request(1, self)
       return


   def btnPrint_clicked(self):
       for item in self.data7210:
           print(item)
       return

   # 엑셀 내보내기
   def btnExcel_clicked(self):
       excelfile = '7210.xlsx'
       df = pd.DataFrame(columns=['code','종목명', '현재가', '대비', '대비율', '거래량', '외국인', '기관계',
                                             '보험기타금융', '투신','은행','연기금','국가지자체','기타법인'])

       for item in self.data7210:
           df.loc[(len(df))] = item

       # create a Pandas Excel writer using XlsxWriter as the engine.
       writer = pd.ExcelWriter(excelfile, engine='xlsxwriter')
       # Convert the dataframe to an XlsxWriter Excel object.
       df.to_excel(writer, sheet_name='Sheet1')
       # Close the Pandas Excel writer and output the Excel file.
       writer.save()
       os.startfile(excelfile)
       return

   def btnExit_clicked(self):
       exit()
       return



if __name__ == "__main__":

   app = QApplication(sys.argv)
   myWindow = MyWindow()
   myWindow.show()
   app.exec_()

</python>

43 주식 분할 주문 예제[편집]

44 해외선물 잔고(미결제약정)과 실시간 주문체결 처리 예제[편집]