2. 해외선물/2-1. 해외선물 자동매매 연구

(키움증권 해외선물 자동매매 파이썬) 18. 진입/청산 시도횟수 체크하기

봄이오네 2023. 10. 25. 08:07
반응형

 

목 차
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번(전체코드)에서 설명 및 결과로도 체크횟수 원리는 이해했으리라 생각된다. 사용자의 취향에 따라 체크할지 말지 결정하면 된다.

 

다음 글에서는 청산 후 대기하는 시간을 설정하는 방법을 알아보자.

 

반응형