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

(키움증권 해외선물 자동매매 파이썬) 20. 오버나잇(overnight) 피하는 방법 (매매 종료시간 설정)

봄이오네 2023. 10. 27. 08:06
반응형

 

목 차
1. 들어가며
2. 사전설명
   1) 청산후 대기(time.sleep)하는 방법
   2) 청산후 시스템 종료(shutdown)하는 방법
3. 전체코드
4. 전체코드
5. 마치며

 

1. 들어가며

지난 글에서는 "진입후 매매시간 및 청산후 대기시간" 설정에 대해 알아보았다. 개인의 투자성향에 따라 달리 설정하거나, 아예 미설정할 수 있는 내용이다. 사용자가 잘 판단하여 본인의 프로그램에 적용하자. 필자의 경우도 "진입후 매매시간"을 1시간 설정을 바꿀 의향이 있다. 1시간은 너무 길어서 "시장의 변동성"에 유연하게 대응하지 못할 것 같기 때문이다. 매매시간을 수정할지는 차차 고민해볼 문제이다.

 

이번 글에서는 매매정지를 위해 자동매매 시스템을 멈추는 방법을 알아보자.

필자의 경우 오버나잇(overnight)을 통한 종가베팅을 싫어한다. 이유는? 그 다음날 무조건 갭상/갭하락을 정통으로 맞기 때문이다. 수익이 나면 괜찮겠지만, 갭하락 등을 통한 손실에 멘탈이 나가버린게 한두번이 아니다. 그래서 무조건 당일 매매를 원칙으로 하며, 오버나잇은 지양하려고 한다.

 

그렇게 하기 위해서 필요한 것은 무엇일까? 2가지 방법이 있다. 첫번째는 일정시간 이후 자동매매 시스템 매매를 멈추는 방법(time.sleep)이 있고, 두번째는 일정시간이 되면 가지고 있는 종목을 청산하고, pc를 종료(shutdown)하는 방법이 있을 것이다.

 


2. 사전설명

지금 우리가 알아보고자 하는 것은 오버나잇을 피하는 방법이다. 각각의 방법에 대한 장단점을 파악 후 사용자 본인에게 맞는 방법을 시스템에 적용하면 된다.

 

필자는 위의 2가지 방법을 모두 설명할 것이다. 다만, 필자의 경우 첫번째인 매매시스템을 멈추는 방법을 선택하고 있다. 이유는? 노트북에서는 잘되는데, 데스크탑에서는 pc종료(shutdown) 명령어가 안 먹힌다. ㅠㅠ

 

1) 청산후 대기(time.sleep)하는 방법

지난 글에서 설명한 청산후 현재시간이 설정한 시간의 범위에 들어오면 대기(time.sleep)로 설정한다. 서머타임이 적용되는 시기에는 500~700으로 시간을 설정하여 현재시간이 오전5시~오전7시 범위를 인식하면 멈추는 구조이다.

 

사실 이 방법은 약간의 리스크가 있다. 위 방법은 청산 후 현재시간이 설정시간 범위(500~700) 내에 있으면 멈추는 구조이다. 그런데 청산을 하지 못한다면? 더 정확히 이야기하면, 사용자가 설정한 진입 알고리즘에 해당하지 않아, 계속 진입시도를 한다면 어떻게 될까?

 

실제 필자의 경우, 시스템 매매를 하는 동안 1~2번 정도는 의도하지 않게 오버나잇을 했다. ㅠㅠ

그 때의 상황은, 설정한 진입 알고리즘에 해당하지 않아 계속 진입 시도를 하다가, 6시 장마감(서머타임 기준) 전인 05:48분에 진입이 되는 것이다. 당연히 청산시도를 했는데, 설정한 수익값, 손실값, 횡보장(60분) 모두에 해당하지 않아 오버나잇이 되었다.

 

2) 청산후 시스템 종료(shutdown)하는 방법

이 방법은 필자는 적용하지 않고 있지만, pc를 바꾸든가 매매 하드웨어 변경시 반드시 적용하고 싶은 내용이다.

청산후 시스템 종료도 위의 "청산후 대기"와 같은 단점(05:48분 진입후 청산 못함)이 있지만, pc의 부담을 줄여줄 수 있다는 측면에서 자동매매를 돌리는 사용자의 마음을 편안하게 해줄 것이다.

 


3. 전체코드

여기서는 매매를 멈추고 대기하는 방법을 알아보자. 매매 종료 후 pc 종료는 필자가 사용하지 않으므로, 별도 설명하지는 않을 것이다.

 

그림1. 매매 종료를 위한 시간(18줄~19줄) 및 대기시간 설정(21줄)

 

 

11줄 : 진입/청산할 기준점이 되는 금액이다. 사용자 취항에 따라 설정한다. 미니 나스닥 1거래 위탁증거금이 18,480달러이다. 사용자에게 22,000달러가 있다고 가정하자. 진입을 하기전 "주문가능금액"은 22,000달러므로 11줄에서 설정(20,000달러)값보다 크므로 59줄~62줄에 의해 진입 알고리즘이 실행된다.

 

14줄~15줄 : 진입후 청산까지, 매매지속 시간은 60초(나중에 60 x 60초 = 3600초)로 설정하였고, 청산후 대기시간 10분으로 설정하였다.

 

18줄~19줄 : 청산후 7200초(21줄) 대기할 시작시간(500)과 종료시간(700)을 설정한다.

21줄 : 시스템 대기시간(7200초)를 설정한다.

 

그림2. 거래가능 시간 체크

 

24줄~32줄 : 현재시간을 설정(32줄, self.now_time4)한다.

 

35줄~40줄 : 거래가능 시간을 체크한다. 

36줄 : 24줄~32줄의 현재시간을 체크한다.

37줄 : 현재시간(self.now_time4)이 18줄~19줄에서 설정한 시간의 범위에 해당하면,

38줄 : 21줄에서 설정한 시간(7200초) 동안 멈추어라.

 

42줄~51줄 : 진입후 청산시도를 하고 있다고 가정하자.

43줄 : 진입이 매도인 경우

44줄 : 청산가능수량을 조회한다.

45줄 : 진입가격-현재가격 >= 설정한 값(10p or 30p)이면,

46줄 : 여기서는 생략했지만, 청산 주문(sendorder) 하라

47줄 : (평소의 경우) 15줄에서 설정한 600초를 대기하라.

48줄 : 이 글의 핵심이다. 현재시간이 35줄~40줄에서 설정한 시간이면, 38줄(7200초)의 내용처럼 대기하라.

 

※ 여기서 잠깐! 시스템 대기(time.sleep)가 아닌, 종료를 하고 싶으면,
38줄을 다음과 같이 변경해주면 된다.
ㅇ 38줄 당초 : time.sleep(self.pc_wait_time)
ㅇ 38줄 변경 : os.system('shutdown -s -f')
    * 응용프로그램을 강제종료하고 시스템을 종료하는 방법
    * 그리고, 맨 위 1번줄에 import os를 넣어주어, os 라이브러리를 활용하게 해준다.

 

54줄~75줄 : 주문가능금액에 따른 진입/청산 알고리즘 실행 및 전체프로그램 실행에 관한 내용으로 설명을 생략한다.


4. 전체코드

아래 < 접은글 >의 코드는 실행되지 않는다. 매매 대기시간 설정을 통해 "매매 종료"시간 설정하는 방법의 감각을 익히면 될 것으로 생각된다.

 

더보기
import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
import time
from datetime import datetime

class btl_system():
    def __init__(self):
        self.kiwoom = QAxWidget("KFOPENAPI.KFOpenAPICtrl.1")

        self.check_money = 20000

        ########## 제한시간 ##########
        self.limit_time = 60  # 60분 * 1시간   # 제한시간 (진입~청산까지 지켜보는 시간, 516줄)
        self.wait_time = 600  # 거래 후 재진입까지 대기 시간 (631줄)

        ########## pc 멈추는 시간 ##########
        self.start_time_pattern_gubun = 500  # 446줄
        self.ending_time_pattern_gubun = 700  # if self.start_time_pattern_gubun <= self.now_time4 <= self.ending_time_pattern_gubun :

        self.pc_wait_time = 7200  # 427줄 (pc 대기), 7200초(2시간)

    ########## 시간별 패턴 구분을 위한 구분 함수 ###########
    def time_pattern_gubun(self):
        now_time1 = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        now_time1 = now_time1[11:16]
        now_time2_m = now_time1[0:2]  # 분 단위를 문자형으로 추출
        now_time3_s = now_time1[3:5]  # 초 단위를 문자형으로 추출

        now_time3 = now_time2_m + now_time3_s  # 분/초 단위를 하나로 붙임(문자형+문자형)
        now_time4 = int(now_time3)  # 문자형을 숫자형으로 변환
        self.now_time4 = now_time4  # 전역변수로 pl_check1에서 활용

    ########## 거래가능 시간 체크 ###########
    def system_wait_time(self):
        btl.time_pattern_gubun()
        if self.start_time_pattern_gubun <= self.now_time4 <= self.ending_time_pattern_gubun:
            time.sleep(self.pc_wait_time)  # 103줄에서 180으로 설정
        else:
            pass

    def "청산함수"(self)
        if self.sell_buy_gubun_d == "1":  # 진입이 매도인 경우 (short으로 진입한 332줄~371줄 관련)

        btl.rq_data_opw30011(self.deposit_num, self.deposit_password, "00", self.stock_code_d, "2", "1", "")  # 청산수량 받아오기 위해 실행, # ~~~ self.stock_code_d, "1" 에서 "2"은 "매수"로 설정한다.


            if self.my_price_d_30012 - self.current_price_d_30012 >= self.profit_loss_price:
                ### 청산 주문(sendorder 함수)
                time.sleep(self.wait_time)  # 103줄에서 180으로 설정
                btl.system_wait_time()  # 해선 05:00~07:00, 2시간 멈춤 (종가베팅 방지)

    ########## 시스템 실행 ##########
    def trading_start(self):
        while True:
            btl.rq_data_opw30009(btl.deposit_num, btl.deposit_password, "00")  # 주문가능금액
            btl.time_pattern_gubun()  # 464줄에서 정의

            if btl.orderable_money > btl.check_money:
                print(f"주문가능금액이 {btl.check_money}달러 이상일 때 진입 준비 중")
                ### 진입 함수 실행
                time.sleep(10)

            else:
                print(f"주문가능금액이 {btl.check_money}달러 이하일 때 청산 준비 중")
                ### 청산 함수 실행
                time.sleep(10)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    btl = btl_system()

    btl.trading_start()

    app.exec_()

 


5. 마치며

종가베팅을 통한 오버나잇 피하는 방법에 대해 알아보았다. 오버나잇을 피하는 방법 중 가장 간단한 방법은 매매를 안하는 것이다. 사람의 심리상 지나치게 가격이 떨어지면, 다음날 갭상을 생각해서 진입 후 잠에 드는 경우가 있는데... 다음날의 기분이나 컨디션을 생각하면, 오버나잇은 왠만하면 자제하기로 했다.

 

다음 시간에는 거래 정보를 엑셀에 기록을 남기는 "로그파일 만들기"에 대해 알아보자.

 

반응형