1. 국내주식/1-2. 키움 OpenAPI (사용)

(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문내역 가져오기 (1) (opt10075)

봄이오네 2022. 10. 9. 08:22
반응형

1. 들어가며

지난 글에서는 SendOrder 함수를 이용하여, 매도취소 주문을 실행해 보았다.

https://springcoming.tistory.com/44?category=1048804 

 

(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문을 SendOrder 함수로 취소하기 (3) 주문번호와 원주문

1. 들어가며 지난 글에서는 키움증권 OpenAPI의 SendOrder 함수를 이용하여 미체결 주문을 취소했다. 이번 글에서는 이미 제출한 주문에 대한 취소주문에 적용되는 번호가 "주문번호"인지 "원주문번

springcoming.tistory.com

 

원래는 "opt10075 TR요청의 미체결내역"에서 받아오는 내용을 알아야만,

주문번호를 제대로 넣을 수 있는데,

SendOrder 함수 부분의 설명을 마무리 짓고 싶었기 때문

"주문번호" 가져와서 취소하는 내용을 먼저 다루었다.

 

이번 글에서는 키움증권 OpenAPI를 이용하여,

미체결내역을 받아오는 opt10075 TR요청에 대해 알아보겠다.


2. 미체결요청(opt10075) TR의 필요성

매수 혹은 매도 주문을 지정가 혹은 현재가로 주문을 넣었다고 하더라도,

원하는 시점에 100% 체결된다는 보장이 없다.

 

키움증권 OpenAPI에서 주문을 제출하면 아래와 같은 2가지로 진행된다.

  • 주문제출 → 체결될 때까지 대기 → 체결되면 종료(①)
  • 주문제출 → 체결될 때까지 대기 → 일정시간 경과 후 주문 취소(②)

 

일정 시간 내 체결이 되지 않으면(②의 경우),

당초 제출한 주문을 취소해야 하는 경우에 대비할 필요가 있다.

 

매도주문을 취소하기 위해 활용하는 것이

키움증권에서 제공하는 SendOrder함수이며,

SendOrder함수는 주문번호를 넣어서 취소해 주어야 한다.

 

결론은 opt10075은 문취소시 사용할 "주문번호"를 알아내는 TR요청이다.

→ 즉, 미체결 내역을 알아야, 매도취소 주문 제출시 "주문번호"를 넣어서

    매도주문 취소를 실시할 수 있기 때문이다.


3. 사전 준비

KOA Studio에서 opt10075를 알아보자

  • opt10075(미체결요청)은 INPUT에서는 5개 인수의 입력이 필요하고, OUTPUT에서는 26개를 제공한다.(①)
  • INPUT은 5개 인수의 입력 설명(계좌번호, 전체종목구분, 매매구분, 종목코드, 체결구분) (②, ③)
  • OUTPUR는  26개 결과를 출력해 준다. (장 종료로 인해 미체결내역을 구현할 수 없음을 양해해 주시길 바란다)

< 그림1. KOA Studio에서 opt10075의 설명 >


4. 코드 설명

  • 키움증권 OpenAPI에 접속/로그인
  • OpenAPI의 SetInputValue함수와 CommRqdata함수를 통해 키움서버에 각각 데이터 입력/요청
  • OpenAPI의 GetCommData함수를 통해 CommRqdata함수에서 요청한 데이터 수신

< 그림2-1. opt10075 TR요청을 위해 SetInputValue/CommRqData 함수 선언하는 화면 >

18줄 : 미체결내역의 데이터를 저장하기 위해 딕셔너리 형태로 선언

22줄~ 23줄 : 모의계좌 번호의 전역변수 선언 및 계좌번호 입력

 

31줄 : 69줄에서 입력해준 "계좌번호"와 "종목코드"를 받아주기 위해

          31줄에서 deposit_num, stock_code를 각각 변수 선언함

32줄~36줄 : 69줄에서 입력한 데이터를 32줄~36줄에서 키움서버에 입력

37줄 : 데이터를 CommRqData를 통해 키움서버에 요청

 

※ 아래 <그림2-2>에서 SetInputData에 입력할 값을 확인하면,

계좌번호        : 변수전달이 필요하여 변수선언 필요

전체종목구분 : 전체종목을 조회할 것이므로, 변수 선언 불요 → 전체를 뜻하는 "0"을 입력

매매구분         : 매수/매도를 활용할 것이므로, 변수 선언 불요 → 전체를 뜻하는 "0"을 입력

종목코드         : 변수전달이 필요하여 변수선언 필요

체결구분         : 여기서는 미체결만 검토할 것이므로, 변수 선언 불요 → 미체결을 의미하는 "1"입력

< 그림2-2. KOA Studio에서 설명하는 opt10075의 SetInput 함수 입력값 >

 

 

< 그림2-3. GetCommData 함수를 통해 데이터를 수신받은 화면 >

 

41줄 : 31줄~39줄까지 입력/요청한 데이터를 수신받기 위해 trdada_get함수를 선언

42줄 : 수신받은 데이터가 rq == 'opt_10075' 이면

43줄 ~ 46줄 : 계좌번호, 종목코드, 주문번호, 원주문 번호 등 4개 변수에 담아라

 

48줄 ~ 51줄 : 43줄~46줄에서 각각 변수에 담은 내용을

                      18줄에서 만든 딕셔너리에 담아라.

        * 당초 딕셔너리에 담아서, 데이터프레임으로 출력하려고 했으나,

           장 종료로 인한 시간부족으로 데이터프레임으로 출력은 못함

53줄 : 18줄에서 선언한 self.not_order_deal을 선언하라

           (이 또한 시간 부족으로 출력 못함)

55줄 ~ 58줄 : 4개 변수를 출력하라 (계좌번호, 주문코드, 주문번호, 원주문번호)

69줄 :  계좌번호(deposit_num)와 코드번호(stock_code) 담아서 31줄의 rq_data_opt10075함수를 실행하라


5. 출력 화면

opt10075 TR요청은 키움증권 영웅문의 화면번호 0341을 나타낸다.

< 그림3-1. 화면번호 0341의 미체결 주문 현황 >

 

위의 코드를 실행한 파이참의 실행결과이다.

여기에서 주의할 점은 주문번호 앞에 0이 붙어있다.

→ 향후 주문번호(order_num)의 변수앞에 int를 넣어주어서 정수화 시킨다.

< 그림3-2. 파이참에서 실행한 결과 >


6. 전체 코드

import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class btl_system():
    def __init__(self):
        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        print("로그인 시작!")

        self.kiwoom.OnEventConnect.connect(self.login_Connect)
        self.kiwoom.OnReceiveTrData.connect(self.trdata_get)

        self.kiwoom.dynamicCall("CommConnect()")
        self.login_event_loop = QEventLoop()
        self.login_event_loop.exec_()

        self.not_order_deal = {'deposit_num': [], 'stock_code': [], 'order_num': [], 'orgorder_num': []}

        # 계좌번호
        global deposit_num
        deposit_num = "계좌번호 10자리 입력"

    def login_Connect(self, err_code):
        if err_code == 0:
            print('로그인 성공했습니다!')
        else:
            print('로그인 실패했습니다!')
        self.login_event_loop.exit()

    def rq_data_opt10075(self, deposit_num, stock_code):
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "계좌번호", deposit_num)
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "전체종목구분", "0")
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "매매구분", "0")
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "종목코드", stock_code)
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "체결구분", "1")
        self.kiwoom.dynamicCall("CommRqData(QString,QString,int,QString)", "opt_10075", "opt10075", 0, "0107")
        self.tr_event_loop = QEventLoop()
        self.tr_event_loop.exec_()

    def trdata_get(self, sScrNo, rqname, trcode, sRecordName, prenext, nDataLength, sErrorCode, sMessage, sSplmMsg):
        if rqname == 'opt_10075':
            deposit_num = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10075", "미체결요청", 0, "계좌번호").strip()
            stock_code = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10075", "미체결요청", 0, "종목코드").strip()
            order_num = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10075", "미체결요청", 0, "주문번호").strip()
            orgorder_num = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10075", "미체결요청", 0, "원주문번호").strip()

            self.not_order_deal['deposit_num'].appeng(deposit_num)
            self.not_order_deal['stock_code'].appeng(stock_code)
            self.not_order_deal['order_num'].appeng(order_num)
            self.not_order_deal['orgorder_num'].appeng(orgorder_num)

            print(self.not_order_deal)

            print("계좌 번호는 {}입니다.".format(deposit_num))
            print("주문코드는 {}입니다.".format(stock_code))
            print("주문번호는 {}입니다.".format(order_num))
            print("원주문 번호는 {}입니다.".format(orgorder_num))

        try:
            self.tr_event_loop.exit()
        except AttributeError:
            pass

if __name__ == "__main__":
    app = QApplication(sys.argv)
    btl = btl_system()

    btl.rq_data_opt10075(deposit_num, "035720")

    app.exec_()

7. 마치며

지금까지 미체결요청의 주문번호 받는 방법을 알아보았다.

 

위의 미체결요청(opt10075)는 장 마감이 된 이후에는 조회할 수 없다.

장 마감(18:00~) 이후에는 기존 제출했던 주문이 자동으로 취소되기 때문이다.

장이 열리는 동안, 매수/매도 주문을 넣어두고, 취소할 때 활용하면 된다.

 

다음 글에서는 매도주문을 하였으나, 체결이 이루어지지 않는 경우

"매도주문"을 취소하는 내용을 알아볼 예정이다.

반응형