초반에 3가지 설치해야 한다.
!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 pdimport FinanceDataReader as fdr
df = fdr.DataReader('005930','2018')
df.head()
그래프
df.plot(y=['Close'])
df.plot(y=['Close'],figsize=[15,8])
좀 더 크게 나온다
df.plot(y=['Close'],figsize=[15,8],grid=True)
좀더 크게 격자선넣기
df.plot(y=['Open','Close'],figsize=[15,8],grid=True)
Open, Close가 같이 나온다.
df.plot()
df에 있는걸 다 그러준다
1) 두 회사를 같이 보고싶을때
최근 100일을 그래프로 그려라
df.tail(100).plot(figsize=[15,8])
2) 이동평균 값만들기
먼저
참고 : 여기서 rolling(3)은 위에서부터 3개씩 묶는다. 예시) 0,1,2 / 1,2,3, / 2,3,4 이런순으로 묶는다고 생각하면 된다.
그런다음 ma값을 한칸씩 내려야 비교대상이 되므로
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df
shift를 넣어 내려준다.
그 후 비교대상과 비교 후 구매할지 판매할지 표시
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy','sell')
df
buy → buy → buy 이면, 사는 게 아니다.
즉, buy와 sell이 바뀌는 순간이 중요하다.
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy','sell')
df['action_temp'] = df['action'].shift(1)df
즉 action_temp는 shift가 1인것과 나 자신을 비교하는 것이다.
1) 사는 시점, 파는시점
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).mean().shift(1)
df['action'] = np.where(df['Close'] > df['ma'], 'buy','sell')
cond = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
df['real_buy'] = np.where(cond,'buy','')
df
real_buy에 표기된 'buy'시기를 모으면 사는 시점이 될것이다.
df = fdr.DataReader('066570','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[cond1]
반대로 'sell'시기를 모으면 파는 시점이 될것이다.
df = fdr.DataReader('066570','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[cond2]
이 것을 한데 모으면
마지막에 df_buy 또는 df_sell을 넣으면 입력값이 나온다.
또한 수익률이기때문에 맨 마지막은 무조건 판매(sell)이 나와야 되므로
df.iloc[-1,-1] = 'sell'
이것을 넣어줘야된다.
여기서 concat을 옆으로 붙여줄려면
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).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]
df_sell = df[cond2]df_result = pd.concat([df_buy, df_sell],axis=1)
df_result.head(30)
그렇지만 한줄이 밑에 있기 때문에 이걸 합쳐줄려면
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).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_sell = df[cond2].reset_index()df_result = pd.concat([df_buy, df_sell],axis=1)
df_result.head(30)
이렇게 하면 깔끔하게 볼 수 있다. 여기서 중요한 부분은 close 인데 두개가 있으므로 이름을 바꿔주자
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).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.head(30)
수익률은 종가(sell)/종가(buy)로 하면 된다.
df = fdr.DataReader('066570','2018')
df = df[['Close']]
df['ma'] = df.rolling(3).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)']
df_result
수익률자료만 가져오자 (오류가 뜰텐데 그 뒤에 자료가 중복되어서 위험하다고 알려주는것이므로 copy를 넣어주자)
df = fdr.DataReader('066570','2018')
df = df[['Close']].copy()
df['ma'] = df.rolling(3).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)']
df_result[['수익률']]
그 후 전체를 곱해주면된다.
df = fdr.DataReader('066570','2018')
df = df[['Close']].copy()
df['ma'] = df.rolling(3).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)']
df_result['수익률cumprod'] = df_result[['수익률']].cumprod()
df_result
수익률cumprod는 그 라인부터 위쪽으로 전부 곱하게 된것이다.
거기서 맨 마지막것을 가져와서 -1을 해주면 수익률이 나온다.
df = fdr.DataReader('066570','2018')
df = df[['Close']].copy()
df['ma'] = df.rolling(3).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)']
df_result[['수익률']].cumprod().iloc[-1,-1]-1
이것을 함수로 나타낼려면?
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은 날짜이다.
예시) 삼성전자 005930
예시) LG전자 066570
먼저 사용했던 곳에서 코드를 뽑아오면
df = fdr.DataReader('005930','2018')
df = df[['Close']].copy()
df.iloc[-1,-1] = 'sell'
df['ma1'] = df.rolling(3).mean().shift(1)
df['ma2'] = df.rolling(30).mean().shift(1)df['action'] = np.where(df['ma1'] > df['ma2'], 'buy','sell')
df
이렇게 하면 오류가 뜨는데 위에 함수가 없는 곳이 있기 때문이다.
df = fdr.DataReader('005930','2018')df = df[['Close']].copy()
df['ma1'] = df['Close'].rolling(3).mean().shift(1)
df['ma2'] = df['Close'].rolling(30).mean().shift(1)df['action'] = np.where(df['ma1'] > df['ma2'], 'buy','sell')
df
이렇게 해야 오류가 안뜬다.
그 후 하나씩 가져오면서 검토해보면
df = fdr.DataReader('005930','2018')
df = df[['Close']].copy()
df['ma1'] = df['Close'].rolling(3).mean().shift(1)
df['ma2'] = df['Close'].rolling(30).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_result[['수익률']].cumprod().iloc[-1,-1]-1
단기는 며칠이고 장기는 며칠이고 수익률은 나는지를 만들어보자
df = fdr.DataReader('005930','2018')
df = df[['Close']].copy()
df['ma1'] = df['Close'].rolling(3).mean().shift(1)
df['ma2'] = df['Close'].rolling(30).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['단기'] = 3
df_final['장기'] = 30df_final
이것을 가지고 함수로 만들어보자.(def get_return_sl(code,short,long)
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['장기'] = longreturn df_final
이렇게 하면 한 종목에서 최적의 단기종목과 최적의 장기종목을 알 수 있다.
숙제
한 종목에 대해 최적의 단기/장기이평선
단기 : 3일~10일
장기 : 30일~60일
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)
처음 dfs.append(df)로 데이터를 축적해야되는데 그걸 까먹었다.
최적의 이평선을 구해야 되므로 수익률로 내림차순하면 볼 수 있다.