PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 자료 요청 구조 구축하기(캡슐화)

  • -

지난 게시글에서 살펴봤듯이, 키움증권 Open API 상에서 데이터를 요청하는 방법에는 SetInputValue와 CommRqData를 사용하는 방법과 dynamicCall("")을 사용하는 방법 두 가지가 있다. 이번 게시글에서는 두 가지 방법 중 전자에 해당하는 방법을 사용하는 방법에 대해 알아볼 예정이다.

본인의 경우 항상 코드를 구축하기 전에 앞서 실질적으로 구현해내고자 하는 형태를 고안한 후에 코드를 제작했다. 그니까, 어떤 버튼을 눌렀을 때 어떤 동작이 수행되도록 처리할 것인지를 생각하고 어떤 데이터들을 받아올 것인지에 대해 고민해본 후에 코드를 제작했다는 것이다. 이 과정에서 반복적으로 사용되어야 할 것 같은 코드라면 잘게 잘게 쪼개서 부분적으로 사용할 수 있도록 하는 캡슐화라는 개념이 등장하게 되는데, 이 캡슐화가 바로 이번 게시글의 핵심이다.

 

 

캡슐화?

지난 게시글에서 살펴봤듯이, 데이터를 요청하고 데이터를 받아오는 코드는 크게   ① SetInputValue → ② CommRqData → ③ Event → ④ connect to definition → ⑤ GetCommData  라는 다섯 개의 절차로 이루어져 있었다. 이는 곧 데이터를 요청하는 모든 코드는 위의 다섯 가지 절차를 거쳐야 한다는 것을 의미하기도 한다. 다시 말해, 우리는 반복되는 코드를 그때그때 호출해서 사용할 수 있도록 구조화를 시켜두어야 한다는 것이다. 그럼, 이제 첫 번째 단계부터 만들어보자.
※ Line : 20~21

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

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()")  ## 로그인 요청


    """데이터 입력 함수"""
    def __setinputvalue(self, item, value):
        self.kiwoom.dynamicCall("SetInputValue(QString, QString)", [item, value])


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = tradesystem()
    myWindow.show()
    app.exec_()

 

지난 게시글에서 살펴봤던 방법 ①과 방법 ②는 서로 다른 방식으로 동작하는 것처럼 보였지만, 사실 dynamicCall("")을 사용한다는 점에서는 한통속이긴 하다. 다만 곧바로 데이터를 전달받는 방식의 dynamicCall("definition")인가 아니면 데이터를 입력하고 전달하는 역할만 수행하는 dynamicCall("definition")인가에 차이점이 있다. 이번 게시글에서 다룰 다섯 단계의 데이터 요청 함수들은 후자에 해당하는 것으로, 각각 데이터 입력(SetInputValue), 데이터 전송(CommRqData), 데이터 발생(Event, 키움증권이 해야 할 일), 데이터 도착(connect to definition), 데이터 획득(GetCommData)의 의미를 가진다.

여기서 SetInputValue 뒤 부분에 (QString)이라 제작되어 있는 부분을 확인할 수 있는데, 이는 단순히 자료형을 나타내는 것이다. 숫자형의 경우에는 Int를, 문자열의 경우에는 QString을 작성하게 된다. 그렇다면 함수별로 요구하는 데이터의 타입은 어디서 확인할 수 있을까? 바로 키움증권에서 제공하는 개발 가이드에서 확인할 수 있다. 

키움증권 개발가이드 내 SetInputValue에 대한 설명 및 사용 예시

원형 부분을 보면 SetInputValue(BSTR sID, BSTR sValue)라고 적혀있는데 여기서 BSTR이 곧 String을 의미하는 것이다. 따라서 우리는 자료형을 설정해주고, 해당 자료형에 값들을 입력해줌으로써 SetInputValue를 사용할 수 있는 것이다.

 

 


728x90

 

 

그렇다면 두 번째 단계인 CommRqData는 어떠한 구조를 갖추고 있는지 한 번 살펴보도록 할 것인데, 아래의 원형을 참고해서 어떠한 형태의 함수를 제작해야 될지 생각해보도록 하자. (참고로 long은 숫자형으로, 파이썬에서는 int에 해당한다.)

 

함수를 제작했다면 아래의 코드와 비교해보도록 하자.
※ Line : 24~25

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

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()")  ## 로그인 요청


    """데이터 입력 구간"""
    def __setinputvalue(self, item, value):
        self.kiwoom.dynamicCall("SetInputValue(QString, QString)", [item, value])

    """데이터 요청 구간"""
    def __commrqdata(self, rqname, trcode, pre, scrno):
        self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", [rqname, trcode, pre, scrno])


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = tradesystem()
    myWindow.show()
    app.exec_()

 

여기까지 데이터를 입력하고 요청하는 절차를 모두 제작했다. 사실 이번 게시글의 목적은 캡슐화라는 개념을 이해하는 것이었는데, 단순하게 말하자면 그냥 하나의 함수를 최대한 간략하게 작성하는 것이 곧 캡슐화라고 이해하면 된다. 그렇다면 다음 게시글에서부터는 캡슐화가 잘 되어 있는 코드를 바탕으로 SetInputValue와 CommRqData에 어떤 데이터를 입력해야 하는지, 그리고 어떤 동작이 이루어져야 데이터가 도착했다는 이벤트가 발생하는지 등에 대해 알아보도록 하자.

 

 


728x90
반응형
Contents

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

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