PYTHON/Back test

백테스팅 구축 (3) - 일자 계산하기

  • -

이전 게시글에서는 차트 데이터를 가공하는 코드를 구축하고 그를 저장하는 방법에 대해 알아보았다. 따라서 이번 포스팅에서는 하루 하루를 돌면서 매수 조건을 충족시키는 종목 리스트를 구하고, 그를 바탕으로 거래를 진행하는 방법에 대해 살펴볼 예정이다.

 

특정 일자에 매수 조건을 충족하는 종목 선정하기

우리는 이전에 백테스팅을 하기 위해 start_date와 end_date, 그리고 all_range라는 세 개의 일자 변수를 설정했고, 이 일자 변수를 기준으로 해서 백테스팅을 진행할 계획을 수립했다. 그렇다면 start_date부터 시작해서 하루하루를 더하며 거래를 할 종목들을 찾아야 하는데, 종목을 찾기 위해서는 그 전에 매수 조건을 설정해야 한다. 매수 조건의 경우 이전 게시글에서 이동평균선을 구축했으니 해당 이동평균선을 기준으로 해서 매수 전략을 수립한 후에 백테스팅을 진행하도록 하겠다. 이번 포스팅에서 테스트해 볼 가장 기본적인 매수 전략은 아래와 같다.

  • 5일 이동평균선이 20일 이동평균선을 돌파할 때 매수
  • 5일 이동평균선이 20일 이동평균선을 이탈할때 매도

이에 따라 우리의 코드는 '일자 설정' → '조건 확인' → '매수 리스트 삽입' → '매수 가격 및 손절률 설정' → '백테스팅'의 절차를 거치게 된다. 따라서 일자를 먼저 돌면서 해당 일자의 조건을 수립하는 부분까지만 일단 제작해보도록 하자.

 

일자 계산 함수 제작하기

일자 계산의 경우에는 datetime 모듈의 timedelta 함수를 통해 계산할 수 있으며, weekday()라는 메서드(함수)를 통해 해당 일자가 주말인지 아닌지 역시 확인 가능하다. 여기서 제작할 함수의 이름은 cal_addday이며, 해당 함수에서 받을 변수로는 standard_day와 howmany 두 개이다. 먼저 standard_day라는 변수를 통해 우리가 계산하고자 하는 일자를 입력한 후에, howmany라는 변수를 통해 standard_day라는 변수에 며칠을 계산할 것인지를 입력하는 것이다. 

[주의] datetime의 경우에는 일자가 2021-01-01과 같은 형태로 출력되지만 우리가 차트 데이터에 저장했던 일자 값은 20210101과 같은, 중간에 하이픈(-)이 생략된 형태이다. 따라서 datetime의 timedelta는 역시 2021-01-01과 같은 형태로 입력해주어야 일자를 계산하기 때문에 일자를 계산하기 위해서는 자료의 구조를 변형시켜야 한다. 

[추신] 코드가 복잡해보인다면 임의로 더 짧은 변수로 입력해주어도 된다.

def cal_addday(self, standard_day, howmany):
	day_list = []
	day_list.append(standard_day)

	for i in range(1, 15):
		current_day = datetime.date(int(standard_day[0:4]), int(standard_day[4:6]), int(standard_day[6:9]))
		end = str(current_day + datetime.timedelta(days=i))
		tempt_var_date = str(end).split("-")
		var_date = tempt_var_date[0] + tempt_var_date[1] + tempt_var_date[2]
		var_week = datetime.date(int(var_date[0:4]), int(var_date[4:6]), int(var_date[6:8])).weekday()

		if var_week < 5:
			day_list.append(var_date)
		else:
			pass

	return day_list[howmany]

 

for문 아래에 있는 변수들이 가지고 있는 의미는 아래와 같다. 

  • current_day : standard_day를 기준으로 [0:4](2021), [4:6](01), [6:9](01)로 나누어 2021-01-01 형태로 변경
  • end : for문을 도는 동안의 i값을 timedelta로 계산해서 일자를 계산
  • tempt_var_date : 계산된 결과값(예:2021-01-02)을 하이픈(-)을 기준으로 분리(split)
  • var_date : 분리된 tempt_var_date(2021, 01, 02)을 하나로 합침
  • var_week : 계산된 일자인 var_date 변수를 datetime 모듈의 weekday()메서드를 통해 주말인지 확인
  • if문 하단 : var_week이 0, 1, 2, 3, 4라면 평일이고 5, 6이라면 주말을 의미함. 따라서 주말을 제외한 값을 day_list에 입력(append)
  • return : howmany에 해당하는 일수만큼 데이터 값을 반환

 


728x90

 

다음으로 다시 class algorithm1():으로 돌아와서, self.today = start_date를 입력해주도록 하자. 그 후에 while문을 통해서 self.today의 값이 end_date의 값과 같지 않다면, self.today라는 변수에 저장되어 있는 일자에 1을 더한 값을 다시 입력해주고, 새로운 일자가 입력된 self.today 변수의 값이 end_date의 값과 동일해질 때까지 while문을 빠져나오지 말라는 구조이다. 코드를 아래와 같이 제작한 후에 실행시켜본 후에 그 결과물들을 확인해보도록 하자.

class algorithm1():
    def __init__(self, start_date, end_date, all_range):
        print("시작일자:", start_date)
        print("종료일자:", end_date)
        print("전체범위:", all_range)

        self.today = start_date
        print("self.today:", self.today)

        while self.today != end_date:
            self.today = self.cal_addday(self.today, 1)
            print(self.today)

 

 

 

시작일자: 20200101
종료일자: 20210101
전체범위: 20150101
self.today: 20200101
20200102
20200103
(중략)
20201231
20210101

 

결과를 보니 우리가 처음에 입력했던 시작일자(start_date)와 종료일자(end_date)까지 하루하루를 더하면서 계산을 해주고 있음을 확인할 수 있다. 또한 결과값이 너무 많은 바람에 중간을 생략하긴 했지만 주말을 제외하고 결과물이 출력되는 것 역시 확인해볼 수 있다. 그렇다면 우리는 이제 while문 아래에서 우리가 사용하고자 하는 거래 전략들을 수립하고, 그를 바탕으로 거래할 종목을 선정하고 진행하면 된다. 

다음 게시글에서는 맨 앞에서 설명했던 매수 기준을 충족시키는 종목을 찾는 코드를 구축해보도록 하자.

 

 


728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.