Hedging and Tracking#

Net exposure and basis#

Long \(\$1\) of asset \(i\) and short \(h\) of asset \(j\) yields net exposure

\[ \epsilon_t = r_{i,t} - h\, r_{j,t} \]

Basis risk is the volatility of \(\epsilon_t\).

Basis risk and the optimal hedge#

With volatilities \(\sigma_i, \sigma_j\) and correlation \(\rho_{i,j}\):

\[ \sigma^2_{\epsilon} = \sigma_i^2 + h^2\sigma_j^2 - 2h\sigma_i\sigma_j\rho_{i,j} \]

Minimizing w.r.t. \(h\) gives the optimal hedge ratio

\[ h^{*} = \frac{\sigma_i}{\sigma_j} \rho_{i,j} \]
  • Higher \(\rho\) \(\Rightarrow\) larger \(h^{*}\).

  • If \(\rho<0\), you hedge by going long the hedge asset.

Regression view of hedging#

The optimal hedge ratio is the regression beta from

\[ r_{i,t} = \beta_{i,j} r_{j,t} + \varepsilon_t \]

so \(\beta_{i,j} = h^{*}\) and the minimized basis variance is the residual variance.

Multiple hedging assets and excess returns#

With multiple hedges:

\[ r_{i,t} = \beta_{i,1} r_{1,t} + \cdots + \beta_{i,k} r_{k,t} + \varepsilon_t \]

In excess returns form:

\[ \tilde r_{i,t} = \beta_{i,1} \tilde r_{1,t} + \cdots + \beta_{i,k} \tilde r_{k,t} + \varepsilon_t \]

Adding an intercept isolates the portion of the mean that the hedge cannot replicate.

Market-hedged positions#

If you want exposure to asset \(i\) without market risk \(m\), estimate

\[ \tilde r_{i,t} = \alpha + \beta_{i,m} \tilde r_{m,t} + \varepsilon_t \]

Then take the position \(\tilde r_{i,t} - \beta_{i,m}\tilde r_{m,t}\), which has

\[ \tilde r_{i,t} - \beta_{i,m}\tilde r_{m,t} = \alpha + \varepsilon_t \]

Mean excess return \(=\alpha\), volatility \(=\sigma_{\varepsilon}\).

Tracking vs. hedging#

A tracking portfolio tries to follow a target factor:

\[ \tilde r_{i,t} = \alpha + \beta \tilde r_{j,t} + \varepsilon_t \]
  • \(\varepsilon\) is tracking error.

  • \(R^2\) gauges tracking quality.

  • \(\text{IR}=\alpha/\sigma_{\varepsilon}\) trades extra mean vs extra tracking error.

Mutual funds often track broad factors; hedge funds often hedge them—though in practice, each may keep some exposure.


Looking at the Data#

import pandas as pd
import numpy as np
import seaborn as sns

from cmds.portfolio import performanceMetrics, get_ols_metrics
LOADFILE = '../data/risk_etf_data.xlsx'
info = pd.read_excel(LOADFILE,sheet_name='descriptions').set_index('ticker')
rets = pd.read_excel(LOADFILE,sheet_name='total returns').set_index('Date')
prices = pd.read_excel(LOADFILE,sheet_name='prices').set_index('Date')

FREQ = 252
performanceMetrics(rets,FREQ).style.format('{:.1%}',na_rep='-')
  Mean Vol Sharpe Min Max
SPY 15.3% 18.9% 81.1% -10.9% 10.5%
VEA 9.7% 17.5% 55.4% -11.2% 8.9%
UPRO 38.8% 56.5% 68.8% -34.9% 28.0%
GLD 12.9% 14.3% 90.2% -5.4% 4.9%
USO 5.0% 38.6% 13.0% -25.3% 16.7%
FXE 1.6% 7.4% 21.7% -2.1% 2.5%
BTC 79.3% 69.8% 113.5% -37.2% 25.2%
HYG 4.6% 8.7% 53.6% -5.5% 6.5%
IEF 1.3% 6.9% 18.3% -2.5% 2.6%
TIP 2.8% 6.0% 45.8% -2.9% 4.5%
SHV 2.2% 0.3% 776.0% -0.1% 0.1%
get_ols_metrics(rets['SPY'],rets,FREQ).style.format('{:.1%}',na_rep='-')
  alpha SPY r-squared Treynor Ratio Info Ratio
SPY 0.0% 100.0% 100.0% 15.3% -
VEA -2.6% 80.3% 74.8% 12.1% -29.4%
UPRO -6.9% 299.4% 99.8% 13.0% -260.8%
GLD 11.9% 6.6% 0.8% 196.3% 83.5%
USO -4.4% 61.6% 9.1% 8.1% -12.0%
FXE 0.8% 5.5% 2.0% 28.9% 10.3%
BTC 65.1% 93.0% 6.3% 85.3% 96.3%
HYG -0.9% 36.0% 61.1% 12.9% -15.8%
IEF 2.0% -4.8% 1.7% -26.2% 29.2%
TIP 2.5% 1.9% 0.4% 144.9% 41.1%
SHV 2.2% -0.1% 0.4% -2362.1% 782.6%

Considering VEA#

TICK_TARGET = 'VEA'
targ = rets[[TICK_TARGET]]
instruments = rets[['SPY','FXE']]
get_ols_metrics(instruments,targ,FREQ).style.format('{:.1%}',na_rep='-')
  alpha SPY FXE r-squared Info Ratio
VEA -3.0% 76.9% 61.7% 81.4% -40.4%

Considering BTC#

TICK_TARGET = 'BTC'
targ = rets[[TICK_TARGET]]
instruments = rets[['SPY', 'IEF', 'GLD','FXE']]
get_ols_metrics(instruments,targ,FREQ).style.format('{:.1%}',na_rep='-')
  alpha SPY IEF GLD FXE r-squared Info Ratio
BTC 61.2% 88.6% -11.8% 32.4% 30.3% 6.9% 90.9%

Monthly Frequency#

CODE_RESAMPLE = 'ME'
FREQ_M = 12

px = (1+rets).cumprod()
retsM = px.resample(CODE_RESAMPLE).last().pct_change().dropna()
retsM.dropna(inplace=True)
targ = retsM[[TICK_TARGET]]
get_ols_metrics(instruments,targ,FREQ_M).style.format('{:.1%}',na_rep='-')
  alpha SPY IEF GLD FXE r-squared Info Ratio
BTC 103.8% -35.0% -540.0% 581.3% 582.8% 5.5% 127.5%