2. 해외선물/2-1. 해외선물 자동매매 연구

(키움증권 해외선물 자동매매 파이썬) 8. tr 동작원리

봄이오네 2023. 9. 27. 21:44
반응형
목 차
1. 들어가며
2. 사전설명
   1) tr 개념
   2) 데이터 요청방법
      ① 실시간 데이터 요청
       ② 비실시간 데이터 요청
       ③ 데이터 요청의 2가지 방법 차이점
3. tr 요청방법
   1) WKOAStudio에서 tr 확인 방법
   2) 코드 설명
4. 전체코드
5. 마치며

 

1. 들어가며

지난 글에서는 클래스의 인스턴스 개념 및 방법에 대해 알아보았다. "클래스의 인스턴스"라고 표현하니 생소하다는 느낌이다. 쉽게 생각하자. 클래스의 인스턴스는 "클래스를 변수화"시키는 것이다. 클래스를 변수화시키는 이유는? 클래스 안/밖에서 클래스 내의 함수를 활용하기 위해서이다.

 

이번 글에서는 키움증권 OpenAPI-W를 통해 키움증권에 데이터를 입력/요청/수신하는 tr 동작원리에 대해 알아볼 것이다. tr 동작을 알아야 하는 이유는? 자동매매 시 해외선물의 시가/고가/저가/종가 및 거래량 등을 받아온 후 사용자가 설정한 알고리즘에 진입/청산하기 위해서이다.


2. 사전설명

1) tr 개념

여기서 쓰이는 trtransaction의 약자이다. 인터넷 검색으로 찾아본 transaction의 사전적 의미는 ①거래,매매(=deal), ②처리(과정)을 뜻한다. 조금 추상적이다. "거래 혹은 처리"로 이해를 하면 tr 개념 및 작동원리를 이해하는데 상당한 어려움을 겪을 것이다. 필자는  자동매매시 tr을 trans(상호) + action(작용)으로 이해하고 있다. 즉 tr 개념은 input을 넣어주면 output이 나오는 상호작용으로 이해해 보자.

 

2) 데이터 요청방법

키움증권 서버에 데이터를 요청은 2가지로 나누어진다. 실시간 요청 및 비실시간 요청으로 이루어진다.

 

① 실시간 데이터 요청

실시간 데이터 요청은... 필자가 활용하지 않고 있다. 처음 자동매매 코딩을 접했을 때 "비실시간"으로 공부를 했고, 굳이 "실시간 데이터 요청"의 필요성을 느끼지 못했다. 실시간데이터 요청은 setinputvalue(입력) - commrqdata(요청) - onreceiverealdata(연결) - getcommrealdata(수신)의 4단계로 이루어진다. 더 설명을 하고 싶지만, 실시간 데이터 요청을 사용하지 않는 필자가 길게 설명해도 의미가 없어 보인다. 참고로 키움증권에서는 "실시간 데이터 요청"을 추천하고 있다. ^^;

실시간 데이터요청은 한번 실행하면 계속 데이터를 받아온다.

 

비실시간 데이터 요청

"비실시간 데이터 요청"은 없는 말이다. 키움측에서 "실시간 데이터 요청'을 사용하는데, 데이터 요청방법을 구분하기 위해 필자가 임의로 지칭한 단어이다.

 

비실시간 데이터 요청도 4단계로 이루어진다. 비실시간 데이터 요청도 setinputvalue(입력) - commrqdata(요청) - onreceivedata(연결) - getcommdata(수신)의 4단계로 이루어진다.

 

비실시간 데이터요청은 일정시간마다 반복하면서 데이터를 받아온다.

 

③ 데이터 요청의 2가지 방법 차이점

키움증권에 데이터를 요청하는 2가지 방법의 차이점을 알아보자. 실시간 데이터요청은 ~~real~~이 붙어있고, 비실시간 데이터 요청은 real이 없는 차이이다.

  • setinputvalue(입력) - commrqdata(요청) - onreceiverealdata(연결) - getcommrealdata(수신)
  • setinputvalue(입력) - commrqdata(요청) - onreceivetrdata(연결) - getcommdata(수신)

즉, 두 방법 모두 입력/요청/연결/수신의 4단계로 이루어지는 구조이다. 향후 필자는 비실시간 데이터 요청으로 설명할 예정이다.


3. tr 요청방법

코드를 작성하기 전에 WKOAStuidio에서 데이터 요청/수신받는 형태를 숙지하도록 하자.

 

1) WKOAStudio에서 tr 확인 방법

아래 < 그림1 >은 WKOAStudio에서 tr목록이다. opc10002는 해외선물옵션 분차트조회하는 tr이다. 간단하게 해석해보자.

input으로 2가지(종목코드, 시간단위)를 입력하면, output으로 7가지(현재가, 거래량, 체결시간, 시가, 고가, 저가, 영업일자)를 받아온다. (비실시간 데이터 요청으로 설명)

 

그림1. WKOAStudio에서 tr목록을 통해 받아온 데이터 내역

 

 

< 그림1 >을 자세히 확인하자. WKOAStudio에서 자료를 받아오는 방법은 ①tr목록을 먼저 확인하고, ②종목코드/시간단위를 입력/조회하면, 화면중앙 ③에 데이터가 출력된다.

 

위의 문장을 이해해보자.

  • ②종목코드/시간단위를 입력 : "종목코드"와 "시간단위(1분)"을 입력(SetInputValue)한다.
  • ②종목코드/시간단위를 조회 : 를 통해 "입력된 데이터(종목코드,시간단위)를 키움서버에 요청(CommRqData)
  • 입력/요청되면 키움서버에서 이벤트 발생(자극-반응) 연결(OnReceiveTrData)
  • ③데이터 출력 : 입력/요청되어 키움서버에 이벤트(자극)가 발생하여 연결되어 데이터를 수신받는다.(GetCommData)

 

2) 코드 설명

WKOAStudio에서는 사용자가 원하는 데이터 요청하는 방법 및 받아온 데이터의 내용/형태 등을 확인했다면, < 그림2 >는 WKOAStudio의 데이터 요청/수신받는 방법을 코드로 작성한 내용이다.

 ※ 참고로 아래 < 그림2 >의 코드를 실행되지 않는다. 간략하게 설명하기 위해, "로그인" 부분은 삭제를 했다. 로그인이 되었다는 가정하에 1분봉의 시가/종가를 받아오는 코드이다.

 

그림2. OpenAPI-W를 통해 키움서버에서 나스닥 1분봉의 시가/종가를 받아오는 코드

 

1줄 ~4줄 : 활용할 라이브러리 4가지이다. 라이브러리에 대한 설명은 생략한다.

6줄 : 임의의 클래스(btl_system)를 선언한다.

7줄 : 코드가 실행되면 처음으로 실행되는 함수(__init__)를 선언한다.

8줄 : 키움증권 OpenAPI-W의 레지스터리를 self.kiwoom에 넣어서 변수화시킨다.

9줄 : 이 글의 첫번째 핵심이다. 9줄은  키움측에서 제공하는 OnReceiveTrData(연결)을 실행한다.

여기서는 9줄의 의미를 잘 이해해야 한다. 29줄의 함수를 실행하면, 12줄의 함수(def rq_data_ope10002)가 실행되면서 데이터를 키움증권에 요청(CommRqData)한다. 데이터 요청에 따른 반응(이벤트)이 일어나고, 데이터를 사용자에게 제공하고자 한다. 반응(이벤트) 후 데이터 제공(20줄)을 연결해 주는 것이 OnReceiveTrData이다.

 

12줄 : 1분봉을 입력/요청하기 위해 임의의 함수(def rq_data_opc10002)를 선언한다.

13줄~14줄 : SetInputValue 함수는 키움증권에 데이터를 입력한다. 여기에서는 "종목코드"와 "시간단위"를 입력한다. 29줄의 실행에서 "NQZ23, 1분"을 입력한다.

15줄 : 13~14줄의 데이터(NQZ23, 1분)를 키움증권 서버에 요청(CommRqData)한다.

16줄 : 데이터를 받아오기 전까지 다음코드가 진행되는 것을 방지하기 위해 self.tr_event_loop = QEventLoop()를 선언한다.

17줄 : 16줄(다음코드 진행 방지)을 실행한다.

 

20줄 : 데이터를 수신받기 위해 임의의 함수(trdata_get)을 선언한다.

21줄 : 이글의 두번째 핵심이다. 9줄의 OnReceiveTrData.connect를 통해 15줄(CommRqData)와 20줄(trdata_get)을 연결하였다. 즉 15줄에서 데이터를 요청하면 9줄의 연결을 통해 20줄을 통해 1분봉의 시가/종가를 수신받을 수 있는 것이다.

만약 15줄에서 요청한 데이터(rqname)가 "opc_10002"라면,

22줄~23줄 : 1분봉의 시가/종가를 받아오라(GetCommData)는 뜻이다.

24줄 : 데이터를 다 받아오면 17줄(QEventLoop, 다음코드 진행방지)를 종료(exit)시킨다.

 

26줄 : 26줄부터 그 아래의 내용을 실행하라.

27줄 : app을 정의한다.

28줄 : 6줄의 클라스를 btl에 변수화 시킨다.

30줄 : 28줄에서 인스턴스한 내용이다. 인스턴스의 필요성을 여기서 느낄 수 있을 것(클라스의 안과 밖에서 실행)이다. 30줄은 "NQZ23 및 1"을 입력하여 12줄을 실행시켜라는 의미이다.

32줄 : 27줄에서 정의한 app이 종료되지 않고, 실행되게 하라는 의미이다.


4. 전체코드

전체 코드는 아래와 같다.

 

더보기
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class btl_system():
    def __init__(self):
        self.kiwoom = QAxWidget("KFOPENAPI.KFOpenAPICtrl.1")
        self.kiwoom.OnReceiveTrData.connect(self.trdata_get)

    ########## 키움서버에 TR 요청하는 함수 모음 ##########
    def rq_data_opc10002(self, stock_code_num, time_unit):  # 분봉 이미지 만들기
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "종목코드", stock_code_num)
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "시간단위", time_unit)
        self.kiwoom.dynamicCall("CommRqData(QString, QString, QString, QString)", "opc_10002", "opc10002", "", "1002")
        self.tr_event_loop = QEventLoop()
        self.tr_event_loop.exec_()

    ########## OnReceiveTrData을 통해 수신받은 데이터 함수  ##########
    def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
        if rqname == "opc_10002":
            self.open_price_one_ago = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", 1, "시가").strip()))
            self.close_price_one_ago = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", 1, "현재가").strip()))
            self.tr_event_loop.exit()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    btl = btl_system()

    btl.rq_data_opc10002("NQZ23","1")

    app.exec_()

5. 마치며

키움증권의 자동매매를 위해 tr목록을 활용하는 방법을 알아보았다. 길게 쓰다보니, 내용이 길어진 것 같다. 그래도 한번 알때 제대로 알면, 향후 필자가 설명할 내용은 쉽게 이해할 수 있을 것이다.

 

키움증권 OpenAPI-W를 활용하여 데이터를 요청/입력/수신 받기위한 핵심은 OnReceiveTrData를 이해하는 것에서 시작된다. 키움서버에 데이터를 요청했는데, 어떻게 수신받는지 유심하게 생각을 해보아야 한다. 데이터 입력(SetInputValue) - 데이터 요청(CommRqData) - 연결(OnReceiveTrData) - 데이터 수신(GetCommData)의 4단계 구조를 머리 속에 넣어두자!

 

이 글도 1분봉 받기의 내용인데, OnReceiveTrData(연결)에 대한 내용을 주로 다루었다. 다음 글에서는 중복될 만한 내용은 최소화하고 opc10002의 tr을 통해 1분봉 받는 코드 설명에 집중할 것이다.

 

반응형