Risk Analytics¶
1. Calculation Name¶
Volatility, Tracking Error, Information Ratio, and Drawdown Summary
2. Description and Mathematical Formula¶
The risk plugin produces rolling risk statistics from periodic returns:
- Portfolio volatility: \( \sigma_P = \mathrm{stdev}(r^P_t) \)
- Tracking error: \( \mathrm{TE} = \mathrm{stdev}(r^P_t - r^B_t) \)
- Information ratio: \( \mathrm{IR} = \frac{\overline{r^P_t - r^B_t}}{\mathrm{TE}} \)
- Maximum drawdown: \( \min_t \left(\frac{V_t}{\max_{s \leq t} V_s} - 1\right) \) where \( V_t = \prod_{k \leq t} (1 + r^P_k) \)
3. Input Sample Data¶
| Month | Portfolio Return | Benchmark Return | Active Return |
|---|---|---|---|
| Jan | 2.00% | 1.80% | 0.20% |
| Feb | 1.50% | 1.20% | 0.30% |
| Mar | -0.50% | -0.60% | 0.10% |
| Apr | 1.20% | 1.00% | 0.20% |
| May | 0.80% | 0.70% | 0.10% |
| Jun | -1.00% | -0.90% | -0.10% |
4. Mathematical Solution¶
- Portfolio standard deviation: \( \sigma_P = 1.18\% \)
- Tracking error: \( \mathrm{TE} = 0.14\% \)
- Mean active return: \( \overline{r^P - r^B} = 0.13\% \)
- Information ratio: \( \mathrm{IR} = 0.13\% / 0.14\% = 0.98 \)
- Cumulative portfolio path: \( V_t = \prod (1 + r^P_t) \) peaks at 1.037 → max drawdown = -1.00%
5. Sample Python and R Code¶
import statistics
from functools import reduce
portfolio = [0.020, 0.015, -0.005, 0.012, 0.008, -0.010]
benchmark = [0.018, 0.012, -0.006, 0.010, 0.007, -0.009]
active = [p - b for p, b in zip(portfolio, benchmark)]
sigma_port = statistics.stdev(portfolio)
tracking_error = statistics.stdev(active)
info_ratio = (sum(active) / len(active)) / tracking_error
cum_values = []
value = 1.0
for r in portfolio:
value *= (1 + r)
cum_values.append(value)
peak = []
max_v = 0.0
for v in cum_values:
max_v = max(max_v, v)
peak.append(max_v)
drawdowns = [c / p - 1 for c, p in zip(cum_values, peak)]
print(f"Volatility: {sigma_port:.4%}")
print(f"Tracking error: {tracking_error:.4%}")
print(f"Information ratio: {info_ratio:.2f}")
print(f"Max drawdown: {min(drawdowns):.4%}")
portfolio <- c(0.020, 0.015, -0.005, 0.012, 0.008, -0.010)
benchmark <- c(0.018, 0.012, -0.006, 0.010, 0.007, -0.009)
active <- portfolio - benchmark
sigma_port <- sd(portfolio)
tracking_error <- sd(active)
info_ratio <- mean(active) / tracking_error
cum_values <- cumprod(1 + portfolio)
peak <- cummax(cum_values)
drawdowns <- cum_values / peak - 1
list(
volatility = scales::percent(sigma_port, accuracy = 0.01),
tracking_error = scales::percent(tracking_error, accuracy = 0.01),
information_ratio = round(info_ratio, 2),
max_drawdown = scales::percent(min(drawdowns), accuracy = 0.01)
)
6. Output Table¶
| Metric | Value |
|---|---|
| Portfolio Volatility (monthly) | 1.18% |
| Tracking Error | 0.14% |
| Information Ratio | 0.98 |
| Maximum Drawdown | -1.00% |
7. Conclusion¶
Use this template to explain how FinFacts calculates key risk statistics from simple return streams. It doubles as a regression harness for the risk plugin and as supporting material for investor factsheets.