키움 OPEN API에 TR 요청하기(feat. 예수금과 계좌잔고 받아오기)

 

 

지난 글 보기

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

04_키움 open api 로그인 하기

 

 

 

지난 시간에 키움 api 자동 로그인까지 성공했다.

로그인을 했으니 나의 계좌 정보를 받아와야 하겠다. 대표적으로 예수금과 계좌평가잔고내역 받아오기를 해보았다.

코드 작성을 위한 전반적인 도움은 지난 글에서 설명한 유튜브 "프로그램 동산" 채널을 도움을 받았다.

 

 

조회하고자 하는 내용은 영웅문에서 다음의 내용이다.

나는 모의투자로 1,000만원을 신청해둔 상태이며, 아직 매매를 하지 않아 1,000만원이 모두 예수금 잔액으로 잡혀있다.

 

영웅문 예수금상세현황 조회

 

영웅문 계좌평가잔고내역 조회

 

 

영웅문에서 화면으로 조회되는 것을 OPEN API로 조회하기 위해서는 TR(Transaction)을 요청해야 하며, 어떤 요구사항들이 있는지 알아보기 위해 KOA를 실행한다.

 

 

키움 KOA TR 요청 - 예수금 검색

 

KOA에서 하단의 "TR목록"을 클릭하고, 상단 검색란에 "예수금"을 입력한 뒤 엔터키 말고 마우스로 "다음"을 클릭한다.

opw00001을 찾아 클릭하면 위와 같은 화면이 조회된다. 받을 수 있는 자료 목록이 왼쪽에 나열되고, C++ 기준 예제 코드가 중앙 상단에 위치하고 있다. 오른쪽에 있는 조회 창에 계좌번호 등의 정보를 입력하면, 하단에 출력된다.

 

나의 예수금이 1,000만원으로 조회되었지만, 앞에 0이 많이 붙어 숫자가 아닌 text 형식임을 추측할 수 있다.

 

 

키움 KOA TR 요청 - 예수금 검색

 

 

위에서 조회한 데이터를 요청하는 방법은 KOA 하단의 "개발가이드"에서 찾을 수 있다. 각종 조회와 실시간데이터처리 중 "OnReceiveTrData"를 활용할 수 있다. 함께 넘겨야하는 파라미터들도 확인할 수 있다.

 

 

 

 

이제 코드로 넘어간다.

지난 시간의 코드와 중복되는 코드는 생략하여 "def" 부분만 표기한다.

from PyQt5.QAxContainer import *
from PyQt5.QtCore import *
from config.errorCode import *

class Kiwoom(QAxWidget):
    def __init__(self):
        super().__init__()

        ### event loop 모음 ###############################
        self.login_event_loop = None
        self.detail_account_info_event_loop = None
        self.detail_account_info_event_loop_2 = None
        ##################################################

        ### 변수 모음 #####################################
        self.account_num = None
        self.account_pw = "********"
        ##################################################

        self.detail_account_info()
        self.detail_account_mystock()

    def get_ocx_instance(self):
    def event_slots(self):
        self.OnReceiveTrData.connect(self.trdata_slot) # 예수금 받기 이벤트 생성
    def signal_login_commConnect(self):
    def login_slot(self, errCode):
    def get_account_info(self):

    def detail_account_info(self):
        # 예수금 조회를 위한 Open API 조회 함수 입력값을 설정
        self.dynamicCall("SetInputValue(String, String)", "계좌번호", self.account_num)
        self.dynamicCall("SetInputValue(String, String)", "비밀번호", self.account_pw)
        self.dynamicCall("SetInputValue(String, String)", "비밀번호입력매체구분", "00")
        self.dynamicCall("SetInputValue(String, String)", "조회구분", "2")
        self.dynamicCall("CommRqData(String, String, int, String)", "예수금상세현황요청", "opw00001", "0", "2000")
        self.detail_account_info_event_loop = QEventLoop()
        self.detail_account_info_event_loop.exec_()

    def detail_account_mystock(self, sPrevNext="0"):
        # 계좌평가 잔고내역 요청
        # sPrevNext="0" : 싱글데이터 받아오기(종목합계 데이터)
        self.dynamicCall("SetInputValue(String, String)", "계좌번호", self.account_num)
        self.dynamicCall("SetInputValue(String, String)", "비밀번호", self.account_pw)
        self.dynamicCall("SetInputValue(String, String)", "비밀번호입력매체구분", "00")
        self.dynamicCall("SetInputValue(String, String)", "조회구분", "2")
        self.dynamicCall("CommRqData(String, String, int, String)", "계좌평가잔고내역요청", "opw00018", sPrevNext, "2000")
        self.detail_account_info_event_loop_2 = QEventLoop()
        self.detail_account_info_event_loop.exec_()

    def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):
        # TR SLOT 만들기
        '''
        TR 요청을 받는 구역, slot임
        :param sScrNo: 스크린 번호
        :param sRQName: 내가 요청했을 때 지은 이름
        :param sTrCode: 요청 ID, TR코드
        :param sRecordName: 사용안함
        :param sPrevNext: 다음 페이지가 있는지
        :return:
        '''

        # 예수금 등 조회 하기
        if sRQName == "예수금상세현황요청":
            deposit = self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "예수금")
            print("예수금 %s" % int(deposit))

            ok_deposit = self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "출금가능금액")
            print("출금가능금액 %s" % int(ok_deposit))

            self.detail_account_info_event_loop.exit()

        # 계좌평가잔고 조회 하기
        if sRQName == "계좌평가잔고내역요청":
            total_buy_money = self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "총매입금액")
            print("총매입금액 %s" % int(total_buy_money))

            total_profit_loss_rate = self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "총수익률(%)")
            print("총수익률 %s" % float(total_profit_loss_rate))

            self.detail_account_info_event_loop_2.exit()

 

 

 

 

조회 요청을 한 뒤, 응답이 오기 전에 다음 라인의 코드가 실행되지 않도록 이벤트 루프를 __init__안에 생성한다.

"self.detail_account_info_event_loop = None"
"self.detail_account_info_event_loop_2 = None"

 

예수금과 계좌잔고 조회를 실행할 수 있도록 __init__안에 마련한다.

"self.detail_account_info()"

"self.detail_account_mystock()"

 

"def event_slots"에 예수금을 받기 위한 이벤트를 만들어 준다(self.OnReceiveTrData.connect(self.trdata_slot)). "OnReceiveTrData"는 위 KOA에서 살펴봤다.

 

 

"def detail_account_info(self):"는 예수금 TR 요청을 위한 공간이다.

SetInputValue로 넘길 값을 형태를 지정해주고 dynamicCall로 데이터를 전송한다. 넘겨야 하는 데이터는 위 KOA에서 예수금 조회할 때 넘긴 것과 동일하다.

 

넘길 데이터를 다 입력했으면, 조회할 데이터는 이벤트 내부에서 OPEN API 조회 함수인 "CommRqData()"를 호출해서 서버로 전송한다. 이때 함께 전송할 자료는 요청이름(각자 네이밍 가능), TR번호, preNext, 화면번호(스크린넘버-하단에 별도 설명)이다.

 

조회 후 결과가 도착하기 전에 다음 코드가 실행되지 않도록 PyQt의 Event Loop를 열어준다.

 

 

"def detail_account_mystock(self, sPrevNext="0"):"는 예수금 조회와 같은 내용이다. 다만, 계좌평가잔고내역을 요청하는 코드이다.

 

 

"def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext):"로 TR 데이터 슬롯을 열어준다. 예수금과 계좌평가잔고 코드를 입력한다. 각 요청한 TR을 받은 뒤 열어둔 Event Loop를 닫아준다.

 

 

코드 실행 결과

 

 

 

 

 

아.... 길다....

 

위에서 넘어간 화면번호(스크린넘버)는 키움 OPEN API가 TR 요청에 의해 데이터를 넘겨주면서 그룹을 지어서 넘겨준다. 그 그룹의 이름을 "화면번호(스크린넘버)"라고 부른다. [1]

 

화면번호(스크린넘버)는 0과 0000을 제외한 4자리 숫자로 구성하여 200개까지 만들 수 있다.

그리고 각 화면번호(스크린넘버)에는 100개의 TR 요청 결과를 담을 수 있다.

 

TR 요청을 중구난방으로 하게 되면, 관리가 안되니 일종의 grouping 기능을 넣어준 것이라 해석된다.

 

예를 들어, 코스피200의 일봉을 요청하는데

화면번호 1000번 : 전자통신 30 종목

화면번호 2000번 : 화학 40 종목

화면번호 3000번 : 바이오 60 종목

화면번호 4000번 : 제조 70개 종목

등으로 그룹을 지어 결과를 저장할 수 있는 방식이다. 

 

화면번호(스크린넘버)는 삭제할 수 있고, 삭제되면 거기에 포함된 TR 요청은 모두 삭제되는 등 관리적 기능도 포함되어 있다.

 

 

 

도움받은 곳

[1] www1.kiwoom.com/nkw.templateFrameSet.do?m=m1408000000

    : 위 고객 문의 게시판에서 "스크린번호"를 검색하면 관련 내용을 찾아볼 수 있다.

 

 

 

파이썬을 학습하며 남기는 블로그입니다.
질문, 지적, 조언은 항상 환영합니다.

 

 

2021.01.05. 코리.

+ Recent posts