볼린저 밴드
- 파일 로드
- 결측치와 이상치를 확인 및 제거
- 시간과 종가만의 데이터프레임으로 변경
- 이동 평균선 : 데이터 20개의 평균을 구해서 새로운 파생변수에 대입
- 상단 밴드 : 이동 평균선 + (2 * 데이터 20개의 표준편차)
- 하단 밴드 : 이동 평균선 - (2 * 데이터 20개의 표준편차)
- 구매 상태를 확인하는 파생변수 생성
- 구매 상태를 입력
- 수익율 계산
import pandas as pd
import numpy as np
df = pd.read_csv("../csv/BND.csv", index_col='Date')
df.head()
## 결측치와 이상치를 확인
df[df.isin([np.nan, np.inf, -np.inf]).any(1)]
## 시간과 종가만으로 이루어져있는 데이터프레임 생성
# price_df = df.loc[ : , ["Adj Close"]]
price_df = df[["Adj Close"]]
## 이동 평균선
# 데이터양이 20개의 평균을 구해서 새로운 파생변수 대입
# 과거의 데이터의 수가 20개가 되지 않으면 결측치로 출력
price_df["center"] = price_df['Adj Close'].rolling(20).mean()
## ub 파생변수를 생성
## 이동평균선 + (2 * 종가 데이터 20개의 표준편차)
price_df["ub"] = \
price_df["center"] + ( 2 * price_df["Adj Close"].rolling(20).std() )
## lb 파생변수 생성
# 이동평균선 - ( 2 * 종가 데이터 20개의 표준편차 )
price_df["lb"] = \
price_df['center'] - ( 2 * price_df['Adj Close'].rolling(20).std() )
## 시작 시간 생성
start_time = '2010-01-02'
## 거래 내역이라는 파생변수 생성
## 비어있는 값을 생성
price_df_2['trade'] = ""
구매내역 추가
- 조건
- 상단 밴드보다 종가가 높은 경우
- 현재 구매 상태인 경우
- 현재 구매 상태가 아닌 경우
- 아무 행동도 하지 않는다. trade = ""
- 하단 밴드보다 종가가 낮은 경우
- 현재 구매 상태인 경우
- 현재 구매 상태가 아닌 경우
- 하단 밴드와 상단 밴드 사이에 종가가 존재하면
- 현재 구매 상태인 경우
- 현재 구매 상태가 아닌 경우
for i in price_df_2.index:
if price_df_2.loc[i, 'Adj Close'] > price_df_2.loc[i, 'ub']:
if price_df_2.shift(1).loc[i, 'trade'] == "buy":
price_df_2.loc[i, 'trade'] = ""
else :
price_df_2.loc[i, 'trade'] = ""
elif price_df_2.loc[i, 'Adj Close'] < price_df_2.loc[i, 'lb']:
if price_df_2.shift(1).loc[i, 'trade'] == "buy":
price_df_2.loc[i, 'trade'] = 'buy'
else :
price_df_2.loc[i, 'trade'] = 'buy'
elif price_df_2.loc[i, 'Adj Close'] >= price_df_2.loc[i, 'lb'] and price_df_2.loc[i, 'Adj Close'] <= price_df_2.loc[i, 'ub']:
if price_df_2.shift(1).loc[i, 'trade'] == 'buy':
price_df_2.loc[i, 'trade'] = 'buy'
else:
price_df_2.loc[i, 'trade'] = ""
price_df_2['trade'].value_counts()
# price_df_2[price_df_2.isin(["buy"]).any(1)]
# price_df_2.query("trade == 'buy'")
# 구매한 시점의 종가
price_df_2[price_df_2['trade'] == 'buy']
수익율 계산
- 구매를 한 날의 종가
- trade 컬럼에서 전 행의 trade가 "" 현재 행 trade가 "buy"인 날의 종가 = 구매 가격
- 판매를 한 날의 종가
- 전 행의 trade가 "buy"이고 현재 행 trade가 "" 인 날의 종가 = 판매 가격
- 수익율 계산
- (판매 가격 - 구매 가격) / 구매 가격 + 1
- 구매 가격과 판매 가격를 초기화
- 여러개의 수익율 발생
- 누적 수익율
# 손익 계산
rtn = 1.0
price_df_2["return"] = 1
buy = 0.0
sell = 0.0
for i in price_df_2.index:
## 구매가를 출력
if price_df_2.shift(1).loc[i, "trade"] == '' and \
price_df_2.loc[i, 'trade'] == 'buy':
buy = price_df_2.loc[i, 'Adj Close']
print('진입일 :', i, "구매 가격 :", buy)
## 판매가를 출력
elif price_df_2.shift(1).loc[i, 'trade'] == 'buy' and \
price_df_2.loc[i, 'trade'] == '':
sell = price_df_2.loc[i, 'Adj Close']
rtn = (sell - buy) / buy + 1
price_df_2.loc[i, 'return'] = rtn
print('청산일 :', i, "판매 가격 :", sell, "수익율 :", round(rtn, 4))
## buy, sell 변수를 초기화
if price_df_2.loc[i, 'trade'] == "":
buy = 0.0
sell = 0.0
## for문을 이용하여 구매 가격 print, 판매 가격 print()
# 구매인 경우 조건 : 전 행의 trade가 "" 이고(그리고) 현재 행의 trade가 "buy"
# 판매인 경우 조건 : 전 행의 trade가 "buy" 이고(그리고) 현재 행의 trade가 ""
# 이 두 경우에 종가를 print()
##누적 수익율
acc_rtn = 1.0
for i in price_df_2.index:
rtn = price_df_2.loc[i, 'return']
acc_rtn *= rtn
price_df_2['acc_rtn'] = acc_rtn
print("누적 수익율 : ", round(acc_rtn, 4))