Ultimate Oscillator를 활용한 트레이딩 전략(Ultimate Oscillator Trading Strategy)

Ultimate Oscillator의 개념과 유래

Ultimate Oscillator는 Larry Williams가 1976년에 개발한 모멘텀 지표로, 단기, 중기, 장기 시장 변동성을 종합적으로 고려하여 매매 신호를 생성한다. 이 지표는 과매수와 과매도 구간을 파악하는 데 유용하며, 다양한 시장 상황에서 활용할 수 있다.

Ultimate Oscillator는 세 가지 기간의 가격 변동을 기반으로 계산된다:

  1. 단기(7일): 시장의 단기적인 변동성을 반영한다.
  2. 중기(14일): 시장의 중기적인 변동성을 반영한다.
  3. 장기(28일): 시장의 장기적인 변동성을 반영한다.

이 세 가지 기간의 가격 변동을 조합하여 Ultimate Oscillator 값을 계산하며, 이를 통해 현재 시장의 강도를 파악할 수 있다.

Ultimate Oscillator 계산 방법

Ultimate Oscillator는 다음과 같은 단계를 통해 계산된다:

  1. 각 기간(7일, 14일, 28일)의 Buying Pressure(BP)와 True Range(TR)를 계산한다.
  • BP = 당일 종가 – min(당일 저가, 전일 종가)
  • TR = max(당일 고가, 전일 종가) – min(당일 저가, 전일 종가)
  1. 각 기간의 BP와 TR의 평균을 계산한다.
  • Average7 = sum(BP, 7) / sum(TR, 7)
  • Average14 = sum(BP, 14) / sum(TR, 14)
  • Average28 = sum(BP, 28) / sum(TR, 28)
  1. 가중 평균을 계산한다.
  • Ultimate Oscillator = 100 × ((4 × Average7) + (2 × Average14) + Average28) / (4 + 2 + 1)

Ultimate Oscillator의 값은 0에서 100 사이로 나타나며, 일반적으로 70 이상은 과매수 구간, 30 이하는 과매도 구간으로 해석된다.

Ultimate Oscillator를 활용한 매매 전략

Ultimate Oscillator를 활용한 매매 전략은 다음과 같이 구성할 수 있다:

  1. 과매수/과매도 구간을 활용한 전략:
  • Ultimate Oscillator가 70 이상의 과매수 구간에 진입하면 매도 신호로 해석한다.
  • Ultimate Oscillator가 30 이하의 과매도 구간에 진입하면 매수 신호로 해석한다.
  1. 다이버전스를 활용한 전략:
  • 가격은 더 높은 고점을 형성하는데 Ultimate Oscillator는 더 낮은 고점을 형성할 경우 베어리시 다이버전스로 해석하여 매도 신호로 활용한다.
  • 가격은 더 낮은 저점을 형성하는데 Ultimate Oscillator는 더 높은 저점을 형성할 경우 불리시 다이버전스로 해석하여 매수 신호로 활용한다.
  1. Ultimate Oscillator의 추세 변화를 포착하는 전략:
  • Ultimate Oscillator가 상승 추세에서 하락 추세로 전환될 때 매도 신호로 해석한다.
  • Ultimate Oscillator가 하락 추세에서 상승 추세로 전환될 때 매수 신호로 해석한다.

실제 트레이딩에서는 Ultimate Oscillator를 다른 기술적 지표나 가격 패턴과 함께 활용하여 매매 신호의 신뢰도를 높이는 것이 효과적이다. 또한 Ultimate Oscillator의 매매 신호를 그대로 따르기보다는 시장 상황과 자산의 특성을 고려하여 유연하게 대응해야 한다.

파이썬을 활용한 Ultimate Oscillator 백테스팅

파이썬을 사용하여 Ultimate Oscillator 기반의 트레이딩 전략을 백테스팅해보자. 다음 라이브러리를 활용할 것이다:

  • pandas: 데이터 조작 및 분석
  • numpy: 수치 계산
  • matplotlib: 데이터 시각화
  • FinanceDataReader: 주가 데이터 수집

먼저 가상환경을 활성화하고 필요한 라이브러리를 설치한다.

source venv/bin/activate
pip install pandas numpy matplotlib FinanceDataReader

FinanceDataReader를 설치하면 종속 모듈도 함께 설치된다.

다음으로 Ultimate Oscillator를 계산하고 매매 신호를 생성하는 코드를 작성해보자.

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)

# Ultimate Oscillator 계산 함수
def ultimate_oscillator(data, period_1=7, period_2=14, period_3=28, weight_1=4, weight_2=2, weight_3=1):
    bp = data['Close'] - data[['Low', 'Close']].shift(1).min(axis=1)
    tr = data[['High', 'Close']].shift(1).max(axis=1) - data[['Low', 'Close']].shift(1).min(axis=1)

    average_1 = bp.rolling(window=period_1).sum() / tr.rolling(window=period_1).sum()
    average_2 = bp.rolling(window=period_2).sum() / tr.rolling(window=period_2).sum()
    average_3 = bp.rolling(window=period_3).sum() / tr.rolling(window=period_3).sum()

    uo = 100 * ((weight_1 * average_1) + (weight_2 * average_2) + (weight_3 * average_3)) / (weight_1 + weight_2 + weight_3)

    return uo

# Ultimate Oscillator 계산
uo = ultimate_oscillator(data)

# 매매 신호 생성 함수
def get_signals(uo, upper_threshold=70, lower_threshold=30):
    signals = pd.DataFrame(index=uo.index)
    signals['signal'] = 0

    signals['signal'][uo > upper_threshold] = -1
    signals['signal'][uo < lower_threshold] = 1

    signals['positions'] = signals['signal'].diff()

    return signals

# 매매 신호 생성
signals = get_signals(uo)

# 백테스팅
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, ax3) = plt.subplots(3, 1, figsize=(15, 15), gridspec_kw={'height_ratios': [3, 1, 1]})

ax1.plot(data['Close'], label='Price')
ax1.set_ylabel('Price')
ax1.set_title('Price Chart')
ax1.legend(loc='upper left')

ax2.plot(uo, label='Ultimate Oscillator')
ax2.axhline(y=70, color='r', linestyle='--', label='Overbought')
ax2.axhline(y=30, color='g', linestyle='--', label='Oversold')
ax2.set_ylabel('Ultimate Oscillator')
ax2.set_title('Ultimate Oscillator')
ax2.legend(loc='upper left')

ax3.plot(portfolio['total'], label='Portfolio Value')
ax3.set_ylabel('Portfolio Value')
ax3.set_title('Portfolio Performance')
ax3.legend(loc='upper left')

plt.tight_layout()
plt.show()

위 코드에서는 FinanceDataReader를 사용하여 VOO ETF의 전체 기간 주가 데이터를 가져온다. start_date를 가능한 한 오래전 날짜로 설정하여 모든 데이터를 가져올 수 있도록 한다.

ultimate_oscillator 함수는 주어진 데이터를 바탕으로 Ultimate Oscillator를 계산한다. 먼저 Buying Pressure와 True Range를 계산하고, 이를 기반으로 세 가지 기간(기본값: 7일, 14일, 28일)의 평균을 구한다. 그 후 가중 평균을 계산하여 Ultimate Oscillator 값을 산출한다.

get_signals 함수는 계산된 Ultimate Oscillator를 기준으로 매매 신호를 생성한다. Ultimate Oscillator가 상단 임계값(기본값: 70)을 초과할 때 매도 신호(-1)를, 하단 임계값(기본값: 30)을 하회할 때 매수 신호(1)를 생성한다.

백테스팅을 위해 초기 자본금을 10,000달러로 설정하고, 생성된 매매 신호를 바탕으로 포트폴리오 가치를 계산한다. 최종적으로 총 수익률과 포트폴리오 가치를 출력한다.

matplotlib을 사용하여 주가, Ultimate Oscillator, 포트폴리오 가치를 시각화한다. Ultimate Oscillator 차트에는 과매수(70)와 과매도(30) 기준선을 표시하여 매매 신호 발생 구간을 나타낸다.

코드 실행 중 발생할 수 있는 오류를 처리하기 위해 try-except 문을 사용하였다. 데이터를 가져오는 과정에서 오류가 발생하면 에러 메시지를 출력하고 프로그램을 종료한다.

Leave a Reply

error: Content is protected !!