반응형
 

[파이썬 초급] 1. 주가 데이터베이스 구축하기

파이썬으로 백테스트를 하기 위해서는 주가 데이터베이스의 구축이 선행이 되어야 합니다. 이번 강의에서는 대신증권 API를 이용하여 주가 데이터를 받은 뒤, 데이터베이스에 저장해 보겠습니다. * Python 32bit,..

lyy9257.tistory.com

이번에는 지난 강의때 구축했던 주가 데이터베이스를 이용해

간단한 백테스트를 진행해 보도록 하겠습니다.


0. 백테스트의 과정

우리가 주식 거래를 하는 과정을 살펴보면 

준비된 자금으로 주식 매수 → (특정 조건에 부합시) 매도 → 수익/손실 기록 의 과정으로 진행됨을 알 수 있습니다.

우리는 이번 강좌에서 파이썬으로 이 과정을 어떤식으로 구현할 수 있는지 간략하게 확인해 보겠습니다.


1. 필요 패키지 호출

import pandas as pd
import numpy as np
import sqlite3
import matplotlib.pyplot as plt​

백테스트를 위해 필요한 패키지를 불러옵니다.

코드 설명
- numpy : pandas와 더불어 데이터 분석에 사용됩니다.
- matplotlib : 데이터를 시각화하기위해 사용되는 패키지입니다.

2. 필요한 데이터 호출

stock_code = 'A233740' ## 불러오고 싶은 종목의 종목코드
con = sqlite3.connect("price.db") ## 주가가 저장되어 있는 데이터베이스 연결
query = "SELECT * FROM %s" %stock_code ## 쿼리문 작성

price_df = pd.read_sql(query, con) ## 데이터베이스에서 불러옴

print(price_df) ## 확인

백테스트를 하기 위해 주가데이터를 불러옵니다.

여기서는 KODEX KOSDAQ150 레버리지 주가데이터를 이용하였습니다.

코드 설명
- stock_code : 주가데이터를 불러오기 위해 원하는 종목의 종목코드를 설정합니다.
이는 주가데이터 테이블의 이름을 종목코드로 설정하였기 때문입니다.

- con : 주가데이터가 저장되어있는 데이터베이스를 연결합니다.

- query : 주가데이터를 불러오기 위한 SQL 명령어를 설정합니다.
설명에 적혀져있는 쿼리문은 종목코드의 이름을 가지는 테이블의 모든 데이터를 선택하는 의미를 가지고 있습니다.

- pd.read_sql(qurey, con) : 쿼리문을 기반으로 연결한 데이터베이스에서 데이터를 가져와 DataFrame 형태로 변환합니다.

< 실행결과 >

          date   open   high    low  close    volume
0     20151217  10240  10405   9970  10330    946156
1     20151218  10230  10710  10165  10710   1841150
2     20151221  10695  10825  10670  10720   1274858
3     20151222  10740  10750  10450  10495   1374974
4     20151223  10535  10635  10415  10425   2532341
...        ...    ...    ...    ...    ...       ...
1055  20200408   6850   7065   6750   6840  54161712
1056  20200409   7005   7050   6855   6950  41679524
1057  20200410   6965   7000   6550   6860  49728027
1058  20200413   6800   6860   6575   6575  26054303
1059  20200414   6735   6990   6670   6920  37525422

[1060 rows x 6 columns]

다음과 같이 데이터프레임의 일부분이 출력됩니다.


3. 불러온 데이터의 시각화

plt.plot(price_df['close'])
plt.show()

불러온 주가데이터의 주가가 어떻게 흘러가는지 시각화하여 확인해봅시다.

코드 설명
plt.plot(데이터) : 입력된 데이터를 기반으로 그래프를 그립니다.
plt.show() : 그래프를 시현합니다.

< 실행결과 >

 

다음과 같이 불러온 종목의 종가기반의 실선 그래프가 그려지게 됩니다.

여기서는 KODEX KOSDAQ150 레버리지의 종가 그래프가 작도되었으며,

이 강의에서는 matplotlib 패키지가 그래프를 그리는데 사용된다는 것만 설명하고 넘어가겠습니다.



4. 백테스트

불러온 데이터를 이용해 백테스트를 진행해 보겠습니다.

여기서는 systrader79님이 소개했던 '래리 윌리엄스의 변동성 돌파' 전략을 테스트 해보겠습니다.

## 변동성 돌파
## 참고책 : 파이썬을 이용한 비트코인 자동매매(조대표 외 1명 지음)

## 1) Range값 및 매수 목표가 산출
price_df['range'] = (price_df['high'] - price_df['low']) * 0.5
price_df['target'] = price_df['open'] + price_df['range'].shift(1)
    
## 2) 매수 시뮬레이션    
price_df['ror'] = np.where(price_df['high'] > price_df['target'], price_df['close'] / price_df['target'], 1)

## 3) 누적수익률 산출
price_df['total'] = price_df['ror'].cumprod()

## 4) 생성된 총 수익률 데이터 확인
print(price_df['total'])

순서는 range값 및 매수 목표가 산출 → 매수 시뮬레이션 → 누적수익률 산출 데이터 확인 순으로 진행이 됩니다.

코드 설명
- df.shift(숫자) : 입력된 값 만큼 데이터를 쉬프트 합니다.
코드에서는 1을 입력하였기 때문에 모든 데이터가 1칸씩 밀려나게 됩니다. (1번째 데이터는 2번째로, 2번째는 3번째로... 형식)
이는 D-1일 데이터를 D-day에 사용하기 위함입니다. (앞에 데이터가 한칸 밀려나면 현재로 오겠죠?)

- np.where(조건, Value1, Value2) : 조건식이 참이면 Value1, 거짓이면 Value2를 반환합니다.
코드에서는 목표가와 고가를 비교하여, 고가가 더 클 경우 종가/목표가를, 그렇지 않을 경우 1을 반환합니다.

df.cumprod() : 누적곱을 계산합니다.
Example) [2, 3, 4]를 cumprod하여 계산할 경우 누적곱인 [2, 6(=2*3), 24(=2*3*4)]가 반환됩니다.

< 실행결과 >

0       1.000000
1       1.025126
2       1.025126
3       1.025126
4       1.025126
          ...   
1055    4.106948
1056    4.106948
1057    4.106948
1058    4.106948
1059    4.132328
Name: total, Length: 1060, dtype: float64

다음과 같은 데이터프레임의 'total' 칼럼의 데이터가 출력됩니다.


5. 성과 지표 계산

백테스트의 결과를 기반으로 CAGR와 MDD지표를 계산해봅시다.

### 계산용 지표 계산 (거래 년수, 총 수익)
trade_year = int(len(price_df.index)/252)
result = round((price_df['total'].iat[-1] / price_df['total'].iat[0] - 1) * 100, 3)

print(trade_year, result)

먼저 거래연수(거래일 / 1년의 영업일(약 252일)) 와 총 수익률(백분율, 소수 3자리까지)을 계산합니다.

< 실행결과 >

4 313.233

거래연수 4년, 누적 수익률 313.233%의 결과값이 출력됩니다.


이 값을 기반으로 CAGR와 MDD를 계산해봅시다.

## CAGR 계산
total_profit = (price_df['total'].iat[-1] / price_df['total'].iat[0])
cagr = round((total_profit ** (1/trade_year)-1) * 100, 2)

## MDD 계산
arr_v = np.array(price_df['total'])
peak_lower = np.argmax(np.maximum.accumulate(arr_v) - arr_v)
peak_upper = np.argmax(arr_v[:peak_lower])

mdd = round((arr_v[peak_lower] - arr_v[peak_upper]) / arr_v[peak_upper] * 100, 3)

print(cagr, mdd)

CAGR 계산식에 대한 설명은 생략하겠습니다.

MDD 계산의 과정은

최대 수익 산출 → 최대 수익 대비 하락폭 산출 → MDD가 발생한 때의 리스트 인덱스 추출

  그때의 값을 이용하여 MDD 계산 순으로 이루어 집니다. 

코드 설명
np.argmax : 가장 큰 값의 인덱스를 반환합니다.
np.maximum : 입력된 값들을 비교하여 최대값을 반환합니다.
np.accumulate : 행의 갯수만큼 반복합니다. (모든 행에 적용)

< 실행결과 >

42.58 -22.355

CAGR와 MDD가 산출됩니다.


5. 수익률 그래프 시각화

주가 데이터를 시각화한 방법을 이용하여 수익률 데이터도 시각화 해보겠습니다.

plt.plot(price_df['total'])
plt.show()

< 실행결과 >

다음과 같은 수익률 그래프가 그려집니다.


이번 강의에서는 백테스트의 흐름을 개략적으로 알아보기 위해 간단히 백테스팅을 진행해 보았습니다.

수수료와 세금이 전혀 고려되지 않았기 때문에, 이 방법을 통해 얻은 백테스팅의 결과는 참고용으로만 쓸 수 있습니다.

다음 강의에서는 조금 더 정교하게 백테스트를 진행해 보도록 하겠습니다.


예제 파일은 아래에서 받아 보실 수 있습니다.

2. 주가데이터를 이용한 간단한 백테스트 (1).ipynb
0.04MB

강의가 도움이 되셨다면, 좋아요와 구독을 눌러주세요.
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기