목 차
1. 들어가며
2. 사전설명
3. 코드설명
4. 전체코드
5. 마치며
1. 들어가며
지난 글에서는 시간대별 다른 코드 적용을 위한 "시간 구분"에 대해 알아보았다. 현재시간을 구하고, while을 이용하여 일정시간 반복 및 if, elif, else를 통해 시간구분을 할 수 있을 것이다.
이번 글에서는 진입/청산 시도횟수 체크하기에 대해 알아볼 것이다.
진입/청산 시도횟수 체크하는 것이 필요한 이유는 무엇일까? 자동매매 시스템을 구축하였다고는 해도, 제대로 돌아가는건지 의문이 들 때가 많다. 파이썬이라는 낯선 언어, 키움증권API를 통해 키움서버에 접속하여 데이터를 요청하고 받아오는 행위가 제대로 이루어지고 있는지 확인하고 싶을 때가 많다. 이러한 이유로 "진입/청산 시도횟수" 체크 및 출력을 통해 시스템이 제대로 돌아가고 있는지 확인하는 것이다.
2. 사전설명
비교적 간단한 코드이다. 최초에 0을 선언하고 1씩 더하면 된다. 생각보다 더 간단하고 짧은 코드이다.
필자는 10~15초마다 진입 혹은 청산을 시도한다. time.sleep(10)으로 설정하면 10초마다 1회씩 조회를 하므로, 60초에는 6번 조회가 될 것이다. 물론 commrqdata 함수를 활용하고, 그 다음번 commrqdata를 다시 한번 활용할 때는 time.sleep(5)를 별도로 주어서 60초에 6회 조회가 아닌 3~4회 조회가 되겠지만, 계속 조회를 한다는 점에서는 변화가 없다.
3. 코드설명
2초 마다 조회를 한다고 가정했을 때, 2초마다 1씩 증가하는 코드이다.
import sys
from PyQt5.QtWidgets import *
import time
class btl_system():
def __init__(self):
self.var_test_1 = 0
self.j = 1
########## 진입/청산 시도 횟수 체크 ##########
def var_test_check(self):
self.var_test_1 = self.var_test_1 + self.j
print(self.var_test_1)
if __name__ == "__main__":
app = QApplication(sys.argv)
btl = btl_system()
while True:
btl.var_test_check()
time.sleep(2)
app.exec_()
### (expected result)
### 1
### 2
### 3
### 4
7줄 : 진입/청산을 할 때 commrqdata를 사용한다. opc10002(1분봉 데이터 조회) 등 데이터 조회를 할 때 commrqdata가 활용되므로 commrqdata 가 실행되는 곳에서 카운팅을 해주면 된다. 초기값은 0으로 설정한다.
8줄 : 1씩 증가시킬 것이므로, self.j는 1로 선언한다.
11줄 : 1씩 증가하는 함수를 정의한다.
12줄 : 11줄 함수(var_test_check)가 실행되면 1씩 증가한다.
19줄~21줄 : 20줄을 통해 11줄의 함수가 실행된다. 11줄~13줄 함수의 실행이 완료되면, 21줄에 의해 2초간 대기 후 20줄에 의해 11줄 함수가 다시 실행된다.
4. 전체코드
아래 < 접은글 >에서는 32줄~34줄(최초 변수 0 및 증가 변수1을 선언) 및 684줄~687줄(1씩 증가되는 함수)이 추가되었다. < 접은글 >을 실행하려면 키움증권에 시세조회 이용료($185)를 지불하여야 한다.
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import numpy
from datetime import datetime
class btl_system():
def __init__(self):
self.kiwoom = QAxWidget("KFOPENAPI.KFOpenAPICtrl.1")
print("로그인 시작!")
self.kiwoom.dynamicCall("CommConnect(1)") # CommConnect() : 괄호 안에 자동(1)을 넣는다.
self.kiwoom.OnEventConnect.connect(self.login_Connect)
self.kiwoom.OnReceiveTrData.connect(self.trdata_get)
self.login_event_loop = QEventLoop()
self.login_event_loop.exec_()
self.kiwoom.dynamicCall("GetCommonFunc(QString, QString)", "ShowAccountWindow", "") # 계좌번호 입력창을 띄우는 내부함수
##### rsi의 현재 1분 데이터의 au/ad 구하기 #####
self.price_rsi_total = [] # 158~163줄 : 1분봉들의 종가데이터를 담는 리스트 모음
self.close_price_rsi_change = [] # 164~167줄 : 기준값(au/ad)를 세팅하기 위해, 최근 15개 값을 담는 리스트
self.close_price_third = [] # 168~179줄 : 기준값 15개의 각 종가들의 차이 모음 리스트
self.early_au1 = [] # 175~179줄 : 음수를 0으로 표시
self.early_ad1 = [] # 175~179줄 : 양수를 0으로 표시
self.rsi_total_list = [] # 214~235줄 : 각각의 rsi를 담는 리스트 모음
##### 진입/청산 조회수 체크 #####
self.var_test_1 = 0
self.j = 1
def login_Connect(self, err_code):
if err_code == 0:
print('로그인 성공했습니다!')
else:
print('로그인 실패했습니다!')
self.login_event_loop.exit()
########## 키움서버에 TR 요청하는 함수 모음 ##########
def rq_data_opc10002(self, stock_code_num, time_unit): # 1분봉 받기
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "종목코드", stock_code_num)
self.kiwoom.dynamicCall("SetInputValue(QString,QString)", "시간단위", time_unit)
self.kiwoom.dynamicCall("CommRqData(QString, QString, QString, QString)", "opc_10002", "opc10002", "", "1002")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
def rq_data_opw30009(self, deposit_num1, password_2, password_enter3): # 주문가능금액, 실현손익, 미실현손익
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("CommRqData(QString, QString, QString, QString)", "opw_30009", "opw30009", "", "3009")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
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")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
def rq_data_opw30012(self, deposit_num1, password_2, password_enter3): # 계좌 현재가, 매도수구분, 보유수량, 매입단가, 계좌현재가, 평가손익
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("CommRqData(QString, QString, QString, QString)", "opw_30012", "opw30012", "", "3012")
self.tr_event_loop = QEventLoop()
self.tr_event_loop.exec_()
########## OnReceiveTrData을 통해 수신받은 데이터 함수 ##########
def trdata_get(self, scrno, rqname, trcode, recordname, prenext):
if rqname == "opc_10002":
getrepeatcnt = self.kiwoom.dynamicCall("GetRepeatCnt(QString,QString)", trcode, recordname)
self.getrepeatcnt = getrepeatcnt
self.tr_event_loop.exit()
btl.rsi_searching()
btl.bollinger_searching()
btl.macd_searching()
elif rqname == "opw_30009": # 주문가능금액, 실현손익, 미실현손익
orderable_money = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30009", "opw30009", 0, "주문가능금액").strip())
withdrawal_money = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30009", "opw30009", 0, "인출가능금액").strip())
realized_pl = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30009", "opw30009", 0, "선물청산손익").strip())
unrealized_pl = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30009", "opw30009", 0, "선물평가손익").strip())
self.orderable_money = orderable_money / 100
self.withdrawal_money = withdrawal_money / 100
self.realized_pl = realized_pl / 100
self.unrealized_pl = unrealized_pl / 100
print(self.orderable_money)
self.tr_event_loop.exit()
elif rqname == "opw_30011": # 주문가능수량
orderable_qty = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30011", "opw30011", 0, "주문가능수량").strip())
liquidable_qty = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30011", "opw30011", 0, "청산가능수량").strip())
orderable_money_30011 = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30011", "opw30011", 0, "주문가능금액").strip())
currency_code = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30011", "opw30011", 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
self.tr_event_loop.exit()
elif rqname == "opw_30012": # 계좌 현재가, 매도수구분, 보유수량, 매입단가, 계좌현재가, 평가손익
stock_code_d = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "종목코드").strip()
sell_buy_gubun_d = self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "매도수구분").strip()
my_qty_d = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "수량").strip())
my_price_d = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "매입가격").strip())
current_price_d = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "현재가격").strip()))
estimate_pl_d = int(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opw_30012", "opw30012", 0, "평가손익").strip())
self.stock_code_d = stock_code_d
self.sell_buy_gubun_d = sell_buy_gubun_d
self.my_qty_d = my_qty_d
self.my_price_d_30012 = my_price_d
self.current_price_d_30012 = current_price_d
self.estimate_pl_d_30012 = estimate_pl_d / 100
self.tr_event_loop.exit()
########## 주문요청하는 함수 (키움 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"); // 취소 매도
"""
def rsi_searching(self):
for i in range(self.getrepeatcnt): # 현재가 → 오래된 값으로 출력된다.
self.current_price_rsi = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "현재가").strip())
self.price_rsi_total.append(self.current_price_rsi)
self.price_rsi_total_final = self.price_rsi_total[::-1]
self.price_rsi_total = []
for i in range(0, 15):
current_price_recent = self.price_rsi_total_final[i]
self.close_price_rsi_change.append(current_price_recent)
for j in range(len(self.close_price_rsi_change) - 1):
self.close_price_second = self.close_price_rsi_change[j + 1] - self.close_price_rsi_change[j]
self.close_price_third.append(self.close_price_second)
self.close_price_rsi_change = []
print("68줄")
for i in self.close_price_third: # 음수를 0으로 표시
if i <= 0:
i = 0
self.early_au1.append(i)
else:
self.early_au1.append(i)
for j in self.close_price_third: # 양수를 0으로 표시
if j >= 0:
j = 0
self.early_ad1.append(j)
else:
self.early_ad1.append(j)
self.au7 = sum(self.early_au1) / len(self.early_au1)
self.ad7 = sum(self.early_ad1) / len(self.early_ad1)
self.ad7 = abs(self.ad7)
self.early_au1 = [] # 초기화
self.early_ad1 = [] # 초기화
del self.close_price_third[:] # 향후 사용하지 않을 분봉 리스트는 초기화(삭제)하여 메모리 효율화 추진
for k in range(1, self.getrepeatcnt-1):
curren_price_rsi_1 = self.price_rsi_total_final[k]
curren_price_rsi_2 = self.price_rsi_total_final[k+1]
current_price_rsi_3 = curren_price_rsi_2 - curren_price_rsi_1
if current_price_rsi_3 >= 0:
positive_price = current_price_rsi_3
negative_price = 0
else:
positive_price = 0
negative_price = abs(current_price_rsi_3)
self.au8 = (self.au7 * 13 + positive_price) / 14
self.ad8 = (self.ad7 * 13 + negative_price) / 14
rs2 = self.au8 / self.ad8
self.rsi_second = rs2 / (1 + rs2) * 100
self.current_rsi = round(self.rsi_second, 2)
self.rsi_total_list.append(self.current_rsi)
self.au7 = self.au8
self.ad7 = self.ad8
self.price_rsi_total_final = []
self.rsi_total_list = self.rsi_total_list[::-1]
self.current_rsi_0 = self.rsi_total_list[0] # 현재시간
self.current_rsi_1 = self.rsi_total_list[1] # 1분전
print(self.current_rsi_0)
print(self.current_rsi_1)
self.rsi_total_list_2_35_minute = [] # 2분전 ~ 35분전
for i in range(2, 36):
self.rsi_total_list_2_35_minute.append(self.rsi_total_list[i])
self.rsi_max_2_35_minute_point = max(self.rsi_total_list_2_35_minute)
self.rsi_max_2_35_minute_position = self.rsi_total_list_2_35_minute.index(self.rsi_max_2_35_minute_point) + 2 # 2를 더한 이유 : 순서가 0부터 시작한다. (2분전~35분까지를 알고 싶음, 2분전에 해당하는 숫자는 for(2, 36)에서 "2"는 0이므로, 0+2를 통해 "2분"을 나타냄)
self.rsi_min_2_35_minute_point = min(self.rsi_total_list_2_35_minute)
self.rsi_min_2_35_minute_position = self.rsi_total_list_2_35_minute.index(self.rsi_min_2_35_minute_point) + 2
def bollinger_searching(self):
self.close_price2 = []
for i in range(0, 20):
close_price1 = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "현재가").strip()))
self.close_price2.append(close_price1)
self.close_price3 = numpy.mean(self.close_price2) + numpy.std(self.close_price2) * 2
self.close_price4 = numpy.mean(self.close_price2) - numpy.std(self.close_price2) * 2
self.bollinger_upper_line = float(round(self.close_price3, 2))
self.bollinger_lower_line = float(round(self.close_price4, 2))
self.close_price2 = [] # 2번째 종목 조회할 때,1종목의 데이터가 들어있어서 누적되는 현상 발생 (초기화 시켜줌)
def macd_searching(self):
##### macd의 현재 1분 데이터의 au/ad 구하기 #####
self.macd_minute_bong_couning = 100 # macd를 구하기 위해 받아올 일봉 갯수
self.price_macd_total = [] # 56~86줄 : 1분봉들의 종가데이터를 담는 리스트 모음
self.macd_12_26_total = [] # macd 시그널을 구하기 위한 리스트 선언
self.ema_var_12 = 2 / (12 + 1)
self.ema_var_26 = 2 / (26 + 1)
self.signal_var_9 = 2 / (9 + 1)
for i in range(self.macd_minute_bong_couning): # 현재가 → 오래된 값으로 출력된다.
self.current_price_macd = float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "현재가").strip())
self.price_macd_total.append(self.current_price_macd)
self.price_macd_total_final = self.price_macd_total[::-1]
### ema_12, ema_26 지수이동평균 구하기 ###
for i in range(self.macd_minute_bong_couning):
if i == 0:
pass
elif i == 1:
self.ema_12_first = (self.price_macd_total_final[1] * self.ema_var_12) + (self.price_macd_total_final[0] * (1 - self.ema_var_12))
self.ema_12_second = self.ema_12_first
self.ema_26_first = (self.price_macd_total_final[1] * self.ema_var_26) + (self.price_macd_total_final[0] * (1 - self.ema_var_26))
self.ema_26_second = self.ema_26_first
elif i >= 2:
self.ema_12_third = self.ema_12_second
self.ema_12_forth = self.price_macd_total_final[i]
self.ema_12_final = (self.ema_12_forth * self.ema_var_12) + (self.ema_12_third * (1 - self.ema_var_12))
self.ema_12_second = self.ema_12_final
self.ema_26_third = self.ema_26_second
self.ema_26_forth = self.price_macd_total_final[i]
self.ema_26_final = (self.ema_26_forth * self.ema_var_26) + (self.ema_26_third * (1 - self.ema_var_26))
self.ema_26_second = self.ema_26_final
# self.macd_12_26 = round(self.ema_12_final - self.ema_26_final, 2) # 소수 셋째 자리에서 반올림 (소수 둘째 자리까지 출력)
self.macd_12_26 = self.ema_12_final - self.ema_26_final # 반올림없이 값 출력
self.macd_12_26_total.append(self.macd_12_26)
if i == self.macd_minute_bong_couning - 7:
self.macd_12_26_6_mintue_ago = self.macd_12_26
elif i == self.macd_minute_bong_couning - 6:
self.macd_12_26_5_mintue_ago = self.macd_12_26
elif i == self.macd_minute_bong_couning - 5:
self.macd_12_26_4_mintue_ago = self.macd_12_26
elif i == self.macd_minute_bong_couning - 4:
self.macd_12_26_3_mintue_ago = self.macd_12_26
elif i == self.macd_minute_bong_couning - 3:
self.macd_12_26_2_mintue_ago = self.macd_12_26
elif i == self.macd_minute_bong_couning - 2:
self.macd_12_26_1_mintue_ago = self.macd_12_26
elif i == self.macd_minute_bong_couning - 1:
self.macd_12_26_current = self.macd_12_26
### macd_signal 구하기 ###
self.macd_12_26_counting = len(self.macd_12_26_total)
print(self.macd_12_26_counting)
for i in range(self.macd_12_26_counting):
if i == 0:
pass
if i == 1:
self.macd_signal_first = (self.macd_12_26_total[1] * self.signal_var_9) + (self.macd_12_26_total[0] * (1 - self.signal_var_9))
self.macd_signal_second = self.macd_signal_first
elif i >= 2:
self.macd_signal_third = self.macd_signal_second
self.macd_signal_forth = self.macd_12_26_total[i]
self.macd_signal_final = (self.macd_signal_forth * self.signal_var_9) + (self.macd_signal_third * (1 - self.signal_var_9))
# self.macd_signal_final = round(self.macd_signal_final, 2) # 소수 셋째 자리에서 반올림 (소수 둘째 자리까지 출력)
self.macd_signal_second = self.macd_signal_final
if i == self.macd_12_26_counting - 7:
self.macd_signal_final_6_mintue_ago = self.macd_signal_final
elif i == self.macd_12_26_counting - 6:
self.macd_signal_final_5_mintue_ago = self.macd_signal_final
elif i == self.macd_12_26_counting - 5:
self.macd_signal_final_4_mintue_ago = self.macd_signal_final
elif i == self.macd_12_26_counting - 4:
self.macd_signal_final_3_mintue_ago = self.macd_signal_final
elif i == self.macd_12_26_counting - 3:
self.macd_signal_final_2_mintue_ago = self.macd_signal_final
elif i == self.macd_12_26_counting - 2:
self.macd_signal_final_1_mintue_ago = self.macd_signal_final
elif i == self.macd_12_26_counting - 1:
self.macd_signal_final_current = self.macd_signal_final
self.price_macd_total = []
self.price_macd_total_final = []
self.macd_12_26_total = []
### macd_oscillators 구하기 ###
self.macd_Oscillator_6_mintue_ago = self.macd_12_26_6_mintue_ago - self.macd_signal_final_6_mintue_ago
self.macd_Oscillator_5_mintue_ago = self.macd_12_26_5_mintue_ago - self.macd_signal_final_5_mintue_ago
self.macd_Oscillator_4_mintue_ago = self.macd_12_26_4_mintue_ago - self.macd_signal_final_4_mintue_ago
self.macd_Oscillator_3_mintue_ago = self.macd_12_26_3_mintue_ago - self.macd_signal_final_3_mintue_ago
self.macd_Oscillator_2_mintue_ago = self.macd_12_26_2_mintue_ago - self.macd_signal_final_2_mintue_ago
self.macd_Oscillator_1_mintue_ago = self.macd_12_26_1_mintue_ago - self.macd_signal_final_1_mintue_ago
self.macd_Oscillator_final_current = self.macd_12_26_current - self.macd_signal_final
self.macd_Oscillator_2_mintue_ago = round(self.macd_12_26_2_mintue_ago - self.macd_signal_final_2_mintue_ago, 2)
self.macd_Oscillator_1_mintue_ago = round(self.macd_12_26_1_mintue_ago - self.macd_signal_final_1_mintue_ago, 2)
self.macd_Oscillator_final_current = round(self.macd_12_26_current - self.macd_signal_final, 2)
print(self.macd_12_26_2_mintue_ago)
print(self.macd_signal_final_2_mintue_ago)
print(self.macd_Oscillator_2_mintue_ago)
print("\n")
print(self.macd_12_26_1_mintue_ago)
print(self.macd_signal_final_1_mintue_ago)
print(self.macd_Oscillator_1_mintue_ago)
print("\n")
print(self.macd_12_26_current)
print(self.macd_signal_final_current)
print(self.macd_Oscillator_final_current)
def stochastic_searching(self):
### 스토캐스틱 지표 #####
self.nq_max_price_list = []
self.nq_min_price_list = []
self.stc_fast_d_list = []
self.stc_slow_k_list_close_min = []
self.stc_slow_k_list_max_min = []
self.stc_slow_d_list_row = []
self.stc_slow_d_list = []
self.stc_slow_k_forth_list = []
self.stc_fast_k_weighting = 2 / (3 + 1)
self.stc_slow_d_weighting = 2 / (5 + 1)
self.stc_oscillator_d_weighting = 2 / (26+1)
self.stc_oscillator_d_9_weighting = 2 / (9+1)
self.stc_slow_oscillator_k_26_close_min_list = []
self.stc_slow_oscillator_k_26_max_min_list = []
self.stc_slow_oscillator_final = []
######################################################
########## 스토캐스틱 패스트 %K, %D ##########
for i in range(0, 50): # 현재 분의 STC_패스트 K, D 구하기
for j in range(i, i + 5):
self.close_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "현재가").strip()))
max_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", j, "고가").strip()))
min_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", j, "저가").strip()))
self.nq_max_price_list.append(max_price_row_data)
self.nq_min_price_list.append(min_price_row_data)
self.close_price_first = self.close_price_row_data
self.max_price_first = max(self.nq_max_price_list)
self.min_price_first = min(self.nq_min_price_list)
self.nq_max_price_list = []
self.nq_min_price_list = []
self.stc_fast_k_first = (self.close_price_first - self.min_price_first) / (self.max_price_first - self.min_price_first) * 100
self.stc_fast_k_first = round(self.stc_fast_k_first, 2) # 소수 셋째자리에서 반올림
self.stc_fast_d_list.append(self.stc_fast_k_first)
self.stc_fast_d_list_final = self.stc_fast_d_list[::-1]
self.stc_fast_k = self.stc_fast_d_list_final[29]
self.stc_fast_d_list = []
for i in range(len(self.stc_fast_d_list_final)):
if i == 0:
self.stc_fast_d_first = self.stc_fast_d_list_final[i]
elif i >= 1:
self.stc_fast_d_second = (self.stc_fast_d_list_final[i] * self.stc_fast_k_weighting) + (self.stc_fast_d_first * (1 - self.stc_fast_k_weighting))
self.stc_fast_d_first = self.stc_fast_d_second
if i == 49:
self.stc_fast_d_0_ago = round(self.stc_fast_d_first, 2) # 현재시간
elif i == 48:
self.stc_fast_d_1_ago = round(self.stc_fast_d_first, 2) # 1분전
elif i == 47:
self.stc_fast_d_2_ago = round(self.stc_fast_d_first, 2) # 2분전
elif i == 46:
self.stc_fast_d_3_ago = round(self.stc_fast_d_first, 2) # 3분전
elif i == 45:
self.stc_fast_d_4_ago = round(self.stc_fast_d_first, 2) # 4분전
elif i == 44:
self.stc_fast_d_5_ago = round(self.stc_fast_d_first, 2) # 5분전
self.stc_fast_d_list_final = []
self.stc_fast_k = round(self.stc_fast_k, 2)
self.stc_fast_d = round(self.stc_fast_d_second, 2)
# print(self.stc_fast_k)
# print(self.stc_fast_d)
########## 스토캐스틱 슬로우 %K, %D ##########
for i in range(0, 50):
for j in range(i, i+5): # 현재 분의 STC_슬로우 K, D 구하기 /// stc_slow_k = ∑(현재가 - 최대값) / ∑(최대값 - 최소값)
for k in range(j, j + 12):
self.close_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", j, "현재가").strip()))
max_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", k, "고가").strip()))
min_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", k, "저가").strip()))
self.nq_max_price_list.append(max_price_row_data)
self.nq_min_price_list.append(min_price_row_data)
self.close_price_first = self.close_price_row_data
self.max_price_first = max(self.nq_max_price_list)
self.min_price_first = min(self.nq_min_price_list)
self.nq_max_price_list = []
self.nq_min_price_list = []
self.price_first_close_min = self.close_price_first - self.min_price_first
self.price_first_max_min = self.max_price_first - self.min_price_first
self.stc_slow_k_list_close_min.append(self.price_first_close_min)
self.stc_slow_k_list_max_min.append(self.price_first_max_min)
self.stc_slow_k_first = sum(self.stc_slow_k_list_close_min)
self.stc_slow_k_second = sum(self.stc_slow_k_list_max_min)
self.stc_slow_k_list_close_min = []
self.stc_slow_k_list_max_min = []
self.stc_slow_k_third = self.stc_slow_k_first / self.stc_slow_k_second * 100
self.stc_slow_k_third = round(self.stc_slow_k_third, 2)
self.stc_slow_k_forth_list.append(self.stc_slow_k_third)
if i == 0:
self.stc_slow_k = self.stc_slow_k_forth_list[0]
elif i == 1:
self.stc_slow_k_1_ago = self.stc_slow_k_forth_list[1]
self.stc_slow_d_list = self.stc_slow_k_forth_list[::-1]
self.stc_slow_k_forth_list = []
for i in range(0, 50):
if i == 0:
self.stc_slow_d_first = self.stc_slow_d_list[i]
elif i >= 1:
self.stc_slow_d_second = (self.stc_slow_d_list[i] * self.stc_slow_d_weighting) + (self.stc_slow_d_first * (1 - self.stc_slow_d_weighting))
self.stc_slow_d_first = self.stc_slow_d_second
if i == 49:
self.stc_slow_d_0_ago = round(self.stc_slow_d_first, 2) # 현재시간
elif i == 48:
self.stc_slow_d_1_ago = round(self.stc_slow_d_first, 2) # 1분전
elif i == 47:
self.stc_slow_d_2_ago = round(self.stc_slow_d_first, 2) # 2분전
elif i == 46:
self.stc_slow_d_3_ago = round(self.stc_slow_d_first, 2) # 3분전
elif i == 45:
self.stc_slow_d_4_ago = round(self.stc_slow_d_first, 2) # 4분전
elif i == 44:
self.stc_slow_d_5_ago = round(self.stc_slow_d_first, 2) # 5분전
self.stc_slow_d = round(self.stc_slow_d_first, 2)
self.stc_slow_d_list = []
# print(self.stc_slow_k)
# print(self.stc_slow_d)
########## 스토캐스틱 오실레이터 ##########
### 오실레이터_fast_%D 구하기 ###
for i in range(0, 150): # 현재 분의 STC_오실레이터 구하기
for j in range(i, i + 12):
self.close_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", i, "현재가").strip()))
max_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", j, "고가").strip()))
min_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", j, "저가").strip()))
self.nq_max_price_list.append(max_price_row_data)
self.nq_min_price_list.append(min_price_row_data)
self.close_price_first = self.close_price_row_data
self.max_price_first = max(self.nq_max_price_list)
self.min_price_first = min(self.nq_min_price_list)
self.nq_max_price_list = []
self.nq_min_price_list = []
self.stc_fast_k_first = (self.close_price_first - self.min_price_first) / (self.max_price_first - self.min_price_first) * 100
self.stc_fast_k_first = round(self.stc_fast_k_first, 2) # 소수 셋째자리에서 반올림
self.stc_fast_d_list.append(self.stc_fast_k_first)
self.stc_fast_d_list_final = self.stc_fast_d_list[::-1]
self.stc_fast_d_list = []
for i in range(len(self.stc_fast_d_list_final)):
if i == 0:
self.stc_oscillator_d_first = self.stc_fast_d_list_final[i]
elif i >= 1:
self.stc_oscillator_d_second = (self.stc_fast_d_list_final[i] * self.stc_oscillator_d_weighting) + (self.stc_oscillator_d_first * (1 - self.stc_oscillator_d_weighting))
self.stc_oscillator_d_first = self.stc_oscillator_d_second
if i == 149:
self.stc_oscillator_fast_d_0_ago = round(self.stc_oscillator_d_first, 2)
elif i == 148:
self.stc_oscillator_fast_d_1_ago = round(self.stc_oscillator_d_first, 2)
elif i == 147:
self.stc_oscillator_fast_d_2_ago = round(self.stc_oscillator_d_first, 2)
elif i == 146:
self.stc_oscillator_fast_d_3_ago = round(self.stc_oscillator_d_first, 2)
elif i == 145:
self.stc_oscillator_fast_d_4_ago = round(self.stc_oscillator_d_first, 2)
elif i == 144:
self.stc_oscillator_fast_d_5_ago = round(self.stc_oscillator_d_first, 2)
self.stc_fast_d_list_final = []
self.stc_oscillator_fast_d = round(self.stc_oscillator_d_first, 2) # 현재시간의 오실레이터_fast_d
# print(self.stc_oscillator_fast_d)
### 오실레이터_slow_%D 구하기 ###
for i in range(0, 150):
for j in range(i, i+26): # 현재 분의 STC_슬로우 K, D 구하기 /// stc_slow_k = ∑(현재가 - 최대값) / ∑(최대값 - 최소값)
for k in range(j, j + 12):
self.close_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", j, "현재가").strip()))
max_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", k, "고가").strip()))
min_price_row_data = abs(float(self.kiwoom.dynamicCall("GetCommData(QString,QString,int,QString)", "opc_10002", "opc10002", k, "저가").strip()))
self.nq_max_price_list.append(max_price_row_data)
self.nq_min_price_list.append(min_price_row_data)
self.close_price_first = self.close_price_row_data
self.max_price_first = max(self.nq_max_price_list)
self.min_price_first = min(self.nq_min_price_list)
self.nq_max_price_list = []
self.nq_min_price_list = []
self.price_first_close_min = self.close_price_first - self.min_price_first
self.price_first_max_min = self.max_price_first - self.min_price_first
self.stc_slow_k_list_close_min.append(self.price_first_close_min)
self.stc_slow_k_list_max_min.append(self.price_first_max_min)
self.stc_slow_k_first = sum(self.stc_slow_k_list_close_min)
self.stc_slow_k_second = sum(self.stc_slow_k_list_max_min)
self.stc_slow_k_list_close_min = []
self.stc_slow_k_list_max_min = []
self.stc_slow_oscillator_k_26_close_min_list.append(self.stc_slow_k_first)
self.stc_slow_oscillator_k_26_max_min_list.append(self.stc_slow_k_second)
self.stc_slow_oscillator_k_26_close_min_list = self.stc_slow_oscillator_k_26_close_min_list[::-1]
self.stc_slow_oscillator_k_26_max_min_list = self.stc_slow_oscillator_k_26_max_min_list[::-1]
self.stc_slow_oscillator_k_26_close_min = sum(self.stc_slow_oscillator_k_26_close_min_list)
self.stc_slow_oscillator_k_26_max_min = sum(self.stc_slow_oscillator_k_26_max_min_list)
self.stc_slow_oscillator_k_26_close_min_list = []
self.stc_slow_oscillator_k_26_max_min_list = []
self.stc_slow_oscillator_k_26 = self.stc_slow_oscillator_k_26_close_min / self.stc_slow_oscillator_k_26_max_min * 100
self.stc_slow_oscillator_k_26 = round(self.stc_slow_oscillator_k_26, 2)
self.stc_slow_oscillator_final.append(self.stc_slow_oscillator_k_26)
self.stc_slow_oscillator_final = self.stc_slow_oscillator_final[::-1]
for i in range(0, 150):
if i == 0:
self.stc_oscillator_d_first = self.stc_slow_oscillator_final[i]
elif i >= 1:
self.stc_oscillator_d_second = (self.stc_slow_oscillator_final[i] * self.stc_oscillator_d_9_weighting) + (self.stc_oscillator_d_first * (1 - self.stc_oscillator_d_9_weighting))
self.stc_oscillator_d_first = self.stc_oscillator_d_second
if i == 149:
self.stc_oscillator_slow_d_0_ago = round(self.stc_oscillator_d_first, 2)
elif i == 148:
self.stc_oscillator_slow_d_1_ago = round(self.stc_oscillator_d_first, 2)
elif i == 147:
self.stc_oscillator_slow_d_2_ago = round(self.stc_oscillator_d_first, 2)
elif i == 146:
self.stc_oscillator_slow_d_3_ago = round(self.stc_oscillator_d_first, 2)
elif i == 145:
self.stc_oscillator_slow_d_4_ago = round(self.stc_oscillator_d_first, 2)
elif i == 144:
self.stc_oscillator_slow_d_5_ago = round(self.stc_oscillator_d_first, 2)
self.stc_slow_oscillator_k = self.stc_slow_oscillator_final[99] # 현재시간의 오실레이터_slow_k
self.stc_slow_oscillator_final = []
self.stc_oscillator_slow_d = round(self.stc_oscillator_d_first, 2)
# print(self.stc_oscillator_slow_d)
self.stc_oscillator_current = self.stc_oscillator_fast_d - self.stc_oscillator_slow_d # 200줄, 262줄
self.stc_oscillator_current = round(self.stc_oscillator_current, 2) # 현재시간의 오실레이터_slow_d /// # 부동소수점 문제로 소수 셋째자리에서 반올림
# print(self.stc_oscillator_current)
self.stc_oscillator_0_ago = round(self.stc_oscillator_fast_d_0_ago - self.stc_oscillator_slow_d_0_ago, 2)
self.stc_oscillator_1_ago = round(self.stc_oscillator_fast_d_1_ago - self.stc_oscillator_slow_d_1_ago, 2)
self.stc_oscillator_2_ago = round(self.stc_oscillator_fast_d_2_ago - self.stc_oscillator_slow_d_2_ago, 2)
self.stc_oscillator_3_ago = round(self.stc_oscillator_fast_d_3_ago - self.stc_oscillator_slow_d_3_ago, 2)
self.stc_oscillator_4_ago = round(self.stc_oscillator_fast_d_4_ago - self.stc_oscillator_slow_d_4_ago, 2)
self.stc_oscillator_5_ago = round(self.stc_oscillator_fast_d_5_ago - self.stc_oscillator_slow_d_5_ago, 2)
########## 시간 현행화 ###########
def time_update(self):
self.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.traded_date = self.date_time[0:10]
self.traded_time = self.date_time[11:19]
########## 시간별 패턴 구분을 위한 구분 함수 ###########
def time_pattern_gubun(self):
now_time1 = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
now_time1 = now_time1[11:16]
now_time2_t = now_time1[0:2] # 시간 단위를 문자형으로 추출
now_time3_m = now_time1[3:5] # 분 단위를 문자형으로 추출
self.now_time3 = now_time2_t + now_time3_m # 분/초 단위를 하나로 붙임(문자형+문자형)
now_time4 = int(self.now_time3) # 문자형을 숫자형으로 변환
########## 진입/청산 시도 횟수 체크 ##########
def var_test_check(self):
self.var_test_1 = self.var_test_1 + self.j
print(self.var_test_1)
if __name__ == "__main__":
app = QApplication(sys.argv)
btl = btl_system()
btl.rq_data_opc10002("NQZ23", "1")
app.exec_()
5. 마치며
진입/청산을 위해 시도하는 횟수를 체크하는 코드를 알아보았다. 실제로 진입/청산 체크하는 결과물을 보면 좋겠지만, 3번(전체코드)에서 설명 및 결과로도 체크횟수 원리는 이해했으리라 생각된다. 사용자의 취향에 따라 체크할지 말지 결정하면 된다.
다음 글에서는 청산 후 대기하는 시간을 설정하는 방법을 알아보자.
'2. 해외선물 > 2-1. 해외선물 자동매매 연구' 카테고리의 다른 글
(키움증권 해외선물 자동매매 파이썬) 22. 진입/청산 알고리즘 구상하기(完) (2) | 2023.10.29 |
---|---|
(키움증권 해외선물 자동매매 파이썬) 21. 매매내역을 엑셀로 기록하기 (8) | 2023.10.28 |
(키움증권 해외선물 자동매매 파이썬) 20. 오버나잇(overnight) 피하는 방법 (매매 종료시간 설정) (5) | 2023.10.27 |
(키움증권 해외선물 자동매매 파이썬) 19. 매매시간 및 대기시간 설정 (0) | 2023.10.26 |
(키움증권 해외선물 자동매매 파이썬) 17. 시간별 다른 코드 적용하기 (3) | 2023.10.24 |
(키움증권 해외선물 자동매매 파이썬) 16. 현재시간 출력하기 (5) | 2023.10.23 |
(키움증권 해외선물 자동매매 파이썬) 15. 보조지표 구하기 (볼린저밴드, MACD, 스토캐스틱) (0) | 2023.10.22 |
(키움증권 해외선물 자동매매 파이썬) 14. rsi 구하기 (4) | 2023.10.21 |