The market model is estimated over \(n = 96\) months:
\[R_i - R_f = \alpha + \beta\,(R_m - R_f) + \varepsilon\]
| Term | Estimate | Std. Error |
|---|---|---|
| Intercept (\(\alpha\)) | 0.0017 | 0.0020 |
| Market premium (\(\beta\)) | 0.98 | 0.17 |
Reported: \(R^2 = 0.50\), average monthly market premium \(E[R_m - R_f] = 0.70\%\), critical \(|t| \approx 1.98\).
n1 <- 96
alpha <- 0.0017; se_alpha <- 0.0020
beta <- 0.98; se_beta <- 0.17
R2_1 <- 0.50
mkt_prem <- 0.0070 # E[R_m - R_f]
tcrit <- 1.98\[t_\beta = \frac{\hat\beta - 0}{SE(\hat\beta)}\]
## [1] 5.764706
\(t_\beta =\) 5.7647. Since \(|t_\beta| > 1.98\), we reject \(H_0:\beta=0\). The loading is highly significant. Economically, \(\beta \approx 0.98\) means the fund moves almost one-for-one with the market; its systematic risk is close to the market’s.
\[t = \frac{\hat\beta - 1}{SE(\hat\beta)}\]
## [1] -0.1176471
\(t =\) -0.1176. Since \(|t| < 1.98\), we fail to reject \(H_0:\beta=1\). There is no statistical evidence the fund’s systematic risk differs from the market’s — it is effectively a market-risk fund.
\[t_\alpha = \frac{\hat\alpha}{SE(\hat\alpha)}\]
## [1] 0.85
\(t_\alpha =\) 0.8500. Since \(|t_\alpha| < 1.98\), we fail to reject \(H_0:\alpha=0\). The data do not statistically justify advertising “positive risk-adjusted performance.” The point estimate is positive, but it is indistinguishable from zero at the 5% level.
50% of the fund’s return variation is systematic (explained by the market); the remaining 50% is diversifiable / idiosyncratic risk.
Under CAPM, \(\alpha = 0\), so:
\[E[R_i - R_f] = \beta \cdot E[R_m - R_f]\]
## [1] 0.00686
## [1] 0.686
CAPM-implied expected monthly excess return \(=\) 0.0069 \(=\) 0.6860%.
Estimated over \(n = 144\) months:
\[R_i - R_f = \alpha + b\cdot MKT + s\cdot SMB + h\cdot HML + \varepsilon\]
| Term | Estimate | Std. Error |
|---|---|---|
| Intercept (\(\alpha\)) | 0.0029 | 0.0018 |
| MKT (\(b\)) | 0.97 | 0.08 |
| SMB (\(s\)) | 0.75 | 0.11 |
| HML (\(h\)) | -0.13 | 0.13 |
Reported: \(R^2 = 0.92\), Adjusted \(R^2 = 0.918\), critical \(|t| \approx 1.98\).
n2 <- 144
est <- c(alpha = 0.0029, MKT = 0.97, SMB = 0.75, HML = -0.13)
se <- c(alpha = 0.0018, MKT = 0.08, SMB = 0.11, HML = 0.13)\[t = \frac{\text{Estimate}}{\text{Std. Error}}\]
t_stats <- est / se
result <- data.frame(
Term = names(est),
Estimate = est,
Std.Error = se,
t = round(t_stats, 4),
Significant = ifelse(abs(t_stats) > tcrit, "Yes", "No")
)
rownames(result) <- NULL
resultSignificant at 5%: MKT and SMB. The intercept and HML are not significant.
Style: a small-cap fund with no statistically significant value-or-growth tilt.
## alpha
## 1.611111
\(\alpha = 0.0029\) (\(\approx 0.29\%\)/month, \(\approx 3.5\%\)/year), \(t =\) 1.6111 \(< 1.98\), so it is not significant. The manager’s risk-adjusted alpha is indistinguishable from zero — the data do not support genuine value-add beyond the factor exposures.
Adding SMB and HML explains substantially more return variation (here driven mainly by the significant SMB loading). We compare models with adjusted \(R^2\) because plain \(R^2\) never decreases when predictors are added — it can rise on pure noise. Adjusted \(R^2\) penalizes the number of regressors:
\[R^2_{adj} = 1 - (1 - R^2)\,\frac{n - 1}{n - p - 1}\]
adjR2 <- function(R2, n, p) 1 - (1 - R2) * (n - 1) / (n - p - 1)
# Three-factor model: p = 3 predictors
adjR2(0.92, n2, 3)## [1] 0.9182857
The computed adjusted \(R^2 \approx\) 0.9183 confirms the genuine improvement (matching the reported 0.918) — the added factors improve fit beyond what extra variables would contribute by chance.
\[\text{logit}\,P(\text{Up}) = \beta_0 + \beta_1 r_{t-1} + \beta_2 \Delta VIX_{t-1}\]
Coefficients: \(\beta_0 = -0.02,\ \beta_1 = 5.4,\ \beta_2 = -0.38\). Inputs: \(r_{t-1} = 0.010,\ \Delta VIX = 1.5\).
\[\text{logit} = \beta_0 + \beta_1 r_{t-1} + \beta_2 \Delta VIX, \qquad P(\text{Up}) = \frac{1}{1 + e^{-\text{logit}}}\]
## [1] -0.536
## [1] 0.3691186
## [1] "Down"
\(\text{logit} =\) -0.5360, so \(P(\text{Up}) =\) 0.3691. Since \(0.3691 < 0.5\), the predicted class is Down.
TP <- 67; FN <- 33 # Actual Up = 100
FP <- 44; TN <- 56 # Actual Down = 100
N <- TP + FN + FP + TN
accuracy <- (TP + TN) / N
sensitivity <- TP / (TP + FN) # TPR for "Up"
specificity <- TN / (TN + FP)
precision <- TP / (TP + FP) # Predicted Up = 111
data.frame(
Metric = c("Accuracy", "Sensitivity (TPR, Up)", "Specificity", "Precision (Up)"),
Value = round(c(accuracy, sensitivity, specificity, precision), 4)
)\[\text{Accuracy} = \frac{TP+TN}{N},\quad \text{Sensitivity} = \frac{TP}{TP+FN},\quad \text{Specificity} = \frac{TN}{TN+FP},\quad \text{Precision} = \frac{TP}{TP+FP}\]
## [1] 0.5
## [1] TRUE
The classes are balanced (100/100), so the majority rule scores 0.5000. The model (0.6150) beats it. Accuracy alone is inadequate for trading because it weights every trade equally and ignores the magnitude of gains/losses and transaction costs — a few large wrong-way trades can erase many small correct ones. A more economically relevant criterion is the strategy’s risk-adjusted return (Sharpe ratio) or expected P&L per trade.
A strategy earns mean monthly return \(0.70\%\) with SD \(5.50\%\) over \(n = 48\) months.
\[SR_{monthly} = \frac{\bar r}{s}, \qquad SR_{annual} = SR_{monthly}\times\sqrt{12}\]
## [1] 0.1272727
## [1] 0.4408857
\(SR_{monthly} =\) 0.1273, annualized \(SR =\) 0.4409. The scaling factor is \(\sqrt{12}\) (assumes i.i.d. monthly returns and risk-free \(\approx 0\)).
Procedure:
# Illustrative bootstrap (synthetic returns matching the moments)
set.seed(1)
sim_returns <- rnorm(n4, mean = mean_ret, sd = sd_ret)
B <- 2000
boot_SR <- replicate(B, {
s <- sample(sim_returns, size = n4, replace = TRUE)
mean(s) / sd(s)
})
se_SR <- sd(boot_SR)
se_SR # bootstrap standard error of the monthly Sharpe ratio## [1] 0.16424
The ordinary i.i.d. bootstrap is inappropriate for monthly returns because they exhibit autocorrelation and volatility clustering; resampling observations independently destroys that time dependence and understates the true variability of the Sharpe ratio. Fix: the block bootstrap (moving-block / stationary bootstrap), which resamples contiguous blocks to preserve serial dependence.
Deploy \(\lambda = 0.065\) (7 factors) — the one-standard-error rule. It is the most parsimonious model whose CV error lies within one standard error of the minimum, sacrificing essentially no measured accuracy for a simpler, more robust model. Fewer factors means less overfitting, better out-of-sample stability, and lower turnover/transaction costs. The \(\lambda = 0.030\) (14-factor) minimum-CV solution is more likely fitting noise in the validation folds.
Walk-forward (expanding or rolling window):
Standard random k-fold CV is unsafe because it shuffles observations across time, placing future data into the training folds used to predict the past — look-ahead leakage. This inflates measured accuracy and breaks the autocorrelation structure of returns. A time-respecting (walk-forward) scheme keeps every training set strictly before its test set.