목 차
1. 들어가며
2. 사전설명
3. 코드설명
4. 전체코드
5. 마치며
1. 들어가며
영웅문G에서 거래가능한 종목은 몇 가지일까?
거래소별로 몇 종목의 거래가 가능한지? 각각의 증거금은 어떻게 되는지?
필자가 지나치게 나스닥, S&P, 엔화, 파운드 등 4종목에만 몰입되어 있는건 아닌지 약간은 의심이 된다.
수익이 날 수 있는 종목을 꾸준히 관찰하고 수익내는 방법에 대한 고민이 부족하지 않았나?
먼저, 영웅문G에서 거래가능한 종목은 몇 종목이고, 각각의 증거금은 얼마일까?
이 글에서는 위의 < 그림1-1 >에서처럼 해외선물의 상품별증거금을 키움증권에서 받아오는 방법을 알아본다.
< 그림1-2 >처럼 거래소별로 거래가능한 종목개수를 알아볼 예정이다.
아래 링크의 종목별 위탁증거금과 유지증거금을 받아오는 것이 목표이다. (단위는 달러)
2. 사전설명
WKOA-Studio에서 데이터 요청 및 수신하는 방법을 알아보자.
① opw20004(상품별증거금조회)는 품목구분, 적용일자, 해외파생구분, 파생품목코드를 입력(input)하고, 파생품목코드, 품목명 등 6가지를 수신(output)받는다.
② SetInputValue 및 CommRqData 함수를 활용한다.
③ 품목구분은 IDX, 적용일자 20230127, 해외파생구분은 FU, 파생품목코드는 빈칸으로 설정한다.
④ 출력된 결과물이다.
< 그림2-2 >는 키움서버에서 받은 종목별 위탁/유지증거금 내역이다.
3. 코드설명
모듈의 임포트 및 로그인 정보 등 중복 정보의 설명은 생략한다. 2-2(해외선물 API) 카테고리를 참고하자.
1줄~32줄 : 필요모듈 및 로그인 정보에 관한 내용이다.
22줄 : 6개 분야를 설정한다.
IDX:지수, CUR:통화, MTL:금속, ENG:에너지, CMD:농축산물, INT:금리
23줄 : 73줄의 데이터프레임 형태를 만들기 위해, "구분"을 만들어준다.
24줄 : 조회날짜를 설정한다. 사용자는 "조회날짜"만 바꾸어주면 조회가 가능하다.
36줄~39줄 : SetInputValue 함수를 이용하여, < 그림2 >의 input의 4가지 데이터를 키움서버에 입력한다.
40줄 : CommRqData 함수를 이용하여,36~39줄의 4가지 데이터를 키움증권 서버에 요청한다.
15줄 : 40줄의 CommRqData의 데이터가 키움증권에 요청(opw20004)되면, 15줄의 OnReceiveTrData를 통해 GetCommData 함수와 연결(connect)된다.
self.kiwoom.OnReceiveTrData.connect(self.trdata_get)
45줄 : 요청받은 rqname가 "opw_20004"이면
46줄 : 받아온 데이터의 총 개수를 카운팅(getrepeat)한다.
50줄~55줄 : 6가지 데이터를 받아온다. 위탁/유지증거금은 100으로 나누어야 화면번호 0773의 증거금으로 표기된다.
* 6가지 수신데이터 : 파생품목코드, 품목명, 해외거래소코드, 통화코드, 위탁증거금, 유지증거금
57줄~63줄 : 23줄의 데이터프레임에 각각의 데이터를 추가(append)한다.
68줄 : for문을 통해 22줄에서 정의한 품목을 하나씩 추출하여 35줄(rq_data_opw20004)를 실행한다.
70줄 : 판다스 모듈을 통해 데이터프레임에 "품목"을 넣어주기 위해 임의로 세팅하였다.
73줄 : 23줄에서 설정한 데이터프레임에 컬럼(columns)을 7가지로 설정한다.
76줄 : 데이터를 저장할 데이터 경로를 설정한다. (6줄의 os모듈은 파일의 경로을 확인한다)
78줄~80줄 : 76줄의 경로에 "margin_data.xlsx" 파일이 있으면, 데이터를 추가하고
81줄~83줄 : 76줄의 경로에 "margin_data.xlsx" 파일이 있으면, 파일을 만들고, 데이터를 추가한다.
89줄 : 67줄의 함수(margin_money_start)를 실행한다.
4. 전체코드
사용자는 24줄의 self.setting_data를 본인이 원하는 날짜로 수정해주고, 파일을 실행해주면 된다.
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import pandas as pd
import os
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)") # CommConnect() : 괄호 안에 자동(1)을 넣는다.
self.login_event_loop = QEventLoop() # from PyQt5.QtCore import * : qtcore가 임포트되어야 함
self.login_event_loop.exec_()
##### 위탁증거금, 유지증거금 관련 #####
self.margin_sort = ['IDX', 'CUR', 'MTL', 'ENG', 'CMD', 'INT'] # IDX:지수, CUR:통화, MTL:금속, ENG:에너지, CMD:농축산물, INT:금리
self.margin_situation = {'gubun' : [], 'form_code' : [], 'form_name' : [], 'market_code' : [], 'currency_code' : [], 'customer_margin' : [], 'maintenance_margin' : []}
self.setting_data = "20230127"
########## 로그인 관련 함수 ##########
def login_Connect(self, err_code):
if err_code == 0:
print('로그인 성공했습니다!')
self.login_event_loop.exit()
else:
print('로그인 실패했습니다!')
########## 키움서버에 TR 요청하는 함수 모음 ##########
def rq_data_opw20004(self, form_gubun_1, data_2, futures_gubun_3, form_codes_4):
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "품목구분", form_gubun_1)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "적용일자", data_2)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "해외파생구분", futures_gubun_3)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "파생품목코드", form_codes_4)
self.kiwoom.dynamicCall("CommRqData(QString, QString, QString, QString)", "opw_20004", "opw20004", "", "2004")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
if rqname == "opw_20004":
getrepeatcnt = self.kiwoom.dynamicCall("GetRepeatCnt(QString,QString)", trcode, recordname) # LONG GetRepeatCnt(BSTR sTrCode, BSTR sRecordName)
print(getrepeatcnt)
for j in range(getrepeatcnt):
form_code1 = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_20004", "opc20004", j, "파생품목코드").strip()
form_name1 = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_20004", "opc20004", j, "품목명").strip()
market_code1 = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_20004", "opc20004", j, "해외거래소코드").strip()
currency_code1 = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_20004", "opc20004", j, "통화코드").strip()
customer_margin1 = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_20004", "opc20004", j, "위탁증거금").strip())/100
maintenance_margin1 = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_20004", "opc20004", j, "유지증거금").strip())/100
self.margin_situation['gubun'].append(self.margin_sort)
self.margin_situation['form_code'].append(form_code1)
self.margin_situation['form_name'].append(form_name1)
self.margin_situation['market_code'].append(market_code1)
self.margin_situation['currency_code'].append(currency_code1)
self.margin_situation['customer_margin'].append(customer_margin1)
self.margin_situation['maintenance_margin'].append(maintenance_margin1)
self.tr_event_loop.exit()
def margin_money_start(self):
for i in btl.margin_sort:
time.sleep(1)
self.margin_sort = i
btl.rq_data_opw20004(i, self.setting_data, "FU", "")
df1 = pd.DataFrame(self.margin_situation, columns=['gubun', 'form_code', 'form_name', 'market_code', 'currency_code', 'customer_margin', 'maintenance_margin'])
print(df1)
dir = r'C:\Users\User\Desktop\margin_data.xlsx' # 경로 설정
if os.path.exists(dir):
with pd.ExcelWriter(dir, mode='a', engine='openpyxl', if_sheet_exists='overlay') as writer:
df1.to_excel(writer, header=False, index=False, sheet_name='sheet1', startrow=writer.sheets['sheet1'].max_row)
else:
with pd.ExcelWriter(dir, mode='w', engine='openpyxl') as writer:
df1.to_excel(writer, index=False, sheet_name='sheet1')
if __name__ == "__main__":
app = QApplication(sys.argv)
btl = btl_system()
btl.margin_money_start()
app.exec_()
5. 마치며
주목할 점은 영웅문G에서 CME 거래소로 구분이 되었다고 하더라도, API에서 Gold는 Comex 거래소, Natural Gas 및 Cruel Oil은 NYMWX 거래소로 분류되어 있다는 점은 알고나서 거래소를 정해야 한다. 즉, 골드, 가스, 오일은 API 거래를 할 때는 CME 시장이 아니므로, 거래를 위해서는 별도의 요금을 지불하여야 한다.
주요종목의 거래소는 아래 링크에서 확인하자.
* 거래소별 종목 현황 링크 (새창에서 열기)
OpenAPI-W를 통해 영웅문G에서 거래되는 해외선물 90종목의 현재 기준, 위탁/유지증거금을 받아오는 방법을 알아보았다. 판다스 모듈의 엑셀로 보내는 기능은 언제보아도 훌륭해보인다. ^^
그간 관심있는 종목의 증거금 파악하는데 급급했던거 같다. 물론 잘 알지도 못하는 종목에 증거금이 낮다는 이유로 진입하는 것도 상당히 문제이지만, 나스닥 등 인기종목에만 함몰되어 있었던 것도 사실이다. 종목을 폭넓게 공부하는 것도 나쁘지 않아보인다. 시간을 가지고 종목들의 특징을 공부하자.
'2. 해외선물 > 2-5. 해외선물 API (기타)' 카테고리의 다른 글
(키움증권 해외선물 OpenAPI-W) 상품별명세및요약조회(opw50004) (2) | 2023.02.03 |
---|