CAPM, Fama-French 다중 팩터 모델과 오늘날 퀀트

2024. 11. 12. 16:11금융공학/모델링

다중 팩터 모델 이전 : CAPM

과거 자산 수익률을 설명하려는 모델은 기본적으로 "시장 수익률"에 집중했습니다. 즉, CAPM(Capital Asset Pricing Model)이라는 모델이 대표적이었는데, 이는 주식의 기대 수익률이 시장 전체의 수익률과 얼마나 일치하는지를 나타내는 방식이었습니다. CAPM은 간단하고 기본적인 모델이었지만, 다양한 자산의 실제 수익률을 설명하는 데 한계가 있었습니다.

더보기

CAPM(Capital Asset Pricing Model)은 1964년에 처음 소개되었습니다. 이 모델은 윌리엄 샤프(William F. Sharpe)가 처음 제안했으며, 동시에 존 린트너(John Lintner)와 잭 트레이너(Jack Treynor)도 비슷한 개념을 연구했습니다. CAPM은 자산의 기대 수익률을 시장 수익률과의 관계를 통해 설명하는 모델로, 현대 포트폴리오 이론과 자본 시장의 기초 이론 중 하나로 자리 잡았습니다. 윌리엄 샤프는 이 연구를 통해 1990년에 노벨 경제학상을 받았으며, CAPM은 이후 자산 가격 결정과 포트폴리오 이론 연구에 중요한 기반을 제공하는 모델로 널리 활용되었습니다.

1. CAPM의 핵심 개념

CAPM의 기본적인 가정은 자산의 수익률이 시장 수익률에 따라 변동하며, 위험이 클수록 더 높은 수익률을 기대할 수 있다는 것입니다. 이를 통해 자산의 수익률을 예측하는 간단한 공식을 제시합니다:

import pandas as pd
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
from scipy import stats

# 1. Load data (Daily price data for Bitcoin and Ethereum)
# Assume Bitcoin as the market return and Ethereum as the individual asset.
btc_data = yf.download("BTC-USD", start="2021-01-01", end="2023-12-31")
eth_data = yf.download("ETH-USD", start="2021-01-01", end="2023-12-31")

# 2. Calculate returns (daily returns)
btc_data['Return'] = btc_data['Close'].pct_change()
eth_data['Return'] = eth_data['Close'].pct_change()

# Combine data
data = pd.DataFrame({
    'BTC_Return': btc_data['Return'],
    'ETH_Return': eth_data['Return']
}).dropna()

# 3. Calculate CAPM coefficients (estimate beta through regression)
# Set BTC returns on the x-axis (market) and ETH returns on the y-axis (asset) to estimate beta.
slope, intercept, r_value, p_value, std_err = stats.linregress(data['BTC_Return'], data['ETH_Return'])
beta = slope  # Sensitivity of Ethereum to the market return (beta)
alpha = intercept  # Excess return outside the market return (alpha)

print(f"Beta: {beta:.4f}")
print(f"Alpha: {alpha:.4f}")

# 4. Calculate expected return
# Apply the CAPM formula using a risk-free rate (example set to 2%)
risk_free_rate = 0.02 / 365  # Convert to daily risk-free rate (assuming 2% annually)
expected_market_return = data['BTC_Return'].mean()  # Average BTC return

# Expected return according to the CAPM formula
expected_return = risk_free_rate + beta * (expected_market_return - risk_free_rate)
print(f"Expected Return: {expected_return:.4%}")

# 5. Visualize results
plt.figure(figsize=(10, 6))
plt.scatter(data['BTC_Return'], data['ETH_Return'], alpha=0.5)
plt.plot(data['BTC_Return'], intercept + slope * data['BTC_Return'], color="red", label="CAPM Regression Line")
plt.xlabel("BTC Daily Return (Market Return)")
plt.ylabel("ETH Daily Return (Asset Return)")
plt.title("CAPM: Relationship between BTC and ETH Returns")
plt.legend()
plt.show()

 

이 코드에서 생성된 CAPM 산포도 및 회귀선 플롯은 비트코인(BTC) 수익률과 이더리움(ETH) 수익률 간의 관계를 시각화하여 CAPM의 개념을 설명하는 데 사용됩니다. 플롯을 해석하는 방법은 다음과 같습니다:

  1. 산포도 해석 (BTC와 ETH 수익률 관계):
    • 각 점은 BTC와 ETH의 일일 수익률을 나타냅니다.
    • x축은 BTC의 일일 수익률(시장 수익률), y축은 ETH의 일일 수익률(자산 수익률)로 설정되어 있습니다.
  2. CAPM 회귀선 해석 (CAPM Regression Line):
    • 빨간색 회귀선은 BTC와 ETH의 수익률 사이의 선형 관계를 나타냅니다. 이 선의 기울기는 베타(beta) 값이며, 시장 수익률에 대한 자산의 민감도를 측정합니다.
      • 베타가 1보다 크면 ETH가 BTC보다 변동성이 크고, 시장이 움직이는 방향과 강도에 대해 더 민감하게 반응한다는 뜻입니다.
      • 베타가 1보다 작으면 ETH의 변동성이 BTC보다 낮아, 시장 수익률 변화에 덜 민감하게 반응함을 나타냅니다.
    • 회귀선의 y절편은 알파(alpha) 값으로, 시장 수익률 외의 추가적인 초과 수익률(시장 요인으로 설명되지 않는 수익률)을 의미합니다.
  3. CAPM 회귀선과 점들 간의 분포 (잔차 확인):
    • 점들이 회귀선에 가까울수록 BTC가 ETH의 수익률을 잘 설명하고 있음을 의미합니다.
    • 그러나 점들이 회귀선에서 많이 떨어져 있다면, CAPM으로는 BTC와 ETH의 수익률 관계를 충분히 설명하지 못하고 있다는 것을 의미하며, 이 경우 추가적인 요인이 필요할 수 있습니다.

 

2. CAPM의 한계

CAPM은 간단하고 기본적인 모델이지만, 현실적인 시장에서 자산의 수익률을 완벽히 설명하기에는 여러 한계가 있습니다. 특히 다음과 같은 점에서 문제가 제기되었습니다:

  • 규모 효과: 연구에 따르면, 소형주가 대형주보다 더 높은 수익률을 보이는 경향이 있습니다. 하지만 CAPM은 이런 효과를 설명하지 못합니다.
  • 가치 프리미엄: 저평가된 주식(예: 저 P/B 비율)이 고평가된 주식보다 높은 수익률을 내는 현상이 관찰됩니다. 그러나 CAPM은 이러한 가치 프리미엄을 설명하는 요인도 포함하고 있지 않습니다.
# Load data for XLK (technology sector ETF), AAPL, and CRSR
xlk_data = yf.download("XLK", start="2022-01-01", end="2023-12-31")
aapl_data = yf.download("AAPL", start="2022-01-01", end="2023-12-31")
crsr_data = yf.download("CRSR", start="2022-01-01", end="2023-12-31")

# Calculate daily returns
xlk_data['Return'] = xlk_data['Close'].pct_change()
aapl_data['Return'] = aapl_data['Close'].pct_change()
crsr_data['Return'] = crsr_data['Close'].pct_change()

# Combine data
data = pd.DataFrame({
    'XLK_Return': xlk_data['Return'],
    'AAPL_Return': aapl_data['Return'],
    'CRSR_Return': crsr_data['Return']
}).dropna()

# Plot AAPL and CRSR returns against XLK returns in a single chart
plt.figure(figsize=(12, 8))
plt.scatter(data['XLK_Return'], data['AAPL_Return'], alpha=0.5, label="AAPL Returns", color="blue")
plt.scatter(data['XLK_Return'], data['CRSR_Return'], alpha=0.5, label="CRSR Returns", color="green")

# Calculate and plot the regression line for AAPL
slope_aapl, intercept_aapl, _, _, _ = stats.linregress(data['XLK_Return'], data['AAPL_Return'])
plt.plot(data['XLK_Return'], intercept_aapl + slope_aapl * data['XLK_Return'], color="blue", linewidth=2, label="AAPL CAPM Line")

# Calculate and plot the regression line for CRSR
slope_crsr, intercept_crsr, _, _, _ = stats.linregress(data['XLK_Return'], data['CRSR_Return'])
plt.plot(data['XLK_Return'], intercept_crsr + slope_crsr * data['XLK_Return'], color="green", linewidth=2, label="CRSR CAPM Line")

# Chart details
plt.xlabel("XLK Daily Return (Market Return)")
plt.ylabel("Asset Daily Return (AAPL & CRSR)")
plt.title("CAPM: Comparison of AAPL and CRSR Returns against XLK")
plt.legend()
plt.show()

 

  • 베타 차이: AAPL과 CRSR의 베타 값이 다를 수 있으며, 이는 XLK에 대한 각 자산의 민감도를 보여줍니다. CRSR의 베타가 더 크게 나타나며, CAPM이 소형주 특성(규모 요인)을 충분히 설명하지 못하고 있다는 점을 확인할 수 있습니다.
  • 알파 차이: AAPL과 CRSR의 알파 값 차이를 통해, CAPM이 시장 요인 외의 추가적인 초과 수익을 설명하지 못하는 부분을 확인할 수 있습니다.
  • 잔차 확인: CRSR의 경우 XLK와 AAPL에 비해 CAPM 회귀선과의 거리가 더 큰 것으로 나타나며, CAPM이 소형주를 설명하는 데 부족하다는 것을 확인할 수 있습니다.

 

 

Fama와 French의 다중 팩터 모델이란?

 

1. 다중 팩터 모델의 등장
CAPM의 한계를 극복하기 위해 Fama와 French의 다중 팩터 모델(3팩터 모델)을 1992년에 발표했습니다. 이 모델은 Eugene Fama와 Kenneth French가 논문 "The Cross-Section of Expected Stock Returns"에서 제안한 것으로, 주식의 수익률을 설명하는 데 시장 요인 외에도 규모 요인(SMB)과 가치 요인(HML)을 추가하여 CAPM의 한계를 보완했습니다.

 

2. 다중 팩터 모델의 기본 개념

  • 규모 요인 (Small Minus Big, SMB): 소형주가 대형주보다 평균적으로 더 높은 수익률을 보이는 경향이 있다는 점에 주목했습니다. 따라서 자산의 규모(대형주 vs. 소형주)가 수익률에 영향을 줄 수 있다고 보았습니다.
  • 가치 요인 (High Minus Low, HML): 주식의 가치(고/저 P/B 비율)도 수익률에 영향을 미친다는 점을 고려했습니다. 가치주(저평가된 주식)는 성장주(고평가된 주식)보다 더 높은 수익률을 나타낼 가능성이 높다는 것이죠.

이 모델은 CAPM보다 훨씬 더 현실적인 예측력을 보이며, 자산의 수익률을 설명하는 데 중요한 도구로 자리 잡았습니다. 즉, 단순히 시장에 연동된 성과만으로 자산을 설명하지 않고, 규모와 가치 요인을 고려해 더 세밀한 설명을 가능하게 했습니다.

import pandas as pd
import numpy as np
import yfinance as yf
from pandas_datareader import data as pdr
import matplotlib.pyplot as plt

# Load AAPL and CRSR data
aapl_data = yf.download("AAPL", start="2023-01-01", end="2023-12-31")
aapl_data['Return'] = aapl_data['Close'].pct_change()

crsr_data = yf.download("CRSR", start="2023-01-01", end="2023-12-31")
crsr_data['Return'] = crsr_data['Close'].pct_change()

# Load Fama-French 3-factor data
ff_data = pdr.get_data_famafrench('F-F_Research_Data_Factors_daily', start='2023-01-01')[0]
ff_data = ff_data / 100  # Convert to decimal form

# Align data on the same dates and merge with AAPL and CRSR returns
aapl_data = aapl_data[['Return']].dropna()
crsr_data = crsr_data[['Return']].dropna()
ff_data = ff_data.join(aapl_data['Return'], how='inner').rename(columns={'Return': 'AAPL_Return'})
ff_data = ff_data.join(crsr_data['Return'], how='inner').rename(columns={'Return': 'CRSR_Return'})

# Define factors and response variables (AAPL and CRSR excess returns)
X = ff_data[['Mkt-RF', 'SMB', 'HML']].values  # Market, Size, Value factors
y_aapl = (ff_data['AAPL_Return'] - ff_data['RF']).values  # AAPL excess return
y_crsr = (ff_data['CRSR_Return'] - ff_data['RF']).values  # CRSR excess return

# Add a column of ones to X for the intercept term
X = np.column_stack([np.ones(X.shape[0]), X])

# Calculate beta coefficients for AAPL and CRSR using the normal equation
beta_aapl = np.linalg.inv(X.T @ X) @ X.T @ y_aapl
beta_crsr = np.linalg.inv(X.T @ X) @ X.T @ y_crsr

# Print beta coefficients for AAPL
print("AAPL Fama-French Model Coefficients:")
print(f"Intercept (Alpha): {beta_aapl[0]:.4f}")
print(f"Market Factor (Beta for Mkt-RF): {beta_aapl[1]:.4f}")
print(f"Size Factor (Beta for SMB): {beta_aapl[2]:.4f}")
print(f"Value Factor (Beta for HML): {beta_aapl[3]:.4f}\n")

# Print beta coefficients for CRSR
print("CRSR Fama-French Model Coefficients:")
print(f"Intercept (Alpha): {beta_crsr[0]:.4f}")
print(f"Market Factor (Beta for Mkt-RF): {beta_crsr[1]:.4f}")
print(f"Size Factor (Beta for SMB): {beta_crsr[2]:.4f}")
print(f"Value Factor (Beta for HML): {beta_crsr[3]:.4f}\n")

# Predicted returns for AAPL and CRSR
ff_data['Predicted_AAPL_Return'] = X @ beta_aapl
ff_data['Predicted_CRSR_Return'] = X @ beta_crsr
ff_data['Residual_AAPL'] = y_aapl - ff_data['Predicted_AAPL_Return']
ff_data['Residual_CRSR'] = y_crsr - ff_data['Predicted_CRSR_Return']

# Plot actual vs predicted excess returns for AAPL and CRSR
plt.figure(figsize=(12, 8))

# AAPL actual and predicted returns
plt.scatter(ff_data.index, y_aapl, label="AAPL Excess Return (Actual)", color="blue", alpha=0.5)
plt.plot(ff_data.index, ff_data['Predicted_AAPL_Return'], color="blue", linewidth=2, label="AAPL Predicted Return (Fama-French)")

# CRSR actual and predicted returns
plt.scatter(ff_data.index, y_crsr, label="CRSR Excess Return (Actual)", color="green", alpha=0.5)
plt.plot(ff_data.index, ff_data['Predicted_CRSR_Return'], color="green", linewidth=2, label="CRSR Predicted Return (Fama-French)")

# Plot settings
plt.xlabel("Date")
plt.ylabel("Excess Return")
plt.title("Fama-French 3-Factor Model: AAPL and CRSR Actual vs Predicted Returns")
plt.legend()
plt.show()

# Plot residuals distribution for AAPL and CRSR
plt.figure(figsize=(12, 6))
plt.hist(ff_data['Residual_AAPL'], bins=30, color='blue', alpha=0.6, edgecolor='black', label='AAPL Residuals')
plt.hist(ff_data['Residual_CRSR'], bins=30, color='green', alpha=0.6, edgecolor='black', label='CRSR Residuals')
plt.title("Residuals Distribution (Fama-French 3-Factor Model)")
plt.xlabel("Residual")
plt.ylabel("Frequency")
plt.legend()
plt.show()

 

 

 

Fama-French 다중 팩터 모델의 발전 방향과 의의

Fama와 French의 모델은 2015년에 수익성 요인(RMW)과 투자 요인(CMA)을 추가하며 5팩터 모델로 확장되었습니다. 이로 인해 자산 수익률을 설명하는 데 더 높은 정확도를 가지게 되었고, 다양한 퀀트 투자 전략의 기초가 되었습니다. 또한 이 모델의 성공은 이후 다양한 새로운 팩터들이 연구되는 계기를 마련했습니다.

  1. 5팩터 모델로의 확장
    • 수익성 요인 (RMW): 수익성이 높은 기업이 더 나은 성과를 보이는 경향을 설명하며, 기업의 재무 건전성이 수익률에 영향을 미칠 수 있음을 반영합니다.
    • 투자 요인 (CMA): 낮은 자본 투자(보수적 투자)를 수행하는 기업이 공격적 투자 기업보다 높은 성과를 낸다는 요인으로, 자본 지출 방식이 수익률에 영향을 미칠 수 있음을 시사합니다.
    5팩터 모델은 기존의 3팩터 모델의 한계를 보완하며, 주식 수익률에 영향을 미치는 요소를 더 정밀하게 분석할 수 있도록 해줍니다.
  2. 추가 팩터의 등장
    • 모멘텀 요인: 주가가 상승하면 추가 상승할 가능성이 높다는 추세에 기반하여, 자산의 과거 수익률이 미래 수익률에 미치는 영향을 반영합니다.
    • 유동성 요인: 거래량과 유동성 수준을 반영하여, 거래가 원활하게 이루어지는 자산일수록 안정성을 가지며 이는 수익률에 영향을 미친다고 봅니다.
    • 변동성 요인: 변동성이 낮은 자산이 장기적으로 더 높은 수익률을 보일 수 있다는 점에 주목해, 자산의 리스크-리턴 특성을 보완합니다.
    이처럼 다양한 추가 요인들은 시장 상황에 맞춘 더 정교한 자산 수익률 예측을 가능하게 하며, 투자자에게 더 폭넓은 분석 도구를 제공합니다.
  3. 현대 퀀트 투자에 미치는 영향
    오늘날 Fama-French 다중 팩터 모델은 퀀트 투자 전략의 기초이자 기준이 되는 모델로 자리잡았습니다. 이를 통해 지속적으로 새로운 팩터가 발굴되고 있으며, 다음과 같은 의의를 가집니다:
    • 팩터 기반 분석 방법론 제공: 투자자들이 특정 요인(가치, 규모, 수익성 등)에 따라 포트폴리오를 구성할 수 있도록 도와줍니다. 이 구조적 접근은 시장에서 초과 수익을 추구하는 데 필요한 기반을 제공합니다.
    • 팩터 전략의 다양화: 다양한 팩터가 개발되면서, 투자자들은 특정 팩터에 기반한 ETF나 다양한 팩터 조합 포트폴리오를 통해 다각화된 전략을 실행할 수 있게 되었습니다.
    • 리스크와 리턴의 균형: 다중 팩터 모델은 투자자들이 리스크와 리턴의 균형을 맞출 수 있도록 돕고, 장기적 성과를 극대화할 수 있는 체계를 제공합니다.

 

추가 : Fama-French 모델을 기준으로 한 평균 회귀 전략 테스트

 

그렇다면 Fama-French 모델을 실제 알고리즘 트레이딩 등에서 간단한 스터디로 사용해볼까요? 여기서는 평균 회귀 전략에 적용하여 테스트 해보겠습니다. 평균 회귀 전략은 자산 가격이 장기 평균으로 돌아가려는 경향을 활용하는 전략입니다. Fama-French 모델이 평균 회귀 전략과 직접적으로 연결되어 있지는 않지만, 이 모델은 평균 회귀 전략을 더 잘 이해하고 효과적으로 적용할 수 있는 기초와 기준을 제공합니다.

1. 시장 요인, 규모 요인, 가치 요인을 통한 평균 회귀 판단 기준 제공

평균 회귀 전략에서는 자산이 과도하게 과대 또는 과소 평가되었을 때 평균으로 되돌아갈 것이라는 가정이 필요합니다. Fama-French 모델의 요인은 이러한 과대/과소 평가를 파악하는 데 중요한 지표를 제공합니다.

  • 규모 요인 (SMB)과 가치 요인 (HML)은 특정 자산이 규모 또는 가치 측면에서 평균에서 벗어난 상태를 반영할 수 있습니다. 예를 들어, 가치주가 평균 수익률보다 크게 벗어났다면 이를 평균으로 돌아가는 신호로 해석해 매수하거나 매도할 수 있습니다.
  • 시장 요인 (Mkt-RF)은 전체 시장의 상승이나 하락 방향을 알려주므로, 자산이 시장의 전반적 움직임에서 벗어난 수준을 확인하는 기준이 될 수 있습니다.

즉, Fama-French 모델을 통해 자산이 평균을 벗어난 이유를 보다 구조적으로 파악할 수 있으며, 이를 평균 회귀 전략에서 매수 또는 매도의 근거로 활용할 수 있습니다.

2. 초과 수익률 분석을 통한 평균 회귀 신호 탐색

평균 회귀 전략에서는 특정 자산의 초과 수익률이 지속 가능하지 않다고 가정합니다. Fama-French 모델은 시장 초과 수익률뿐만 아니라 규모와 가치 요인을 고려하여 초과 수익률을 구조적으로 설명하는 기준을 제공합니다.

  • 예를 들어, 특정 소형주가 과도한 초과 수익률을 보일 때, 이 수익률이 규모나 가치 요인에 의한 것인지, 단순히 일시적인 시장 변동인지 구분할 수 있습니다.
  • 모델을 통해 구한 베타 계수와 알파 값을 바탕으로, 자산의 현재 초과 수익률이 평균 회귀할 가능성이 높은지 판단하는 데 참고할 수 있습니다. 알파 값이 지속적으로 높다면 평균 회귀를 통해 초과 수익률이 감소할 가능성을 염두에 둘 수 있습니다.

3. 팩터 기반 포트폴리오로 평균 회귀 전략 강화

Fama-French 모델을 통해 다양한 요인을 반영한 팩터 기반 포트폴리오를 구성함으로써, 평균 회귀 전략의 성과를 높일 수 있습니다. 예를 들어, 저평가된 가치주소형주 포트폴리오를 구성해 평균 회귀 전략을 적용하면 시장이 장기적으로 이들 자산을 평균 수준으로 평가할 것이라는 가정을 활용할 수 있습니다.

  • 가치주는 역사적으로 평균 회귀 경향이 강한 것으로 나타났으므로, 가치 팩터(HML)를 이용해 저평가된 주식을 매수하여 평균 회귀 효과를 노리는 전략을 구성할 수 있습니다.
  • 소형주 또한 규모 요인(SMB)에 따라 초과 수익률을 보여주며, 시간이 지나면서 평균으로 회귀할 가능성을 탐색할 수 있습니다.