How do we know whether a fund manager adds value? This lecture introduces the canonical returns-based framework for fund performance evaluation, following the survey by Wermers (2011). The central takeaway from Wermers: the Carhart (1997) four-factor model is the baseline model for evaluating actively managed equity portfolios.
We will:
Motivate the need for multi-factor performance models
Build from CAPM to Fama-French 3-factor to Carhart 4-factor, step by step
Download price data for 10 popular US ETFs using tidyquant
Obtain factor returns directly from Kenneth French’s Data Library using the frenchdata package
Estimate and interpret Carhart alphas and factor loadings
Visualize the results with interactive highcharter charts
1. Motivation: Why Not Just Compare Raw Returns?
A fund that returned 15% last year sounds impressive—until you learn it was a small-cap value fund during a year when small-cap value stocks returned 18%. The fund actually destroyed value relative to the passive alternative.
Wermers (2011) states the core principle clearly: “Managers should be rewarded for bets not easily replicated by uninformed investors.” In other words, we need to control for the passive risk factors that investors can access cheaply, and only then can we attribute the residual—alpha—to manager skill.
Wermers (2011) (Section 3.1) notes that a regression of a diversified long-only portfolio on the Carhart model typically yields \(R^2 > 90\%\), meaning nearly all return variation is explained by these four systematic factors. This is precisely why it serves as the baseline: it leaves little room for data mining.
2. Setup
Code
library(tidyverse)library(tidyquant)library(frenchdata) # Kenneth French's Data Librarylibrary(broom)library(gt)library(scales)library(highcharter) # interactive charts (replaces ggplot2 for all figures)# Optional: apply one of your own highcharter themes to every chart, e.g.# options(highcharter.theme = hc_theme_smpl())
3. The Ten US ETFs
We use ten ETFs spanning broad market, style (size/value), sector, and active strategies. This cross-section lets students observe how factor loadings vary systematically across fund types—a key pedagogical goal.
The Carhart model is estimated on monthly returns—the same frequency as the French factor data.
Code
returns_monthly <- prices_raw |>group_by(symbol) |>tq_transmute(select = adjusted,mutate_fun = periodReturn,period ="monthly",type ="arithmetic", # simple returns to match French data conventioncol_rename ="ret" ) |>ungroup() |>left_join(etf_labels, by ="symbol")
French data uses end-of-month dates; tq_transmute() returns the last trading day of each month. We align on year-month.
Code
# Standardize ETF returns to year-month for mergingreturns_ym <- returns_monthly |>mutate(ym = lubridate::floor_date(date, "month")) |>select(symbol, name, category, ym, ret)factors_ym <- factors |>mutate(ym = lubridate::floor_date(date, "month")) |>select(ym, RMRF, SMB, HML, UMD, RF)# Merge and compute excess returndata_merged <- returns_ym |>left_join(factors_ym, by ="ym") |>mutate(excess_ret = ret - RF) |>filter(!is.na(RMRF)) # drop months outside factor data range
5. Cumulative Return Plot
The chart is interactive: hover to compare all ETFs at a given month, click a legend entry to hide or show a series, and drag across the plot to zoom in on a sub-period.
Figure 1: Cumulative simple returns of 10 US ETFs (2015–2024)
6. Step 1 — CAPM / Jensen’s Alpha (Single Factor)
Before moving to Carhart, we start with the CAPM as a baseline. Jensen (1968) showed that fund performance can be measured as the regression intercept \(\alpha\) from:
\(\alpha > 0\) means the fund earned more than its CAPM-implied expected return.
Code
# Helper: significance stars from a p-valuesig_stars <-function(p) {case_when( p <0.01~"***", p <0.05~"**", p <0.10~"*",TRUE~"" )}capm_results <- data_merged |>group_by(symbol, name) |>do({ fit <-lm(excess_ret ~ RMRF, data = .)bind_cols(tidy(fit) |>select(term, estimate, std.error, statistic, p.value),glance(fit)|>select(r.squared, adj.r.squared) |>slice(1) ) }) |>select(symbol, name, term, estimate, std.error, statistic, p.value, r.squared) |>filter(term %in%c("(Intercept)", "RMRF")) |>mutate(term =recode(term, "(Intercept)"="alpha", "RMRF"="beta_mkt")) |>pivot_wider(names_from = term,values_from =c(estimate, std.error, statistic, p.value),names_glue ="{term}_{.value}" ) |>ungroup() |>mutate(alpha_ann = alpha_estimate *12, # annualized alphaalpha_stars =sig_stars(alpha_p.value), # new: stars for alphabeta_mkt_stars =sig_stars(beta_mkt_p.value) # new: stars for beta )capm_results |>arrange(desc(alpha_ann)) |>select(name, alpha_ann, alpha_stars, alpha_statistic, alpha_p.value, beta_mkt_estimate, beta_mkt_stars, beta_mkt_statistic,# kept (hidden by the merges below) so downstream chunks still work alpha_estimate, r.squared) |>gt() |># numeric formattingfmt_number(columns =c(alpha_ann, alpha_statistic, beta_mkt_estimate, beta_mkt_statistic, r.squared),decimals =3 ) |>fmt(columns = alpha_p.value, fns = \(x) sprintf("%.3f", x)) |># attach stars to the coefficient they belong to, e.g. "0.042**"cols_merge(columns =c(alpha_ann, alpha_stars), pattern ="{1}{2}") |>cols_merge(columns =c(beta_mkt_estimate, beta_mkt_stars), pattern ="{1}{2}") |>cols_hide(alpha_estimate) |>cols_label(name ="ETF",alpha_ann ="α (Ann.)",alpha_statistic ="t(α)",alpha_p.value ="p(α)",beta_mkt_estimate ="Beta",beta_mkt_statistic ="t(β)",r.squared ="R²" ) |>cols_align(align ="right", columns =-name) |># shade rows where alpha is significant at the 10% leveltab_style(style =cell_fill(color ="#f0f4ff"),locations =cells_body(rows = alpha_p.value <0.10) ) |>tab_header(title ="CAPM / Jensen's Alpha",subtitle ="Monthly excess returns regressed on market factor only" ) |>tab_source_note("Significance: *** p < 0.01, ** p < 0.05, * p < 0.10 (two-sided; OLS standard errors). Shaded rows: alpha significant at the 10% level." ) |>tab_source_note("Stars on annualized alpha come from the monthly alpha t-test; multiplying by 12 changes the scale but not the t-statistic or p-value." )
CAPM / Jensen’s alpha with statistical significance
CAPM / Jensen's Alpha
Monthly excess returns regressed on market factor only
ETF
α (Ann.)
t(α)
p(α)
Beta
t(β)
R²
Nasdaq-100
0.045*
1.847
0.067
1.065***
24.620
0.837
Vanguard Growth
0.023
1.200
0.232
1.058***
31.505
0.894
S&P 500
0.005
1.019
0.311
0.957***
100.684
0.988
Vanguard Value
−0.013
−0.668
0.505
0.870***
25.899
0.850
Financials Sector
−0.015
−0.451
0.653
1.065***
17.808
0.729
Russell 1000 Value
−0.034*
−1.886
0.062
0.928***
28.983
0.877
ARK Innovation
−0.042
−0.553
0.581
1.740***
12.884
0.585
Real Estate (REIT)
−0.054
−1.388
0.168
0.860***
12.336
0.563
Russell 2000
−0.058*
−1.962
0.052
1.173***
22.241
0.807
Energy Sector
−0.067
−0.892
0.374
1.200***
8.963
0.405
Significance: *** p < 0.01, ** p < 0.05, * p < 0.10 (two-sided; OLS standard errors). Shaded rows: alpha significant at the 10% level.
Stars on annualized alpha come from the monthly alpha t-test; multiplying by 12 changes the scale but not the t-statistic or p-value.
Limitation of CAPM alpha: If IWM (small cap) has \(\alpha > 0\) in the CAPM, it might simply be capturing the size premium that any investor could access by buying small stocks passively—not manager skill. This is why we need additional factors.
7. Step 2 — Fama-French 3-Factor Model
Fama and French (1993) document that two additional risk factors—size (SMB) and value (HML)—explain cross-sectional variation in average returns beyond the market. Adding these factors purges the CAPM alpha of style-related biases:
Notice how alpha estimates change relative to CAPM—this is the style-correction at work. IWM’s alpha shrinks once we control for SMB; VTV’s alpha changes once we control for HML.
8. Step 3 — Carhart 4-Factor Model (Baseline)
Carhart (1997) adds the momentum factor (UMD) to the Fama-French model. Stocks that have outperformed over the prior 12 months tend to continue outperforming over the next few months (Jegadeesh and Titman 1993). If a fund merely holds past winners, its FF3 alpha is overstated—Carhart strips this out.
As Wermers (2011) (p. 542) states: “The returns-based model most widely used among academics in analyzing equity managers is the four-factor model of Carhart (1997).”
highcharter has no direct equivalent of facet_wrap(), so we build one bar chart per factor and arrange the four panels in a grid with hw_grid(). All panels use the same ETF ordering (by median loading across the four factors), so you can read across a row to compare one ETF’s exposures.
Code
loadings_long <- carhart_results |>select(name, b_mkt_estimate, b_smb_estimate, b_hml_estimate, b_umd_estimate) |>pivot_longer(cols =-name,names_to ="factor",values_to ="loading" ) |>mutate(factor =recode(factor,"b_mkt_estimate"="MKT","b_smb_estimate"="SMB","b_hml_estimate"="HML","b_umd_estimate"="UMD" ))# One common ETF order for all four charts (highest median loading at the top)etf_order <- loadings_long |>group_by(name) |>summarise(med =median(loading), .groups ="drop") |>arrange(desc(med)) |>pull(name)
Wermers (2011) notes that managed long-only portfolios typically have \(R^2 > 90\%\) under the Carhart model, precisely because these four factors capture most passive variation. Low \(R^2\) signals idiosyncratic strategies not captured by the standard factors.
Code
r2_df <- carhart_results |>select(name, r.squared) |>arrange(desc(r.squared)) # highest R² at the top of the bar charthighchart() |>hc_chart(type ="bar", height =380) |>hc_title(text ="R² from Carhart 4-Factor Model") |>hc_xAxis(categories = r2_df$name) |>hc_yAxis(min =0, max =105, tickInterval =20, endOnTick =FALSE,title =list(text ="R-squared"),labels =list(format ="{value}%")) |>hc_add_series(name ="R²",data =round(r2_df$r.squared *100, 1),color ="#4682B4",dataLabels =list(enabled =TRUE, format ="{y:.1f}%")) |>hc_legend(enabled =FALSE) |>hc_tooltip(pointFormat ="R²: <b>{point.y:.1f}%</b>")
Figure 2: R² from Carhart model — how much return variation is explained by the four factors?
Note
ARKK typically has a lower R² than passive ETFs—consistent with its active, concentrated strategy in disruptive-technology stocks. Wermers (2011) discusses this in the context of hedge funds (Section 6.3): funds with lower R² tend to take more idiosyncratic bets, which may or may not translate into outperformance.
12. What Alpha Means for Passive ETFs
For passive index ETFs like SPY and IWM, alpha should be:
Why? If markets are competitive and these factors are the right benchmark, a well-implemented passive fund should have zero alpha before costs. Any measured positive alpha from a passive fund is a red flag—it may indicate benchmark misspecification.
For actively managed funds like ARKK, we are genuinely asking: did the manager add value beyond passive factor exposure? The answer is in \(\hat{\alpha}\) and its \(t\)-statistic.
Important
A positive (or negative) alpha that is statistically insignificant should be interpreted cautiously. With 10 years of monthly data (T ≈ 120), the power to detect even a 2% annual alpha at conventional significance levels is limited. Wermers (2011) (Section 3.3) discusses how the Kosowski et al. (2006) bootstrap method addresses this problem for large cross-sections of funds.
Table 2: Fund performance summary: annualized statistics
Performance Summary
Sample: 2015-01-01 to 2024-12-31
ETF
Category
Ann. Return
Ann. Vol.
Sharpe
Carhart α
Beta
R²
Nasdaq-100
Tech/Growth
18.4%
18.5%
0.919
0.033
1.082
0.928
Vanguard Growth
Large growth
15.9%
17.8%
0.826
0.012
1.074
0.967
S&P 500
Broad market
13.0%
15.3%
0.771
0.001
0.981
0.996
Vanguard Value
Large value
10.0%
15.0%
0.600
−0.009
0.886
0.948
Financials Sector
Sector
11.3%
19.8%
0.556
−0.002
1.061
0.888
Russell 1000 Value
Large value
8.3%
15.8%
0.479
−0.025
0.915
0.959
ARK Innovation
Active growth
12.2%
36.2%
0.450
−0.014
1.518
0.761
Russell 2000
Small cap
7.8%
20.7%
0.386
−0.024
1.032
0.987
Real Estate (REIT)
REIT
4.8%
18.2%
0.258
−0.052
0.857
0.571
Energy Sector
Sector
4.8%
29.9%
0.248
−0.024
1.093
0.675
14. Key Takeaways
The Carhart four-factor model is the academic standard for evaluating equity fund performance (Wermers 2011). It controls for market, size, value, and momentum exposures—the four main dimensions of passive strategy that any uninformed investor can exploit.
Alpha is model-dependent. CAPM alpha, FF3 alpha, and Carhart alpha can differ substantially. A fund that looks good in CAPM may simply be loading on the size or value premium, which requires no skill.
For passive ETFs,\(\alpha \approx 0\). The expense ratio creates a small negative alpha. Any significant positive alpha from a passive ETF signals factor model misspecification.
R² near or above 90% is expected for diversified long-only portfolios. Low R² (like ARKK) indicates concentrated, idiosyncratic bets—which may or may not reflect skill (Wermers 2011, sec. 3.3).
Statistical power is limited with 10 years of monthly data. A 2% annual alpha may not be detectable at the 5% level with only 120 observations.
Discussion Questions
SPY tracks the S&P 500. Theoretically, what should its Carhart alpha be? If you find a positive alpha, what are three possible explanations?
IWM (Russell 2000) will have a large positive SMB loading. Does this mean IWM outperforms? Or that it merely holds small stocks? What is the difference?
ARKK is actively managed. Suppose its Carhart alpha is positive but statistically insignificant (\(p = 0.15\)). How should an investor interpret this?
Compare the CAPM alpha and Carhart alpha of QQQ. Why do they differ? What factor explains most of the difference?
Wermers (2011) writes that the Carhart model regression of a managed portfolio typically yields \(R^2 > 90\%\). Which ETF in our sample has the lowest R²? Why does this make intuitive sense given that fund’s investment strategy?
References
Carhart, Mark M. 1997. “On Persistence in Mutual Fund Performance.”Journal of Finance 52 (1): 57–82.
Fama, Eugene F., and Kenneth R. French. 1993. “Common Risk Factors in the Returns on Stocks and Bonds.”Journal of Financial Economics 33 (1): 3–56.
Jegadeesh, Narasimhan, and Sheridan Titman. 1993. “Returns to Buying Winners and Selling Losers: Implications for Stock Market Efficiency.”Journal of Finance 48 (1): 65–91.
Jensen, Michael C. 1968. “The Performance of Mutual Funds in the Period 1945–1964.”Journal of Finance 23 (2): 389–416.
Wermers, Russ. 2011. “Performance Measurement of Mutual Funds, Hedge Funds, and Institutional Accounts.”Annual Review of Financial Economics 3: 537–74.