돈치안 채널의 개념과 유래
돈치안 채널(Donchian Channel)은 리처드 돈치안(Richard Donchian)이 개발한 기술적 분석 지표로, 일정 기간 동안의 최고가와 최저가를 이용하여 상한선과 하한선을 그리는 방법이다. 이 지표는 1930년대에 고안되었으며, 현재까지도 많은 트레이더들에게 활용되고 있다.
돈치안 채널은 일반적으로 20일을 기준으로 계산되며, 상한선은 해당 기간 내 최고가, 하한선은 해당 기간 내 최저가로 설정된다. 또한, 중간선은 상한선과 하한선의 평균값으로 계산된다. 이 채널은 가격 움직임의 범위를 시각적으로 보여주며, 변동성의 확장과 수축을 파악하는 데 유용하다.
돈치안 채널 계산 예시
예를 들어, 어떤 주식의 지난 20일간 최고가와 최저가가 다음과 같다고 가정해보자:
- 20일 최고가: $100
- 20일 최저가: $80
이 경우, 돈치안 채널의 상한선은 $100, 하한선은 $80이 된다. 중간선은 ($100 + $80) / 2 = $90이 된다.
이렇게 계산된 돈치안 채널은 주가의 움직임 범위를 나타내며, 상한선과 하한선을 벗어나는 가격 변동은 강세 또는 약세 신호로 해석될 수 있다.
돈치안 채널을 활용한 매매 전략
돈치안 채널을 활용한 대표적인 매매 전략은 다음과 같다:
- 브레이크아웃 전략: 가격이 상한선을 돌파할 때 매수하고, 하한선을 돌파할 때 매도하는 전략이다. 이는 가격이 일정 범위를 벗어나는 움직임에 주목하여 강세 또는 약세 시장에 대응하는 방식이다.
- 풀백 전략: 가격이 상한선에서 하락하여 중간선에 접근할 때 매수하고, 하한선에서 상승하여 중간선에 접근할 때 매도하는 전략이다. 이는 가격이 일시적으로 채널의 상단이나 하단에서 벗어난 후 다시 채널 내부로 회귀하는 특성을 이용한다.
- 트렌드 추종 전략: 가격이 중간선 위에서 움직일 때는 상승 추세로, 중간선 아래에서 움직일 때는 하락 추세로 판단하여 매매하는 전략이다. 채널의 기울기를 관찰하여 추세의 강도를 파악할 수도 있다.
실제 트레이딩에서는 돈치안 채널과 다른 기술적 지표를 함께 사용하여 시장 상황을 종합적으로 판단하는 것이 효과적이다. 또한, 거래량, 모멘텀 등의 추가 지표를 활용하여 매매 신호의 정확성을 높일 수 있다.
파이썬을 활용한 돈치안 채널 백테스팅
이제 파이썬을 사용하여 돈치안 채널 기반의 트레이딩 전략을 백테스팅해보자. 다음 라이브러리를 활용할 것이다:
pandas
: 데이터 조작 및 분석numpy
: 수치 계산matplotlib
: 데이터 시각화FinanceDataReader
: 주가 데이터 수집
먼저 가상환경을 활성화하고 필요한 라이브러리를 설치한다.
source venv/bin/activate
pip install pandas numpy matplotlib FinanceDataReader
FinanceDataReader를 설치하면 종속 모듈도 함께 설치된다.
다음으로 돈치안 채널을 계산하고 매매 신호를 생성하는 코드를 작성해보자.
import FinanceDataReader as fdr
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 데이터 가져오기
symbol = "VOO"
start_date = "1900-01-01"
end_date = "2023-05-01"
try:
data = fdr.DataReader(symbol, start_date, end_date)
except Exception as e:
print(f"Error occurred while fetching data: {e}")
exit(1)
# 돈치안 채널 계산 함수
def get_donchian_channel(data, period=20):
high = data['High'].rolling(window=period).max()
low = data['Low'].rolling(window=period).min()
middle = (high + low) / 2
return high, middle, low
# 매매 신호 생성 함수
def get_signals(data, upper, middle, lower):
signals = pd.DataFrame(index=data.index)
signals['signal'] = 0
signals['signal'][data['Close'] > upper] = 1
signals['signal'][data['Close'] < lower] = -1
signals['positions'] = signals['signal'].diff()
return signals
# 돈치안 채널 계산
upper, middle, lower = get_donchian_channel(data)
# 매매 신호 생성
signals = get_signals(data, upper, middle, lower)
# 백테스팅
initial_capital = 10000
positions = pd.DataFrame(index=signals.index).fillna(0.0)
positions[symbol] = 100 * signals['signal']
portfolio = positions.multiply(data['Adj Close'], axis=0)
pos_diff = positions.diff()
portfolio['holdings'] = (positions.multiply(data['Adj Close'], axis=0)).sum(axis=1)
portfolio['cash'] = initial_capital - (pos_diff.multiply(data['Adj Close'], axis=0)).sum(axis=1).cumsum()
portfolio['total'] = portfolio['cash'] + portfolio['holdings']
portfolio['returns'] = portfolio['total'].pct_change()
# 결과 출력
print(f"Final portfolio value: ${portfolio['total'][-1]:,.2f}")
print(f"Total returns: {100 * (portfolio['total'][-1] / initial_capital - 1):.2f}%")
# 시각화
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 10), gridspec_kw={'height_ratios': [3, 1]})
ax1.plot(data['Close'], label='Close Price')
ax1.plot(upper, label='Upper Channel')
ax1.plot(middle, label='Middle Channel')
ax1.plot(lower, label='Lower Channel')
ax1.legend(loc='upper left')
ax1.set_title(f'{symbol} Donchian Channels')
ax2.plot(portfolio['total'], label='Portfolio Value')
ax2.legend(loc='upper left')
ax2.set_title('Portfolio Performance')
plt.tight_layout()
plt.show()
위 코드에서는 FinanceDataReader를 사용하여 VOO ETF의 전체 기간 주가 데이터를 가져온다. start_date
를 가능한 한 오래전 날짜로 설정하여 모든 데이터를 가져올 수 있도록 한다.
get_donchian_channel
함수는 주가 데이터와 채널 기간을 입력받아 돈치안 채널의 상한선, 중간선, 하한선을 계산한다.
get_signals
함수는 주가가 상한선을 돌파할 때 매수 신호(1), 하한선을 돌파할 때 매도 신호(-1)를 생성한다.
백테스팅을 위해 초기 자본금을 10,000달러로 설정하고, 생성된 매매 신호를 바탕으로 포트폴리오 가치를 계산한다. 최종적으로 총 수익률과 포트폴리오 가치를 출력한다.
matplotlib
을 사용하여 주가, 돈치안 채널, 포트폴리오 가치를 시각화한다.
코드 실행 중 발생할 수 있는 오류를 처리하기 위해 try-except
문을 사용하였다. 데이터를 가져오는 과정에서 오류가 발생하면 에러 메시지를 출력하고 프로그램을 종료한다.