PYTHON/AUTO TRADE SYSTEM

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

  • -

이전 게시글에서 특정 시간이 되면 자동 매매 함수를 실행하도록 하는 부분까지 구현해두었다. 하지만 아직 그 안에 실행하도록 제작한 함수라고 할 만한 게 마땅히 없기 때문에 자동 매매 시스템이라는 이름이 무색하게 느껴질 정도다. 자동적으로 매매가 이루어지도록 하기 위해서는 무엇이 필요한지에 대해 고찰하고, 필요한 데이터들을 하나씩 생성하면서 프로그램이라는 명색에 알맞게 구색을 갖춰나가는 수밖에 없다.

그 중 가장 첫 번째로 사용할 것이 실시간 등록(  SetRealReg  )이다. 실시간 등록이라는 것은 단순하게 설명하자면, 실시간 등록이 이루어져야만 해당 종목에 대한 주가 데이터를 실시간으로 얻어올 수 있다는 의미이다. 예를 들어, 키움증권 Open API를 이용해서 로그인을 한다는 것만으로 키움증권 서버에서 우리에게 특정 데이터를 전달해주지 않는다. 우리는 반드시   SetRealReg   함수를 통해 "오늘 이 종목에 대한 데이터좀 전달해주세요."라는 의사를 표명해야만 서버에서 그 데이터를 전달해주는 것이다.

 

 

실시간 등록 함수 제작하기 : SetRealReg

[키움증권 개발가이드] 내 SetRealReg

실시간 등록 함수는 단순하게 생각해보면 정말 다양한 지점에서 사용할 것이기 때문에 앞서 제작했던 SetInputValue나 CommRqData와 같이 하나의 캡슐처럼 제작해주도록 하자. 제작하기 전에 앞서, 해당 함수를 사용할 때 필요한 정보는 무엇이 있을까? 바로 종목코드이다. 종목코드 외의 다른 데이터는 고정적으로 사용해도 되지만, 종목코드 변수는 우리가 직접 매번 변경해줘야 하는 데이터이기 때문에 하나의 인자(  item_code  )로 받아와야 한다.

    def __setrealreg(self, item_code):
        pass

 

그 후에는 이제 다른 함수와 마찬가지로   self.kiwoom.dynamicCall("")  을 사용해서 나머지 부분을 제작해주면 된다. 일단은 가장 기본적인 형태를 알아보는 것이 목적이니 만큼, FID값 등의 정보에 대해서는 자세한 설명을 생략하고 일단 제작해보도록 하겠다. 위의 설명상 정보들을 확인해보면 반환값으로 통신결과를 전달한다고 하니,   return  을 사용해서 그 결과값을 얻어오도록 하자.

    def __setrealreg(self, item_code):
        return self.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", ["0101", item_code, '10', '0'])

 

이제 실시간 등록을 위한 함수를 제작했다. 해당 함수를 기반으로 실시간 등록을 하는 방법은 아래처럼, 종목코드를 전달해주면 된다.

self.__setrealreg('005930')

## 이는 def __setrealreg(self, item_code): 함수 내에서 아래와 같이 실행된다.
self.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", ["0101", "005930", '10', '0'])

 

하지만 실시간 등록은 예상외로 위의 기능 외에도 구현해줘야 할 개념들이 좀 많고, 복잡하다. 가장 먼저 파라미터 중   RealType  에 전달받을 수 있는 인자로 0과 1이 있는데, 0은 첫 등록 시에만 입력할 수 있고 두 번째 등록 시에는 1을 전달해줘야 한다. 만약 삼성전자(005930)를 첫 번째로 등록해둔 상태에서, LG전자(066570)를 실시간으로 등록할 때   RealType  의 인자로 0을 전달하게 되면 오류가 발생하게 된다. 그렇다면 어떻게 해야해야 할까? 이제부터 하나씩 해결해보도록 하자. 

 

 


728x90

 

 

파라미터 RealType에 0과 1 중 어떤 값을 전달할지 어떻게 판단할까?

위의 개발가이드 상 설명에 따르면, 최초 실시간 등록 시에는 0을 전달해야 하고 이후의 실시간 등록 시에는 1이라는 값을 전달해줘야 한다. 하지만 여기서 가장 큰 문제는, 키움증권 Open API 상에서 "현재 실시간 등록으로 조회되고 있는 종목의 개수"를 알려주는 기능이 제공되지 않고 있다는 것이다. 그러니, 우리가 알아서 등록되어 있는 종목의 개수를 계속해서 카운트하고 그걸 기반으로 해서 0을 전달할지 1을 전달할지를 판단해야 한다는 것이다. 다시 말해, 우리가 기능을 구현해야 한다.

이제부터 앞서 차트 데이터를 조회할 때 알아봤던 데이터프레임이라는 개념이 본격적으로 활약하게 되는 시점이다. valuable이라는 새로운 폴더를 생성하고, 해당 폴더 내에 _df.py 파일을 생성해주도록 하자. _df.py라는 파일 내에서는 우리가 앞으로 사용할 모든 데이터프레임의 자료형을 사전에 생성해주고 필요할 때마다 해당 함수를 호출해서 사용할 예정이다.

이번 게시글에서는 _df.py 파일 내에서 현재 실시간 등록이 되어 있는 종목의 리스트를 입력받아 보관하고 있는 변수를 생성할 것이다. _df.py 파일 내에서 아래와 같은   setrealreg()  함수를 생성한 후에, 해당 함수를 호출하면 칼럼이 'item_code'하나만 있는 데이터프레임을 생성한 후 해당 변수를 반환하도록 코드를 구축해보자.
※ Line : 1~6

import pandas as pd

def setrealreg():
    data = {'item_code':[]}
    data = pd.DataFrame(data, columns=['item_code'])
    return data

 

이제 다시 main.py 파일로 돌아와서,   def __init__(self):   하단부에서   _df.setrealreg()  을 사용해서   data  라는 변수를 얻어와 해당 데이터프레임 정보를   self.setrealreg   변수에 입력해주도록 하자. 그리고 제대로 불러와졌는지 확인하기 위해 print()문을 통해 self.setrealreg 변수를 출력해보도록 하자.
※ Line : 10, 25~26

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5.QtCore import *
import pandas as pd
import time
import manage_db
from threading import Thread
import valuable._df as _df


form_class = uic.loadUiType("main.ui")[0]


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.kiwoom.OnReceiveTrData.connect(self.receive_trdata)  ## 데이터 조회 요청 처리 함수
        self.kiwoom.OnEventConnect.connect(self.process_login)    ## 로그인 반환값 처리 함수

 

>>>
Empty DataFrame
Columns: [item_code]
Index: []

 

데이터프레임이 비어 있다는 내용과 함께, 우리가 _df.py 파일 내에서 생성했던 데이터프레임 정보가 그대로   self.setrealreg  라는 변수에 입력되었음을 확인할 수 있다. 따라서 우리는 앞으로 self.setrealreg 안에 입력되어 있는 정보가 있다면 RealType의 인자로 1을 전달하고, 입력돼있는 정보가 없다면 RealType의 인자로 0을 전달해주면 만사 OK가 되는 것이다.

그렇다면 이제 def __setrealreg()함수가 실행됐을 때, self.setrealreg()함수 내에 있는 데이터 개수(len() 메서드를 사용한다.)를 확인한 후에 데이터 개수가 0개라면 RealType의 인자로 0을 입력하고, 0개가 아니라면 1을 입력해서 실시간 등록을 해주면 된다. 

    def __setrealreg(self, item_code):
        if len(self.setrealreg['item_code']) == 0:
            return self.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", ["0101", item_code, '10', 0])
        else:
            return self.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", ["0101", item_code, '10', 1])

 

하지만 실시간 등록만 하는데 self.setrealreg 변수 안에 있는 데이터의 개수가 변할 수가 있을까? 매번 실시간 등록만 하고 데이터를 변경해주지 않는다면 위 함수는 평생 RealType의 인자로 0만을 전달하게 될 것이다. 따라서 실시간 등록을 한 이후에는 self.setrealreg 변수에 item_code라는 데이터를 추가해줘야 한다. 이 부분은 다음 게시글에서 구축해보도록 하자.

 

 


728x90
반응형
Contents

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

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