마지막 백테스팅 전략은 월-금 전략이다.
요일을 어떻게 표기하는지,
월요일과 금요일 가격을 어떻게 붙이는지,
월요일에 사서 금요일에 팔 때, 수익률을 어떻게 구하는지,
월-금 전략 최적의 종목은 무엇인지 알아보았다.
이런 복잡한 전략도 쉽게 구현이 가능하다니,
정말 코딩의 위대함을 느꼈다.
5. 나만의 전략 구현하기
1) 나만의 전략 구현하기: 월-금 전략
* 어떤 것이든 전략이 될 수 있다.
- 언젠가 나만의 전략을 구상해보아도 좋다.
· 삼성전자가 오를 때 LG전자를 사자!
· 비오는 날에 주식을 사자!
· 어제 10% 이상 떨어진 종목을 사서 점심 때 팔자!
⇒ 모두 좋다.
* 오늘 다뤄볼 전략은
- 간단하게, `월요일에 사서 → 금요일에 파는 걸` 해보고,
- 가장 적합한 종목은 무엇일지도 구해본다.
2) 요일 표기와 주별 가격 붙이기
* 요일 표기하기
- 주가 가져오기
df = fdr.DataReader('005930','2018')
df
- 요일 표기하기
· .reset_index()를 사용하여 Date를 리셋시키면 값으로 변환시켜 사용하기 편리하다.
· 우리에게 필요한, `Day` , `Open` 만 가져온다.
df = fdr.DataReader('005930','2018')
df = df.reset_index()
df = df[['Date','Open']]
df
· .to_datetime을 이용하여 Date를 변환시켜주고, .dt.day_name()를 이용해 날짜를 요일로 나타나게 한다.
df['Day'] = pd.to_datetime(df['Date']).dt.day_name()
df
* 월, 금요일만 남기기
- 월, 금요일만 가져오기
· 월요일에서 사서 → 금요일에 파는 것이니까, 월요일, 금요일만 보여주도록 한다.
df = fdr.DataReader('005930','2018')
df = df.reset_index()
df = df[['Date','Open']]
df['Day'] = pd.to_datetime(df['Date']).dt.day_name()
cond = (df['Day'] == 'Monday') | (df['Day'] == 'Friday')
df = df[cond]
df
- 처음 / 마지막 고려해주기
· 첫 날이 금요일이고 마지막이 월요일이라면 안된다.
· 그래서, 만약에 첫 날이 금요일이거나, 마지막 날이 월요일이면, .drop(index = )를 이용해 행을 없앤다.
if df.iloc[0,2] == 'Friday':
df = df.drop(index = df.index[0])
if df.iloc[-1,2] == 'Monday':
df = df.drop(index = df.index[-1])
- 휴일 고려하기
· 예를 들어 금요일이 휴일이면, 월요일 > 월요일이 연속으로 나온다. 월요일이 연속으로 나오는 날을 뽑아보면 다음과 같다.
cond = (df['Day'] == 'Monday') & (df['Day'].shift(-1) == 'Monday')
df[cond]
· 월요일 > 월요일이면 처음 나온 월요일을 날리고, 금요일 > 금요일이면 나중에 나온 금요일을 날리면 된다.
cond = (df['Day'] == 'Monday') & (df['Day'].shift(-1) == 'Monday')
df = df.drop(index = df[cond].index)
cond = (df['Day'] == 'Friday') & (df['Day'].shift(1) == 'Friday')
df = df.drop(index = df[cond].index)
* 수익률 구하기
- 주가 모으기
· 금요일 가격을 한칸씩 위로 올린 새로운 열을 만든다. 그러면 월요일과 금요일 가격을 한 행에 나란히 볼 수 있다.
· 월요일 행만 뽑아서 보여주면, 월요일-금요일의 주가만 한 행에 두고 볼 수 있다.
df['Open_fri'] = df['Open'].shift(-1)
df = df[df['Day']=='Monday']
df
· 이제, 'Open'과 'Open_fri' 값만 보여주고, 컬럼 이름을 'buy_at', 'sell_at'으로 바꿔준다.
df = df[['Open','Open_fri']]
df.columns = ['buy_at','sell_at']
df
- 수익률 구하기
· 'sell_at'에서 'buy_at'을 나눠 수익률을 구해준다.
df['return'] = df['sell_at'] / df['buy_at']
df
· 이제 `cumprod()`를 이용해 누적수익률을 구하면 끝!!...... 이라고 생각했지만, 아니다.
df[['return']].cumprod().iloc[-1,-1] - 1
· 'sell_at' 가격과 'buy_at' 가격이 0인 케이스를 없애줘야 한다.
df['return'] = df['sell_at'] / df['buy_at']
cond = (df['sell_at'] != 0) & (df['buy_at'] != 0)
df = df[cond]
df[['return']].cumprod().iloc[-1,-1] - 1
- 함수로 만들기
· 함수로 만들면, 월-금 전략이 가장 잘 맞는 종목을 찾을 수도 있다.
def get_return_mf(code):
df = fdr.DataReader(code,'2018')
df = df.reset_index()
df = df[['Date','Open']]
df['Day'] = pd.to_datetime(df['Date']).dt.day_name()
cond = (df['Day'] == 'Friday') | (df['Day'] == 'Monday')
df = df[cond]
if df.iloc[0,2] == 'Friday':
df = df.drop(index = df.index[0])
if df.iloc[-1,2] == 'Monday':
df = df.drop(index = df.index[-1])
cond = (df['Day'] == 'Monday') & (df['Day'].shift(-1) == 'Monday')
df = df.drop(index = df[cond].index)
cond = (df['Day'] == 'Friday') & (df['Day'].shift(1) == 'Friday')
df = df.drop(index = df[cond].index)
df['Open_fri'] = df['Open'].shift(-1)
df = df[df['Day']=='Monday']
df = df[['Open','Open_fri']]
df.columns = ['buy_at','sell_at']
df['return'] = df['sell_at'] / df['buy_at']
cond = (df['sell_at'] != 0) & (df['buy_at'] != 0)
df = df[cond]
return df[['return']].cumprod().iloc[-1,-1] - 1
· 알맞게 나오는지 코드를 넣어 확인해본다.
6. 최적화 종목 찾기
1) `dart-fss` 라이브러리 사용하기
- dart-fss 라이브러리를 설치한다.
!pip install dart-fss
- 종목 코드를 가져온다.
import dart_fss as dart_fss
import pandas as pd
api_key = 'API키 입력하기'
dart_fss.set_api_key(api_key=api_key)
all = dart_fss.api.filings.get_corp_code()
df = pd.DataFrame(all)
df_listed = df[df['stock_code'].notnull()]
for row in df_listed.sample(10)[['stock_code','corp_name']].itertuples():
print(row)
2) 최적화된 종목를 찾기
- 이전에 했던 방법들과 동일하게, df를 만들어 찾는다.
- 여기서 .sample(10)을 빼면, 전체 상장 종목에서 월-금전략이 가장 좋은 회사를 찾을 수 있다.
df = pd.DataFrame()
for row in df_listed.sample(10)[['stock_code','corp_name']].itertuples():
try:
doc = {
'name' : row[2],
'return' : get_return_mf(row[1])
}
df = df.append(doc, ignore_index = True)
except:
print(f'error - {row[2]}')
df.sort_values(by='return', ascending=False)
'CODING > PYTHON' 카테고리의 다른 글
[Python] 5주차_백테스팅 기초(2) : 변동성 돌파 전략 (Feat. 스파르타코딩클럽) (0) | 2022.12.20 |
---|---|
[Python] 4주차_백테스팅 기초(1) : 골든/데드크로스 전략 구현 (2편) (Feat. 스파르타코딩클럽) (0) | 2022.12.13 |
[Python] 4주차_백테스팅 기초(1) : 골든/데드크로스 전략 구현 (1편) (Feat. 스파르타코딩클럽) (0) | 2022.12.13 |
[Python] 3주차_DART 데이터 내 마음대로 활용하기(3편) (Feat. 스파르타코딩클럽) (1) | 2022.12.08 |
[Python] 3주차_DART 데이터 내 마음대로 활용하기(2편) (Feat. 스파르타코딩클럽) (0) | 2022.12.08 |