728x90
이번에 사용할 알고리즘을 간략하게 소개하겠습니다.
매수 1번째 조건: 20일, 120일 EMA 골든 크로스 발생시 50% 비중으로 매수합니다.
매수 2번째 조건: 1번째 조건 발생후, 캔들이 EMA 20일 선을 터치하면 나머지 50% 추가 매수합니다.
단, 조건 1에서의 매수단가보다 높은 가격에서 추가 진입해야 할 경우 매수하지 않습니다.
매도 조건: 데드크로스 발생시 전액 매도
S&P500의 3000일의 일봉 데이터를 사용하였습니다.
본격적인 코드를 소개하겠습니다.
우선 S&P500데이터를 다운받은 후, talib 패키지를 통해 ema 20일, 120일을 계산해줍니다.
import talib
import yfinance as yf
stock_data = yf.download('^GSPC')#S&P500 데이터에 해당
count = 3000
stock_data = stock_data.tail(count) #최근 3000일
stock_data['EMA_20'] = talib.EMA(stock_data['Close'], 20)
stock_data['EMA_120'] = talib.EMA(stock_data['Close'], 120)
필요한 열을 추가해줍니다.
stock_data = stock_data[["Open","High","Low","Close","EMA_20","EMA_120"]]
stock_data['buy_condition'] = 0 # 0 = 안 삼, 1 = 조건1 충족, 2 = 조건2 충족
stock_data['hpr'] = 1 # 누적 수익률
stock_data['ror'] = 1
stock_data['buy_price'] = 0 # 평단가
stock_data['dr'] = 1 # 금일 수익률
stock_data["weight"] = 0 # 비중
stock_data["trading_number"] = 0
stock_data["win"] = 0
stock_data["lose"] = 0
for문을 통해 백테스팅을 진행해줍니다.
for i in range(1, count):
if stock_data.iloc[i-1,6] == 0: # 안삼
# 첫번째 조건 충족
if stock_data.iloc[i-1,4] <= stock_data.iloc[i-1,5] and stock_data.iloc[i,4] > stock_data.iloc[i,5]:
stock_data.iloc[i,6] = 1 # buy condition
stock_data.iloc[i,9] = stock_data.iloc[i,3] # 평단가
stock_data.iloc[i,11] = 0.5 # 비중
stock_data.iloc[i,12] = stock_data.iloc[i-1,12] + 1 # 매매횟수 +1
else: # 매수 조건 불충족
stock_data.iloc[i,12] = stock_data.iloc[i-1,12]
elif stock_data.iloc[i-1,6] == 1:
# 두번째 조건 충족
if stock_data.iloc[i,2] <= stock_data.iloc[i,4] and stock_data.iloc[i,1] >= stock_data.iloc[i,4] and stock_data.iloc[i,3] < stock_data.iloc[i-1,8]:
stock_data.iloc[i,6] = 2 # buy condition
stock_data.iloc[i,9] = (stock_data.iloc[i-1,9] + stock_data.iloc[i,3])/2 # 평단가
stock_data.iloc[i,11] = 1 # 비중
stock_data.iloc[i,12] = stock_data.iloc[i-1,12] + 1 # 매매횟수 +1
# 매도 조건 충족
elif stock_data.iloc[i-1,4] >= stock_data.iloc[i-1,5] and stock_data.iloc[i,4] < stock_data.iloc[i,5]:
stock_data.iloc[i,6] = 0
stock_data.iloc[i,9] = 0
stock_data.iloc[i,11] = 0
stock_data.iloc[i,12] = stock_data.iloc[i-1,12]
else:
stock_data.iloc[i,6] = stock_data.iloc[i-1,6] # buy condition
stock_data.iloc[i,9] = stock_data.iloc[i-1,8] # 평단가
stock_data.iloc[i,11] = stock_data.iloc[i,3]/stock_data.iloc[i-1,3] * stock_data.iloc[i-1,10]
stock_data.iloc[i,11] = stock_data.iloc[i,10]/(stock_data.iloc[i,10] + 0.5) # 비중
stock_data.iloc[i,12] = stock_data.iloc[i-1,12]
#금일 수익률
stock_data.iloc[i,10] = stock_data.iloc[i,3]/stock_data.iloc[i-1,3]*stock_data.iloc[i-1,11] + (1-stock_data.iloc[i-1,11])
#갖고 있는 포지션에 대한 수익률
stock_data.iloc[i,8] = stock_data.iloc[i-1,8] * stock_data.iloc[i,10]
else: # stock_data.iloc[i-1,6] == 2
# 매도 조건 충족
if stock_data.iloc[i-1,4] >= stock_data.iloc[i-1,5] and stock_data.iloc[i,4] < stock_data.iloc[i,5]:
stock_data.iloc[i,6] = 0 # buy condition
stock_data.iloc[i,9] = 0 # 평단가
stock_data.iloc[i,11] = 0
else:
stock_data.iloc[i,6] = stock_data.iloc[i-1,6]# buy condition
stock_data.iloc[i,9] = stock_data.iloc[i-1,8] # 평단가
stock_data.iloc[i,11] = stock_data.iloc[i-1,10]
stock_data.iloc[i,12] = stock_data.iloc[i-1,12]
#금일 수익률
stock_data.iloc[i,10] = stock_data.iloc[i,3]/stock_data.iloc[i-1,3]*stock_data.iloc[i-1,11] + (1-stock_data.iloc[i-1,11])
#갖고 있는 포지션에 대한 수익률
stock_data.iloc[i,8] = stock_data.iloc[i-1,8] * stock_data.iloc[i,10]
stock_data['hpr'] = stock_data['dr'].cumprod()
for i in range(1,count):
if stock_data.iloc[i-1,6] != 0 and stock_data.iloc[i,6] == 0: # 매도했을때
if stock_data.iloc[i-1,8] > 1: # 이기면
stock_data.iloc[i,13] = stock_data.iloc[i-1,13] + 1
stock_data.iloc[i,14] = stock_data.iloc[i-1,14]
elif stock_data.iloc[i-1,8] <= 1: # 지면
stock_data.iloc[i,14] = stock_data.iloc[i-1,14] + 1
stock_data.iloc[i,13] = stock_data.iloc[i-1,13]
else:
stock_data.iloc[i,13] = stock_data.iloc[i-1,13]
stock_data.iloc[i,14] = stock_data.iloc[i-1,14]
#결과
결과를 plot 해봅시다.
import matplotlib.pyplot as plt
plt.figure(figsize=(14,10))
plt.plot(range(count), stock_data['hpr']*stock_data.iloc[120,0], label = "trading", color='black')
plt.plot(range(count), stock_data['Close'], label="index", color="orange")
plt.xlim(120,count)
plt.legend()
약 2012년 부터 현재까지 S&P500 차트 데이터와 백테스팅 수익률 비교 그래프입니다.
그저 buy and hold가 훨씬 수익률이 높네요.
win_ratio=stock_data.iloc[-1,13]/stock_data.iloc[-1,12]
buy_and_hold = stock_data.iloc[-1,3]/stock_data.iloc[0,0]
hpr = stock_data.iloc[-1,7]
print("승률: ",win_ratio)
print("buy and hold: ", buy_and_hold)
print("hpr: ",hpr)
승률: 0.5
buy and hold: 3.57659930029685
hpr: 1.4859917181401687
다음에는 더 나은 알고리즘으로 돌아오겠습니다.
'파이썬으로 퀀트 프로그램 만들기 project > 백테스팅' 카테고리의 다른 글
[백테스팅]MACD와 RSI를 이용한 선물 매매하기 (2) | 2024.02.06 |
---|---|
[백테스팅]MACD 와 MACD signal을 이용하여 매매하기 (2) | 2024.02.05 |
[백테스팅] 하이킨아시 캔들 이용하여 매매하기 (2) | 2024.02.03 |
[벡테스팅]볼린저 밴드를 이용한 백테스팅 (0) | 2023.11.13 |
[백테스팅]EMA 60 상향 돌파 시 매수 (0) | 2023.11.10 |