정보

[파이썬] 주식 자동 매매 시스템 구현 #4 - 로그인 정보 가져오기

바다♬~♪ 2022. 3. 21. 17:32

파이썬을 모르는 내가 파이썬을 활용하여 키움 자동 매매 시스템을 구현하는 과정을 정리하고자 한다. 1인칭 시점으로 이해한걸 정리하는 것으로 혹시나 잘못 이해하고 정리된 부분이 있을 수 있다.

 

KOA에서 설명하는 GetLoginInfo 함수는 다음과 같다.

[LONG GetLoginInfo()]
로그인 후 사용할 수 있으며 인자값에 대응하는 정보를 얻을 수 있습니다.
인자는 다음값을 사용할 수 있습니다.
"ACCOUNT_CNT" : 보유계좌 갯수를 반환합니다.
"ACCLIST" 또는 "ACCNO" : 구분자 ';'로 연결된 보유계좌 목록을 반환합니다.
"USER_ID" : 사용자 ID를 반환합니다.
"USER_NAME" : 사용자 이름을 반환합니다.
"GetServerGubun" : 접속서버 구분을 반환합니다.(1 : 모의투자, 나머지 : 실거래서버)
"KEY_BSECGB" : 키보드 보안 해지여부를 반환합니다.(0 : 정상, 1 : 해지)
"FIREW_SECGB" : 방화벽 설정여부를 반환합니다.(0 : 미설정, 1 : 설정, 2 : 해지)
리턴값 인자값에 대응하는 정보를 얻을 수 있습니다.

-------------------------------------------------------------
[보유계좌 목록 예시]
CString strAcctList = GetLoginInfo("ACCLIST"); 여기서 strAcctList는 ';'로 분리한 보유계좌 목록임
예) "3040525910;5678905510;3040526010"
-------------------------------------------------------------

 

앞의 단계까지 잘 작성되었다면 이 부분은 쉽게 진행할 수 있다.

  • 함수 생성 - Login 정보를 반환하는 함수 (get_login_info) 생성 - 얻고자 하는 정보 유형을 받는 파라미터 필요
  • 함수 호출 - Login 정보를 반환하는 함수 호출

 

1. 함수 생성 - Login 정보를 반환하는 함수 생성

파라미터 값 및 결과 값 출력을 위해 print 구문을 2번 넣었다.

    def get_login_info(self, info_type):
        print("info_type: ", info_type)
        return_value = self.dynamicCall("GetLoginInfo(QString)", info_type)
        if info_type == "ACCLIST" or info_type == "ACCNO":
            return_value = return_value.split(';')

        print(return_value)
        return return_value

 

kiwoom.py 전체 코드

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


class Kiwoom(QAxWidget):  # PyQt5 패키지의 QAxContainer 모듈에 있는 QAxWidget 클래스를 상속받아 Kiwoom 클래스 객체를 정의한다.

    def __init__(self):  # Kiwoom 클래스의 생성자 : Kiwoom 클래스 객체가 생성될 때 호출되어 내부 정의된 구문 실행
        super().__init__()  # 상속받은 QAxWidget 객체 초기화
        self.create_kiwoom_instance()  # 키움 인스턴스 생성
        self.comm_login()  # 키움 연결 설정 / 로그인 실행

    def create_kiwoom_instance(self):
        self.setControl("KHOPENAPI.KHOpenAPICtrl.1")  # Kiwoom Open API+를 설치하면서 registry에 등록된 값으로 Kiwoom 인스턴스 생성

    def comm_login(self):
        self.OnEventConnect.connect(self.login_slot)  # OnEventConnect 이벤트와 slot 을 메모리에 적재
        self.dynamicCall("CommConnect()")  # signal 함수 호출 (login)
        self.login_event_loop = QEventLoop()  # login event loop 정의
        self.login_event_loop.exec_()  # login event loop 실행

    def login_slot(self, err_code):  # OnEventConnect 함수의 return 값을 err_code로 받음
        if err_code == 0:
            print("login success")
        else:
            print("login failed")
        self.login_event_loop.exit()  # loging event loop 종료

    def get_login_info(self, info_type):
        return_value = self.dynamicCall("GetLoginInfo(QString)", info_type)
        if info_type == "ACCLIST" or info_type == "ACCNO":
            return_value = return_value.split(';')

        print(info_type, ": ", return_value)
        return return_value

 

2. 함수 호출 - Login 정보를 반환하는 함수 호출

main에 각 타입으로 호출하는 구문을 추가한다.

 

main.py 전체 코드

from api.kiwoom import *
import sys

# app 객체 생성
app = QApplication(sys.argv)
# import 한 Kiwoom class object 생성 (인스턴스화)
kiwoom = Kiwoom()

# kiwoom 객체의 get_login_info 함수 호출
kiwoom.get_login_info("ACCOUNT_CNT")
kiwoom.get_login_info("ACCLIST")
kiwoom.get_login_info("ACCNO")
kiwoom.get_login_info("USER_ID")
kiwoom.get_login_info("USER_NAME")
kiwoom.get_login_info("GetServerGubun")
kiwoom.get_login_info("KEY_BSECGB")
kiwoom.get_login_info("FIREW_SECGB")

# app 객체의 exec_() 함수 실행
app.exec_()

 

출력 결과를 보면 뭔가 이상한 부분을 확인할 수 있다.

계좌 수와 계좌번호 출력 화면

총 계좌 수는 2개로 나오는데 계좌 번호는 배열로 반환하면서 3개를 반환했다. 물론 배열의 마지막은 빈 값 ('') 으로 되어 있어 계좌로 인식할 수 없을 것 같지만 뭔가 이상한 점은 있다. 이건 split 하면서 의미없는 마지막 값이 붙은 것이라고 한다. 이걸 빼는 방법은 배열을 활용할 때 [:-1]을 뒤에 붙여주면 된다.

 

다음 예시에서 ACCNO 를 출력한 결과에는 마지막에 빈 값이 없는것을 확인할 수 있다.

배열의 마지막 빈 값 제거

kiwoom.py 전체 코드 (수정)

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


class Kiwoom(QAxWidget):  # PyQt5 패키지의 QAxContainer 모듈에 있는 QAxWidget 클래스를 상속받아 Kiwoom 클래스 객체를 정의한다.

    def __init__(self):  # Kiwoom 클래스의 생성자 : Kiwoom 클래스 객체가 생성될 때 호출되어 내부 정의된 구문 실행
        super().__init__()  # 상속받은 QAxWidget 객체 초기화
        self.create_kiwoom_instance()  # 키움 인스턴스 생성
        self.comm_login()  # 키움 연결 설정 / 로그인 실행

    def create_kiwoom_instance(self):
        self.setControl("KHOPENAPI.KHOpenAPICtrl.1")  # Kiwoom Open API+를 설치하면서 registry에 등록된 값으로 Kiwoom 인스턴스 생성

    def comm_login(self):
        self.OnEventConnect.connect(self.login_slot)  # OnEventConnect 이벤트와 slot 을 메모리에 적재
        self.dynamicCall("CommConnect()")  # signal 함수 호출 (login)
        self.login_event_loop = QEventLoop()  # login event loop 정의
        self.login_event_loop.exec_()  # login event loop 실행

    def login_slot(self, err_code):  # OnEventConnect 함수의 return 값을 err_code로 받음
        if err_code == 0:
            print("login success")
        else:
            print("login failed")
        self.login_event_loop.exit()  # loging event loop 종료

    def get_login_info(self, info_type):
        return_value = self.dynamicCall("GetLoginInfo(QString)", info_type)
        if info_type == "ACCLIST":
            return_value = return_value.split(';')
        elif info_type == "ACCNO":
            return_value = return_value.split(';')[:-1]

        print(info_type, ": ", return_value)
        return return_value

 

 

계좌 번호, 내 계정, 이름 등등 출력이 되니 뭔가 진행된 느낌이다.

 

 

로그인 버전처리 관련 함수

함수 명 내용
LONG CommConnect() OnReceiveMsg(
  BSTR sScrNo,   // 화면번호
  BSTR sRQName,  // 사용자 구분명
  BSTR sTrCode,  // TR이름
  BSTR sMsg     // 서버에서 전달하는 메시지
)
          
데이터 요청 또는 주문전송 후에 서버가 보낸 메시지를 수신합니다.
  예) "조회가 완료되었습니다"
  예) "계좌번호 입력을 확인해주세요"
  예) "조회할 자료가 없습니다."
  예) "증거금 부족으로 주문이 거부되었습니다."
  
※ 주의할 점 : 
메시지에 포함된 6자리 코드번호는 변경될 수 있으니, 여기에 수신된 코드번호를 특정 용도로 사용하지 마시기 바랍니다.
void CommTerminate() 프로그램 종료없이 서버와의 접속만 단절시키는 함수입니다.
※ 함수 사용 후 사용자의 오해소지가 생기는 이유로 더 이상 사용할 수 없는 함수입니다.
LONG GetConnectState() 서버와 현재 접속 상태를 알려줍니다.
리턴값 1:연결, 0:연결안됨
BSTR GetLoginInfo(BSTR sTag) 로그인 후 사용할 수 있으며 인자값에 대응하는 정보를 얻을 수 있습니다.

인자는 다음값을 사용할 수 있습니다.

"ACCOUNT_CNT" : 보유계좌 갯수를 반환합니다.
"ACCLIST" 또는 "ACCNO" : 구분자 ';'로 연결된 보유계좌 목록을 반환합니다.
"USER_ID" : 사용자 ID를 반환합니다.
"USER_NAME" : 사용자 이름을 반환합니다.
"GetServerGubun" : 접속서버 구분을 반환합니다.(1 : 모의투자, 나머지 : 실거래서버)
"KEY_BSECGB" : 키보드 보안 해지여부를 반환합니다.(0 : 정상, 1 : 해지)
"FIREW_SECGB" : 방화벽 설정여부를 반환합니다.(0 : 미설정, 1 : 설정, 2 : 해지)

리턴값
인자값에 대응하는 정보를 얻을 수 있습니다.
-------------------------------------------------------------------

[보유계좌 목록 예시]

CString   strAcctList = GetLoginInfo("ACCLIST");
여기서 strAcctList는 ';'로 분리한 보유계좌 목록임
예) "3040525910;5678905510;3040526010"
          
-------------------------------------------------------------------
void OnEventConnect(long nErrCode) OnEventConnect(
  long nErrCode   // 로그인 상태를 전달하는데 자세한 내용은 아래 상세내용 참고
)

로그인 처리 이벤트입니다. 성공이면 인자값 nErrCode가 0이며 에러는 다음과 같은 값이 전달됩니다.

nErrCode별 상세내용
  -100 사용자 정보교환 실패
  -101 서버접속 실패
  -102 버전처리 실패
void OnReceiveMsg(BSTR sScrNo, BSTR sRQName, BSTR sTrCode, BSTR sMsg) OnReceiveMsg(
  BSTR sScrNo,   // 화면번호
  BSTR sRQName,  // 사용자 구분명
  BSTR sTrCode,  // TR이름
  BSTR sMsg     // 서버에서 전달하는 메시지
)

데이터 요청 또는 주문전송 후에 서버가 보낸 메시지를 수신합니다.
  예) "조회가 완료되었습니다"
  예) "계좌번호 입력을 확인해주세요"
  예) "조회할 자료가 없습니다."
  예) "증거금 부족으로 주문이 거부되었습니다."

※ 주의할 점 :
메시지에 포함된 6자리 코드번호는 변경될 수 있으니, 여기에 수신된 코드번호를 특정 용도로 사용하지 마시기 바랍니다.

 

2022.03.21 - [정보] - [파이썬] 주식 자동 매매 시스템 구현 #3 - 시스템트레이딩 프로젝트 생성 및 키움증권 로그인

2022.03.16 - [정보] - [파이썬] 주식 자동 매매 시스템 구현 #2 - 키움 증권 API 활용 환경 구성

2022.03.16 - [정보] - [파이썬] 주식 자동 매매 시스템 구현 #1 - 관련 프로그램 설치 (개발 환경 구성)

2022.03.16 - [정보] - [파이썬] 주식 자동 매매 시스템 구현