[키움API]파이썬 주식 종가정보 불러오기2: 개별종목 종가조회
종목별 종가 입수 함수 확인: KOA 스튜디오 구현 예시
종목별 종가정보 조회는 키움 API로 "주식일봉차트조회요청"을 하면 된다. KOA Studio에서 Open API 접속을 한 뒤에 아래 그림 1의 좌측처럼 표시된 칸에 종목코드와 기준일자 정도를 넣으면 그림 1의 우측처럼 결과를 볼 수 있다. 그림 1의 우측 상단에는 어떤 API 함수를 호출해야 하는지 안내가 되어 있다.
SetInputValue 함수를 통해서( SetInputValue("종목코드" , "005930"), SetInputValue("기준일자" , "20231129"), SetInputValue("수정주가구분" , "") ) 종목코드, 기준일자, 수정주가구분 설정을 해주고, CommRqData( "RQName" , "opt10081" , "0" , "화면번호")를 통해서 SetInputValue 한 데이터에 대해서 정보를 요청하는 구조이다.
종가입수 함수 구조
KOAStudio 화면을 잘 보면 아래 그림 2의 왼쪽 처럼 주식일봉차트조회요청을 한 화면은 TR 목록에 위치하고 TR번호는 "opt10081"인 것을 알 수 있다. 그리고 키움API개발 가이드에서는 Tr 데이터에서 대해서 OnReceiveTrData라는 이벤트 메서드를 아래 그림 2의 오른쪽처럼 설명해 두고 있다.
Tr 데이터에 대해서 OnReceiveTrData 메서드를 정의하고 있기 때문에 단순히 CommRqData 를 요청만 해서는 Tr 데이터를 볼 수는 없다. Tr 데이터는 아래 그림 3처럼 데이터를 요청하고 받아서 그것을 다시 처리해서 보는 구조인 것이다.
위 그림 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에서 종목코드만 나오는 이유는 getstockpriceinfo 함수를 콜백 할 때, GetCommData를 불러올 때 item 항목에 "종목코드"를 넣어줬기 때문이다. 아래 그림 5의 KOAStudio 화면을 잘 보면 item항목으로 던져줄 수 있는 항목이 "종목코드", "일자", "현재가", "거래량", "시가", "고가", "저가" 정도인 것을 알 수 있다. 즉 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과 같은 데이터프레임을 얻을 수 있다.
개별종목 종가정보 입수를 위한 코드를 전부 정리하면 아래와 같다.
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_())