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

(주식 자동 매매) 키움증권 OpenAPI 현재가 조회(opt10001)

봄이오네 2022. 9. 25. 22:39
반응형

1. 들어가며

이전에는 예수금/주문가능금액 조회(opw00001)을 알아보았다.

이번 시간에는 키움증권 OpenAPI를 통해 삼성전자(005930)의 현재가 조회를 알아본다.


2. 사전 준비

파이썬을 통해 키움증권 OpenAPI에 접근하는 코드를 짜기 전에,

KOA StudioSA에 접속하여,

어떤 정보를 입력하고, 어떤 정보가 출력되는지 확인해 보자.

 

TR목록에서 현재가로 검색하면 opt10001 TR번호(①)로 "현재가(③)"를 찾을 수 있다.

입력(INPUT, ②)은 종목코드(⑤) 1개만 입력하면 된다.

출력(OUTPUT, ③)으로 종목코드와 현재가를 출력할 것이다.

화면 중간의 코드로 쓰이는 함수(④)는 SetInputValue, CommRqData이다.

    * ④의 SetInputValue, CommRqData는 dynamicCall로 호출 신호를 보낸다.

마지막으로 수신받은 내용(⑥)은 종목코도(005930)과 현재가(54,500원)이다.

< 그림1. 코드번호와 현재가를 받아오는&nbsp;KOA StudioSA 화면 >


3. 코드 구현

  • 키움증권 OpenAPI에 접속 후 로그인
  • 삼성전자의 현재가를 키움서버에 요청(opt10001)하고 데이터 수신

 

11줄 : OpenAPI에서 제공하는 OnReceiveTrdata와 trdada_get을 연결

25줄 : rq_data_opt10001 임의의 함수를 구현하되,

          괄호 안에는 43줄에서 입력할 종목코드를 받을 수 있게,

           stock_code로 1개 변수가 들어갈 수 있도록 자리를 만들었음

27줄 : dynamicCall 함수을 통해 SetInputValue함수의 1개 변수(종목코드)를 입력

28줄 : dynamicCall 함수을 통해 CommRqdata함수의 opt10001 TR실행을 요청

29줄 : 데이터 제대로 요청/수신할 때까지, 이벤트 루프 설정

30줄 : 이벤트 루프 실행

 

32번 : 27~28줄에서 입력/요청한 데이터를 받아오는 trdata_get 함수 선언

33줄 : 요청한 내용인 CommRqdata의 "opt_10001"이라면,

34줄 : 종목코드를 stock_code에 넣어

35줄 : 종목의 현재가를 current_price에 넣어달라.

           (주의) OpenAPI를 통해 받아오는 데이터는 문자형(str)이며 인수형(int)으로 변경한다.

                     또한 이전의 봉보다 가격이 낮으면, 현재가에 (-)가 붙는다.

                     양수(+)로 만들어주기 위해, abs(절대값)을 붙인다.

36줄 : 종목코드 출력

37줄 : 종목의 현재가 출력

 

43줄 : 27줄의 stock_code에 삼성전자(005930)의 종목코드를 입력하여,

          27줄의 SetInputValue함수를 실행해 달라


4. 전체코드

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")

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

        print("로그인 요청")
        self.kiwoom.dynamicCall("CommConnect()")
        self.login_event_loop = QEventLoop()
        self.login_event_loop.exec_()

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

    def rq_data_opt10001(self, stock_code):
        print("43줄에서 입력받은 종목코드를 키움서버에 요청합니다.")
        self.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드", stock_code)
        self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", "opt_10001", "opt10001", 0, "0303")
        self.tr_event_loop = QEventLoop()
        self.tr_event_loop.exec_()

    def trdata_get(self, sScrNo, rqname, strcode, sRecordName, sPreNext, nDataLength, sErrorCode, sMessage, sSplmMsg):
        if rqname == "opt_10001":
            stock_code = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10001", "주식기본정보요청", 0, "종목코드").strip()
            current_price = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10001", "주식기본정보요청", 0, "현재가")))
            print(stock_code)  # 결과값 출력하는 곳
            print(current_price)  # 결과값 출력하는 곳

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

    btl.rq_data_opt10001("005930")

    app.exec_()

5. 마치며

현재가를 받는 코드를 설명해 보았다.

45줄의 app.exe_() 때문에 종료가 되지 않기 때문에,

실행했다면, ctrl + f2를 눌러 강제로 종료해 주어야 한다.

 

다음 시간에는 4종목의 현재가를 10초마다 받는 코드를 설명할 예정이다.

첫술에 배부를 수는 없다고 한다.

어떤 코드가 어디에서 어떻게 쓰이는지 관심을 가지는 습관을 갖자.

반응형