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

(키움증권 해외선물 OpenAPI-W) 진입을 위한 SendOrder 함수

봄이오네 2023. 2. 6. 08:09
반응형
목 차
1. 들어가며
2. 사전설명
1) 국내주식 OpenAPI의 SendOrder 함수
2) 해외선물 OpenAPI-W의 SendOrder 함수
3) 국내주식과 해외선물 비교
3. 코드설명
4. 전체코드
5. 마치며

1. 들어가며

지난 글에서는 진입을 위한 조건 4가지에 대해 알아보았다. 현재가 기준, 20분 이전의 양봉과 음봉 개수에 따라 단기 횡보장/상승/하락장을 구분하였다. 횡보장에서는 볼린저밴드 터치 + rsi 35미만/65 초과한 곳에서 진입하고, 상승/하락장은 양봉/음봉이 13개 이상인 곳으로 판단하여 진입할 예정이다.

이번 글에서는 앞의 글에서 설명한 진입 조건이 충족되었다면, 종목에 진입(SendOrder 함수)하는 방법을 알아볼 것이다.

2. 사전설명

1) 국내주식 OpenAPI의 SendOrder 함수

국내주식 OpenAPI에서는 9개 인자를 필요로 한다.
국내주식 OpenAPI 에 대한 설명은 링크에서 참고하자.

그림1-1. 국내주식 OpenAPI를 통해 매수하는 방법

2) 해외선물 OpenAPI-W의 SendOrder 함수

진입을 위해 필요한 변수는 총 10가지이다. 10가지 변수 중 문자형이 8개 이며, 인수형(int)은 2개이다.
자세한 설명은 아래에서 설명한다.

그림1-2. 해외선물 OpenAPI-W에서 확인가능한 SendOrder함수이다.

3) 국내주식과 해외선물 비교

국내주식은 9개 인수를 필요로 하고, 해외선물은 10개 인수를 필요로 한다. 2가지 차이가 있다.

  • 7번의 주문가격은 국내주식은 정수형(int)이고 해외선물은 문자형이다.
  • 8번의 국내주식은 stop 단가가 없는 반면, 해외선물은 stop 단가가 존재한다.
그림1-3. 국내주식/해외선물의 SendOrder 함수의 비교

3. 코드설명

모듈 및 로그인 설명은 생략한다.
< 그림2 >의 짤린 부분은 4번(전체코드)에서 확인 후 적용하도록 하자.

그림2-1. 모듈 및 로그인에 관한 설명이다.


1줄~31줄 : 모듈 및 로그인에 관한 내용이며 중복되는 내용이 많으므로 여기서는 설명을 생략한다.

그림2-2. SendOrder 함수 내용


33줄 : SendOrder 함수는 CommRqData 함수와는 달리, 독립적으로 실행된다. 즉 OpenAPI-W에서는 10개 인수를 SendOrder 함수에 넣고 키움서버에 요청하면 진입/청산이 이루어진다.

38줄~54줄 : 10개 인자에 대한 설명이다. 필자도 가끔씩 헷갈려서 주석처리를 통해 인수 순서, 태형(type) 등을 숙지하였다. 익숙해질 때까지는 "주석 처리"하되, 거래 시스템에는 남겨두도록 하자.

61줄 : SendOrder 함수에 10가지 인수를 담아 33줄의 sendorder_func 함수를 실행한다.


4. 전체코드

SendOrder 함수의 인수가 많은 관계로, 주석을 넣어서 필요할 때마다 인수의 태형(type)과 순서를 확인하자.

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

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

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

        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 = "12345678910"
        self.interesting_codes = ["NQH23"]
        self.orderable_qty = "1"

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

    ########## 주문요청하는 함수 (키움 OPENApi-w에서 제공) ##########
    def sendorder_func(self, rqname, scr, acc, ordertype, futures_code, qty, futures_price, s_stop, hogagb, orgno):
        self.kiwoom.dynamicCall("SendOrder(Qstring, Qstring, Qstring, int, Qstring, int, Qstring, Qstring, Qstring, Qstring)",
                                [rqname, scr, acc, ordertype, futures_code, qty, futures_price, s_stop, hogagb, orgno])

    """
        1) BSTR sRQName,
        2) BSTR sScreenNo,
        3) BSTR sAccNo,
        4) LONG nOrderType, *주문유형(1: 신규매도, 2: 신규매수, 3: 매도취소, 4: 매수취소, 5: 매도정정, 6: 매수정정)
        5) BSTR sCode,
        6) LONG nQty,
        7) BSTR sPrice,
        8) BSTR sStop,      * stop 단가
        9) BSTR sHogaGb,    * 거래구분(1: 시장가, 2: 지정가, 3: STOP, 4: STOP LIMIT)
        10) BSTR sOrgOrderNo)
            *(예시)  ## openApi.SendOrder("RQ_1", "1000", "5077000072", 1, "6AZ20", / 1, "0.7900", "0",        "2",  "");       // 지정가 매도
                       openApi.SendOrder("RQ_1", "1000", "5077000072", 1, "6AZ20", / 1, "0",      "0",        "1",  "");       // 시장가 매도
                    ## openApi.SendOrder("RQ_1", "1000", "5077000072", 1, "6AZ20", / 1, "0",       "0.7900", "3", "");       // STOP 매도
                    ## openApi.SendOrder("RQ_1", "1000", "5077000072", 1, "6AZ20", / 1, "0.7850", "0.8000",   "4", "");       // STOP LIMIT 매도
                    ## openApi.SendOrder("RQ_1", "1000", "5077000072", 5, "6AZ20", / 1, "0.7850", "0",       "2", "500060"); // 정정 매도
                    ## openApi.SendOrder("RQ_1", "1000", "5077000072", 3, "6AZ20", / 1, "0",     "0",       "2", "500060"); // 취소 매도
    """


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

    btl.sendorder_func("long 진입", "4949", btl.deposit_num, 2, btl.interesting_codes[1], btl.orderable_qty, "0", "0", "1", "")

    app.exec_()



5. 마치며

해외선물에서 SendOrder 함수를 통해 진입하는 화면을 첨부하려고 했으나, 글을 쓰고 있는 현재는 장이 종료된 관계로 첨부하지 못한 점은 양해 부탁드린다.

필자는 진입은 SendOrder 함수를 이용하고, 청산은 일괄청산(지정청산)을 선호하고 있다. 해외선물에서 일괄청산은 opw30023(해외파생지정청산대상조회)를 통해 opw10007(해외파생지정청산주문)으로 이루어진다.

다음 글에서는 청산을 위한 "평가손익"을 조회하는 내용을 알아보고, 그 다음에 "일괄청산"에 대해 알아보도록 하자.

반응형