금융퀀트/(퀀트)증권사API활용(키움)

[키움API]파이썬 주식 종가정보 불러오기2: 개별종목 종가조회

문송한투자자 2023. 11. 30. 07:52
반응형

종목별 종가 입수 함수 확인: KOA 스튜디오 구현 예시

종목별 종가정보 조회는 키움 API로 "주식일봉차트조회요청"을 하면 된다. KOA Studio에서 Open API 접속을 한 뒤에 아래 그림 1의 좌측처럼 표시된 칸에 종목코드와 기준일자 정도를 넣으면 그림 1의 우측처럼 결과를 볼 수 있다. 그림 1의 우측 상단에는 어떤 API 함수를 호출해야 하는지 안내가 되어 있다.

그림1: 주식 종가 입수 KOAStudio

SetInputValue 함수를 통해서( SetInputValue("종목코드" ,  "005930"), SetInputValue("기준일자" ,  "20231129"), SetInputValue("수정주가구분" ,  "")  ) 종목코드, 기준일자, 수정주가구분 설정을 해주고, CommRqData( "RQName" ,  "opt10081" ,  "0" ,  "화면번호")를 통해서 SetInputValue 한 데이터에 대해서 정보를 요청하는 구조이다.

종가입수 함수 구조

KOAStudio 화면을 잘 보면 아래 그림 2의 왼쪽 처럼 주식일봉차트조회요청을 한 화면은 TR 목록에 위치하고 TR번호는 "opt10081"인 것을 알 수 있다. 그리고 키움API개발 가이드에서는 Tr 데이터에서 대해서 OnReceiveTrData라는 이벤트 메서드를 아래 그림 2의 오른쪽처럼 설명해 두고 있다.

그림2: onReceiveTrData

Tr 데이터에 대해서 OnReceiveTrData 메서드를 정의하고 있기 때문에 단순히 CommRqData 를 요청만 해서는 Tr 데이터를 볼 수는 없다. Tr 데이터는 아래 그림 3처럼 데이터를 요청하고 받아서 그것을 다시 처리해서 보는 구조인 것이다.

그림3: Tr 데이터 처리 구조

위 그림 3을 간단히 설명하면 OnReceiveTrData의 Connect 메서드를 통해서 먼저 데이터 수신 상태를 활성화해 놓고, SetInputValue 함수를 통해서 요청 변수를 먼저 세팅한 뒤 CommRqData를 통해서 데이터를 요청하는 구조이다. Connect 메서드를 통해서 데이터를 수신하는 상태라서 데이터를 받아올 수 있지만 받아온 데이터를 처리하는 함수가 있어야 하는데 그것이 GetCommData라는 함수이다. 결론적으로 OnReceiveTrData의 Connect 메서드 안에 콜백 함수로 GetCommData로 구성된 함수를 넣어놓아야 CommRqData를 통해서 데이터를 요청했을 때 데이터 처리가 된다.

개별종목 종가조회

종목에 대한 개별항목 조회

위의 그림 3의 구조에 따라 Tr목록에 있는 데이터를  처리하는 함수들을 아래와 같이 만들 수 있다.

import sys
import pandas as pd
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5 import uic

#UI파일 연결
form_class = uic.loadUiType("C:/Users/admin/Documents/kiwoom_test/mainform.ui")[0]

class KiwoomAPIform(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("KiwoomTest")
        
...(중략)...
    
    def btn_loginFunc(self):
        self.CommConnect()
        def login_callback(err_code):
            result = self.ConnectEvent(err_code)
            self.drawresult(result)
        self.ocx.OnEventConnect.connect(login_callback)

    def btn_datagetFunc(self):
        data = self.GetCodeListByMarket("0")
        stockcodes = data.split(";")
        stockcodes = stockcodes[:-1] if stockcodes[-1] == "" else stockcodes
        # 콜백함수 불러오기
        callback = lambda: self.getstockpriceinfo("opt10081", "주식일봉차트", "종목코드")
        # 정보 입수 상태 켜기
        self.ocx.OnReceiveTrData.connect(callback)
        # 정보요청, stockcodes 목록 중 첫번째 항목만 선택(stockcodes[0], 20231129 데이터 선택
        self.rqstockpriceinfo("주식일봉차트", "opt10081", "주식일봉차트", stockcodes[0], "20231129")

...(중략)...
    # API 요청하는 SetInputValue 와 CommRqData 를 rqstockpriceinfo 하나로 묶어 냄
    def rqstockpriceinfo(self, rqname: str, trcode: str, trname: str, stockcode: str, date: str):
        self.SetInputValue("종목코드", stockcode)
        self.SetInputValue("기준일자", date)
        self.SetInputValue("수정주가구분", "")
        self.CommRqData(rqname, trcode, trname)
    
    # GetCommData 데이터를 불러서 Tr 정보 처리하는 콜백함수 구성
    def getstockpriceinfo(self, trcode: str, trname: str, item: str):
        result = self.GetCommData(trcode, trname, item)
        print(result)
    
    # 키움 API 객채(ocx)에서 API를 직접 갖다 쓰는 함수들

...(중략)...    

    def GetCodeListByMarket(self, mkcode: str):
        return self.ocx.dynamicCall("GetCodeListByMarket(Qstring)", mkcode)

    def SetInputValue(self, valuename: str, value: str):
        self.ocx.dynamicCall("SetInputValue(QString, QString)", valuename, value)
        
    def CommRqData(self, rqname: str, trcode: str, trname: str):
        self.ocx.dynamicCall("CommRqData(QString, QString, int, QString)", rqname, trcode, 0, trname)
        
    def GetCommData(self, trcode: str, trname: str, item: str):
        return self.ocx.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, trname, 0, item)    
    
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = KiwoomAPIform()
    window.show()
    sys.exit(app.exec_())

 

전체항목 조회

[키움API]python 코스피 종목별 종가정보 불러오기1: 종목코드 목록 입수에서 짠 코드에 위의 코드를 잘 붙였다면 기간별 종가 데이터 입수를 눌렀을 때 아래 그림 4와 같이 종목코드 하나가 나올 것이다.

그림4: 종목코드 조회

위 그림 4에서 종목코드만 나오는 이유는 getstockpriceinfo 함수를 콜백 할 때, GetCommData를 불러올 때 item 항목에 "종목코드"를 넣어줬기 때문이다. 아래 그림 5의 KOAStudio 화면을 잘 보면 item항목으로 던져줄 수 있는 항목이 "종목코드", "일자", "현재가", "거래량", "시가", "고가", "저가" 정도인 것을 알 수 있다. 즉 item 항목에 "종목코드", "일자", "현재가" 등을 넣으면 그에 해당하는 값들을 각각 얻을 수 있는 것이다.

그림5: opt10081 의 item 항목 목록

결과적으로 item 항목에 종목코드", "일자", "현재가" 등을 순서대로 넣어주는 함수로 getstockpriceinfo 함수를 아래와 같이 바꿀 수 있다.

    def getstockpriceinfo(self, trcode: str, trname: str):
        # item 항목 빈 리스트 정의
        items = []
        # GetCommData 에 item 으로 넣을 항목들 columns라는 변수에 list 로 정의
        columns = ["종목코드", "일자", "현재가", "거래량", "시가", "고가", "저가"]
        # for 문을 통해서 columns list를 하나씩 column 에 넣어서 GetCommData 결과 받아오기
        for column in columns:
            item = self.GetCommData(trcode, trname, column)
            items.append(item.strip())
        # # item 리스트를 [] 로 한 번 더 감싸서 DataFrame으로 만들 수 있도록 변경
        items = [items]
        data = pd.DataFrame(columns=columns, data=items)
		print(data)

 

함수를 위와 같이 변경하면 아래 그림 6과 같은 데이터프레임을 얻을 수 있다. 

그림6: 개별종목 종가조회

개별종목 종가정보 입수를 위한 코드를 전부 정리하면 아래와 같다.

import sys
import pandas as pd
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5 import uic

#UI파일 연결
form_class = uic.loadUiType("C:/Users/admin/Documents/kiwoom_test/mainform.ui")[0]

class KiwoomAPIform(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("KiwoomTest")
        
...(중략)...
    
    def btn_loginFunc(self):
        self.CommConnect()
        def login_callback(err_code):
            result = self.ConnectEvent(err_code)
            self.drawresult(result)
        self.ocx.OnEventConnect.connect(login_callback)

    def btn_datagetFunc(self):
        data = self.GetCodeListByMarket("0")
        stockcodes = data.split(";")
        stockcodes = stockcodes[:-1] if stockcodes[-1] == "" else stockcodes
        # 콜백함수 불러오기, "종목코드"를 더 이상 변수로 입력할 필요 없음
        callback = lambda: self.getstockpriceinfo("opt10081", "주식일봉차트")
        # 정보 입수 상태 켜기
        self.ocx.OnReceiveTrData.connect(callback)
        # 정보요청, stockcodes 목록 중 첫번째 항목만 선택(stockcodes[0], 20231129 데이터 선택
        self.rqstockpriceinfo("주식일봉차트", "opt10081", "주식일봉차트", stockcodes[0], "20231129")

...(중략)...
    # API 요청하는 SetInputValue 와 CommRqData 를 rqstockpriceinfo 하나로 묶어 냄
    def rqstockpriceinfo(self, rqname: str, trcode: str, trname: str, stockcode: str, date: str):
        self.SetInputValue("종목코드", stockcode)
        self.SetInputValue("기준일자", date)
        self.SetInputValue("수정주가구분", "")
        self.CommRqData(rqname, trcode, trname)
    
    # GetCommData 데이터를 불러서 Tr 정보 처리하는 콜백함수 구성
    def getstockpriceinfo(self, trcode: str, trname: str):
        # item 항목 빈 리스트 정의
        items = []
        # GetCommData 에 item 으로 넣을 항목들 columns라는 변수에 list 로 정의
        columns = ["종목코드", "일자", "현재가", "거래량", "시가", "고가", "저가"]
        # for 문을 통해서 columns list를 하나씩 column 에 넣어서 GetCommData 결과 받아오기
        for column in columns:
            item = self.GetCommData(trcode, trname, column)
            items.append(item.strip())
        # # item 리스트를 [] 로 한 번 더 감싸서 DataFrame으로 만들 수 있도록 변경
        items = [items]
        data = pd.DataFrame(columns=columns, data=items)
        print(data)
    
    # 키움 API 객채(ocx)에서 API를 직접 갖다 쓰는 함수들
    
...(중략)...

    def GetCodeListByMarket(self, mkcode: str):
        return self.ocx.dynamicCall("GetCodeListByMarket(Qstring)", mkcode)

    def SetInputValue(self, valuename: str, value: str):
        self.ocx.dynamicCall("SetInputValue(QString, QString)", valuename, value)
        
    def CommRqData(self, rqname: str, trcode: str, trname: str):
        self.ocx.dynamicCall("CommRqData(QString, QString, int, QString)", rqname, trcode, 0, trname)
        
    def GetCommData(self, trcode: str, trname: str, item: str):
        return self.ocx.dynamicCall("GetCommData(QString, QString, int, QString)", trcode, trname, 0, item)    
    
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = KiwoomAPIform()
    window.show()
    sys.exit(app.exec_())
반응형