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

(키움증권 해외선물 OpenAPI-W) 청산을 위해 계좌에서 평가손익 등 받기 (opw30003)

봄이오네 2023. 2. 7. 08:10
반응형
목 차
1. 들어가며
2. 사전설명
1) WKOA Studio에서 opw30003 확인
2) 매도수구분 개념
3. 코드 설명
4. 전체코드
5. 마치며

1. 들어가며

지난 글에서는 진입을 위해 SendOrder 함수를 알아보았다. 해외선물 매매를 위한 SendOrder 활용을 위해서는 총 10가지의 인자가 필요하였다.

이 글에서는 < 그림1 >은 WKOA-Studio에서 안내한 SenOrder 함수의 필요한 10개 인자 및 태형이다.

이 글에서는 SendOrder의 10가지 인수 중 4가지(주문유형, 코드번호, 수량, 가격) 등 opw30003(미체결잔고내역조회)를 통해 받아올 수 있는 보유종목 코드, 매도수구분, 보유/청산 수량, 보유종목의 현재가, 평가손익 등의 데이터를 받아오는 방법에 대해 알아보자.

그림1. WKOA Studio에서 확인 가능한 SendOrder 함수

2. 사전설명

1) WKOA Studio에서 opw30003 확인

먼저 WKOA Studio에서 opw30003 TR의 내용을 확인해보자. 입력은 4가지(계좌번호, 비밀번호, 입력매체, 통화코드)이며, 6가지 데이터(종목코드, 매도수구분, 수량, 청산가능수량, 현재가격, 평가손익)를 받아올 것이다.

현재는 계좌에 보유하고 있는 종목이 없는 관계로 어떤 데이터도 수신되지 않는다.

그림2-1. WKOA Studio에서 확인가능한 opw30003 TR의 입/출력 내역

2) 매도수구분 개념

매도수구분은 < 그림2-2 >에서 확인가능하다. 6가지 유형 중 매매시 신규매도(1번), 신규매수(2번)을 사용한다.
국내주식과는 달리 양방향으로 각각 진입할 수 있는 점을 감안하면, 신규매도(1.신규매도)로 진입(sendorder)하면

그림2-2. WKOA Studio에서 확인 가능한 매도수구분 번호이다.


개념이 약간 어려울 수 있는데,

  • 신규매도(1)로 sendorder 진입했다면, 청산할 때 sendorder 함수의 매도수구분은 2번(매수)으로 청산
  • 신규매수(2)로 sendorder 진입했다면, 청산할 때 sendorder 함수의 매도수구분은 1번(매도)으로 청산

아래 코드의 5번째 줄에서 평가손익이 0보다 크다면, 9번째 줄에서 long으로 진입한 수량을 청산하는 코드이며, sendorder 함수의 4번째 인자는 int형으로 숫자 1을 넣는다.

if self.sell_buy_gubun_d == "2":  # 진입이 매수인 경우
    btl.rq_data_opw30011(self.deposit_num, self.deposit_password, "00", self.stock_code_d, "1", "1", "")  # 청산수량 받아오기 위해 실행, # ~~~ self.stock_code_d, "1" 에서 "1"은 "매도"로 설정한다.
    time.sleep(1)
    print(self.liquidable_qty)

    if self.estimate_opw30003 > 0:
        print(self.estimate_pl_d)
        print(type(self.estimate_pl_d))
            if self.estimate_opw30003 > int(self.profit_scale):
            btl.sendorder_func("long청산", "8987", self.deposit_num, 1, self.stock_code_d, self.liquidable_qty, "0", "0", "1", "")

3. 코드 설명

모듈 설명 및 로그인 정보는 생략한다.

그림3-1. 모듈 설명 및 로그인 정보는 생략한다.


1줄~29줄 : 모듈 설명 및 로그인 정보는 생략한다.
21줄 : 사용자의 계좌번호 10자리 입력이 필요하다.

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


32줄~39줄 : 63줄에서 4개 인자(계좌번호, 모의 계좌비번, 입력매체, 통화코드)를 입력받는다.
41줄~48줄 : 6가지 데이터를 수신받는다. (종목코드, 매도수구분, 보유수량, 청산가능수량, 보유종목 현재가격, 평가손익)

50줄 : 평가손익은 100으로 나누어 주어야 한다.
52줄~57줄 : 6가지 데이터를 출력한다.
63줄 : 32줄의 함수를 실행한다.


4. 전체코드

21번째 줄에 계좌번호 10자리를 입력해주고, 63줄에는 계좌번호, 계좌비밀번호 등을 입력한다.

더보기
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")
        print("로그인 시작!")

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

        self.kiwoom.dynamicCall("CommConnect(1)")  # CommConnect() : 괄호 안에 자동(1)을 넣는다.
        self.login_event_loop = QEventLoop()  # from PyQt5.QtCore import * : qtcore가 임포트되어야 함
        self.login_event_loop.exec_()

        self.kiwoom.dynamicCall("GetCommonFunc(QString, QString)", "ShowAccountWindow", "")  # 계좌번호 입력창을 띄우는 내부함수

        ##### 계좌 번호, 종목코드, 익절/손절 타점 설정 #####
        self.deposit_num = "계좌번호 10자리 입력"

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

    ########## 키움서버에 TR 요청하는 함수 모음 ##########
    def rq_data_opw30003(self, deposit_num1, password_2, password_enter3, currency_code4):  # 실시간 잔고(화면번호 4541), currency_code는 빈칸
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "계좌번호", deposit_num1)
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "비밀번호", password_2)
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "비밀번호입력매체", password_enter3)
        self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "통화코드", currency_code4)
        self.kiwoom.dynamicCall("CommRqData(QString, QString, QString, QString)", "opw_30003", "opw30003", "", "3003")
        self.tr_event_loop = QEventLoop()
        self.tr_event_loop.exec_()

    def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
        if rqname == "opw_30003":  # 계좌 현재가, 매도수구분, 보유수량, 매입단가, 계좌현재가, 평가손익
            futures_code = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30003", "opw30003", 0, "종목코드").strip()
            sell_buy_gubun_opw30003 = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30003", "opw30003", 0, "매도수구분").strip()
            my_qty = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30003", "opw30003", 0, "수량").strip())
            eliminate_qty = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30003", "opw30003", 0, "청산가능").strip())
            current_price = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30003", "opw30003", 0, "현재가격").strip()))
            estimate_opw30003 = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30003", "opw30003", 0, "평가손익").strip())

            self.estimate_opw30003 = estimate_opw30003 / 100

            print(futures_code)
            print(sell_buy_gubun_opw30003)
            print(my_qty)
            print(eliminate_qty)
            print(current_price)
            print(self.estimate_opw30003)

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

    btl.rq_data_opw30003(btl.deposit_num, "계좌비밀번호 4자리 입력", "00", "")

    app.exec_()


5. 마치며

진입한 종목의 계좌의 보유하고 있는 종목코드, 매도수구분, 보유종목 및 평가손익 등에 대해 받아오는 방법을 알아보았다. 매수를 하고나서, 나중에 조회해보면 된다.

이 글에서 의미있게 받아오는 데이터는 57줄의 self.estimate_opw30003(평가손익)이다. 평가손익을 기준으로 일정 수익이나 손실이 발생하면 청산(sendorder)하는 프로세스가 있다.

다음 글에서는 지정청산(opw30023, opw10007)에 대해 알아보자.

반응형