일목균형표의 개념과 유래
일목균형표(一目均衡表, Ichimoku Kinko Hyo)는 1930년대 일본의 journalist인 Goichi Hosoda가 개발한 기술적 분석 도구로, 추세와 모멘텀을 파악하는 데 사용된다. 이 지표는 과거 가격 데이터를 기반으로 미래의 지지선과 저항선을 예측하며, 단기 및 중기 추세를 식별하는 데 도움을 준다.
일목균형표는 5개의 주요 구성 요소로 이루어져 있다:
- 전환선(Tenkan-sen): 단기 추세를 나타내며, 일반적으로 과거 9일간의 최고가와 최저가의 중간값으로 계산한다.
- 계산식: (9일간의 최고가 + 9일간의 최저가) / 2
- 기준선(Kijun-sen): 중기 추세를 나타내며, 일반적으로 과거 26일간의 최고가와 최저가의 중간값으로 계산한다.
- 계산식: (26일간의 최고가 + 26일간의 최저가) / 2
- 선행스팬 A(Senkou Span A): 미래의 지지선이나 저항선을 나타내며, 전환선과 기준선의 중간값을 26일 앞으로 투영하여 계산한다.
- 계산식: (전환선 + 기준선) / 2를 26일 앞으로 투영
- 선행스팬 B(Senkou Span B): 미래의 지지선이나 저항선을 나타내며, 과거 52일간의 최고가와 최저가의 중간값을 26일 앞으로 투영하여 계산한다.
- 계산식: (52일간의 최고가 + 52일간의 최저가) / 2를 26일 앞으로 투영
- 후행스팬(Chikou Span): 현재 시점에서 26일 전의 종가를 나타낸다.
일목균형표에서는 구름대(Kumo)라는 개념도 중요한데, 이는 선행스팬 A와 선행스팬 B 사이의 영역을 의미한다. 구름대는 미래의 지지선과 저항선의 강도를 시각적으로 표현한다.
선행스팬의 의미와 근거
일목균형표에서 선행스팬 A와 선행스팬 B는 26일 앞의 미래 시점에 투영되는 지지선과 저항선의 역할을 한다. 이 선행스팬들은 현재 시장의 추세와 모멘텀을 바탕으로 미래의 가격 움직임을 예측하는 데 사용된다.
- 선행스팬 A: 전환선과 기준선의 중간값을 26일 앞으로 투영
- 선행스팬 A는 단기 추세(전환선)와 중기 추세(기준선)의 조화를 바탕으로 미래의 지지선이나 저항선을 예측한다.
- 이는 현재 시장의 추세가 지속될 것이라는 가정 하에, 단기와 중기 추세의 균형점이 미래에도 유효할 것이라는 관점을 반영한다.
- 선행스팬 B: 52일간의 최고가와 최저가의 중간값을 26일 앞으로 투영
- 선행스팬 B는 장기 추세(52일)를 고려하여 미래의 지지선이나 저항선을 예측한다.
- 이는 현재 시장의 장기적인 추세와 변동성을 바탕으로, 미래에도 이러한 추세와 변동성이 유지될 것이라는 가정을 반영한다.
선행스팬을 26일 앞으로 투영하는 근거는 다음과 같다:
- 중기 추세의 반영: 26일은 일목균형표에서 중기 추세를 나타내는 기준선의 기간이다. 선행스팬을 26일 앞으로 투영함으로써, 현재의 중기 추세가 미래에도 지속될 것이라는 가정을 반영한다.
- 시장 사이클의 고려: 26일은 시장의 주요 사이클 중 하나로 여겨진다. 이는 월별 주기(약 20거래일)와 유사하며, 계절적 요인이나 경제 이벤트 등의 영향을 포착할 수 있다.
- 실용적인 관점: 26일은 약 1달 간의 거래일에 해당하며, 이는 투자자들이 중기적인 관점에서 시장을 바라보고 대응하기에 적절한 기간으로 여겨진다.
선행스팬은 현재 시장의 추세와 모멘텀을 바탕으로 미래의 가격 움직임을 예측하는 도구로 사용되지만, 이는 어디까지나 예측일 뿐이며 실제 시장 상황과는 차이가 있을 수 있다. 따라서 선행스팬을 해석할 때는 다른 기술적 지표 및 시장 상황을 종합적으로 고려해야 한다.
또한, 선행스팬이 형성하는 구름대(Kumo)는 미래 시점에서의 지지선과 저항선의 강도를 시각적으로 표현한다. 구름대의 두께와 방향성은 미래 시장 추세의 강도와 방향에 대한 통찰을 제공할 수 있다.
일목균형표 파라미터의 동양철학적 의미
일목균형표의 주요 파라미터인 9일, 26일, 52일은 단순한 숫자가 아닌 동양철학에 근거한 의미를 가지고 있다.
- 9일: 양의 극치
- 9는 양의 극치를 나타내는 숫자로, 음양오행설에서 양의 숫자 중 가장 큰 값이다.
- 전환선(Tenkan-sen)에 9일을 사용하는 것은 단기 추세의 전환점을 포착하기 위한 것으로 해석할 수 있다.
- 26일: 음과 양의 조화
- 26은 2와 6의 곱으로, 2는 음의 시작, 6은 양의 시작을 의미한다.
- 26일은 음과 양의 조화를 나타내며, 시장에서 중기 추세를 파악하는 데 적합한 기간으로 여겨진다.
- 기준선(Kijun-sen)에 26일을 사용하는 것은 중기 추세를 확인하기 위한 것이다.
- 52일: 음양의 순환
- 52는 양의 극치인 9와 음의 극치인 6의 합인 15에서 파생된 숫자이다. (1+5=6, 5+2=7, 6+7=13, 1+3=4, 52=5+2)
- 52일은 음양의 한 주기를 나타내며, 장기적인 시장 사이클을 파악하는 데 적합한 기간으로 여겨진다.
- 선행스팬 B(Senkou Span B)에 52일을 사용하는 것은 장기 추세를 예측하기 위한 것이다.
또한, 26일을 선행스팬 A와 선행스팬 B의 선행 이동 기간으로 사용하는 것은 중기 추세의 반절인 13일(26일/2)의 두 배를 나타낸다. 이는 음양의 조화와 균형을 상징하는 것으로 해석될 수 있다.
일목균형표의 창시자인 Goichi Hosoda는 이러한 동양철학적 개념을 바탕으로 지표를 개발하였으며, 이는 일목균형표가 단순한 기술적 지표를 넘어 시장의 자연스러운 리듬을 파악하는 도구로 활용될 수 있음을 시사한다.
트레이딩에 있어서 이러한 동양철학적 관점을 이해하는 것은 시장을 바라보는 통찰력을 깊이 있게 만들어 줄 수 있다. 다만, 실제 트레이딩에서는 이러한 철학적 배경과 함께 객관적인 시장 분석과 리스크 관리가 병행되어야 한다는 점을 잊지 말아야 한다.
일목균형표를 활용한 매매 전략
일목균형표를 활용한 대표적인 매매 전략은 다음과 같다:
- 전환선과 기준선의 교차:
- 전환선이 기준선을 상향 돌파할 때 매수하고, 하향 돌파할 때 매도한다.
- 이는 단기 추세와 중기 추세의 전환을 포착하는 전략이다.
- 구름대 돌파:
- 가격이 구름대를 상향 돌파할 때 매수하고, 하향 돌파할 때 매도한다.
- 이는 강력한 추세의 시작을 포착하는 전략이다.
- 후행스팬과 가격의 관계:
- 후행스팬이 가격 위에 있을 때는 강세 추세로, 가격 아래에 있을 때는 약세 추세로 판단한다.
- 후행스팬이 가격을 돌파할 때 추세 전환 신호로 해석할 수 있다.
실제 트레이딩에서는 일목균형표의 여러 구성 요소를 종합적으로 분석하여 매매 결정을 내리는 것이 효과적이다. 또한 일목균형표와 함께 다른 기술적 지표나 차트 패턴 등을 활용하여 시장을 다각도로 분석할 수 있다.
파이썬을 활용한 일목균형표 백테스팅
이제 파이썬을 사용하여 일목균형표 기반의 트레이딩 전략을 백테스팅해보자. 다음 라이브러리를 활용할 것이다:
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 ichimoku(data, tenkan_period=9, kijun_period=26, senkou_period=52, chikou_period=26):
tenkan_sen = (data['High'].rolling(window=tenkan_period).max() + data['Low'].rolling(window=tenkan_period).min()) / 2
kijun_sen = (data['High'].rolling(window=kijun_period).max() + data['Low'].rolling(window=kijun_period).min()) / 2
senkou_span_a = ((tenkan_sen + kijun_sen) / 2).shift(kijun_period)
senkou_span_b = ((data['High'].rolling(window=senkou_period).max() + data['Low'].rolling(window=senkou_period).min()) / 2).shift(kijun_period)
chikou_span = data['Close'].shift(-chikou_period)
return pd.DataFrame({'Tenkan Sen': tenkan_sen, 'Kijun Sen': kijun_sen, 'Senkou Span A': senkou_span_a, 'Senkou Span B': senkou_span_b, 'Chikou Span': chikou_span})
# 매매 신호 생성 함수
def get_signals(data, ichimoku_data):
signals = pd.DataFrame(index=data.index)
signals['signal'] = 0
# 전환선과 기준선의 교차
signals['signal'][ichimoku_data['Tenkan Sen'] > ichimoku_data['Kijun Sen']] = 1
signals['signal'][ichimoku_data['Tenkan Sen'] < ichimoku_data['Kijun Sen']] = -1
# 구름대 돌파
signals['signal'][data['Close'] > ichimoku_data['Senkou Span A']] = 1
signals['signal'][data['Close'] < ichimoku_data['Senkou Span B']] = -1
# 후행스팬과 가격의 관계
signals['signal'][ichimoku_data['Chikou Span'] > data['Close']] = 1
signals['signal'][ichimoku_data['Chikou Span'] < data['Close']] = -1
signals['positions'] = signals['signal'].diff()
return signals
# 일목균형표 데이터 계산
ichimoku_data = ichimoku(data)
# 매매 신호 생성
signals = get_signals(data, ichimoku_data)
# 백테스팅
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(ichimoku_data['Tenkan Sen'], label='Tenkan Sen')
ax1.plot(ichimoku_data['Kijun Sen'], label='Kijun Sen')
ax1.plot(ichimoku_data['Senkou Span A'], label='Senkou Span A')
ax1.plot(ichimoku_data['Senkou Span B'], label='Senkou Span B')
ax1.plot(ichimoku_data['Chikou Span'], label='Chikou Span')
ax1.legend(loc='upper left')
ax1.set_title('Ichimoku Kinko Hyo')
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
를 가능한 한 오래전 날짜로 설정하여 모든 데이터를 가져올 수 있도록 한다.
ichimoku
함수는 일목균형표의 주요 구성 요소인 전환선, 기준선, 선행스팬 A, 선행스팬 B, 후행스팬을 계산한다.
get_signals
함수는 일목균형표의 구성 요소를 기반으로 매매 신호를 생성한다. 전환선과 기준선의 교차, 구름대 돌파, 후행스팬과 가격의 관계를 고려하여 매수 신호(1)와 매도 신호(-1)를 생성한다.
백테스팅을 위해 초기 자본금을 10,000달러로 설정하고, 생성된 매매 신호를 바탕으로 포트폴리오 가치를 계산한다. 최종적으로 총 수익률과 포트폴리오 가치를 출력한다.
matplotlib
을 사용하여 주가, 일목균형표의 구성 요소, 포트폴리오 가치를 시각화한다.
코드 실행 중 발생할 수 있는 오류를 처리하기 위해 try-except
문을 사용하였다. 데이터를 가져오는 과정에서 오류가 발생하면 에러 메시지를 출력하고 프로그램을 종료한다.