설날으로 인해 한 주 수업을 못들었다
이번주에 와다다 들었더니 빡세긴 하다ㅎㅎ
넷째주에는 장기/단기 이동평균선을 활용하여 언제 주식을 사고 팔아야 하는지 백테스팅을 하는 법을 배웠다
!pip install yfinance pandas-datareader finance-datareader
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
우선 필요한 라이브러리들이다
yfinance, pandas-datareader, finance-datareader 총 3가지가 필요하다
df_1 = fdr.DataReader('005930','2018')
df_2 = fdr.DataReader('066570','2018')
df = pd.DataFrame()
df['Samsung'] = df_1['Change']
df['Lg'] = df_2['Change']
df.plot(figsize = [15, 8])
df_1은 삼성전자, df_2는 LG의 2018년 주식정보이다
데이터프레임을 만들고 각 회사의 '변화'추이를 plot으로 그려 확인한다
figsize는 그래프의 사이즈를 조절하는 함수이다
그래프를 그리면,
이렇게 나온다
df.tail(100).plot(figsize = [15, 8])
마지막 100개 항목에 대해서만 추려 그래프를 그려보면,
이렇게 나온다
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
이번에는 함수를 만들어보았다
회사의 code와 원하는 연도 갯수 n을 대입하면 수익률이 나오는 함수이다
df.rolling(n).mean()은 n개 연도 이동평균선을 뜻하고
그 뒤의 shift(1)은 데이터 프레임에서 한 줄 내려서 비교하겠다는 의미이다
이동평균선을 그리기 위해 데이터를 조작하기 위해서는 사고, 파는 때의 열이 일치해야 하기 때문에 한 줄 민 것이다
cond1은 buy에서 sell로 바뀔 때를, cond2는 sell에서 buy로 바뀌는 순간을 정의한 것이고
df_result에서 axis = 1은 데이터 프레임을 가로방향으로 합칠 때 사용하는 방법이다
get_return('005930', 3)
삼성전자의 3일 이동평균선 누적 수익률은 약 0.45정도이고
get_return('066570', 3)
LG의 경우에는 -0.58 정도이다
ㅏ....LG.....
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
이번에는 사고 팔았을 때 수익률을 계산하는 함수이다
맨 마지막 날은 무조건 팔아야 하므로 df.iloc[-1,-1] = 'sell'로 지정하였다
get_return_sl('005930', 6, 30)
삼성전자의 6일과 30일 이동평균선을 구분하여 사고 팔 때의 수익률을 구하면
6일과 30일 이동평균선이 31번째 교차할 때 팔았을 때 수익률이 4.63 나온다
dfs = []
for short in range(3,11):
for long in range(30,61):
df = get_return_sl('005930',short,long)
dfs.append(df)
df_result = pd.concat(dfs)
df_result.sort_values(by='수익률', ascending=False)
그럼 최적의 단기/장기 이동평균선은 어떻게 구할 수 있을까?
연산을 하는데 굉장히 오래 걸리지만 위의 코드를 실행해보면
6일 / 59일 이동평균선을 활용하여 사고 팔 때를 결정하는 것이 수익률을 극대화할 수 있다는 것을 알 수 있다
'[데이터분석]SpartaCodingClub' 카테고리의 다른 글
마지막주_백테스팅(2) (0) | 2023.02.03 |
---|---|
Python 셋째주_DART 데이터 활용하기 (0) | 2023.01.19 |
Python 둘째주_해외주식 분석 (0) | 2023.01.16 |
Python 첫째주_파이썬 기초 (0) | 2023.01.04 |