1. 들어가며
2. 사전설명
1) 주문가능수량 및 청산가능수량 개념 및 화면번호
2) WKOA Studio 설명
3. 코드설명
4. 전체 코드
5. 마치며
1. 들어가며
지난 글에서는 opw30009(예탁금및증거금요청) TR요청을 통해 주문가능금액을 조회해 보았다.
이번 글에서 설명하겠지만, 국내주식과 달리 해외선물의 주문가능금액은 주문을 할 때 쓰이지는 않는다.
왜냐하면, 해외선물에서는 주문가능수량을 구할 수 있기 때문이다. 국내주식은 주문가능금액을 구할 필요가 있다. 왜냐하면 (주문가능금액 ÷ 현재가)를 통해 주문가능수량을 구한다.
이번 글에서는 opw30011(주문가능수량요청)을 통해 주문가능수량, 청산가능수량, 주문가능금액을 조회해 보도록 하자.
여기서 구한 주문/청산가능수량은 향후 주문(sendorder)에서 쓰이는 수량인 만큼 차분히 읽어보시길 권한다.
아래 예시는 S&P 500 (ESH23)으로 설명할 예정이다.
2. 사전설명
1) 주문가능수량 및 청산가능수량 개념 및 화면번호
① 주문가능수량 : long/short 진입을 위해 계산된 수량
② 청산가능수량 : long/short 청산을 위해 계산된 수량
영웅문G에서 화면번호는 4560(주문가능수량요청)이다.
※ 주문을 넣을 때 쓰이는 함수의 형태
아래는 키움증권 개발가이드에 나온 주문(send order)에 관한 내용이다.
진입/청산 시 적용되는 함수는 동일하다. 주문/청산가능수량이 6번째 nQty에 들어간다.
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"); // 취소 매도
"""
2) WKOA Studio 설명
opw30011(주문가능수량조회)를 통해 얻는 주요 데이터는 3가지이다. (주문/청산가능수량, 주문가능금액)
입력해야 할 데이터는 7가지인데, 아래에서 설명한다.
3. 코드설명
로그인 등 중복된 설명은 최소화할 예정이다.
1줄~5줄 : 동시성 처리 등 필요모듈을 임포트한다.
9줄 : 키움증권 레지스트리를 self.kowoom에 넣는다.
12줄~19줄 : 로그인/이벤트를 연결하고, 로그인 화면을 띄운다.
21줄 : 사용자 본인의 계좌 10자리를 입력한다.
24줄~29줄 : 로그인 관련 함수
32줄~43줄 : SetInput 함수 및 CommRqData 함수를 이용하여 키움증권 OpenAPI-W에 데이터를 입력/요청한다.
37줄 : 매도수구분 관련하여 매도는 1번, 매수는 2번이다. → 매수로 진입할 것이므로 68줄에서는 "2"로 입력함
38줄 : 해외주문유형으로, 1번(시장가), 2번(지정가), 3번(STOP), 4번(Stop Limit)
39줄 : 시장가로 진입한 경우 빈칸으로 데이터를 키움증권에 입력한다. ( " " )
47줄~60줄 : 주문가능수량, 청산가능수량, 주문가능금액, 통화코드 4가지 데이터를 받아와서 출력한다.
68줄 : 32줄의 함수(rq_data_opw30011)을 실행한다. (시장가로 주문하므로 39줄의 주문표시가격은 빈칸으로 둔다)
4. 전체 코드
전체 코드는 아래와 같다.
21줄에는 사용자 본인의 계좌 10자리를 입력한다.
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
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.login_event_loop = QEventLoop()
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 요청하는 함수 모음 (키움 OPENApi-w에서 제공) ##########
def rq_data_opw30011(self, deposit_num1, password_2, password_enter3, futures_code4, sell_buy_gubunm5, order_type6, order_price7): # 주문가능수량
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)", "종목코드", futures_code4)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "매도수구분", sell_buy_gubunm5)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "해외주문유형", order_type6)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "주문표시가격", order_price7) # "시장가"로 주문할 경우, 함수 실행시 빈칸("")으로 요청
self.kiwoom.dynamicCall("CommRqData(QString, QString, QString,QString)", "opw_30011", "opw30011", "", "3011")
time.sleep(0.5)
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
if rqname == "opw_30011": # 주문가능수량c
orderable_qty = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "주문가능수량").strip())
liquidable_qty = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "청산가능수량").strip())
orderable_money_30011 = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "주문가능금액").strip())
currency_code = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "통화코드").strip()
self.orderable_qty = orderable_qty
self.liquidable_qty = liquidable_qty
self.orderable_money_30011 = orderable_money_30011 / 100
self.currency_code = currency_code
print(self.orderable_qty)
print(self.liquidable_qty)
print(self.orderable_money_30011)
print(self.currency_code)
self.tr_event_loop.exit()
if __name__ == "__main__":
app = QApplication(sys.argv)
btl = btl_system()
btl.rq_data_opw30011(btl.deposit_num, "0000", "00", "ESH23", "2", "1", "")
app.exec_()
# (expected result)
# 2
# 0
# 29552.25
# USD
5. 마치며
주문/청산가능수량은 진입과 청산을 위한 매매를 할 때 상당히 중요한 개념이다.
필자도 실투를 할 때 가끔씩 실수를 한다.
long으로 2개(매수)로 진입해 수익이 많이 났는데,
청산을 하고 싶어 수기로 "매도" 창에서 "주문가능수량"을 눌렀는데 3이 떴고, 매도를 눌렀다.
나중에 알게 되었지만, 이렇게 주문이 된 경우 long 2개는 청산되지만, short 1개가 추가로 진입되어버리는 경우이다.
필자도 수익났다고 좋아했는데, 그 다음날 확인해 보니 손실이 1,000달러 이상이 발생해서, 눈물의 손절을 했다.
진입은 주문가능수량으로, 청산은 "청산가능수량"으로 투자를 해야, 추가 진입을 막을 수 있을 것이다.
'2. 해외선물 > 2-4. 해외선물 API (사용)' 카테고리의 다른 글
(키움증권 해외선물 OpenAPI-W) 볼린저밴드 상한선/하한선 값 구하기 (2) | 2023.01.30 |
---|---|
(키움증권 해외선물 OpenAPI-W) CommRqDATA 및 SendOrder 함수의 호출 제한 (0) | 2023.01.29 |
(키움증권 해외선물 OpenAPI-W) 볼린저밴드와 RSI를 활용하여 매매하는 글 작성 방향 (0) | 2023.01.28 |
(키움증권 해외선물 OpenAPI-W) 미체결내역 조회 (opw30002) (0) | 2023.01.25 |
(키움증권 해외선물 OpenAPI-W) 주문가능금액 조회 (opw30009, 예수금및증거금현황조회) (2) | 2023.01.22 |
(키움증권 해외선물 OpenAPI-W) 패턴 만들기 (8) 참고사항 (5) | 2023.01.21 |
(키움증권 해외선물 OpenAPI-W) 패턴 만들기 (7) eval모듈, zip함수, for문으로 패턴 추출하기 (2) | 2023.01.20 |
(키움증권 해외선물 OpenAPI-W) 패턴 만들기 (6) 패턴 만들기(엑셀) (0) | 2023.01.19 |