키움증권 API 를 통해 주가 가져오기

  • 관련 카테고리 : Python, 스터디LAB

  • 안녕하세요 라이프온룸 입니다. ㅎㅎ 할로할로 

    오늘은 저번 시간에 이어서 키움증권 API를 이용해 주가를 한번 가져와 보겠습니다. 일단 설명을 위해 기존 프로젝트에서 빼서 간단하게 만들었어요 .. ㅎㅎ 

    일단 이번에 간단히 만든 코드는 삼성전자의 2019/05/16 일 부터 600 거래일 전날의 주가데이터 가져오는 코드입니다. 

    결과는 아래와 같이 출력되요 !!

     

    자 그럼 어떻게 이런 결과가 나오게 되었는지 과정을 한번 보러 가실까요 ~! ㅎㅎ 

     

    1. 키움증권 OpenAPI 시스템 구성

    네 이렇게 되있습니다. 

    주가를 받아오는 루틴을 기반으로 설명을 해볼게요 ㅎㅎ 사실 다른 기능들도 거의 비슷합니다. 

    1. 먼저 OnReceiveTrData 함수를 이용해 이벤트를 등록합니다. 이 함수는 Callback 함수를 인자로 받는데 이부분은 일단 쪼금 아래에서 설명할게요 
    2. CommRqData 에 일봉차트조회 라는 TR과 관련정보를 넣어서 호출합니다. 
    3. OCX가 요청을 처리해서 키움증권 서버로 Python 프로그램이 요청한 데이터를 요청합니다. 
    4. 그럼 키움증권이 주가 데이터를 주겠죠 기준일 전으로 600개 를 주더라구요
    5. 받은 데이터는 OCX 가 보관하고 Python 프로그램에게 데이터 받았어 ~ 라고 알려줍니다.  
    6. GetCommData 함수로 OCX에 보관 중인 데이터를 내놔라고 요청합니다.
    7. GetCommData 함수 인자로 요청했던 TR 및 Request Name을 줌으로써 OCX는 어떤 데이터를 내노라는 건지 알 수 있습니다. 그리고 요청한 데이터를 보내 줍니다. 

    넵 그럼 1번 과정부터 7번 과정을 코드로 표현 하면 되겠죠 !!! 한번 들어가보죠 

    마동석 와라 표정 인상 무서운 마요미 드루와 일루와 맞자 맞고시작 쳐맞는

    2. 코드잉

    1. OnReceiveTrData 

    저번 시간에 만들었던 로그인 소스를 사용하겠습니다.  원 소스는 아래 URL 에서 가져 왔습니다. 

    https://wikidocs.net/4240

    class 의 __init__ 함수를 아래와 같이 만들어 줍니다. 아래 보면 OnReceiveTrData.connect 에서 Callback 함수인 receive_trade 데이터를 받고 있습니다. 

    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyStock")
        self.setGeometry(300, 300, 300, 500)
    
        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
        self.kiwoom.CommConnect()
    
    
        self.kiwoom.OnEventConnect.connect(self.event_connect)
        # Tran 수신시 이벤트
        self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)
    
        # TextEdit 생성
        self.text_edit = QTextEdit(self)
        self.text_edit.setGeometry(0, 0, 200, 200)
        self.text_edit.setEnabled(False)
    
        # 버튼 생성
        btn1 = QPushButton("조회", self)
        btn1.setGeometry(0, 202, 200, 60)
        btn1.clicked.connect(self.btn1_clicked)

     

    버튼을 하나 생성했는데 누르게 되면 btn1_clicked 함수가 호출됩니다. 이 함수에서 2번 과정을 해줄거에요 !

    2. CommRqData 

    위 함수 바로 아래에 다음 내용을 추가해 주세요 

    def btn1_clicked(self):
        self.callStockPrice()
    
    def callStockPrice(self):
        # 파라미터 세팅
        self.kiwoom.SetInputValue("종목코드", "005930")
        self.kiwoom.SetInputValue("기준일자", "20190516")
        self.kiwoom.SetInputValue("수정주가구분", "0")
        # sRQName, sTrCode, nPrevNext, sScreenNo
        res = self.kiwoom.CommRqData("opt10081_주가조회", "opt10081", 0, "10081")
        if res == 0:
            print('주가 요청 성공!!!!!!' + str(res))
        else:
            print('주가 요청 실패 !!!!!!' + str(res))

    여기서 CommRqData 메서드가 나오죠 이 메서드의 Input 은 (리퀘스트이름, TR 코드,  조회/연속, 스크린번호) 입니다. 어떻게 알았냐구요 ? 아래 스펙에서요 ㅋㅋ

    CommRqData 를 검색하면 아래처럼 나올 거에요 참고로 sRQName는 마음것 정하시되 추후 6 번과정을 할 때 식별자로 쓰인다는 것을 알고 가셔야 합니다. (sScreenNo 는 HTS 의 Screen 번호인것 같은데 아무렇게나 해도 동작하는데 지장은 없는것 같아요!)

    sTrCode 코드는 CommRqData 메소드를 통해 조회할 수 있는 키움증권이 제공하는 데이터입니다. 정말 다양한 데이터가 있는데요 ! 이는 KOA 스튜디오를 통해 확인 할 수 있어요 ! 또한 TR 코드별 입력으로 줘야할 인자도 확인할 수 있습니다. 이 입력 인자는 SetInputValue 라는 메소드로 줄 수 있어요 ! 주식일봉차트조회의 경우에는 아래 세가지를 주내요 

    • 종목코드
    • 기준일자
    • 수정주가구분

    3, 4. 키움증권 서버에 데이터 요청 

    은 OCX 가 잘 알아서 하니깐 ㅋㅋ 패스하도록 하겠습니다. 우리 프로그램이랑은 상관 없는 프로세스 이기도 하구여 ㅎㅎ 

    5, 6, 7. Callback 호출 -> 데이터 가져오기 -> 출력하기 

    귀찮아서가 아니라 receive_trdata 에서 5,6,7 번을 모두 하기 때문에…. 

    여튼 이벤트가 드루왔습니다. 그럼 1번 과정에서 입력했던 Callback 함수가 호출 되겠죠 ? 아래 코드를 입력해 주세요 

    # CallBack 함수
    def receive_trdata(self, sScrNo, sRQName, sTrCode, sRecordName, sPreNext, nDataLength, sErrorCode, sMessage, sSplmMsg):
    
        if sRQName == "opt10081_주가조회":
            dataCount = self.kiwoom.GetRepeatCnt(sTrCode, sRQName)
            print('총 데이터 수 : ', dataCount)
            code = self.kiwoom.GetCommData(sTrCode, sRQName, 0, "종목코드")
            print("종목코드: " + code)
            print("------------------------------")
            # 가장최근에서 10 거래일 전까지 데이터 조회
            for dataIdx in range(0, 10):
                inputVal = ["일자", "거래량", "시가", "고가", "저가", "현재가"]
                outputVal = ['', '', '', '', '', '']
                for idx, j in enumerate(inputVal):
                    outputVal[idx] = self.kiwoom.GetCommData(sTrCode, sRQName, dataIdx, j)
    
                for idx, output in enumerate(outputVal):
                    print(inputVal[idx] + output)
                print('----------------')

     

    함수가 호출되면 2번 과정에서 호출했던 sRQName 과 sTrCode가 그대로 들어옵니다. 

    그리고 GetRepeatCnt 라는 뉴페이스 메소드가 등장했어요 스펙을 보니 레코드 반복횟수를 반환 한답니다. 

    네 일봉조회 TR을 호출하면 OCX 가 600개의 일봉 정보를 저장하게 되는데 이 갯수를 GetRepeatCnt 메소드로 얻어 올 수 있습니다. 이 Count 로 for 문을 돌려 전체 일봉 데이터를 얻어 올 수 있구요 !

    그럼 일봉 데이터는 어떻게 얻어오느냐 ! 6번의 과정인데요 GetCommData 메소드를 이용하면 됩니다. 

    여기서 stritemName은 일자, 시가, 고가 등의 그 데이터가 가지는 항목을 의미합니다. 

    그리고 strRecordName 이 나오는데 sRQName을 입력해도 동작합니다. 심지어 CommGetData(이 함수는 동작하지만 지원 안할거라내요 .. ) 에 찾아보면 GetCommData 에  sRQName을 넘기라고 되어있네요 ;;; 

     

    여튼 데이터를 얻어와서 출력하면 됩니다. ! 

     

    3. 전체 코드 

    전체 코드입니다. 

    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QAxContainer import *
    
    COM_CODE = "005930" # 삼성전자
    COM_DATE = "20190516" # 기준일자 600 거래일 전일 부터 현제까지 받아옴
    
    class KiwoomAPIWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("PyStock")
            self.setGeometry(300, 300, 300, 500)
    
            self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
            self.kiwoom.CommConnect()
    
    
            self.kiwoom.OnEventConnect.connect(self.event_connect)
            # Tran 수신시 이벤트
            self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)
    
            # TextEdit 생성
            self.text_edit = QTextEdit(self)
            self.text_edit.setGeometry(0, 0, 200, 200)
            self.text_edit.setEnabled(False)
    
            # 버튼 생성
            btn1 = QPushButton("조회", self)
            btn1.setGeometry(0, 202, 200, 60)
            btn1.clicked.connect(self.btn1_clicked)
    
    
    
        def btn1_clicked(self):
            self.callStockPrice()
    
        def callStockPrice(self):
            # 파라미터 세팅
            self.kiwoom.SetInputValue("종목코드", COM_CODE)
            self.kiwoom.SetInputValue("기준일자", COM_DATE)
            self.kiwoom.SetInputValue("수정주가구분", "0")
            # sRQName, sTrCode, nPrevNext, sScreenNo
            res = self.kiwoom.CommRqData("opt10081_주가조회", "opt10081", 0, "10081")
            if res == 0:
                print('주가 요청 성공!!!!!!' + str(res))
            else:
                print('주가 요청 실패 !!!!!!' + str(res))
    
        # CallBack 함수
        def event_connect(self, nErrCode):
            if nErrCode == 0:
                self.text_edit.append("Login Success")
    
        # CallBack 함수
        def receive_trdata(self, sScrNo, sRQName, sTrCode, sRecordName, sPreNext, nDataLength, sErrorCode, sMessage, sSplmMsg):
    
            if sRQName == "opt10081_주가조회":
                dataCount = self.kiwoom.GetRepeatCnt(sTrCode, sRQName)
                print('총 데이터 수 : ', dataCount)
                code = self.kiwoom.GetCommData(sTrCode, sRQName, 0, "종목코드")
                print("종목코드: " + code)
                print("------------------------------")
                # 가장최근에서 10 거래일 전까지 데이터 조회
                for dataIdx in range(0, 10):
                    inputVal = ["일자", "거래량", "시가", "고가", "저가", "현재가"]
                    outputVal = ['', '', '', '', '', '']
                    for idx, j in enumerate(inputVal):
                        outputVal[idx] = self.kiwoom.GetCommData(sTrCode, sRQName, dataIdx, j)
    
                    for idx, output in enumerate(outputVal):
                        print(inputVal[idx] + output)
                    print('----------------')
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        kaWindow = KiwoomAPIWindow()
        kaWindow.show()
        app.exec_()

     

    네 오늘은 키움증권을 통해서 주가를 받아와 받는데요 !! 다음 포스팅에서는 이제까지 한 내용을 GUI로 좀 이쁘게 만들어 봐야 겠어요 ㅎㅎ 

    여튼 긴글 읽느라 수고 많으셨습돠 다음 시간에 볼게요 제발 ~ 

     

    You may also like...

    댓글 남기기

    이메일은 공개되지 않습니다.