P.13 Fund Forensics: Risk Parity (RPAR)#
Project Statement#
Risk parity promises “balanced risk across asset classes” — equal risk contribution from equities, bonds, commodities, and inflation-linked assets. RPAR (Risk Parity ETF, launched December 2019) is a retail implementation of this idea, packaged as a daily-liquid ETF with a 0.51% expense ratio. In 2022, when both stocks and bonds fell together, RPAR lost over 22% — worse than the S&P 500 and worse than a simple 60/40 portfolio. Was this a failure of the risk parity concept, a failure of the implementation, or both?
Your task is to decompose RPAR’s actual return exposures, construct your own equal-risk-contribution portfolio from the same asset classes, test how leverage and correlation regimes interact, design a regime-conditioned improvement, and evaluate the result with the Ch 9 toolkit. The most famous implementation of risk parity is Bridgewater’s All Weather strategy (~$100B AUM); Bridgewater launched its own ETF version, ALLW, in March 2025.
Context#
Risk Parity as a Portfolio Construction Strategy#
Risk parity allocates capital so that each asset class contributes equally to total portfolio risk. Low-volatility assets (bonds, TIPS) receive large capital allocations, while high-volatility assets (equities, commodities) receive smaller ones. The result is a portfolio dominated by bond exposure in dollar terms, but (in theory) balanced in risk terms.
The strategy requires leverage. An unlevered risk parity portfolio is mostly bonds, earning bond-like returns. To achieve competitive total returns, the portfolio must be levered to a target volatility — typically matching or exceeding the vol of a 60/40 portfolio. This leverage comes from futures, swaps, or margin. The Ch 8 leverage frontier is directly relevant: if Sharpe ratios are invariant to leverage, then the only reason to lever is to raise the return level — but every other risk metric (drawdown, VaR, skewness) degrades linearly with leverage.
The Stock-Bond Correlation Problem#
Risk parity’s diversification benefit depends on the correlation between stocks and bonds. From roughly 2000 to 2021, the stock-bond correlation was predominantly negative — bonds rallied when stocks fell, providing natural hedging. In this regime, leveraging bonds is relatively safe: when equities draw down, the bond position cushions the portfolio.
When stock-bond correlation turns positive — as it did in 2022 when the Fed hiked rates aggressively — the hedging mechanism breaks. Stocks and bonds fall together, and the leveraged bond position amplifies losses rather than cushioning them. The question is whether this regime dependence was discoverable from the fund’s factor exposures before the drawdown occurred — a structural property, not hindsight.
Decomposition vs. Pricing Factors#
This project uses two types of factor analysis:
Decomposition factors (asset-class ETFs like SPY, TLT, TIP, GLD, DBC): These reveal what the fund is actually exposed to in terms of market risk. They answer: “what is RPAR?” A regression of RPAR on these ETFs shows the effective portfolio composition — including whether total loadings exceed 1.0, which signals leverage.
Pricing factors (MKT, SMB, HML, UMD, RMW from the Fama-French framework): These test whether RPAR earns alpha after adjusting for systematic risk premia. They answer: “is RPAR a good investment?” For a multi-asset strategy, equity pricing factors should explain relatively little of the return — most of the risk comes from bond duration and real asset exposure.
RPAR Metadata#
Bloomberg classifies RPAR as a “Global Allocation” fund. Its stated benchmark is RPARTR (Advanced Research Risk Parity Index) — the fund’s own custom index. ALLW (Bridgewater’s All Weather ETF, launched March 2025) benchmarks against MXWDIM (MSCI World Index).
Resources#
Course Materials#
Discussion 1.2: Optimizing Risk and Return — Portfolio construction, constrained optimization
Discussion 3.1: Risk — Volatility, drawdown, risk decomposition, time diversification
Discussion 6.1: Factor Pricing — Multi-factor decomposition, interpreting factor loadings
Discussion 8.1: Leverage — Leverage frontier, Sharpe invariance, drawdown scaling
Discussion 9.1: Managed Funds — Alpha estimation, Sharpe ratio standard error, Asness lagged-market diagnostic
External Reading#
Bridgewater Associates, The All Weather Story — Original articulation of risk parity by Ray Dalio
AQR, Understanding Risk Parity — Cliff Asness’s primer on the strategy’s logic and limitations
RPAR Advisors, RPAR Risk Parity ETF — Fund marketing materials and methodology description
Data#
File |
Description |
Frequency |
Date Range |
|---|---|---|---|
|
Monthly total returns for RPAR, ALLW, SPY, IEF, TLT, TIP, GLD, DBC, SHV, AGG, and benchmark indices BM_RPARTR, BM_MXWDIM |
Monthly |
2014–2026 (RPAR from Jan 2020, ALLW from Apr 2025) |
|
Fama-French 5 factors + Momentum (MKT, SMB, HML, RMW, CMA, UMD) + risk-free rate |
Monthly |
1980–2025 |
Bloomberg data has been pre-pulled for convenience. If you have Bloomberg access, you can explore additional metrics such as daily returns, leverage ratio filings, or holdings data.
Data Preview#
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
import warnings
warnings.filterwarnings('ignore')
DATAPATH = '../../../data/'
# Load monthly returns (Bloomberg-sourced)
rets = pd.read_excel(f'{DATAPATH}forensics_etf_data.xlsx',
sheet_name='monthly returns', index_col=0, parse_dates=True)
# Load pricing factors
factors = pd.read_excel(f'{DATAPATH}factor_pricing_data_monthly.xlsx',
sheet_name='factors (excess returns)', index_col=0, parse_dates=True)
# Align
common = rets.index.intersection(factors.index)
rets = rets.loc[common]
factors = factors.loc[common]
# RPAR sample
rpar_idx = rets['RPAR'].dropna().index
print(f'RPAR sample: {rpar_idx[0].strftime("%Y-%m")} to {rpar_idx[-1].strftime("%Y-%m")} ({len(rpar_idx)} months)')
print(f'ALLW sample: {rets["ALLW"].dropna().shape[0]} months')
print(f'\nAvailable columns: {list(rets.columns)}')
fig, ax = plt.subplots(figsize=(12, 5))
for name in ['RPAR', 'SPY', 'AGG', 'GLD']:
r = rets[name].loc[rpar_idx].dropna()
cum = (1 + r).cumprod()
ax.plot(cum.index, cum, label=name, linewidth=2 if name == 'RPAR' else 1)
# 60/40 benchmark
r60 = 0.6 * rets['SPY'].loc[rpar_idx] + 0.4 * rets['IEF'].loc[rpar_idx]
ax.plot(rpar_idx, (1 + r60).cumprod(), '--', label='60/40', linewidth=1)
ax.set_ylabel('Growth of $1')
ax.set_title('RPAR vs Benchmarks')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Questions#
Q1: Performance and Benchmarking#
(a) Compute annualized return, volatility, Sharpe ratio, maximum drawdown, and skewness for RPAR over its full sample. Compare to SPY, a 60/40 portfolio (0.60 × SPY + 0.40 × IEF), AGG, and GLD.
(b) Compute the tracking error between RPAR and its stated benchmark, RPARTR.
(c) Discuss what it means for a fund to benchmark against its own index.
Q2: Asset-Class Decomposition#
(a) Regress RPAR’s monthly returns on asset-class ETFs: SPY, TLT, TIP, GLD, and DBC. Report coefficients, \(R^2\), and annualized intercept.
(b) Re-run the decomposition in rolling 36-month windows. Plot coefficients and the implied leverage ratio (sum of coefficients) over time.
(c) Interpret RPAR’s effective portfolio and its stability over time.
Q3: Correlation Regimes and the 2022 Stress Test#
(a) Compute the rolling 12-month correlation between SPY and TLT. Split RPAR’s sample into months where trailing stock-bond correlation is positive vs. negative. Report annualized return, volatility, and Sharpe ratio for RPAR, 60/40, and SPY in each regime.
(b) Report 2022 calendar-year returns for RPAR, RPARTR, SPY, 60/40, and the individual asset-class ETFs.
(c) Discuss RPAR’s 2022 performance in light of the decomposition and correlation regime evidence.
Q4: Constructing a Risk Parity Portfolio#
(a) Construct an equal risk contribution (ERC) portfolio from SPY, TLT, TIP, GLD, and DBC using rolling 36-month covariance estimates. ERC weights equalize each asset’s marginal contribution to portfolio risk: \(w_i \cdot (\Sigma \mathbf{w})_i\) is the same for all \(i\). Plot the weight time series.
Hint: ERC weights can be found by minimizing the dispersion of risk contributions subject to \(\sum w_i = 1\) and \(w_i > 0\). See the
scipy.optimizedocumentation for constrained minimization.
(b) Compare the ERC weights to RPAR’s revealed allocation from Q2.
(c) Compare the ERC weights to the tangency portfolio weights for the same assets. Discuss what drives any differences.
Q5: The Leverage Frontier#
(a) Scale the ERC portfolio to leverage levels from 0.5× to 2.5×. Report annualized return, volatility, Sharpe ratio, and maximum drawdown at each level. Plot the leverage frontier.
(b) Construct a vol-targeted version of the ERC portfolio: each month, scale leverage so that trailing 12-month realized volatility equals 10% annualized. Plot the leverage time series.
Q6: Regime-Conditioned Risk Parity#
(a) Design two regime-conditioned versions of the ERC portfolio from Q4, each using a different conditioning mechanism based on the trailing stock-bond correlation from Q3. Describe both rules.
(b) Backtest both strategies over RPAR’s sample. Report annualized return, volatility, Sharpe ratio, maximum drawdown, and skewness alongside RPAR, the static ERC portfolio, and 60/40.
(c) Discuss how much of the performance difference comes from regime conditioning vs. the base ERC allocation.
Q7: Evaluation and Recommendation#
(a) Regress RPAR on pricing factors (MKT, SMB, HML, UMD, RMW). Report \(R^2\), factor loadings, and annualized alpha.
(b) Run the Asness lagged-market test and the Treynor-Mazuy quadratic regression on RPAR. Report the results.
(c) Compute the Sharpe ratio standard error for RPAR and its benchmarks:
Estimate how many years of data would be needed for RPAR’s Sharpe ratio to be statistically distinguishable from 60/40’s.
(d) An allocator asks whether to use RPAR, build an ERC portfolio, or hold levered 60/40. Make a recommendation grounded in Q1–Q6.
Deliverables#
Review the Project Guidelines for submission standards, conciseness expectations, and AI usage policy.
Submit a Jupyter notebook with analysis for all seven questions (Q1–Q7), including code, figures, and written interpretation.
Conciseness is a graded criterion — see Project Guidelines.