PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 실시간 데이터 얻기 (4) - OnReceiveRealData

  • -

지난 게시글에서 실시간 데이터를 추가하고   self.setrealreg  변수를 활용해서 실시간 등록 종목을 관리하는 방법까지 모두 구현했다. 하지만 아직은 실시간으로 등록한 종목들의 실시간 데이터를 얻어올 수 없다. 그 이유는 단순하게도, 실시간 데이터를 얻어오는   OnReceiveRealData  이벤트를 처리해주지 않았기 때문이다. 예전에 차트 데이터를 조회할 때 데이터를 입력하고 요청한 후 서버로부터 데이터를 얻기 위해   OnReceiveTrData  라는 이벤트를 처리해줬는데, 기억할지 모르겠지만 아무튼 했었다. 그리고 키움증권 Open API는 총 8개의 이벤트를 제공하고 있으며, 모든 이벤트를 처리해줘야 하는 것은 아니고 필요한 이벤트만 적재적소에 구현해서 사용하면 된다.

 

 

OnReceiveRealData 이벤트 구현하기

이벤트를 구현하는 건 단순하게, 이벤트가 발생했을 때 connect 메서드를 활용해서 특정 함수로 연결해주면 된다.
※ Line : 21

class tradesystem(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)  ## GUI 켜기
        self.setWindowTitle("주식 프로그램")  ## 프로그램 화면 이름 설정

        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")  ## OpenAPI 시작
        self.kiwoom.dynamicCall("CommConnect()")  ## 로그인 요청

        self.setrealreg = _df.setrealreg()
        print(self.setrealreg)

        """데이터 요청 구간"""
        self.pushButton.clicked.connect(self.request_opt10016)
        self.pushButton_2.clicked.connect(self.request_opt10080)
        self.pushButton_3.clicked.connect(self._pushbtn_3)

        """이벤트 처리 구간"""
        self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)        ## 데이터 조회 요청 처리 함수
        self.kiwoom.OnEventConnect.connect(self.process_login)          ## 로그인 반환값 처리 함수
        self.kiwoom.OnReceiveRealData.connect(self.receive_realdata)    ## 실시간 데이터 수신 처리 함수

 

 

self.receive_realdata 함수 제작하기

개발 가이드 상에서 설명하고 있는 OnReceiveRealData 이벤트는 아래와 같이 세 개의 데이터를 인자로 전달받는다.

이를 바탕으로 def receive_realdata 함수의 인자로 위 세 개(jongmokcode, realtype, realdata) 인자를 추가해주도록 하자.
※ Line : 44~45

class tradesystem(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)  ## GUI 켜기
        self.setWindowTitle("주식 프로그램")  ## 프로그램 화면 이름 설정

        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")  ## OpenAPI 시작
        self.kiwoom.dynamicCall("CommConnect()")  ## 로그인 요청

        self.setrealreg = _df.setrealreg()
        print(self.setrealreg)

        """데이터 요청 구간"""
        self.pushButton.clicked.connect(self.request_opt10016)
        self.pushButton_2.clicked.connect(self.request_opt10080)
        self.pushButton_3.clicked.connect(self._pushbtn_3)

        """이벤트 처리 구간"""
        self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)        ## 데이터 조회 요청 처리 함수
        self.kiwoom.OnEventConnect.connect(self.process_login)          ## 로그인 반환값 처리 함수
        self.kiwoom.OnReceiveRealData.connect(self.receive_realdata)    ## 실시간 데이터 수신 처리 함수

    """자동 매매 구간"""
    def _auto_trade(self):
        while 1:
            now_time = QTime.currentTime().toString('hh:mm:ss')
            print(f"[{now_time}] 정상 동작 중입니다.")
            time.sleep(1)

    """로그인 처리 구간"""
    def process_login(self):
        account_cnt = self.__getlogininfo("ACCOUNT_CNT")
        accno = self.__getlogininfo("ACCNO")
        key_b = self.__getlogininfo("KEY_BSECGB")
        firew = self.__getlogininfo("FIREW_SECGB")

        if account_cnt != "0" and key_b == "0":
            auto_trade = Thread(target=self._auto_trade)
            auto_trade.start()


    """실시간 데이터 수신 구간"""
    def receive_realdata(self, jongmokcode, realtype, realdata):
        pass

    """데이터 수신 구간"""
    def receive_trdata(self, ScrNo, RqName, TrCode, RecordName, PreNext):
        print(f"RQNAME:{RqName}, TRCODE:{TrCode}, RECORDNAME:{RecordName}, PRENEXT:{PreNext}")
        (이하 생략)

 

 

RealType에 따라 데이터 구분하기

개발 가이드 상에서 실시간 FID로 제공하고 있는 RealType은 아래와 같이 상당히 많은 데이터를 전달해주고 있지만, 너무 많은 데이터를 구현하는 것은 둘쨰치고 여기서는 단순하게 주식체결에 대한 데이터만 수신해보도록 할 예정이다. 이 주식체결 데이터가 장중에 주가 변동에 따라 발생하는 데이터이기 때문이다. 물론 추후에는 주식시세가 됐든 잔고 데이터가 됐든 필요한 모든 데이터를 구현하게 될 것이다.

 

일단 주식체결이라는 실시간 데이터를 받아올 것인데, 위의 사진 상에 적혀 있는 모든 이름들은 RealType에 해당하는 이름이다. 다시 말해, def receive_realdata 내에서 realtype을 위의 이름으로 구분한 후에, 데이터를 얻어오면 된다는 것이다.
※ Line : 4~5

    """실시간 데이터 수신 구간"""
    def receive_realdata(self, jongmokcode, realtype, realdata):

        if realtype == "주식체결":
            pass

 

 


728x90

 

 

이제 주식체결 데이터를 얻어와보자

이제 realtype이 "주식체결"인 경우 데이터를 얻어와야 하는데, 실시간 데이터는 여타 다른 데이터를 조회할 때 사용했던 GetCommData 함수와 별다를 것 없는 GetCommRealData 함수를 사용하면 된다. 하지만 데이터별로 다른 FID 번호를 가지고 있어 그걸 기반으로 데이터를 분류해줘야 한다. 이 FID 번호는 우리가 GetCommData를 사용할 때 "거래량", "고가", "시가"라고 입력했던 것과 동일한 역할을 수행한다. 

개발 가이드 상에서 주식체결 설명서를 보면 각 데이터별로 해당하는 FID 번호를 알려주고 있음을 확인할 수 있다. 여기서는 일단 기본적으로 현재가·체결가·실시간종가(FID:10), 누적거래량(FID:13), 누적거래대금(FID:14), 시가(FID:16), 고가(FID:17), 저가(FID:18), 거래회전율(FID:31), 체결강도(FID:228), 장구분(FID:290)에 대해서만 얻어와보도록 하자.

 

 

GetCommRealData 구현하기

개발 가이드 상 내용을 살펴보면   GetCommRealData   함수는 종목코드(strCode)와 피드 번호(Fid)를 전달해주면 반환값으로 수신 데이터를 전달해줌을 확인할 수 있다. 따라서 아래와 같은 코드를 새롭게 추가해주면 된다. 캡슐화는 필수다!

    """실시간 데이터 수신 구간"""
    def __getcommrealdata(self, jongmokcode, fid):
        return self.kiwoom.dynamicCall("GetCommRealData(QString, int)", [jongmokcode, fid])

 

 

실시간 데이터 얻어와보기

이제 앞서 언급했던 현재가·체결가·실시간종가(FID:10), 누적거래량(FID:13), 누적거래대금(FID:14), 시가(FID:16), 고가(FID:17), 저가(FID:18), 거래회전율(FID:31), 체결강도(FID:228), 장구분(FID:290)에 대한 데이터를 얻어오기 위해서는 어떻게 해야 할까? 단순하게   def getcommrealdata  함수에 종목코드와 데이터별로 부여되어 있는 FID 번호를 전달해주면 된다.
※ Line : 5~15

    """실시간 데이터 수신 구간"""
    def receive_realdata(self, jongmokcode, realtype, realdata):

        if realtype == "주식체결":
            now = self.__getcommrealdata(jongmokcode, 10)
            acc_vol = self.__getcommrealdata(jongmokcode, 13)
            acc_tvol = self.__getcommrealdata(jongmokcode, 14)
            open = self.__getcommrealdata(jongmokcode, 16)
            high = self.__getcommrealdata(jongmokcode, 17)
            low = self.__getcommrealdata(jongmokcode, 18)
            turnover = self.__getcommrealdata(jongmokcode, 31)
            strength = self.__getcommrealdata(jongmokcode, 228)
            gubun = self.__getcommrealdata(jongmokcode, 290)

            print(f"[{jongmokcode}] NOW:{now}, HIGH:{high}, LOW:{low}, OPEN:{open}, ACC VOL:{acc_vol}, ACC TVOL:{acc_tvol}, TURNOVER:{turnover}, STRENGTH:{strength}, GUBUN:{gubun}")

 

 


728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.