스파르타 코딩클럽 데이터분석 4주차 강의 '핵심' 노트정리
1. 백테스팅 개념
▶ 백테스팅이란?
: 이전 주가의 추이를 보고 전략을 대입해 보는 것
ex. 만약 어떤 조건에 따라 사고 파는 걸 반복하면 돈을 벌 수 있을까?
→ 만약 날씨가 흐리면 사고, 좋으면 팔고를 반복하면 수익이 날까?
2. 백테스팅 전략 세우기
2-1) 이동평균선
▶이동평균선이란?
: 이전 며칠(3일, 5일, 20일, 50일 등) 간의 가격의 평균값이 움직이는 선
: 일 수가 커질수록 곡선이 완만해지는 게 특징
2-2) 우리가 쓸 전략: 골든크로스, 데드크로스 전략
▶ 골든크로스: 주가가 높아질 가능성이 있다는 신호
▶ 데드크로스: 주가가 낮아질 가능성이 있다는 신호
→ 그럼 골든크로스 때 사고, 데드크로스 때 팔면 싸게 사서 비싸게 파는 것인가?
3. 주가 가져오기
▶ yfinance, pandas-datareader, finance-datareader 라이브러리 설치
!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
df = fdr.DataReader('005930','2020')
df.head()
: '005930' 은 삼성전자의 종목코드
: '2020' 년도 데이터부터 불러와라
4. 간단한 그래프 그려보기
① 한 종목 그래프만 그려보기
df.plot(y = ['Close'], figsize = (15,8), grid = True)
: df.plot(y = ['Close']) Close 값으로 그래프를 그려라
: figsize = 그래프의 크기 조정
: grid = True 그래프에 격자무늬를 넣어라
: df.plot(y = ['Open', 'Close']) 하면 Open과 Close 열의 그래프가 같이 그려짐
② 여러 종목 그래프 그려보기
df_1 = fdr.DataReader('005930','2020')
df_2 = fdr.DataReader('066570','2020')
df = pd.DataFrame()
df['Samsung'] = df_1['Change']
df['LG'] = df_2['Change']
df.tail(100).plot(figsize = (15,8))
: '005930'은 삼성전자 , '066570'은 LG전자의 종목코드
: 새로운 DataFrame을 하나 만들고 삼성전자의 변동율과 LG전자의 변동율 나타내기
: df.plot 으로 그래프 그리는데
: figsize = 로 그래프 크기 조정해주고
: .tail(100) 으로 최근 100일 정도의 데이터만 불러와서 그래프 그려보기
5. 이동평균값 만들기(3일)
df = fdr.DataReader('005930','2020')
df = df[['Close']]
df['ma'] = df.rolling(3).mean()
df
: df.rolling(3) 3일씩 묶어서
: .mean() 3일간의 이동평균 값을 구해줌
6. buy 와 sell 표기
① 한 칸 내려주기
: 3일의 평균이 파란색 박스
: 각 날짜의 종가가 빨간색 박스
→ 빨간색 박스와 파란색 박스의 값을 비교해야 함.
: 그 날의 종가가 3일간의 이동평균선 값을 뚫고 올라가면 사겠다는 것.
→ 보기 좋게 만들려면 파란색 박스를 한 칸 내려줘야 함.
df['ma'] = df.rolling(3).mean().shift(1)
: .shift(1) 만 뒤에 붙여서 적어주면 한 칸 내려주기 끝!
② buy인지 sell인지 액션을 새로운 열에 표시하기
df['action'] = np.where(df['Close'] > df['ma'], 'buy', 'sell')
: np.where(조건, 조건에 맞을 때 표시할 값, 조건에 맞지 않을 때 표시할 값)
7. 수익률 구하기(1)
◈ 실제로 사는 시점 생각하기
: buy - buy - buy 인 경우에는 사는 게 아니라 산 주식을 들고 있는 상태임.
→ buy가 sell로, sell이 buy로 바뀌는 순간이 중요!
① action값과 action.shift(1) 값 비교
df['action_temp'] = df['action'].shift(1)
: df['action_temp'] 는 action을 .shift(1)한 값
: action값과 action_temp값이 다를 때 (buy와 sell이 바뀌는 시점) buy 해야 함.
: action은 오늘의 행동
: action.shift(1)은 오늘의 행동을 한 칸 내린 값.
즉, 내일의 action값 입장에서는 어제의 행동이 됨.
② real_buy값 도출하기
cond = (df['action'] == 'buy') & (df['action'].shift(1) == 'sell')
df['real_buy'] = np.where(cond, 'buy', '')
: df['real_buy'] 어제 sell이었는데 오늘 buy로 바뀌었으면 buy 라고 표시해줌.
③ buy → sell , sell → buy 바뀔 때를 cond 이용해서 잡아내기
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_buy는 buy 타이밍만 모은 데이터
: df_sell은 sell 타이밍만 모은 데이터
④ 데이터의 마지막은 무조건 sell
→ 그래야 수익률을 구할 수 있음.
df.iloc[-1,-1] = 'sell'
8. 수익률 구하기(2)
① df_buy와 df_sell 옆으로 이어붙이기
df_result = pd.concat([df_buy, df_sell], axis = 1)
: .axis = 1 df_buy와 df_sell을 옆으로 이어붙이기
: 빨간 박스일 때 사고, 파란 박스일 때 팔고~
: 파란 박스가 또 한 줄 밑에 있기 때문에 이걸 합쳐줘야 함.
② .reset_index()
df_buy = df[cond1].reset_index()
df_sell = df[cond2].reset_index()
: 1 / 7일에 사고, 1 / 15일에 팔고~
: 1 / 16일에 사고, 1 / 21일에 팔고~
③ 열 이름 바꾸기, 수익률 구하기
df_buy.columns = ['날짜','종가(buy)','이평값','액션']
df_sell.columns = ['날짜','종가(sell)','이평값','액션']
df_result['수익률'] = df_result['종가(sell)'] / df_result['종가(buy)']
9. 수익률 구하기(3)
① 수익률 계산하기
df = df[['Close']].copy() # .copy를 안 하면 오류 남.
df_result[['수익률']].cumprod().iloc[-1,-1] -1
: .cumprod() 각각의 수익률 값을 누적으로 계속 곱해줌.
: .iloc[-1,-1] 열의 마지막 값 출력
: -1을 해줘야 수익률이 얼마인지 제대로 나옴.
② def 함수 사용하기
def get_return(code, n):
df = fdr.DataReader(code,'2020')
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', 6)
10. 단기/장기 이평선 적용하기
① 단기/장기 이평선 구하기
→ rolling( )의 숫자만 바꾸면 됨.
→ df['action'] 조건 바꿔주기
: ma1이 단기 이평선
: ma2가 장기 이평선
: ma1 > ma2 일 때 buy 해야 함.
df = fdr.DataReader('005930','2020')
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['장기'] = 30
df_final
: df_final 값에서 .tail(1) 은 수익률의 마지막 값을 보여줌.
② def 함수 사용하기
→ df_result[['수익률']].cumprod().iloc[-1,-1] -1 로 나온 값을 표로 만드는 게 목적
(단기는 며칠이고, 장기는 며칠이고, 수익률은 어떻게 되는지)
def get_return_sl(code,short,long):
df = fdr.DataReader(code,'2020')
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)
♥ 한 종목에 대한 최적 단기/장기 이동평균선 구해보기
(단기 며칠 / 장기 며칠이 이 종목에 가장 적절한 전략일지)
>> 데이터분석 4주차 숙제 (데이터분석 4주차 후기에서 확인 가능!)
♣ 데이터분석 4주차 강의 후기 ♣ https://nasena.tistory.com/20
'데이터분석 과정 > 데이터 분석' 카테고리의 다른 글
데이터분석 | 타이타닉 생존자의 비밀 파헤치기 | 생존율과 가장 관련이 깊은 요인은? (1) | 2024.01.15 |
---|---|
데이터분석 5주차 강의 노트정리 [국비지원_스파르타 코딩클럽] (0) | 2023.02.15 |
데이터분석 3주차 강의 노트정리 [국비지원_스파르타 코딩클럽] (0) | 2023.02.11 |
데이터분석 2주차 강의 노트정리 [국비지원_스파르타 코딩클럽] (0) | 2023.01.25 |
데이터분석 1주차 강의 노트정리 [국비지원_스파르타 코딩클럽] (0) | 2023.01.20 |
댓글