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

(키움증권 해외선물 자동매매 파이썬) 19. 매매시간 및 대기시간 설정

봄이오네 2023. 10. 26. 08:09
반응형

 

목 차
1. 들어가며
2. 사전설명
   1) 진입후 매매시간 설정 필요성
   2) 청산후 대기시간 설정 필요성
3. 코드설명
4. 전체코드
5. 마치며

 

1. 들어가며

지난 글에서는 진입/청산 시도횟수를 구하는 방법을 알아보았다. 개인의 취향이겠지만, 자동매매 과정에서 파이참(pycharm) 화면에 아무것도 출력되지 않는다면, 매매가 제대로 이루어지고 있는지 고민이 많을 것이다. 자동매매 시스템에 익숙해질 때까지는 화면에 시도횟수를 출력하는 것도 좋아보인다.

 

이번 글에서는 시간을 설정/제한하는 방법을 알아보자. 

 


2. 사전설명

1) 진입후 매매시간 설정 필요성

long이든 short이든 진입을 해서 수익/손실로 설정한 값에 도달하면 청산을 하는 경우로 설정한다. 그런데, 진입 후 횡보장일 때 어떻게 할 것인가? 대개 횡보가 길다는 것은 "힘을 비축"하고 있다고들 한다. 즉 대규모의 거래량을 동반한 큰 변화가 올 수 있다. 바꾸어말하면 우리가 설정한 알고리즘으로 시장이 움직이지 않고 계속 횡보하다가, 시장의 급격한 변화에 그대로 노출되는 것이다.

 

시장은 매시간 변한다. 어제 수익을 얻었던 알고리즘이 오늘은 손실을 줄 수도 있다. 그렇다면, 무엇을 해야할까?

진입 후 보유하는 시간, 즉 매매시간을 일정하게 가져가야 한다. 사람들마다 다르겠지만, 필자의 경우 60분 정도는 보유하고 있다. 60분 동안 수익이든 손실이든, 무엇인가 결론이 나게 설정하되, 횡보장으로 가격/거래량 변동이 없는 경우 60분 이후에는 시장가로 청산을 하는 식으로 시스템을 구성한다.

 

2) 청산후 대기시간 설정 필요성

청산을 했다는 것은 어찌되었든 가격의 변동이 있을 때이다.

예를 들어 사용자가 설정한 알고리즘1이 "돌파매매"라고 가정하자. 알고리즘2인 long으로 진입했는데 하필 신고가(新高價)에서 청산하였다고 하자. 그런데 여기서 알고리즘1이 적용되어 "돌파매매"로 진입이 된다면, 수익이 날것인가? 상황에 따라 다르고 사용자의 취향에 따라 다르겠지만, 필자의 경우 신고가 돌파매매는 하지 않는다. 즉, 필자는 청산 후 몇분정도는 대기시간(time.sleep)를 주어 시장을 관망한다. 청산 후 대기시간은 대개 3분~10분으로 주고 있다.

 

※ 시장상황과 개인의 투자성향 차이라고 생각된다. 지속적으로 진입/청산하고 싶으면 "매매시간 및 대기시간"을 설정해줄 필요는 없을 것이다.

여기서 잠깐! 매매시간 및 대기시간 설정 필요성 정리
① 진입후 매매시간 설정 필요성 : 횡보장에 대응할 필요 있음
② 청산후 대기시간 설정 필요성 : 수익/손실이 났다는 것은 "불이 한번 났다"는 것이라 볼 수 있다. 불이 꺼질 때까지 기다리는 여유를 갖자.

 


3. 코드설명

특별히 추가할 코드는 없다. 적용원리를 설명하는 정도에서 설명할 것이다.

 

그림1. 진입후 매매시간 및 청산후 대기시간을 설정하는 내용

 

8줄 : 진입/청산의 기준이 되는 금액을 설정한다. 43줄~51줄에서 활용된다.

12줄 : 진입후 설정한 시간을 넣어준다. 여기에서 설정한 60초는 19줄에서 활용된다. 19줄에서 60 x 60 = 3600초(=1시간)이 된다.

13줄 : 청산후 설정한 시간을 넣어준다. 13줄에서 설정한 600초는 35줄에서 활용된다. 33줄에서 확인가능하겠지만, time.time()는 현재시간을 뜻한다. 현재시간이 19줄에서 설정한 self.ending_time보다 크면(시간 초과하면) 시장가로 청산한다.

16줄 : 익절가 및 손절가를 넣어준다.(=현재가격-청산가격)

 

※ 참고로 time라이브러리를 이용하여 현재시간을 표기할 때는 UNIX시간이 적용된다. UNIX시간 설정 관련하여서는 예전에 설명하였다. 링크(https://springcoming.tistory.com/57)를 참고하자.

 

※ 프로그램이 최초 실행되면 57줄이 실행되면서 43줄의 함수(trading_start)가 실행된다. 주문가격의 크기에 따라 18줄 진입함수가 실행될지 24줄 청산함수가 실행될지 결정된다. 즉, 주문가격이 설정한 금액보다 크다면(=아직은 미진입) 15줄의 함수가 실행(진입함수)되고, 주문가격이 설정 금액보다 작으면(=이미 진입) 24줄의 함수(청산함수)가 실행된다.

 

18줄~22줄 : 진입 알고리즘을 임의로 설정해보았다. "현재가격의 rsi가 30이하일 때 롱 진입"하라는 것을 사례로 들었다.

 

19줄 : 현재가격의 rsi가 30이하이면,

20줄 : 여기서는 생략했지만, sendorder 함수를 실행하여 진입하라는 코드이다.

22줄 : 12줄에서 설정한 숫자(60초)가 self.limit_time에 들어가서, 32줄, 에서 활용될 self.ending_time의 내용을 규정한다.

 

24줄~40줄 : 주문(sendorder)함수에 대한 내용은 생략(###으로 표기)한다.

25줄 : 계좌에 있는 매도수구분, 매입단가 등 을 알아보기 위해 opw30012를 실행한다.

27줄 : 진입이 매수(long)인 경우(매도수구분 2)이면,

28줄 : 청산가능수량을 알아보기 위해 opw30011을 실행한다.

 

그림2. 설정한 시간에 따라 적용될 수익/손실/횡보장 청산 코드 내용

 

30줄 : "현재가격 - 진입가격" >  10이면, (16줄에서 10을 설정해 주었다)

31줄 : 청산주문을 실행하라. (지금은 long진입을 예시로 들었다)

32줄 : 13줄에서 설정한 숫자(600초)에 따라 10분간 대기(time.sleep)한다. (청산후 대기시간 설정)

 

34줄 : "현재가격 - 진입가격" < 10이면,

35줄 : 청산주문을 실행하라.

36줄 : 13줄에서 설정한 숫자(600초)에 따라 10분간 대기(time.sleep)한다. (청산후 대기시간 설정)

 

38줄 : 현재시간이 22줄에서 설정한 시간(self.ending_time)을 초과하면, (진입후 횡보장에 해당하면)

39줄 : 청산주문을 실행하라

40줄 : 13줄에서 설정한 숫자(600초)에 따라 10분간 대기(time.sleep)한다. (청산후 대기시간 설정)

 

→ 32줄, 36줄, 40줄은 모두 600초(10분) 동일하게 청산 후 대기하라는 의미이다.

 


4. 전체코드

아래 < 접은글 >의 코드는 실행되지 않는다. "진입후 횡보장 탈출시간 설정" 및 "청산후 대기시간 설정"의 코드흐름만 파악하는 용도로 활용하자.

 

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

class btl_system():
    def __init__(self):

        ########## 진입/청산할지 기준이 되는 금액 ##########
        self.check_money = 20000

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

        ########## 진입/청산을 위한 수익/손실 선언 ##########
        self.profit_loss_price = 10  # 진입/청산 차이

    def enter_trading(self):
        if self.current_rsi <= 30:
            ### sendorder 함수를 이용하여 "long"으로 진입하라는 코드

            self.ending_time = time.time() + (60 * self.limit_time)  # 진입한 시점 / + (60 * 10)  # 10분 설정

    def liquidable_trading(self):
        btl.rq_data_opw30012(self.deposit_num, self.deposit_password, "00")  # 매도수 구분 조회위해 실행 # 계좌의 종목, 매도수구분, 수량, 매입단가, 현재가, 평가손익을 나타냄

        if self.sell_buy_gubun_d == "2":  # 진입이 매수인 경우 (long으로 진입한 291줄~330줄 관련)
            btl.rq_data_opw30011(self.deposit_num, self.deposit_password, "00", self.stock_code_d, "1", "1", "")  # 청산수량 받아오기 위해 실행, # ~~~ self.stock_code_d, "1" 에서 "1"은 "매도"로 설정한다.

            if self.current_price_d_30012 - self.my_price_d_30012 >= self.profit_loss_price:
                ### 수익으로 청산하라
                time.sleep(self.wait_time)  # 103줄에서 180으로 설정

            elif self.current_price_d_30012 - self.my_price_d_30012 <= -1 * self.profit_loss_price:
                ### 손실로 청산하라
                time.sleep(self.wait_time)  # 103줄에서 180으로 설정

            if time.time() > self.ending_time:
                ### 시장가로 청산하라
                time.sleep(self.wait_time)  # 103줄에서 180으로 설정

    ########## 시스템 실행 ##########
    def trading_start(self):
        while True:
            btl.rq_data_opw30009(btl.deposit_num, btl.deposit_password, "00")  # 주문가능금액
            if btl.orderable_money > btl.check_money:
                btl.enter_trading()
                time.sleep(10)
            else:
                btl.liquidable_trading()
                time.sleep(10)

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

    btl.trading_start()

    app.exec_()

 


5. 마치며

진입후 매매 시간 및 청산후 대기시간에 대해 알아보았다. 개인의 투자성향에 따라 다르게 설정될 것 같다. 진입후 매매시간 60분이 길어, 20분으로 설정한 이용자도 있을 것이고, 청산후 대기시간을 설정하지 않는 이용자도 있을 것이다. 각각의 투자성향에 맞혀 설정하는 것이 좋아보인다.

 

다음 시간에는 종가베팅을 방지하기 위해 "pc 멈추는 시간 설정"하는 방법에 대해 알아보자.

 

반응형