04. 키움 open api 로그인 하기

 

이전 글 보러 가기

01_시작

02_기본설정

03_pykiwoom vs. 직접코딩

 

 

하루 사이에 대문이 조금 바뀌었다.

IDE를 vs code에서 pycharm으로 변경했다. vs code가 전반적으로 많은 사람들이 사용하지만, python 사용자들은 pycharm을 더 많이 사용한다는 글을 보았다. 그리고, pycharm이 python 문법을 작성하는게 더 편리했다. 

 

 

키움 open api에 로그인하기 위한 코드는 다음과 같다.

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

 

 

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

필요한 패키지를 import 한다.

"PyQt5.QAxContainer"는 ActiveX를 비롯한 OCX에 대한 관리를 위한 것이고 [1]

"PyQt5.QtCore"는 event loop를 사용하기 위함이고  [2]

세 번째 라인은 에러 메시지를 관리하기 위함이다. 이건 아래에서 다시 설명한다.

 

 

 

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

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

        ### 변수 모음 #####################################
        self.account_num = None
        ##################################################

        self.get_ocx_instance()
        self.event_slots()
        self.signal_login_commConnect()
        self.get_account_info()

    def get_ocx_instance(self):
        self.setControl("KHOPENAPI.KHOpenAPICtrl.1")

    def event_slots(self):
        self.OnEventConnect.connect(self.login_slot)

    def signal_login_commConnect(self):
        self.dynamicCall("CommConnect()")
        self.login_event_loop = QEventLoop()
        self.login_event_loop.exec()

    def login_slot(self, errCode):
        print(errors(errCode))
        self.login_event_loop.exit()

    def get_account_info(self):
        account_list = self.dynamicCall("GetLogininfo(String)", "ACCNO")
        self.account_num = account_list.split(';')[0]
        print("나의 보유 계좌번호 %s" % self.account_num)

 

"get_ocx_instance"는 QAxWidget에 있는 setControl 사용하여, 설치된 경로(레지스트리)를 지정("KHOPENAPI.KHOpenAPICtrl.1")하여야 한다.

 

"event_slots"은 자동로그인 이벤트를 생성하기 위함이다.

 

"signal_login_commConnect"는 네트워크에 데이터를 전송하고(dynamicCall), 자동 로그인하기 위함이다.

 

키움 KOA CommConnect 설명

 

"self.login_event_loop = QEventLoop()" 가 실행되면, 아이디와 비밀번호를 입력하라는 창이 출력된다. 자동 로그인을 하기 위해서는 다음의 조치가 필요하다.

 

 

키움 open api 자동 로그인 설정

 

윈도우 작업표시줄 오른쪽 아래에 빨간색 상자로 표기된 아이콘에 마우스 우클릭하여 자동로그인을 설정한다.

 

처음 로그인을 하거나, 버전 업데이트 등으로 버전 처리가 필요한 경우, 버전처리 알림 창이 뜨는데 다음을 잘 읽어보고 순서대로 해야 성공한다.

1. 알림창을 그대로 둔다. (확인을 눌러 닫지 않는다.)

2. 키움 관련 프로그램을 모두 종료한다.(KOA, OPEN API 등)

3. 알림창을 "확인"을 눌러 닫는다.

4. 코드를 다시 실행한다.

 

키움 open api 버전처리 알림창

 

"login_event_loop.exec()"는 로그인이 완료될 때까지 다음 코드 실행을 막기 위함이다. 로그인하는 과정은 필요한 파일 등을 다운로드하기 위해 시간이 다소 소요되는데, 이 코드 없이는 아직 로그인 준비가 진행 중인 상황에서 다음 코드를 실행해버리는 결과가 나타난다. 

 

 

 

"login_slot"은  로그인 상태를 확인하고, 로그인 완료 시 위에서 생성한 event loop를 종료(login_event_loop.exit())하는 코드이다.

 

가장 위에 있는 import 단계에서 "config.errorCode"를 import 했다.

현재 나의 작업 폴더에 config 폴더를 만들고 그 안에 errorCode.py 파일을 하나 만들어서 다음의 코드를 입력해 두어야 한다.

 

 

def errors(err_code):
    err_dic = {
        0: ("OP_ERR_NONE", "정상처리"),
        -10: ("OP_ERR_FAIL", "실패"),
        -100: ("OP_ERR_LOGIN", "사용자정보교환실패"),
        -101: ("OP_ERR_CONNECT", "서버접속실패"),
        -102: ("OP_ERR_VERSION", "버전처리실패"),
        -103: ("OP_ERR_FIREWALL", "개인방화벽실패"),
        -104: ("OP_ERR_MEMORY", "메모리보호실패"),
        -105: ("OP_ERR_INPUT", "함수입력값오류"),
        -106: ("OP_ERR_SOCKET_CLOSED", "통신연결종료"),
        -200: ("OP_ERR_SISE_OVERFLOW", "시세조회과부하"),
        -201: ("OP_ERR_RQ_STRUCT_FAIL", "전문작성초기화실패"),
        -202: ("OP_ERR_RQ_STRING_FAIL", "전문작성입력값오류"),
        -203: ("OP_ERR_NO_DATA", "데이터없음"),
        -204: ("OP_ERR_OVER_MAX_DATA", "조회가능한종목수초과"),
        -205: ("OP_ERR_DATA_RCV_FAIL", "데이터수신실패"),
        -206: ("OP_ERR_OVER_MAX_FID", "조회가능한FID수초과"),
        -207: ("OP_ERR_REAL_CANCEL", "실시간해제오류"),
        -300: ("OP_ERR_ORD_WRONG_INPUT", "입력값오류"),
        -301: ("OP_ERR_ORD_WRONG_ACCTNO", "계좌비밀번호없음"),
        -302: ("OP_ERR_OTHER_ACC_USE", "타인계좌사용오류"),
        -303: ("OP_ERR_MIS_2BILL_EXC", "주문가격이20억원을초과"),
        -304: ("OP_ERR_MIS_5BILL_EXC", "주문가격이50억원을초과"),
        -305: ("OP_ERR_MIS_1PER_EXC", "주문수량이총발행주수의1%초과오류"),
        -306: ("OP_ERR_MIS_3PER_EXC", "주문수량은총발행주수의3%초과오류"),
        -307: ("OP_ERR_SEND_FAIL", "주문전송실패"),
        -308: ("OP_ERR_ORD_OVERFLOW", "주문전송과부하"),
        -309: ("OP_ERR_MIS_300CNT_EXC", "주문수량300계약초과"),
        -310: ("OP_ERR_MIS_500CNT_EXC", "주문수량500계약초과"),
        -340: ("OP_ERR_ORD_WRONG_ACCTINFO", "계좌정보없음"),
        -500: ("OP_ERR_ORD_SYMCODE_EMPTY", "종목코드없음")
        }

    result = err_dic[err_code]

    return result

 

위 코드에서는 로그인을 포함한 모든 오류 코드를 담아 두고, 필요시 가져다 쓰고자 함이다.

 

자동로그인에서 정상적으로 로그인이 되면, "print(errors(errCode))"에 의해 다음과 같은 출력물이 나타난다. 

"('OP_ERR_NONE', '정상처리')"

 

오류코드는 KOA에서 확인할 수 있다.

KOA OPEN API 오류코드

 

 

"get_account_info"는 로그인이 되었으니, 사용자 정보를 가져오기 위한 부분이다.

"dynamicCall("GetLogininfo(String)", "ACCNO")" 코드로 사용자 정보를 호출한다.

 

이렇게 호출된 계좌번호는 "8154749111;" 와 같이 끝에 세미콜론이 붙어있다. 아마 아이디가 2개 이상인 경우 구분하기 위한 목적으로 보인다. 

 

"account_list.split(';')[0]"으로 콜론을 지워주고, 첫 번째 값을 가져와서 사용한다.

 

 

 

이제 키움 OPEN API에 로그인하고, 계좌정보까지 가지고 왔다.

 

 

 

도움받은 감사한 글들

[1] docs.huihoo.com/pyqt/PyQt5/QAxContainer.html

[2] docs.huihoo.com/pyqt/PyQt5/QtCore.html

 

 

 

2020.01.04. 코리.

 

+ Recent posts