1. 개요
투자자들은 주식의 매매 타이밍을 결정하기 위해 다양한 기술적 지표를 활용합니다. 그중 골든크로스(Golden Cross)와 데드크로스(Death Cross)는 대표적인 매매 신호로, 단기 이동 평균선이 장기 이동 평균선을 상향 돌파하면 매수 신호(골든크로스), 반대로 하향 돌파하면 매도 신호(데드크로스)로 활용됩니다.
본 포스트에서는 Python과 Pandas, Matplotlib을 활용하여 주식 데이터에 기반한 골든크로스 및 데드크로스 백테스팅 전략을 구현하는 방법을 소개합니다.
2. 데이터 준비 및 이동 평균선 계산
우선, 1,000일간의 가상 주식 가격 데이터를 생성하고, 20일 단기 이동 평균선(SMA 20)과
50일 장기 이동 평균선(SMA 50)을 계산합니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 가상의 주식 데이터 생성
date_range = pd.date_range(start='2020-01-01', periods=1000, freq='D')
data = {
'Date': date_range,
'Close': np.cumsum(np.random.randn(1000) * 2 + 0.5) + 100
}
df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
# 이동 평균선 계산
df['SMA_20'] = df['Close'].rolling(window=20).mean()
df['SMA_50'] = df['Close'].rolling(window=50).mean()
위 코드에서는 numpy.random.randn()을 이용해 가상의 주식 가격 데이터를 생성하였으며,
rolling(window=n).mean()을 이용해 이동 평균선을 계산하였습니다.
3. 골든크로스 및 데드크로스 매매 신호 생성
이제 이동 평균선을 활용하여 매매 신호를 생성합니다.
# 매매 시그널 생성
df['Signal'] = 0
df.loc[df['SMA_20'] > df['SMA_50'], 'Signal'] = 1 # 매수 신호
df.loc[df['SMA_20'] < df['SMA_50'], 'Signal'] = -1 # 매도
여기서, Signal 값이 1이면 매수 신호, -1이면 매도 신호를 의미합니다.
4. 백테스팅 로직 구현
백테스팅을 위해 초기 투자금 10,000달러를 설정하고, 매수 및 매도 신호에 따라 주식을 거래하는 로직을 구현합니다.
# 백테스팅 구현
initial_balance = 10000 # 초기 투자금
cash = initial_balance
shares = 0 # 보유 주식 수
trade_log = []
for i in range(1, len(df)):
current_price = df['Close'].iloc[i]
previous_signal = df['Signal'].iloc[i - 1]
current_signal = df['Signal'].iloc[i]
# 매수 (골든크로스 발생)
if previous_signal != 1 and current_signal == 1:
shares = cash // current_price # 최대한 매수
cash -= shares * current_price
trade_log.append((df.index[i], 'BUY', shares, current_price, cash))
# 매도 (데드크로스 발생)
elif previous_signal != -1 and current_signal == -1:
cash += shares * current_price # 모든 주식 매도
trade_log.append((df.index[i], 'SELL', shares, current_price, cash))
shares = 0
매수는 골든크로스 발생 시 최대한 많은 주식을 매수하고, 데드크로스 발생 시 전량 매도하는 방식입니다.
5. 최종 평가 및 결과 출력
백테스팅이 완료된 후, 최종 자산 가치를 평가합니다.
# 최종 평가
final_value = cash + (shares * df['Close'].iloc[-1])
profit = final_value - initial_balance
# 결과 출력
print(f"최초 투자금: ${initial_balance}")
print(f"최종 자산 가치: ${final_value}")
print(f"총 수익: ${profit}")
print(f"총 거래 횟수: {len(trade_log)}")
# 매매 히스토리 출력
trade_df = pd.DataFrame(trade_log, columns=['Date', 'Type', 'Shares', 'Price', 'Cash'])
print(trade_df.tail(10))
6. 시각화
마지막으로 주가와 이동 평균선을 그래프로 시각화하여 골든크로스 및 데드크로스의 발생 시점을 확인합니다.
# 차트 시각화
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['Close'], label='Stock Price', alpha=0.7)
plt.plot(df.index, df['SMA_20'], label='20-day SMA', linestyle='--', alpha=0.7)
plt.plot(df.index, df['SMA_50'], label='50-day SMA', linestyle='--', alpha=0.7)
plt.legend()
plt.title("Stock Price and Moving Averages")
plt.show()
7. 결론
위의 백테스팅 결과를 통해, 골든크로스 및 데드크로스를 활용한 매매 전략이 실제 시장에서 어떻게 작동하는지 확인할 수 있습니다. 하지만 단순 이동 평균선을 이용한 전략은 과거 데이터에 대한 후행적 특성이 있기 때문에, 시장 변동성이 높은 경우에는 예측력이 떨어질 수 있습니다.
이를 개선하기 위해서는 RSI, MACD 등의 추가적인 기술적 지표를 결합하거나 리스크 관리 전략을 적용하는 것이 필요합니다. 본 전략을 바탕으로 다양한 변수를 실험해보며 최적의 매매 전략을 구성해보시길 바랍니다!
전체코드
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 가상의 주식 데이터 생성 (실제 데이터 사용 시 API를 활용할 수도 있음)
date_range = pd.date_range(start='2020-01-01', periods=1000, freq='D')
data = {
'Date': date_range,
'Close': np.cumsum(np.random.randn(1000) * 2 + 0.5) + 100
}
df = pd.DataFrame(data)
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
# 이동 평균선 계산 (단기: 20일, 장기: 50일)
df['SMA_20'] = df['Close'].rolling(window=20).mean()
df['SMA_50'] = df['Close'].rolling(window=50).mean()
# 매매 시그널 생성 (골든크로스 및 데드크로스 전략)
df['Signal'] = 0
df.loc[df['SMA_20'] > df['SMA_50'], 'Signal'] = 1 # 매수 신호
df.loc[df['SMA_20'] < df['SMA_50'], 'Signal'] = -1 # 매도 신호
# 백테스팅 로직 구현
initial_balance = 10000 # 초기 투자금
cash = initial_balance
shares = 0 # 보유 주식 수
trade_log = []
for i in range(1, len(df)):
current_price = df['Close'].iloc[i]
previous_signal = df['Signal'].iloc[i - 1]
current_signal = df['Signal'].iloc[i]
# 매수 (골든크로스 발생)
if previous_signal != 1 and current_signal == 1:
shares = cash // current_price # 최대한 매수
cash -= shares * current_price
trade_log.append((df.index[i], 'BUY', shares, current_price, cash))
# 매도 (데드크로스 발생)
elif previous_signal != -1 and current_signal == -1:
cash += shares * current_price # 모든 주식 매도
trade_log.append((df.index[i], 'SELL', shares, current_price, cash))
shares = 0
# 최종 평가
final_value = cash + (shares * df['Close'].iloc[-1])
profit = final_value - initial_balance
# 결과 출력
print(f"최초 투자금: ${initial_balance}")
print(f"최종 자산 가치: ${final_value}")
print(f"총 수익: ${profit}")
print(f"총 거래 횟수: {len(trade_log)}")
# 매매 히스토리 출력
trade_df = pd.DataFrame(trade_log, columns=['Date', 'Type', 'Shares', 'Price', 'Cash'])
print(trade_df.tail(10))
# 차트 시각화
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['Close'], label='Stock Price', alpha=0.7)
plt.plot(df.index, df['SMA_20'], label='20-day SMA', linestyle='--', alpha=0.7)
plt.plot(df.index, df['SMA_50'], label='50-day SMA', linestyle='--', alpha=0.7)
plt.legend()
plt.title("Stock Price and Moving Averages")
plt.show()
'코딩교육 > Python 초등교육에서 전문가까지' 카테고리의 다른 글
2단계 : 4. 함수 (매개변수와 반환값의 사용법) (0) | 2025.03.18 |
---|---|
2단계 : 4. 함수 (함수 정의와 호출 - def 키워드) (0) | 2025.03.17 |
2단계 : 3. 반복문 (무한 루프와 그 활용 사례) (0) | 2025.03.08 |
2단계 : 3. 반복문 (break 와 continue의 사용 방법과 차이) (0) | 2025.03.07 |
2단계 : 3. 반복문 (중첩 반복문 활용) (0) | 2025.03.06 |