2023. 1. 4. 18:55ㆍ자격증(다다익선)/파이썬
https://chanytv.tistory.com/137
https://chanytv.tistory.com/138
https://chanytv.tistory.com/139
https://chanytv.tistory.com/142
https://chanytv.tistory.com/143
https://chanytv.tistory.com/148
[파이썬] 백테스팅(Back-testing)
주식 기본용어 파악하기
백테스팅이란 단어는 주식에 ㅈ자도 모르는 나로선 아주 생소한 단어다. 그 뜻은 '이전 주가의 추이에 전략을 대입해보는 것'이란 거다. 즉 주식의 흐름을 파악하는 것 같다. 이 번 주차를 공부하기 위해선 약간의 주식지식이 필요한 듯하다. 수학공식을 알아야 수학문제를 풀 수 있듯이 어찌 보면 당연한 게 아니겠는가.
이동평균선 : 며칠 간의 가격을 평균하여 움직이는 선
골든크로스 : 주가가 높아질 가능성이 있다는 신호
데스크로스 : 주가가 낮아질 가능성이 있다는 신호
파이썬으로 주가정보 불러오기
환경구성은 아래와 같이 하면 된다.
!pip install yfinance pandas-datareader finance-datareader
#yfinance : 주가정보를 불러올 수 있는 API
from pandas_datareader import data as pdr
import yfinance as yf
yf.pdr_override()
import numpy as np
import pandas as pd
import FinanceDataReader as fdr
잘 구동이 되는지 회사코드랑 연도를 집어넣어 확인이 가능하다.
df = fdr.DataReader('005930','2018')
df.head()
조회를 해보면 'Open: 시초가 / High: 고가 / Low: 저가 / Close: 종가 / Volume: 거래량 / Change: 변동' 을 기준으로 결과물이 프린팅 된다. 결과물이 잘 나오는 게 확인 됐으니 이제 골든크로스와 데스크로스 볼 수 있는 코딩을 하면 되는 거다.
데이터를 그래프롤 만들기
그래프를 그리는 방법은 아래와 같다.
df.plot(y=['Close'],figsize=(15,8),grid=True)
plot : df를 그래프화 하는 명령어
y=['Close'] : y축은 Close(종가)로 한다.
figsize(15,8) : 그래프의 사이즈다(가로,세로)
grid : 격자추가
종목 두 개를 비교하는 방법은 아래와 같다.
df_1 = fdr.DataReader('005930','2018')
df_2 = fdr.DataReader('066570','2018')
df_tot = pd.DataFrame()
df_tot['Samsung'] = df_1[['Change']]
df_tot['LG'] = df_2[['Change']]
df_tot.tail(100).plot(figsize=(15,8))
각 회사 코드별로 명령어를 지정해주고 회사별로 '변동'값을 불러온다.
불러온 값의 마지막 100개의 값을 가로 15 / 세로 8 사이즈 그래프로 프린팅 한다.
이동평균값 구해서 그래프 만들기
이동평균은 예를 들면 3일의 평균값의 이동변화를 나타내는 선이다.
즉 내가 불러온 데이터의 1,2,3일의 평균 / 2,3,4일의 평균 / 3,4,5일의 평균..... 의 값을 구하면 이동평균선을 그릴 수 있다는 것이다.
매일 3일마다의 평균값을 구하는 명령어는 아래와 같다.
df = fdr.DataReader('005930','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean()
df
비교를 하기 위해서 'ma'행을 추가해서 표를 출력한다.
날짜별로 종가를 알고 3일 별 평균의 값을 알기 때문에 예를 들어 1,2,3일의 평균의 값에서 4일 날 값을 비교하여 올랐다면 3일 날 샀어야 하고 내려갔다면 3일날 팔았어야 할 것이다. 그 변화추이는 아래 코딩을 통해 확인이 가능하다.
df = fdr.DataReader('005930','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')
df
'ma'행에 값을 'shift(1)'로 한 칸씩 밀려서 값을 출력한다.
'action'행을 하나 만드는데 'Close'의 값이 'ma'값보다 크면 'buy'를 적으면 'sell'을 출력한다.
수익률 구하기
기본적으로 값을 불러와 비교하여 사고파는 값까지 불러낼 수 있다면 이제 코딩 전략을 짜야할 것이다.
'buy'란 값이 3일 연속으로 출력됐다면 당연히 사는 타이밍이고 그다음 값이 'sell'이면 팔아야할 시점이다.
df = fdr.DataReader('005930','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')
cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')
# df_buy = df[cond1]
#df_sell = df[cond2]
df_sell #파는시점(df_buy는 사는 시점)
'action'의 값이 'buy'이고 그 다음 값이 'sell'이면 'real_buy'에 'buy' 아니면 공란
반대로 'sell'이 반복되다 'buy'이면 팔아야 한 시점이니 마찬가지로 코딩을 해주면 된다.
수익률을 구할 수 있으니, 사고파는 시점을 표에 표시할 수 있게 됐다.
수익률은 판 값 / 산 값이다. 수익률 행을 하나 더 추가해서 수식을 적용해주면 된다.
한 회사만 조회할 것이 아니기 때문에 함수를 사용하여 코드와 이동평균값을 바꿔주면 되겠다. 완성 코드는 아래와 같다.
def get_return(code,n):
df = fdr.DataReader(code,'2018')
df = df[['Close']].copy()
df['ma'] = df.rolling(n).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')
df.iloc[-1,-1] = 'sell'
cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')
df_buy = df[cond1].reset_index()
df_buy.columns = ['날짜','종가(buy)','이평값','액션']
df_sell = df[cond2].reset_index()
df_sell.columns = ['날짜','종가(sell)','이평값','액션']
df_result = pd.concat([df_buy,df_sell],axis=1)
df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']
return df_result[['수익률']].cumprod().iloc[-1,-1] - 1
get_return('005930',3)
get_return('066570',6)
골든/데스 크로스
골든/데스 크로스를 구하려면 단기이평선과 장기이평선을 먼저 구해야 한다.
위에 완성된 코드에서 def 함수의 'n'값만 변경해주면 되기 때문에 값을 구하기는 쉽다.
최종 결과물은 아래와 같다.
def get_return_sl(code, short, long):
df = fdr.DataReader(code,'2018')
df = df[['Close']].copy()
df['ma1'] = df['Close'].rolling(short).mean().shift(1)
df['ma2'] = df['Close'].rolling(long).mean().shift(1)
df['action'] = np.where(df['ma1'] > df['ma2'], 'buy', 'sell')
df.iloc[-1,-1] = 'sell'
cond1 = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
cond2 = (df['action'] == 'sell') & (df['action'].shift(1) == 'buy')
df_buy = df[cond1].reset_index()
df_buy.columns = ['날짜','종가(buy)','이평값1','이평값2','액션']
df_sell = df[cond2].reset_index()
df_sell.columns = ['날짜','종가(sell)','이평값1','이평값2','액션']
df_result = pd.concat([df_buy,df_sell],axis=1)
df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']
df_final = (df_result[['수익률']].cumprod().tail(1) - 1)*100
df_final['단기'] = short
df_final['장기'] = long
return df_final
get_return_sl('005930',3,30)
'005930'코드의 회사 주식정보를 불러오는데 3일 평균과 30일 평균의 이동평균선을 구해내는 코드다.
'자격증(다다익선) > 파이썬' 카테고리의 다른 글
[파이썬] 백테스팅 최종 및 강의종료 (0) | 2023.01.14 |
---|---|
[파이썬] Open API (0) | 2022.12.28 |
[파이썬] yfinance을 이용한 해외 주식 정보 분석 (0) | 2022.12.24 |
[파이썬] Pandas와 DataFrame (1) | 2022.12.23 |
[파이썬] openpyxl / 파일 업로드, 다운로드 (0) | 2022.12.16 |