목 차
1. 들어가며
2. 사전설명
1) 주식호가요청(opt10004) 확인
2) 호가창 확인
3. 코드설명
4. 전체 코드 및 결과
5. 마치며
1. 들어가며
키움증권 OpenAPI를 활용하여 현재가로 매수/매도 주문할 때가 있는데,
여기서 관건은 현재가로 주문을 할 때,
사용자가 원하는 시간에 주문이 정확히 체결되느냐이다.
현재가가 5,000원인데,
기 매수자가 1호가 낮추어서(4,990원)으로 시장에 매도를 했다면,
현재가는 4,990원이 된다.
한 호가 낮추어서 매도를 했다면,
한 호가 낮게 현재가가 설정(4,990원)된다.
사용자가 현재가로 제출하면, 최우선매수호가로 제출이 된다.
→ 즉, 현재가(5,000원) 체결이 안되고, 4,990원에서 매수대기를 하게 된다.
사용자의 성향에 따라 무조건 진입(매수)하고 싶을 때가 있다.
매도주문을 제출한 내역에 대해 매수(최우선 매도호가)주문을 제출하면,
바로 체결이 된다.
이 글에서는 "현재가"의 개념보다는 "최우선 매도호가"를 받아오는 방법을 알아보겠다.
2. 사전설명
1) KOA Studio에서 주식호가요청(opt10004)를 확인하자.
① 입력항목은 종목코드이다.
② 출력항목은 매도/매수 최우선호가 및 잔량이다.
③ 키움증권 OpenAPI의 SetInputValue, CommRqData를 활용하여 데이터 입력/요청한다.
④ 종목코드는 아프리카TV(067160)을 넣는다.
⑤ 호가잔량시간, 최우선 매도/매수호가 및 잔량 등을 출력한다.
2) 호가창을 확인하자.
- 아프리카TV의 매도/매수호가, 매도/매수잔량 현황이다.
① 매도호가 : 아프리카TV의 매도호가이다. (93,100원은 최우선매도호가)
② 매수호가 : 아프리카TV의 매수호가이다. (93,000원은 최우선매수호가)
③ 매도잔량 : 아프리카TV의 매도잔량이다. (매도잔량은 6,622주)
④ 매수잔량 : 아프리카TV의 매수잔량이다. (매수잔량은 18,315주)
3. 코드 설명
- 키움증권 OpenAPI에 접속/로그인하여 opt10004(주식호가요청)를 활용한다.
1줄~4줄 : 동시성처리, 로그인을 위해 sys 모듈, PyQt 모듈을 임포트한다.
6줄 : 임의의 클래스를 선언한다.
7줄~23줄 : 키움증권 OpenAPI 로그인을 한다.
11줄 : 25줄(rq_data_opt10004)와 32줄(trdata_get)을 연결한다.
25줄 : 임의의 함수 rq_data_opt10004를 선언한다.
27줄~28줄 : 키움증권 OpenAPI의
SetInputValue함수와 CommRqData함수로 데이터를 입력/요청한다.
29줄~30줄 : 이벤트루브를 실시한다.
32줄 : 키움증권에서 데이터를 받아오기 위해, 임의의 함수를 선언한다.
33줄 : 28줄에서 요청하는 내용이 opt_10004이면,
34줄~45줄 : 시간, 매수/매도 최우선 호가/잔량을 나타낸다.
68줄 : 아프리카TV(067160)의 종목코드를 입력하여,
25줄의 rq_data_opt10004를 실행한다.
4. 전체 코드 및 결과
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class btl_system():
def __init__(self):
self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
self.kiwoom.OnEventConnect.connect(self.login_Connect)
self.kiwoom.OnReceiveTrData.connect(self.trdata_get)
print("로그인 요청!")
self.kiwoom.dynamicCall("CommConnect()")
self.login_event_loop = QEventLoop()
self.login_event_loop.exec_()
def login_Connect(self, nErrCode):
if nErrCode == 0:
print('로그인 성공하였습니다!')
else:
print('로그인 실패하였습니다!')
self.login_event_loop.exit()
def rq_data_opt10004(self, stock_code):
print("70줄에서 입력받은 종목코드를 키움서버에 요청합니다.""\n")
self.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드", stock_code)
self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)", "opt_10004", "opt10004", 0, "1018")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
def trdata_get(self, sScrNo, rqname, strcode, sRecordName, sPreNext, nDataLength, sErrorCode, sMessage, sSplmMsg):
if rqname == "opt_10004":
hoga_time = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "호가잔량기준시간").strip()
selling_first_price = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매도최우선호가").strip()))
selling_first_qty = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매도최우선잔량").strip()))
selling_second_price = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매도2차선호가").strip()))
selling_second_qty = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매도2차선잔량").strip()))
buying_first_price = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매수최우선호가").strip()))
buying_first_qty = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매수최우선잔량").strip()))
buying_second_price = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매수2차선호가").strip()))
buying_second_qty = abs(int(self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString)", "opt10004", "주식호가요청", 0, "매수2차선잔량").strip()))
print(f"호가잔량기준시간은 {hoga_time}입니다.""\n")
print(f"매도최우선호가는 {selling_first_price}원 입니다.")
print(f"매도최우선잔량은 {selling_first_qty}주 입니다.""\n")
print(f"매도2차선호가는 {selling_second_price}원 입니다.")
print(f"매도2차선잔량은 {selling_second_qty}주 입니다.""\n")
print(f"매수최우선호가는 {buying_first_price}원 입니다.")
print(f"매수최우선잔량은 {buying_first_qty}주 입니다.""\n")
print(f"매수2차선호가는 {buying_second_price}원 입니다.")
print(f"매수2차선잔량은 {buying_second_qty}주 입니다.")
try:
self.tr_event_loop.exit()
except AttributeError:
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
btl = btl_system()
btl.rq_data_opt10004("067160")
app.exec_()
# (expected result)
# 70줄에서 입력받은 종목코드를 키움서버에 요청합니다.
# 호가잔량기준시간은 160000입니다.
# 매도최우선호가는 93100원 입니다.
# 매도최우선잔량은 109주 입니다.
# 매도2차선호가는 93200원 입니다.
# 매도2차선잔량은 969주 입니다.
# 매수최우선호가는 93000원 입니다.
# 매수최우선잔량은 1347주 입니다.
# 매수2차선호가는 92900원 입니다.
# 매수2차선잔량은 1805주 입니다.
5. 마치며
최우선 매도/매수호가를 알아보았다.
현재가가 반드시 최우선매도호가와 일치한다는 보장은 없다.
100% 체결을 원한다면,
최우선 매도호가로 매수주문을 제출하면 100% 체결된다.
향후 매수/매도주문을 할 때,
현재가로 주문을 넣을지, 최우선매도/매수호가로 주문을 넣을지
고민해보는 것도 좋은 방법일 것이다.
'1. 국내주식 > 1-2. 키움 OpenAPI (사용)' 카테고리의 다른 글
(주식 자동 매매) 키움증권 OpenAPI - 가격급등락요청(opt10019) (0) | 2023.02.11 |
---|---|
(주식 자동 매매) 키움증권 OpenAPI - 파이썬을 통해 1분봉 받기 (opt10080) (0) | 2022.10.11 |
(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문내역 가져와서 주문취소하기 (2) (opt10075 + SendOrder) (0) | 2022.10.10 |
(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문내역 가져오기 (1) (opt10075) (0) | 2022.10.09 |
(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문을 SendOrder 함수로 취소하기 (3) 주문번호와 원주문번호 구분 필요 (0) | 2022.10.08 |
(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문을 SendOrder 함수로 취소하기 (2) 취소주문 테스트 (5) | 2022.10.07 |
(주식 자동 매매) 키움증권 OpenAPI - 미체결 주문을 SendOrder 함수로 취소하기 (1) 취소 방법 (0) | 2022.10.06 |
(주식 자동 매매) 키움증권 OpenAPI - 1분봉 데이터 실시간 받기(opt10080) (2) | 2022.10.05 |