AB Ratio를 활용한 트레이딩 전략(AB Ratio Trading Strategy)

AB Ratio의 개념과 유래

AB Ratio는 주가의 상대적인 강도를 측정하는 지표로, 일반적으로 두 가지 이동평균선의 비율을 통해 계산된다. AB Ratio는 장기 이동평균선과 단기 이동평균선의 관계를 파악하여 현재 주가의 상태를 판단하는 데 사용된다.

AB Ratio의 유래는 명확하게 알려져 있지 않지만, 이동평균선을 활용한 다양한 기술적 지표 중 하나로 발전해 왔다. 이 지표는 주가의 상대적인 위치를 파악하고, 추세의 강도를 측정하는 데 유용하다.

AB Ratio 계산 방법

AB Ratio는 다음과 같은 공식으로 계산된다:

AB Ratio = (장기 이동평균선 - 단기 이동평균선) / 단기 이동평균선

일반적으로 장기 이동평균선은 50일 또는 200일 이동평균선을, 단기 이동평균선은 10일 또는 20일 이동평균선을 사용한다. 이 비율은 장기 이동평균선이 단기 이동평균선 위에 있을 때 양수 값을, 아래에 있을 때 음수 값을 가진다.

예를 들어, 50일 이동평균선이 100달러이고 20일 이동평균선이 90달러인 경우 AB Ratio는 (100 – 90) / 90 = 0.11이 된다. 이는 장기 이동평균선이 단기 이동평균선보다 11% 위에 있음을 나타낸다.

AB Ratio를 활용한 매매 전략

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

  1. 과매수/과매도 구간 활용:
  • AB Ratio가 일정 수준(예: 0.2) 이상일 때 과매수 구간으로 판단하여 매도 신호로 해석한다.
  • AB Ratio가 일정 수준(예: -0.2) 이하일 때 과매도 구간으로 판단하여 매수 신호로 해석한다.
  1. AB Ratio의 변화 추이 활용:
  • AB Ratio가 상승 추세를 보일 때 상승 추세 지속으로 판단하여 매수 기회로 활용한다.
  • AB Ratio가 하락 추세를 보일 때 하락 추세 지속으로 판단하여 매도 기회로 활용한다.
  1. AB Ratio와 주가 추세 결합:
  • AB Ratio가 양수이고 주가가 상승 추세일 때 매수 신호로 해석한다.
  • AB Ratio가 음수이고 주가가 하락 추세일 때 매도 신호로 해석한다.

AB Ratio는 주가의 상대적인 위치를 파악하는 데 유용하지만, 단독으로 사용하기보다는 다른 기술적 지표나 주가 패턴과 함께 활용하는 것이 효과적이다. 또한 시장 상황과 개별 종목의 특성을 고려하여 적절한 매매 기준을 설정해야 한다.

파이썬을 활용한 AB Ratio 백테스팅

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

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

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

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

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

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

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)

# AB Ratio 계산 함수
def calculate_ab_ratio(data, long_term=50, short_term=20):
    data = data.copy()
    data['long_term_ma'] = data['Close'].rolling(window=long_term).mean()
    data['short_term_ma'] = data['Close'].rolling(window=short_term).mean()
    data['ab_ratio'] = (data['long_term_ma'] - data['short_term_ma']) / data['short_term_ma']
    return data

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

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

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

    return signals

# AB Ratio 계산
ab_ratio_data = calculate_ab_ratio(data)

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

# 백테스팅
initial_capital = 10000
positions = pd.DataFrame(index=signals.index).fillna(0.0)
positions[symbol] = 100 * signals['signal']

portfolio = positions.multiply(ab_ratio_data['Adj Close'], axis=0)
pos_diff = positions.diff()

portfolio['holdings'] = (positions.multiply(ab_ratio_data['Adj Close'], axis=0)).sum(axis=1)
portfolio['cash'] = initial_capital - (pos_diff.multiply(ab_ratio_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(ab_ratio_data['Close'], label='Price')
ax1.plot(ab_ratio_data['long_term_ma'], label='Long-term MA')
ax1.plot(ab_ratio_data['short_term_ma'], label='Short-term MA')
ax1.set_ylabel('Price')
ax1.set_title('Price Chart with Moving Averages')
ax1.legend(loc='upper left')

ax2.plot(ab_ratio_data['ab_ratio'], label='AB Ratio')
ax2.axhline(y=0.2, color='r', linestyle='--', label='Overbought')
ax2.axhline(y=-0.2, color='g', linestyle='--', label='Oversold')
ax2.set_ylabel('AB Ratio')
ax2.set_title('AB Ratio')
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를 가능한 한 오래전 날짜로 설정하여 모든 데이터를 가져올 수 있도록 한다.

calculate_ab_ratio 함수는 주어진 데이터를 바탕으로 AB Ratio를 계산한다. 장기 이동평균선(기본값: 50일)과 단기 이동평균선(기본값: 20일)을 구한 후, 이를 이용하여 AB Ratio를 계산한다.

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

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

matplotlib을 사용하여 주가, 장단기 이동평균선, AB Ratio, 포트폴리오 가치를 시각화한다. AB Ratio 차트에는 과매수/과매도 구간을 나타내는 기준선도 표시한다.

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

Leave a Reply

error: Content is protected !!