2. 해외선물/2-4. 해외선물 API (사용)

(키움증권 해외선물 OpenAPI-W) 패턴 만들기 (1) 해외선물 종목의 시가, 고가, 저가, 종가 받아오기

봄이오네 2023. 1. 14. 08:09
반응형
목 차
1. 들어가며
2. 사전 설명
3. 코드 설명
4. 전체 코드
5. 마치며

1. 들어가며

지난 글에서는 for문을 활용하여 CME 거래소의 4종목에 대한

현재가를 조회(opt10001)해 보았다.

 * 4종목 : Nasdaq, E&P, 엔화, 브리티시 파운드

 

이번 글부터는 opc10002 (해외선물옵션 분차트조회)를 통해

패턴 만들기를 알아볼 것이다.

 

(1) 1분전의 봉의 시가, 고가, 저가, 종가 받아오기

(2) 부동소수점 문제 회피하기

(3) 1분전 봉의 패턴만들기

 

국내주식과 비트코인에 비해, 부동소수점의 문제가 발생하는데,

위 문제의 회피하는 방법은 다음 글에서 설명할 예정이다.

 

※ 부동소수점의 개념 및 예시

 

더보기

※ 부동소수점
 ① 개념 : 실수(float)로 표현시 소수점의 위치가 고정되지 않는 것을 말한다. @.@
    → 내용이 어렵다. 간단한 사례로 개념만 이해하자.

 ② 우리가 일상으로 계산한 내용과
      파이썬은 소수점 이하의 사칙연산은 서로 다르게 인지한다.
     - (일상적으로 쓰는 경우)  0.25 - 0.21 = 0.04
     - (파이썬에 적용한 경우) 0.25 - 0.21  = 0.04000000000000001

그림1. 부동소수점 에러


 ③ 파이썬에서 부동소수점 에러가 발생한 원인은 중요하지 않다.
     중요한 건, 부동소수점 에러를 회피하는 방법이 중요하다.
       → 다음 글에서 이를 설명한다. 

 

 


2. 사전 설명

WKOA Studio에서 분봉의 1분전 시가, 고가, 저가, 종가(이하 "OHLC")를

받아오는 화면을 확인해보자.

 

그림2. WKOA Studio 에서 분차트를 조회하는 화면

 

① opc10002(해외선물옵션 분차트조회)에서 input / output을 각각 확인할 수 있다.

② 데이터 입력 / 요청하는 함수 설명

③ 종목코드는 나스닥(NQH23), 시간단위는 1분봉이다.

④ 현재시간의 OHLC 이다.

⑤ 1분번의 OHLC 이다. → 필자가 받고 싶은 정보는 ⑤(1분전 봉)이다.


3. 코드 설명

앞에서 설명했던 필요 모듈 및 로그인 내용은 생략한다.

그림3-1. 필요 모듈 현황 및 로그인 관련

 

1줄~6줄 : sys 및 PyQt5 모듈 등 필요 모듈을 임포트 한다.

10줄 : 키움 리지스트리를 self.kiwoom에 인스턴스화 한다. (향후 사용하기 위해 변수화 시킨다)

13줄 : 16줄의 CommConnect 함수와 24줄의 login_Connect 함수를 연결한다.

14줄 : 46줄의 rq_data_opc10002 함수와 54줄의 trdata_get 함수를 연결한다.

17줄 : 31줄의 password_login 함수를 실행한다.

24줄~29줄 : 로그인 관련 함수이다.

 

그림3-2. 패스워드 및 데이터 입력/요청/수신받는 화면

 

31줄~44줄 : 로그인 비밀번호를 입력한다.

47줄~52줄 : SetInputValue 및 CommRqData 함수를 통해

                   OpenAPI-W에 데이터 입력 및 요청한다.

54줄~68줄 : GetCommData 함수를 통해 데이터를 받아온다.

56줄 : for 문을 주목하자.

          for i in range(0, 1) → 현재 시간의 데이터(OHLC) 받기

          for i in range(1, 2) → 1분 전의 데이터(OHLC) 받기

74줄 : 47줄의 rq_data_opc("NQH23", "1")을 실행한다.

데이터를 수신받는다.

 

그림3-3. 데이터를 출력한다.


4. 전체코드

전체코드는 아래와 같다.

 

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

class btl_system():
    def __init__(self):
        self.kiwoom = QAxWidget("KFOPENAPI.KFOpenAPICtrl.1")
        print("로그인 시작!")

        self.kiwoom.OnEventConnect.connect(self.login_Connect)
        self.kiwoom.OnReceiveTrData.connect(self.trdata_get)

        self.kiwoom.dynamicCall("CommConnect(1)")
        self.password_login()
        self.login_event_loop = QEventLoop()
        self.login_event_loop.exec_()

        self.kiwoom.dynamicCall("GetCommonFunc(QString, QString)", "ShowAccountWindow", "")

    ########## 로그인 관련 함수 ##########
    def login_Connect(self, err_code):
        if err_code == 0:
            print('로그인 성공했습니다!')
            self.login_event_loop.exit()
        else:
            print('로그인 실패했습니다!')

    def password_login(self):
        with open(r'C:\Users\User\Desktop\btlg_password.txt') as f:
            lines = f.readlines()
            self.password = lines[0].strip()
            self.cetification_password = lines[1].strip()
            self.deposit_password = lines[2].strip()

        pyautogui.moveTo(1010, 485)  # 비밀번호: Point(x=1010, y=490)
        pyautogui.click()     # 실행 안될 때는 파이참을 "관리자 권한 실행"으로 실행
        time.sleep(1)
        pyautogui.write(self.password, interval=0.1)
        # time.sleep(3)
        # pyautogui.write(self.cetification_password, interval=0.1)  # 실투시 비번 활성화
        pyautogui.press('enter')

    ########## 키움서버에 TR 요청하는 함수 모음 (키움 OPENApi-w에서 제공) ##########
    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", "", "1012")
        self.tr_event_loop = QEventLoop()
        self.tr_event_loop.exec_()

    def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
        if rqname == "opc_10002":
            for i in range(1,2):
                dealed_time = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "체결시간").strip()
                open = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "시가").strip()
                high = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "고가").strip()
                low = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "저가").strip()
                close = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "현재가").strip()

                print(dealed_time)
                print(open)
                print(high)
                print(low)
                print(close)
                self.tr_event_loop.exit()

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

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

    app.exec_()
    
    
# (expected result)
# 20230103203200
# 11131.000000
# 11133.250000
# 11129.750000
# 11131.750000

5. 마치며

나스닥의 1분봉을 알아보았다.

코드 결과에서 확인하였겠지만,

시가, 고가, 저가 종가는 각각 11131.000000, 11133.250000, 11129.750000, 11131.750000 이다.

 

수정해야될 내용이 상당히 많아 보인다.

키움에서 제공하는 데이터를 그대로 출력해 보았는데,

종가는 11131.750000 이다.

(strip 함수를 넣어주었음에도, 불필요하게 소수점 3자리~7자리가 붙어서 출력된다)

 

다음 시간에는 불필요한 소수점 3자리~7자리를 없애는 방법 등

부동소수점 관련 문제를 해결해보자

반응형