반응형

소스 출처는 위키독스의 파이썬으로 배우는 알고리즘 트레이딩을 보며 학습했습니다.

pyqt를 활용하여 GUI를 만드는 작업까지는 저번 시간에 진행했습니다. 파이썬으로 키움 API 연습을 활용하는 연습을 진행하도록 하겠습니다. 풀 소스는 위키독스에서 제공이 됩니다. 어떻게 학습을 하고 어떻게 소스코드를 이해하는지 잘 살펴 봐주세요.

 

1. Open API+ 로그인

def __init__(self):
    super().__init__()
    self.setWindowTitle("PyStock")
    self.setGeometry(300, 300, 300, 150)

    self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")

    btn1 = QPushButton("Login", self)
    btn1.move(20, 20)
    btn1.clicked.connect(self.btn1_clicked)

    btn2 = QPushButton("Check state", self)
    btn2.move(20, 70)
    btn2.clicked.connect(self.btn2_clicked)

def btn1_clicked(self):
    ret = self.kiwoom.dynamicCall("CommConnect()")

def btn2_clicked(self):
    if self.kiwoom.dynamicCall("GetConnectState()") == 0:
        self.statusBar().showMessage("Not connected")
    else:
        self.statusBar().showMessage("Connected")

GUI를 만드는 작업은 진행을 했으니 API 사용을 집중적으로 보겠습니다.

키움 증권에서 제공하는 키움 클래스를 활용하기 위해서 키움 API를 설치할 때 우리의 컴퓨터에 미리 등록되어 있는 ID를 갖고 옵니다. ID는 레지스트리에 등록이 되어 있으며 다음과 같습니다. -> KHOPENAPI.KHOpenAPICtrl.1

이로써 우리는 키움 클래스를 사용할 수 있습니다. 아래는 2개 버튼을 만들었는데 1)하나는 로그인 그리고 다른 하나는 2)접속 상태를 확인 하는 버튼입니다. 버튼이 눌릴 때 이벤트 clicked라는 이벤트가 발생합니다. 이때 등록해놓은 btn1_clicked / btn2_clicked 함수가 호출이 되는 것입니다. 

키움 API에서 제공되는 함수는 1)Commconnect() 와 2)GetConnectState() 함수입니다. 일반적으로 API를 호출한다고 하면 함수를 그냥 호출하면 되지만 OCX 방식이기 때문에 API 호출 시 dynamiccall을 wrapper로 사용해주셔야 됩니다.

QAxWidget -> self.kiwoom -> dynamiccall

API 호출 할 때 이점을 유의해주세요.

또 하나 눈여 볼 것은 kiwoom은 self라는 키워드가 붙어 있고 btn1, btn2는 그냥 쓰여 있습니다. kiwoom은 다른 메서드에서도 사용이 되기 때문에 self 키워드를 붙여 줍니다.

 

 

2. 로그인 이벤트

def __init__(self):
    super().__init__()
    self.setWindowTitle("PyStock")
    self.setGeometry(300, 300, 300, 150)

    self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
    self.kiwoom.dynamicCall("CommConnect()")

    self.text_edit = QTextEdit(self)
    self.text_edit.setGeometry(10, 60, 280, 80)
    self.text_edit.setEnabled(False)

    self.kiwoom.OnEventConnect.connect(self.event_connect)

def event_connect(self, err_code):
    if err_code == 0:
        self.text_edit.append("로그인 성공")

1번 코드에서는 CommentConnect() 호출을 통해서 로그인을 진행했습니다. CommentConnect() 호출 이후로그인을 하면 OnEventConnect 이벤트가 발생(연결 상태가 변경될 때마다 발생)이 됩니다. 서버로부터 받는 응답입니다. 이벤트가 발생이 되면 등록되어 있는 event_connect() 함수가 호출이 됩니다.

 

3. 주식 기본정보 갖고 오기

단어 정리를 하나하고 가자면 TR은 서버로부터 데이터를 주고받는 작업입니다. 서버와 데이터를 주고받아 보도록 하겠습니다.

    # OpenAPI+ Event
    self.kiwoom.OnEventConnect.connect(self.event_connect)
    self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)

    self.code_edit = QLineEdit(self)
    self.code_edit.setText("039490")

    btn1 = QPushButton("조회", self)
    btn1.clicked.connect(self.btn1_clicked)

    self.text_edit = QTextEdit(self)

def btn1_clicked(self):
    code = self.code_edit.text()
    self.text_edit.append("종목코드: " + code)

    # SetInputValue
    self.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드", code)

    # CommRqData
    self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", "opt10001_req", "opt10001", 0, "0101")

def receive_trdata(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2):
    if rqname == "opt10001_req":
        name = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "종목명")
        volume = self.kiwoom.dynamicCall("CommGetData(QString, QString, QString, int, QString)", trcode, "", rqname, 0, "거래량")

        self.text_edit.append("종목명: " + name.strip())
        self.text_edit.append("거래량: " + volume.strip())

데이터 요청을 하는 API 호출 시 패턴이 있습니다. 패턴은 아래와 같습니다.

 

SetInputValue(값 세팅) -> CommRqData(요청) -> 서버 -> 이벤트 대기 중(OnReceiveTrData) -> CommGetData(수신데이터 갖고 오기)

 

버튼이 눌릴 때 아래 함수가 호출이 됩니다.

-> dynamicCall("SetInputValue(QString, QString)""종목코드", code)

종목코드라는 필드 값과 코드 값이 세팅이 됩니다.

 

-> dynamicCall("CommRqData(QString, QString, int, QString)""opt10001_req""opt10001"0"0101")

TR을 구분하기 위한 문자열을 첫번 째 인자로 입력해줍니다 -> opt10001_req

TR 구분을 위한 값 동일하게 입력해줍니다. -> opt10001

단순 조회 TR 일 때는 -> 0

화면번호 동일하게 입력해줍니다. -> 0101

 

* TR 구분(2번째 인자 - KOA Studio 문서 확인)

 

요청 이후에는 OnReceiveTrData 이벤트가 발생됩니다. 이벤트에 등록된 함수 receive_trdata 함수가 호출이 되고 등록된 함수 인자 값도 키움 문서와 동일해야 됩니다.

이전에 요청했던 opt10001 TR이면 이라면 분기를 한번 해주고 CommGetData() 함수를 통해서 종목명, 거래량을 갖고 옵니다.

종목명, 거래량 이외에도 자본금, 매출액, 영업이익 등 필드가 정말 많습니다.

필요하신 필드  KOA Studio를 열어서 TR목록 탭 -> OUTPUT을 보시면 되겠습니다.

 

4) 계좌 정보 갖고 오기

    btn1.clicked.connect(self.btn1_clicked)

def btn1_clicked(self):
    account_num = self.kiwoom.dynamicCall("GetLoginInfo(QString)", ["ACCNO"])
    self.text_edit.append("계좌번호: " + account_num.rstrip(';'))

GetLoginInfo() 함수를 호출하면 계좌 정보를 갖고 옵니다. 이벤트 호출이 아닌 경우에는 값이 바로 반환이 됩니다. 값을 바로 받아와서 텍스트 창에 보여 줄 수 있습니다. 간단합니다 :)

 

 

 

5) 종목코드, 종목명 갖고 오기

    btn1.clicked.connect(self.btn1_clicked)

def btn1_clicked(self):
    ret = self.kiwoom.dynamicCall("GetCodeListByMarket(QString)", ["0"])
    kospi_code_list = ret.split(';')
    kospi_code_name_list = []

    for x in kospi_code_list:
        name = self.kiwoom.dynamicCall("GetMasterCodeName(QString)", [x])
        kospi_code_name_list.append(x + " : " + name)

    self.listWidget.addItems(kospi_code_name_list)

 

종목코드를오기 위해서 GetCodeListByMarket() 함수를 호출 했습니다.

종목명을 갖고 오기 위해서 GetMasterCodeName() 함수를 호출했습니다.

 

 

호출하는 함수들에 대해서 KOA Studio 내용을 직접 확인하면서 학습을 해주세요.

기본을 다지고 이후에 활용하는 부분은 우리의 몫이니까요.

재료들은 주어져있습니다. 잘 만들고 잘 소화시킬 수 있도록 이해하고 연습하고 코드들을 또 읽고 읽어야겠습니다.

감사합니다.

 

 

* 참고 소스 및 참고

https://wikidocs.net/4239

반응형

+ Recent posts