스파르타/파이썬

파이썬 _ 04주차 _ 백테스팅1 _ 수익률 구하기

옒르 2023. 1. 17. 15:18

1) 생각하기

# 나는 buy인데, 실제 action_temp가 sell인 경우 OR 나는 sell인데, 실제 action_temp가  buy인 경우

# fdr = finance data reader

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['action_temp'] = df['action'].shift(1)

df

✳️ 생각하기1 _ 실제로 사는 시점

# buy와 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')

cond=(df['action']=='buy') & (df['action'].shift(1) =='sell')

df['real_buy']= np.where(cond,'buy','sell')
df

 

# 사는 순간 모아보기

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')
cond=(df['action']=='buy') & (df['action'].shift(1) =='sell')
df[cond]
df

 

✳️ 생각하기2 _ 실제로 파는 시점

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')

cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')
 

df_buy = df[cond_1]          # buy해야 되는 순간들을 모아놓음
df_sell = df[cond_2]          # sell해야 되는 순간들을 모아놓음

df_sell

 

✳️ 생각하기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.iloc[-1,-1] = 'sell'             # 마지막은 무조건 판매

cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')

df_buy = df[cond_1]
df_sell = df[cond_2]

df_sell     OR      df_buy

 

2) 사고, 파는 시점 붙이기

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.iloc[-1,-1] = 'sell'

cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')
 
 

df_buy = df[cond_1]
df_sell = df[cond_2]
 
 
df_result = pd.concat([df_buy,df_sell],axis=1)
 # concat은 데이터를 이어 붙여주는 함수
 # axis = 1은 왼쪽 + 오른쪽으로 합치기 /  #axis=0은 위 + 아래로 합치기
                                                                                      

df_result.head(30)             # head(3) -> 맨 앞 30개만 보기
 

[해설]

01/05에 52,120원에 구매해서 01/09에 50,400원에 판매

01/15에 48,540원에 구매해서 01/19에 49,320에 판매

 

# buy 시점과 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')

df.iloc[-1,-1] = 'sell'

cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')
 
 
# rest_index() : 인덱스를 열로 변환 + 설정 인덱스를 제거하고 기본 인덱스(0,1,2, ... , n)으로 변경하는 메서드
df_buy = df[cond_1].reset_index()  
df_sell = df[cond_2].reset_index()

df_result = pd.concat([df_buy,df_sell],axis=1)

df_result.head(30)

[해설]

01/05에 52,120원에 구매해서 01/09에 50,400원에 판매

01/15에 48,540원에 구매해서 01/19에 49,320에 판매

01/23에 49,160원에 구매해서 01/30에 49,800원에 판매

 

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.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

 

4) 오류 해결하기

⇒ dataframe을 복사해서 그렇습니다.

⇒ 아래처럼 바꿔주세요!

df = df[['Close']].copy()
# copy를 하지 않으면 기존의 것에 계속 덧붙여 사용하여 오류가 발생할 수 있음
 
 

5) 수익률 계산하기

# 누적 곱 추출하기 => cumprod()

df = fdr.DataReader('005930','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'

cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')

df_buy = df[cond_1].reset_index()
df_buy.colums=['날짜','종가(buy)','이평값','액션']

df_sell = df[cond_2].reset_index()
df_sell.colums=['날짜','종가(sell)','이평값','액션']

df_result = pd.concat([df_buy,df_sell],axis=1)

df_result['수익률'] = df_sell['Close'] / df_buy['Close']

df_result['수익률cumprod'] = df_result[['수익률']].cumprod()

df_result
 

# 마지막 값 가져오기 => .iloc[-1,-1]

df = fdr.DataReader('005930','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'

cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')

df_buy = df[cond_1].reset_index()
df_buy.colums=['날짜','종가(buy)','이평값','액션']

df_sell = df[cond_2].reset_index()
df_sell.colums=['날짜','종가(sell)','이평값','액션']

df_result = pd.concat([df_buy,df_sell],axis=1)

df_result['수익률'] = df_sell['Close'] / df_buy['Close']
 
 
 # 수익률은 누적 곱에서 -1을 해줘야한다
df_result[['수익률']].cumprod().iloc[-1,-1]-1             
 
 
 

6) 함수로 만들기

def get_return(code,n):    # 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'

    cond_1=(df['action']=='buy') & (df['action'].shift(1) =='sell')
    cond_2=(df['action']=='sell') & (df['action'].shift(1) =='buy')
 
 
    df_buy = df[cond_1].reset_index()
    df_buy.colums=['날짜','종가(buy)','이평값','액션']
 
 
    df_sell = df[cond_2].reset_index()
    df_sell.colums=['날짜','종가(sell)','이평값','액션']
 
 
    df_result = pd.concat([df_buy,df_sell],axis=1)
 

    df_result['수익률'] = df_sell['Close'] / df_buy['Close']

 

    return df_result[['수익률']].cumprod().iloc[-1,-1]-1