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

[키움API]파이썬 주식 종가정보 불러오기1: 종목코드 목록 입수

문송한투자자 2023. 11. 24. 07:06
반응형

종목리스트 입수 함수 확인

이제 아래 그림 1의 "기간별 종가 데이터 입수" 버튼 기능을 만들어보자.(버튼 이름의 뜻이 명확하지 않아서 바꿨다.) 

그림1: 작업대상 버튼

주식 종목의 기간별 종가 데이터 입수 작업은 "주식코드의 입수 및 목록화 -> 기준일자의 주식코드별 종가 데이터 수집 -> 일자를 바꿔가면서 종가 데이터 반복 수집-> DB저장"으로 나눌 수 있다. 먼저 주식코드의 입수 및 목록화부터 진행해 보자. 키움 API 개발 가이드를 보면 아래 그림 2와 같이 GetCodeListByMarket이라는 함수를 써서 주식코드 목록을 받을 수 있다는 것을 확인할 수 있다.

그림2:  GetCodeListByMarket API함수 안

여기에서 함수에 패러미터로 "0"을 넣으면 장내, "3"을 넣으면 ELW, "4"를 넣으면 뮤추얼펀드 등이 나오는 방식이다. 

코스피 종목 리스트 불러오기

아래 코드와 같이 "btn_dataget"이라는 버튼에 btn_datagetFunc 라는 함수를 연결해 주고, btn_datagetFunc 안에서 키움 API로 종목정보 목록을 요청하는 GetCodeListByMarket이라는 구조로 코드를 짜면 된다.

import sys
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5 import uic

#UI파일 연결
form_class = uic.loadUiType("UI 파일의 경로 입력")[0]

# PyQt5의 QMainWindow 클래스와 UI 폼 클래스를 상속받은 사용자 지정 클래스 정의
class KiwoomAPIform(QMainWindow, form_class):
    def __init__(self):
    	# 부모 클래스의 초기화 메서드 호출
        super().__init__()
        # UI 폼을 현재 창에 설정
        self.setupUi(self)
        # 창의 제목 설정
        self.setWindowTitle("KiwoomTest")
        
        # 키움 API Active X 호출
        self.ocx = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        
        # 로그인 버튼 클릭 시 작동 함수 정의(UI 생성시 오브젝트 명이 "btn_login"이어야 함)
        self.btn_login.clicked.connect(self.btn_loginFunc)
        # 데이터 입수 클릭 시 작동 함수 정의(UI 생성시 오브젝트 명이 "btn_dataget"이어야 함)
        self.btn_dataget.clicked.connect(self.btn_datagetFunc)
    
	...(생략)...
    # btn_datagetFunc 함수
    def btn_datagetFunc(self):
    	# 아래 GetCodeListByMarket 함수를 호출해서 API로 종목정보 받아옴(패러미터로 "0")
        data = self.GetCodeListByMarket("0")
        # 입수된 데이터가 있으면 상태창에 Success!!, 아니면 Failed 반환
        if data is not None and len(data) > 0:
            self.drawresult("Success!!")
        else:
            self.drawresult("Failed")
        print(data)
 
    # drawresult 함수
    def drawresult(self, data: object):
    	# 화면에서 "txt_result"라는 오브젝트를 찾은 뒤 txt_result로 객체화
        txt_result = self.findChild(QTextEdit, "txt_result")
        # txt_result에 data를 받아서 data를 set 함
        txt_result.setPlainText(str(data))
	
    ...(생략)...
    
    # GetCodeListByMarket 함수 
    def GetCodeListByMarket(self, mkcode: str):
    	# 키움 API로 종목 정보 입수
        return self.ocx.dynamicCall("GetCodeListByMarket(Qstring)", mkcode)
    
if __name__ == "__main__":
	# PyQt5 어플리케이션 생성
    app = QApplication(sys.argv)
    # KiwoomAPIform 클래스의 인스턴스 생성
    window = KiwoomAPIform()
    # 창을 화면에 표시
    window.show()
    # 어플리케이션 실행 및 이벤트 루프 시작
    sys.exit(app.exec_())

 

위 코드를 실행할 때 주의할 점은 반드시 화면상 로그인 버튼을 통해서 로그인을 한 이후에 데이터를 입수해야 한다는 점이다.( [키움API]python API로그인(Qt Designer 사용) 참조)

입수된 종목 리스트 가공

코드를 실행하면 아래 그림 3과 같은 데이터가 print 된다. API 함수를 통해서 종목정보를 받아오면 종목코드를 ";"로 구분해서 하나의 통문자열로 데이터를 뿌려주는 것이다. 이런 데이터로는 n 번째 종목코드를 뽑아낼 수도 없고, 조작도 힘들어서 입수된 데이터를 적어도 List 형식으로는 바꿔주는 작업이 필요하다.

그림 3: 종목코드 입수 API를 그대로 요청했을 때 결과

기본적인 방법은 종목코드가 세미콜론(;)을 기준으로 나눠져 있기 때문에 split(";") 함수를 써서 세미콜론(;)을 기준으로 list를 만드는 것이다. 주의할 점은 데이터 마지막이 "900140;" 로(세미콜론으로 끝남) 끝나므로 세미콜론을 기준으로 list를 만들 경우 리스트에 빈 항목이 하나 생기기 때문에 "데이터의 마지막이 공란(if data[-1] == "") 이면 데이터를 마지막 직전항까지로 재정의(data[:-1]) 아니면 그대로 data 갖다 쓰는 조건문"을 추가해 준다. 완성된 코드는 아래와 같다.

import sys
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5 import uic

#UI파일 연결
form_class = uic.loadUiType("UI 파일의 경로 입력")[0]

# PyQt5의 QMainWindow 클래스와 UI 폼 클래스를 상속받은 사용자 지정 클래스 정의
class KiwoomAPIform(QMainWindow, form_class):
    def __init__(self):
    	# 부모 클래스의 초기화 메서드 호출
        super().__init__()
        # UI 폼을 현재 창에 설정
        self.setupUi(self)
        # 창의 제목 설정
        self.setWindowTitle("KiwoomTest")
        
        # 키움 API Active X 호출
        self.ocx = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        
        # 로그인 버튼 클릭 시 작동 함수 정의(UI 생성시 오브젝트 명이 "btn_login"이어야 함)
        self.btn_login.clicked.connect(self.btn_loginFunc)
        # 데이터 입수 클릭 시 작동 함수 정의(UI 생성시 오브젝트 명이 "btn_dataget"이어야 함)
        self.btn_dataget.clicked.connect(self.btn_datagetFunc)
    
	...(생략)...
    # btn_datagetFunc 함수
    def btn_datagetFunc(self):
    	# 아래 GetCodeListByMarket 함수를 호출해서 API로 종목정보 받아옴(패러미터로 "0")
        data = self.GetCodeListByMarket("0")
        # 세미콜론을 기준으로 데이터를 List 형식으로 변경
        data = data.split(";")
        # 마지막항이 비어있으면 직전항까지만 List로 사용하도록 data 를 재정의
        data = data[:-1] if data[-1] == "" else data
        # 입수된 데이터가 있으면 상태창에 Success!!, 아니면 Failed 반환
        if data is not None and len(data) > 0:
            self.drawresult("Success!!")
        else:
            self.drawresult("Failed")
        print(data)
 
    # drawresult 함수
    def drawresult(self, data: object):
    	# 화면에서 "txt_result"라는 오브젝트를 찾은 뒤 txt_result로 객체화
        txt_result = self.findChild(QTextEdit, "txt_result")
        # txt_result에 data를 받아서 data를 set 함
        txt_result.setPlainText(str(data))
	
    ...(생략)...
    
    # GetCodeListByMarket 함수 
    def GetCodeListByMarket(self, mkcode: str):
    	# 키움 API로 종목 정보 입수
        return self.ocx.dynamicCall("GetCodeListByMarket(Qstring)", mkcode)
    
if __name__ == "__main__":
	# PyQt5 어플리케이션 생성
    app = QApplication(sys.argv)
    # KiwoomAPIform 클래스의 인스턴스 생성
    window = KiwoomAPIform()
    # 창을 화면에 표시
    window.show()
    # 어플리케이션 실행 및 이벤트 루프 시작
    sys.exit(app.exec_())

 

최종적으로 아래와 같이 결과가 출력되면 정상이다.

그림4: API 요청 결과를 List로 가공한 결

 

반응형