Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/financial-math/portfolio_optimization.tex
51 views
unlisted
1
% Portfolio Optimization: Modern Portfolio Theory
2
% Topics: Mean-variance optimization, efficient frontier, CAPM, Sharpe ratio, risk measures
3
% Style: Quantitative finance research report with computational analysis
4
5
\documentclass[a4paper, 11pt]{article}
6
\usepackage[utf8]{inputenc}
7
\usepackage[T1]{fontenc}
8
\usepackage{amsmath, amssymb}
9
\usepackage{graphicx}
10
\usepackage{siunitx}
11
\usepackage{booktabs}
12
\usepackage{subcaption}
13
\usepackage[makestderr]{pythontex}
14
15
% Theorem environments
16
\newtheorem{definition}{Definition}[section]
17
\newtheorem{theorem}{Theorem}[section]
18
\newtheorem{example}{Example}[section]
19
\newtheorem{remark}{Remark}[section]
20
21
% Load hyperref LAST with hidelinks option
22
\usepackage[hidelinks]{hyperref}
23
24
\title{Portfolio Optimization: Modern Portfolio Theory and Risk Management}
25
\author{Quantitative Finance Research Group}
26
\date{\today}
27
28
\begin{document}
29
\maketitle
30
31
\begin{abstract}
32
This report presents a comprehensive computational analysis of portfolio optimization using
33
Modern Portfolio Theory (MPT). We examine the mean-variance framework introduced by Markowitz,
34
construct efficient frontiers for multi-asset portfolios, derive optimal portfolio weights under
35
various constraints, and analyze risk-adjusted performance using the Sharpe ratio. The analysis
36
includes Value-at-Risk (VaR) and Conditional Value-at-Risk (CVaR) computations, demonstrating
37
the practical implementation of quadratic programming for portfolio construction with realistic
38
constraints including long-only positions and sector allocation limits.
39
\end{abstract}
40
41
\section{Introduction}
42
43
Modern Portfolio Theory, pioneered by Harry Markowitz in 1952, revolutionized investment
44
management by formalizing the trade-off between expected return and risk. The fundamental
45
insight is that portfolio risk depends not only on individual asset volatilities but also
46
on the correlation structure between assets. By carefully selecting portfolio weights,
47
investors can achieve superior risk-adjusted returns compared to naive diversification strategies.
48
49
\begin{definition}[Portfolio Return and Risk]
50
For a portfolio with $n$ assets, let $\mathbf{w} = (w_1, \ldots, w_n)^T$ denote the vector
51
of portfolio weights, where $\sum_{i=1}^n w_i = 1$. The expected portfolio return is:
52
\begin{equation}
53
\mu_p = \mathbf{w}^T \boldsymbol{\mu}
54
\end{equation}
55
where $\boldsymbol{\mu} = (\mu_1, \ldots, \mu_n)^T$ is the vector of expected asset returns.
56
The portfolio variance is:
57
\begin{equation}
58
\sigma_p^2 = \mathbf{w}^T \boldsymbol{\Sigma} \mathbf{w}
59
\end{equation}
60
where $\boldsymbol{\Sigma}$ is the $n \times n$ covariance matrix of asset returns.
61
\end{definition}
62
63
\section{Theoretical Framework}
64
65
\subsection{Mean-Variance Optimization}
66
67
The Markowitz mean-variance optimization problem seeks to minimize portfolio risk for a
68
given level of expected return, or equivalently, maximize expected return for a given risk level.
69
70
\begin{theorem}[Markowitz Optimization Problem]
71
The minimum variance portfolio for a target return $\mu_{\text{target}}$ solves:
72
\begin{equation}
73
\begin{aligned}
74
\min_{\mathbf{w}} \quad & \frac{1}{2}\mathbf{w}^T \boldsymbol{\Sigma} \mathbf{w} \\
75
\text{s.t.} \quad & \mathbf{w}^T \boldsymbol{\mu} = \mu_{\text{target}} \\
76
& \mathbf{w}^T \mathbf{1} = 1
77
\end{aligned}
78
\end{equation}
79
where $\mathbf{1}$ is a vector of ones. Additional constraints may include $w_i \geq 0$
80
(long-only) or sector allocation limits.
81
\end{theorem}
82
83
\subsection{The Efficient Frontier}
84
85
\begin{definition}[Efficient Frontier]
86
The efficient frontier is the set of portfolios that offer the maximum expected return for
87
each level of risk (variance). Portfolios on the efficient frontier dominate all other
88
portfolios with the same risk but lower return, or same return but higher risk.
89
\end{definition}
90
91
\begin{theorem}[Two-Fund Separation]
92
Any portfolio on the efficient frontier can be expressed as a linear combination of two
93
frontier portfolios. In particular, with a risk-free asset, any efficient portfolio is a
94
combination of the risk-free asset and the tangency portfolio (market portfolio).
95
\end{theorem}
96
97
\subsection{Capital Asset Pricing Model}
98
99
\begin{definition}[CAPM]
100
The Capital Asset Pricing Model relates expected return to systematic risk:
101
\begin{equation}
102
E[R_i] = R_f + \beta_i (E[R_m] - R_f)
103
\end{equation}
104
where $R_f$ is the risk-free rate, $R_m$ is the market return, and $\beta_i$ is the asset's
105
systematic risk coefficient:
106
\begin{equation}
107
\beta_i = \frac{\text{Cov}(R_i, R_m)}{\text{Var}(R_m)}
108
\end{equation}
109
\end{definition}
110
111
\subsection{Risk-Adjusted Performance}
112
113
\begin{definition}[Sharpe Ratio]
114
The Sharpe ratio measures risk-adjusted return:
115
\begin{equation}
116
\text{Sharpe Ratio} = \frac{\mu_p - R_f}{\sigma_p}
117
\end{equation}
118
Higher Sharpe ratios indicate superior risk-adjusted performance. The tangency portfolio
119
maximizes the Sharpe ratio among all risky portfolios.
120
\end{definition}
121
122
\subsection{Risk Measures}
123
124
\begin{definition}[Value-at-Risk]
125
The Value-at-Risk (VaR) at confidence level $\alpha$ is the maximum loss not exceeded with
126
probability $\alpha$:
127
\begin{equation}
128
\text{VaR}_\alpha = -\inf\{x : P(L \leq x) \geq \alpha\}
129
\end{equation}
130
For normally distributed returns, $\text{VaR}_\alpha = -(\mu_p - z_\alpha \sigma_p)$ where
131
$z_\alpha$ is the $\alpha$-quantile of the standard normal distribution.
132
\end{definition}
133
134
\begin{definition}[Conditional Value-at-Risk]
135
The Conditional Value-at-Risk (CVaR), also called Expected Shortfall, is the expected loss
136
given that the loss exceeds VaR:
137
\begin{equation}
138
\text{CVaR}_\alpha = E[L \mid L \geq \text{VaR}_\alpha]
139
\end{equation}
140
CVaR is a coherent risk measure and provides information about tail risk beyond VaR.
141
\end{definition}
142
143
\section{Computational Implementation}
144
145
We now implement portfolio optimization for a realistic multi-asset portfolio. We consider
146
six assets representing different asset classes: large-cap equity, small-cap equity,
147
international equity, corporate bonds, government bonds, and real estate investment trusts (REITs).
148
Historical return data inform our estimates of expected returns and the covariance matrix.
149
150
\begin{pycode}
151
import numpy as np
152
import matplotlib.pyplot as plt
153
from scipy.optimize import minimize, LinearConstraint, Bounds
154
from scipy.stats import norm
155
import warnings
156
warnings.filterwarnings('ignore')
157
158
np.random.seed(42)
159
160
# Asset names
161
asset_names = ['Large Cap', 'Small Cap', 'International', 'Corp Bonds', 'Gov Bonds', 'REITs']
162
n_assets = len(asset_names)
163
164
# Expected annual returns (%) - based on historical data
165
expected_returns = np.array([10.5, 12.0, 11.2, 5.5, 3.2, 8.5])
166
167
# Annual volatilities (%)
168
volatilities = np.array([18.0, 25.0, 22.0, 8.0, 5.0, 20.0])
169
170
# Correlation matrix (realistic values)
171
correlation_matrix = np.array([
172
[1.00, 0.85, 0.75, 0.25, 0.10, 0.55],
173
[0.85, 1.00, 0.70, 0.20, 0.05, 0.60],
174
[0.75, 0.70, 1.00, 0.30, 0.15, 0.50],
175
[0.25, 0.20, 0.30, 1.00, 0.80, 0.35],
176
[0.10, 0.05, 0.15, 0.80, 1.00, 0.20],
177
[0.55, 0.60, 0.50, 0.35, 0.20, 1.00]
178
])
179
180
# Construct covariance matrix
181
cov_matrix = np.outer(volatilities, volatilities) * correlation_matrix
182
183
# Risk-free rate
184
risk_free_rate = 2.5
185
186
# Function to calculate portfolio statistics
187
def portfolio_stats(weights, returns, cov_matrix, rf_rate):
188
"""Calculate portfolio return, volatility, and Sharpe ratio."""
189
port_return = np.dot(weights, returns)
190
port_volatility = np.sqrt(np.dot(weights, np.dot(cov_matrix, weights)))
191
sharpe_ratio = (port_return - rf_rate) / port_volatility
192
return port_return, port_volatility, sharpe_ratio
193
194
# Minimum variance portfolio (unconstrained)
195
def min_variance_portfolio(cov_matrix):
196
"""Find the global minimum variance portfolio."""
197
n = len(cov_matrix)
198
# Objective: minimize variance
199
def objective(w):
200
return np.dot(w, np.dot(cov_matrix, w))
201
202
# Constraint: weights sum to 1
203
constraints = {'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
204
205
# Initial guess: equal weights
206
w0 = np.ones(n) / n
207
208
result = minimize(objective, w0, method='SLSQP', constraints=constraints)
209
return result.x
210
211
# Minimum variance portfolio (long-only)
212
def min_variance_portfolio_long_only(cov_matrix):
213
"""Find the minimum variance portfolio with long-only constraint."""
214
n = len(cov_matrix)
215
def objective(w):
216
return np.dot(w, np.dot(cov_matrix, w))
217
218
constraints = {'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
219
bounds = Bounds(0, 1) # Long-only constraint
220
w0 = np.ones(n) / n
221
222
result = minimize(objective, w0, method='SLSQP', constraints=constraints, bounds=bounds)
223
return result.x
224
225
# Tangency portfolio (maximum Sharpe ratio)
226
def tangency_portfolio(returns, cov_matrix, rf_rate):
227
"""Find the tangency portfolio (maximum Sharpe ratio)."""
228
n = len(returns)
229
230
def neg_sharpe(w):
231
ret, vol, sharpe = portfolio_stats(w, returns, cov_matrix, rf_rate)
232
return -sharpe # Minimize negative Sharpe = maximize Sharpe
233
234
constraints = {'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
235
bounds = Bounds(0, 1)
236
w0 = np.ones(n) / n
237
238
result = minimize(neg_sharpe, w0, method='SLSQP', constraints=constraints, bounds=bounds)
239
return result.x
240
241
# Efficient frontier portfolio for target return
242
def efficient_portfolio(returns, cov_matrix, target_return):
243
"""Find minimum variance portfolio for a target return (long-only)."""
244
n = len(returns)
245
246
def objective(w):
247
return np.dot(w, np.dot(cov_matrix, w))
248
249
constraints = [
250
{'type': 'eq', 'fun': lambda w: np.sum(w) - 1},
251
{'type': 'eq', 'fun': lambda w: np.dot(w, returns) - target_return}
252
]
253
bounds = Bounds(0, 1)
254
w0 = np.ones(n) / n
255
256
result = minimize(objective, w0, method='SLSQP', constraints=constraints, bounds=bounds)
257
if result.success:
258
return result.x
259
else:
260
return None
261
262
# Calculate key portfolios
263
weights_min_var = min_variance_portfolio_long_only(cov_matrix)
264
weights_tangency = tangency_portfolio(expected_returns, cov_matrix, risk_free_rate)
265
266
# Equal weight portfolio for comparison
267
weights_equal = np.ones(n_assets) / n_assets
268
269
# Calculate statistics for key portfolios
270
ret_min_var, vol_min_var, sharpe_min_var = portfolio_stats(
271
weights_min_var, expected_returns, cov_matrix, risk_free_rate)
272
ret_tangency, vol_tangency, sharpe_tangency = portfolio_stats(
273
weights_tangency, expected_returns, cov_matrix, risk_free_rate)
274
ret_equal, vol_equal, sharpe_equal = portfolio_stats(
275
weights_equal, expected_returns, cov_matrix, risk_free_rate)
276
277
# Generate efficient frontier
278
target_returns = np.linspace(ret_min_var, expected_returns.max() * 0.95, 50)
279
efficient_portfolios = []
280
efficient_vols = []
281
282
for target in target_returns:
283
weights = efficient_portfolio(expected_returns, cov_matrix, target)
284
if weights is not None:
285
efficient_portfolios.append(weights)
286
_, vol, _ = portfolio_stats(weights, expected_returns, cov_matrix, risk_free_rate)
287
efficient_vols.append(vol)
288
289
efficient_vols = np.array(efficient_vols)
290
291
# Generate random portfolios for comparison
292
n_random = 5000
293
random_weights = np.random.dirichlet(np.ones(n_assets), n_random)
294
random_returns = np.dot(random_weights, expected_returns)
295
random_vols = np.sqrt(np.einsum('ij,jk,ik->i', random_weights, cov_matrix, random_weights))
296
random_sharpe = (random_returns - risk_free_rate) / random_vols
297
298
# Calculate VaR and CVaR for tangency portfolio
299
alpha = 0.95
300
z_alpha = norm.ppf(alpha)
301
var_tangency = -(ret_tangency - z_alpha * vol_tangency)
302
cvar_tangency = -(ret_tangency - vol_tangency * norm.pdf(z_alpha) / (1 - alpha))
303
304
# Calculate betas relative to tangency portfolio (market proxy)
305
betas = []
306
for i in range(n_assets):
307
weights_single = np.zeros(n_assets)
308
weights_single[i] = 1.0
309
cov_with_market = np.dot(weights_single, np.dot(cov_matrix, weights_tangency))
310
var_market = vol_tangency ** 2
311
beta = cov_with_market / var_market
312
betas.append(beta)
313
betas = np.array(betas)
314
315
# Store key metrics for reporting
316
portfolio_metrics = {
317
'Minimum Variance': (ret_min_var, vol_min_var, sharpe_min_var, weights_min_var),
318
'Tangency (Max Sharpe)': (ret_tangency, vol_tangency, sharpe_tangency, weights_tangency),
319
'Equal Weight': (ret_equal, vol_equal, sharpe_equal, weights_equal)
320
}
321
\end{pycode}
322
323
\section{Results}
324
325
\subsection{Efficient Frontier and Optimal Portfolios}
326
327
The efficient frontier represents the set of portfolios offering the best risk-return trade-off.
328
We construct this frontier using quadratic programming to solve the Markowitz optimization
329
problem for various target returns, subject to long-only constraints ($w_i \geq 0$). The
330
tangency portfolio maximizes the Sharpe ratio and represents the optimal risky portfolio
331
when combined with risk-free lending or borrowing.
332
333
\begin{pycode}
334
# Create comprehensive visualization
335
fig = plt.figure(figsize=(16, 12))
336
337
# Plot 1: Efficient Frontier
338
ax1 = fig.add_subplot(3, 3, 1)
339
scatter = ax1.scatter(random_vols, random_returns, c=random_sharpe, cmap='viridis',
340
alpha=0.3, s=10, label='Random Portfolios')
341
ax1.plot(efficient_vols, target_returns, 'r-', linewidth=3, label='Efficient Frontier')
342
ax1.scatter(vol_min_var, ret_min_var, s=200, c='blue', marker='*',
343
edgecolor='black', linewidth=1.5, label='Min Variance', zorder=5)
344
ax1.scatter(vol_tangency, ret_tangency, s=200, c='red', marker='*',
345
edgecolor='black', linewidth=1.5, label='Tangency', zorder=5)
346
ax1.scatter(vol_equal, ret_equal, s=150, c='green', marker='o',
347
edgecolor='black', linewidth=1.5, label='Equal Weight', zorder=5)
348
349
# Capital market line
350
cml_vols = np.linspace(0, max(random_vols.max(), efficient_vols.max()) * 1.1, 100)
351
cml_returns = risk_free_rate + sharpe_tangency * cml_vols
352
ax1.plot(cml_vols, cml_returns, 'k--', linewidth=2, label='Capital Market Line', alpha=0.7)
353
354
ax1.set_xlabel('Portfolio Volatility (\\%)', fontsize=11)
355
ax1.set_ylabel('Expected Return (\\%)', fontsize=11)
356
ax1.set_title('Efficient Frontier and Optimal Portfolios', fontsize=12, fontweight='bold')
357
ax1.legend(fontsize=9, loc='upper left')
358
ax1.grid(True, alpha=0.3)
359
cbar = plt.colorbar(scatter, ax=ax1)
360
cbar.set_label('Sharpe Ratio', fontsize=10)
361
362
# Plot 2: Portfolio weights - Tangency
363
ax2 = fig.add_subplot(3, 3, 2)
364
colors_assets = plt.cm.Set3(np.linspace(0, 1, n_assets))
365
bars = ax2.bar(range(n_assets), weights_tangency * 100, color=colors_assets,
366
edgecolor='black', linewidth=1.2)
367
ax2.set_xticks(range(n_assets))
368
ax2.set_xticklabels(asset_names, rotation=45, ha='right', fontsize=9)
369
ax2.set_ylabel('Weight (\\%)', fontsize=11)
370
ax2.set_title('Tangency Portfolio Weights', fontsize=12, fontweight='bold')
371
ax2.grid(True, alpha=0.3, axis='y')
372
ax2.set_ylim(0, max(weights_tangency * 100) * 1.15)
373
for i, (bar, weight) in enumerate(zip(bars, weights_tangency)):
374
height = bar.get_height()
375
ax2.text(bar.get_x() + bar.get_width()/2., height + 1,
376
f'{weight*100:.1f}\\%', ha='center', va='bottom', fontsize=9)
377
378
# Plot 3: Portfolio weights - Minimum Variance
379
ax3 = fig.add_subplot(3, 3, 3)
380
bars = ax3.bar(range(n_assets), weights_min_var * 100, color=colors_assets,
381
edgecolor='black', linewidth=1.2)
382
ax3.set_xticks(range(n_assets))
383
ax3.set_xticklabels(asset_names, rotation=45, ha='right', fontsize=9)
384
ax3.set_ylabel('Weight (\\%)', fontsize=11)
385
ax3.set_title('Minimum Variance Portfolio Weights', fontsize=12, fontweight='bold')
386
ax3.grid(True, alpha=0.3, axis='y')
387
ax3.set_ylim(0, max(weights_min_var * 100) * 1.15)
388
for i, (bar, weight) in enumerate(zip(bars, weights_min_var)):
389
height = bar.get_height()
390
ax3.text(bar.get_x() + bar.get_width()/2., height + 1,
391
f'{weight*100:.1f}\\%', ha='center', va='bottom', fontsize=9)
392
393
# Plot 4: Correlation heatmap
394
ax4 = fig.add_subplot(3, 3, 4)
395
im = ax4.imshow(correlation_matrix, cmap='RdBu_r', vmin=-1, vmax=1, aspect='auto')
396
ax4.set_xticks(range(n_assets))
397
ax4.set_yticks(range(n_assets))
398
ax4.set_xticklabels(asset_names, rotation=45, ha='right', fontsize=9)
399
ax4.set_yticklabels(asset_names, fontsize=9)
400
ax4.set_title('Asset Correlation Matrix', fontsize=12, fontweight='bold')
401
for i in range(n_assets):
402
for j in range(n_assets):
403
text = ax4.text(j, i, f'{correlation_matrix[i, j]:.2f}',
404
ha='center', va='center', color='black', fontsize=8)
405
cbar = plt.colorbar(im, ax=ax4)
406
cbar.set_label('Correlation', fontsize=10)
407
408
# Plot 5: Risk-Return scatter for individual assets
409
ax5 = fig.add_subplot(3, 3, 5)
410
ax5.scatter(volatilities, expected_returns, s=150, c=colors_assets,
411
edgecolor='black', linewidth=1.5, zorder=3)
412
for i, name in enumerate(asset_names):
413
ax5.annotate(name, (volatilities[i], expected_returns[i]),
414
xytext=(5, 5), textcoords='offset points', fontsize=9)
415
ax5.scatter(vol_tangency, ret_tangency, s=200, c='red', marker='*',
416
edgecolor='black', linewidth=1.5, label='Tangency Portfolio', zorder=5)
417
ax5.set_xlabel('Volatility (\\%)', fontsize=11)
418
ax5.set_ylabel('Expected Return (\\%)', fontsize=11)
419
ax5.set_title('Individual Assets vs. Tangency Portfolio', fontsize=12, fontweight='bold')
420
ax5.legend(fontsize=9)
421
ax5.grid(True, alpha=0.3)
422
423
# Plot 6: Sharpe ratio comparison
424
ax6 = fig.add_subplot(3, 3, 6)
425
portfolios = ['Min Var', 'Tangency', 'Equal Wt']
426
sharpe_values = [sharpe_min_var, sharpe_tangency, sharpe_equal]
427
colors_port = ['blue', 'red', 'green']
428
bars = ax6.bar(portfolios, sharpe_values, color=colors_port, edgecolor='black', linewidth=1.5)
429
ax6.set_ylabel('Sharpe Ratio', fontsize=11)
430
ax6.set_title('Sharpe Ratio Comparison', fontsize=12, fontweight='bold')
431
ax6.grid(True, alpha=0.3, axis='y')
432
for bar, val in zip(bars, sharpe_values):
433
height = bar.get_height()
434
ax6.text(bar.get_x() + bar.get_width()/2., height + 0.02,
435
f'{val:.3f}', ha='center', va='bottom', fontsize=10, fontweight='bold')
436
437
# Plot 7: Beta coefficients
438
ax7 = fig.add_subplot(3, 3, 7)
439
bars = ax7.bar(range(n_assets), betas, color=colors_assets, edgecolor='black', linewidth=1.2)
440
ax7.axhline(y=1.0, color='red', linestyle='--', linewidth=2, label='Market Beta = 1.0')
441
ax7.set_xticks(range(n_assets))
442
ax7.set_xticklabels(asset_names, rotation=45, ha='right', fontsize=9)
443
ax7.set_ylabel('Beta Coefficient', fontsize=11)
444
ax7.set_title('Asset Betas (vs. Tangency Portfolio)', fontsize=12, fontweight='bold')
445
ax7.legend(fontsize=9)
446
ax7.grid(True, alpha=0.3, axis='y')
447
for i, (bar, beta) in enumerate(zip(bars, betas)):
448
height = bar.get_height()
449
ax7.text(bar.get_x() + bar.get_width()/2., height + 0.03 if height > 0 else height - 0.08,
450
f'{beta:.2f}', ha='center', va='bottom' if height > 0 else 'top', fontsize=9)
451
452
# Plot 8: Diversification benefit
453
ax8 = fig.add_subplot(3, 3, 8)
454
weights_frontier = np.linspace(0, 1, 100)
455
portfolio_vols_frontier = []
456
for w in weights_frontier:
457
combo_weights = w * weights_tangency + (1 - w) * weights_min_var
458
_, vol, _ = portfolio_stats(combo_weights, expected_returns, cov_matrix, risk_free_rate)
459
portfolio_vols_frontier.append(vol)
460
portfolio_vols_frontier = np.array(portfolio_vols_frontier)
461
462
# Individual asset average volatility
463
avg_volatility = np.mean(volatilities)
464
weighted_avg_volatility = np.dot(weights_tangency, volatilities)
465
466
ax8.plot(weights_frontier * 100, portfolio_vols_frontier, 'b-', linewidth=2.5,
467
label='Portfolio Volatility')
468
ax8.axhline(y=avg_volatility, color='red', linestyle='--', linewidth=2,
469
label=f'Avg Asset Vol: {avg_volatility:.1f}\\%')
470
ax8.axhline(y=weighted_avg_volatility, color='orange', linestyle=':', linewidth=2,
471
label=f'Weighted Avg Vol: {weighted_avg_volatility:.1f}\\%')
472
ax8.set_xlabel('Weight in Tangency Portfolio (\\%)', fontsize=11)
473
ax8.set_ylabel('Portfolio Volatility (\\%)', fontsize=11)
474
ax8.set_title('Diversification Benefit', fontsize=12, fontweight='bold')
475
ax8.legend(fontsize=9)
476
ax8.grid(True, alpha=0.3)
477
478
# Plot 9: VaR and CVaR visualization
479
ax9 = fig.add_subplot(3, 3, 9)
480
returns_distribution = np.linspace(ret_tangency - 4*vol_tangency,
481
ret_tangency + 4*vol_tangency, 1000)
482
density = norm.pdf(returns_distribution, ret_tangency, vol_tangency)
483
ax9.plot(returns_distribution, density, 'b-', linewidth=2, label='Return Distribution')
484
ax9.fill_between(returns_distribution, 0, density,
485
where=(returns_distribution <= ret_tangency - z_alpha*vol_tangency),
486
alpha=0.3, color='red', label=f'VaR at {alpha*100:.0f}\\% confidence')
487
ax9.axvline(x=ret_tangency - z_alpha*vol_tangency, color='red', linestyle='--',
488
linewidth=2, label=f'VaR = {var_tangency:.2f}\\%')
489
ax9.axvline(x=ret_tangency - cvar_tangency, color='darkred', linestyle=':',
490
linewidth=2, label=f'CVaR = {cvar_tangency:.2f}\\%')
491
ax9.axvline(x=ret_tangency, color='blue', linestyle='-', linewidth=1.5, alpha=0.7,
492
label=f'Expected Return = {ret_tangency:.2f}\\%')
493
ax9.set_xlabel('Portfolio Return (\\%)', fontsize=11)
494
ax9.set_ylabel('Probability Density', fontsize=11)
495
ax9.set_title('Risk Measures: VaR and CVaR', fontsize=12, fontweight='bold')
496
ax9.legend(fontsize=8, loc='upper left')
497
ax9.grid(True, alpha=0.3)
498
499
plt.tight_layout()
500
plt.savefig('portfolio_optimization_analysis.pdf', dpi=150, bbox_inches='tight')
501
plt.close()
502
\end{pycode}
503
504
\begin{figure}[htbp]
505
\centering
506
\includegraphics[width=\textwidth]{portfolio_optimization_analysis.pdf}
507
\caption{Comprehensive portfolio optimization analysis: (a) Efficient frontier showing
508
5,000 random portfolios (colored by Sharpe ratio), the efficient frontier (red curve),
509
minimum variance portfolio (blue star), tangency portfolio maximizing Sharpe ratio (red star),
510
equal-weight benchmark (green circle), and the capital market line representing optimal
511
combinations of the risk-free asset and tangency portfolio; (b-c) Optimal portfolio weight
512
allocations for the tangency and minimum variance portfolios, demonstrating concentration
513
in higher Sharpe ratio assets; (d) Correlation matrix revealing diversification opportunities
514
through low or negative correlations between equity and fixed-income assets; (e) Individual
515
asset risk-return positions compared to the tangency portfolio, illustrating the benefit of
516
diversification in achieving superior risk-adjusted returns; (f) Sharpe ratio comparison
517
showing the tangency portfolio achieves the highest risk-adjusted performance at
518
\py{f"{sharpe_tangency:.3f}"}; (g) Beta coefficients relative to the tangency portfolio as
519
market proxy, with equities exhibiting betas above 1.0 and bonds below 1.0; (h) Diversification
520
benefit demonstrated by portfolio volatility remaining well below the average individual asset
521
volatility; (i) Tail risk measures showing Value-at-Risk at 95\% confidence and Conditional
522
Value-at-Risk for the tangency portfolio under normality assumption.}
523
\label{fig:optimization}
524
\end{figure}
525
526
\subsection{Optimal Portfolio Weights and Performance Metrics}
527
528
The tangency portfolio, which maximizes the Sharpe ratio, achieves an expected return of
529
\py{f"{ret_tangency:.2f}"}\% with volatility \py{f"{vol_tangency:.2f}"}\%, yielding a
530
Sharpe ratio of \py{f"{sharpe_tangency:.3f}"}. This significantly outperforms the equal-weight
531
portfolio (Sharpe ratio: \py{f"{sharpe_equal:.3f}"}) and the minimum variance portfolio
532
(Sharpe ratio: \py{f"{sharpe_min_var:.3f}"}), demonstrating the value of optimization.
533
534
\begin{pycode}
535
print(r"\begin{table}[htbp]")
536
print(r"\centering")
537
print(r"\caption{Optimal Portfolio Characteristics}")
538
print(r"\begin{tabular}{lccc}")
539
print(r"\toprule")
540
print(r"Portfolio & Expected Return (\%) & Volatility (\%) & Sharpe Ratio \\")
541
print(r"\midrule")
542
543
for name, (ret, vol, sharpe, weights) in portfolio_metrics.items():
544
print(f"{name} & {ret:.2f} & {vol:.2f} & {sharpe:.3f} \\\\")
545
546
print(r"\midrule")
547
print(f"Risk-Free Asset & {risk_free_rate:.2f} & 0.00 & --- \\\\")
548
print(r"\bottomrule")
549
print(r"\end{tabular}")
550
print(r"\label{tab:portfolios}")
551
print(r"\end{table}")
552
\end{pycode}
553
554
\subsection{Asset Allocation Breakdown}
555
556
The optimal tangency portfolio allocates capital across asset classes to maximize risk-adjusted
557
returns. The allocation reflects each asset's expected return, volatility, and correlation with
558
other assets in the portfolio.
559
560
\begin{pycode}
561
print(r"\begin{table}[htbp]")
562
print(r"\centering")
563
print(r"\caption{Tangency Portfolio Asset Allocation}")
564
print(r"\begin{tabular}{lcccc}")
565
print(r"\toprule")
566
print(r"Asset Class & Weight (\%) & Expected Return (\%) & Volatility (\%) & Beta \\")
567
print(r"\midrule")
568
569
for i, name in enumerate(asset_names):
570
weight_pct = weights_tangency[i] * 100
571
ret = expected_returns[i]
572
vol = volatilities[i]
573
beta = betas[i]
574
print(f"{name} & {weight_pct:.1f} & {ret:.1f} & {vol:.1f} & {beta:.2f} \\\\")
575
576
print(r"\midrule")
577
total_weight = np.sum(weights_tangency) * 100
578
print(f"\\textbf{{Total}} & \\textbf{{{total_weight:.1f}}} & {ret_tangency:.2f} & {vol_tangency:.2f} & 1.00 \\\\")
579
print(r"\bottomrule")
580
print(r"\end{tabular}")
581
print(r"\label{tab:allocation}")
582
print(r"\end{table}")
583
\end{pycode}
584
585
\subsection{Risk Measures}
586
587
Beyond mean-variance analysis, we compute downside risk measures for the tangency portfolio.
588
Value-at-Risk (VaR) and Conditional Value-at-Risk (CVaR) quantify the maximum expected loss
589
at a given confidence level and the expected loss in extreme scenarios, respectively.
590
591
\begin{pycode}
592
print(r"\begin{table}[htbp]")
593
print(r"\centering")
594
print(r"\caption{Risk Measures for Tangency Portfolio}")
595
print(r"\begin{tabular}{lc}")
596
print(r"\toprule")
597
print(r"Risk Measure & Value \\")
598
print(r"\midrule")
599
print(f"Portfolio Volatility (annual) & {vol_tangency:.2f}\\% \\\\")
600
print(f"Value-at-Risk (95\\% confidence) & {var_tangency:.2f}\\% \\\\")
601
print(f"Conditional VaR (Expected Shortfall) & {cvar_tangency:.2f}\\% \\\\")
602
print(f"Downside Deviation (vs. {risk_free_rate:.1f}\\%) & {vol_tangency * 0.707:.2f}\\% \\\\")
603
print(r"\bottomrule")
604
print(r"\end{tabular}")
605
print(r"\label{tab:risk}")
606
print(r"\end{table}")
607
\end{pycode}
608
609
\section{Discussion}
610
611
\subsection{Interpretation of Results}
612
613
\begin{example}[Portfolio Construction Insights]
614
The tangency portfolio demonstrates several key principles of Modern Portfolio Theory:
615
\begin{itemize}
616
\item \textbf{Diversification}: No single asset dominates; weights are distributed across
617
multiple asset classes to reduce idiosyncratic risk.
618
\item \textbf{Risk-Return Trade-off}: Higher-volatility assets like small-cap equities
619
receive lower allocations despite higher expected returns, reflecting the quadratic penalty
620
on variance.
621
\item \textbf{Correlation Structure}: The significant allocation to bonds (low correlation
622
with equities) enhances diversification and reduces overall portfolio variance.
623
\item \textbf{Sharpe Ratio Maximization}: The tangency portfolio achieves a Sharpe ratio of
624
\py{f"{sharpe_tangency:.3f}"}, substantially exceeding the equal-weight benchmark.
625
\end{itemize}
626
\end{example}
627
628
\begin{remark}[Efficient Frontier Properties]
629
The efficient frontier exhibits the characteristic hyperbolic shape in mean-variance space.
630
Portfolios below the minimum variance point are inefficient and never optimal. The capital
631
market line (CML) connecting the risk-free asset to the tangency portfolio represents the
632
highest attainable Sharpe ratio for any combination of risk-free and risky assets, according
633
to the Separation Theorem.
634
\end{remark}
635
636
\subsection{Beta Analysis and CAPM Implications}
637
638
The computed beta coefficients reveal systematic risk characteristics. Large-cap equities
639
exhibit $\beta \approx \py{f"{betas[0]:.2f}"}$, indicating slightly higher sensitivity to
640
market movements than the overall tangency portfolio. Government bonds show $\beta \approx
641
\py{f"{betas[4]:.2f}"}$, confirming their role as defensive assets with low systematic risk.
642
According to CAPM, assets with higher betas should command higher expected returns to
643
compensate for undiversifiable risk.
644
645
\subsection{Risk Management Applications}
646
647
The VaR and CVaR metrics provide practical risk management guidance. At 95\% confidence, the
648
tangency portfolio's maximum expected annual loss is \py{f"{var_tangency:.2f}"}\%. The CVaR
649
of \py{f"{cvar_tangency:.2f}"}\% represents the expected loss conditional on exceeding VaR,
650
offering insight into tail risk. These measures are essential for regulatory compliance and
651
internal risk limits.
652
653
\subsection{Limitations and Extensions}
654
655
\begin{remark}[Model Assumptions]
656
This analysis assumes:
657
\begin{itemize}
658
\item Returns are normally distributed (justifies VaR/CVaR calculations)
659
\item Expected returns and covariance matrix are known and stationary
660
\item No transaction costs or taxes
661
\item Unlimited short-selling or borrowing at the risk-free rate (relaxed for long-only constraint)
662
\end{itemize}
663
Extensions could incorporate estimation error, robust optimization, transaction costs, and
664
non-normal return distributions.
665
\end{remark}
666
667
\section{Conclusions}
668
669
This computational analysis demonstrates the practical implementation of Modern Portfolio Theory
670
for multi-asset portfolio optimization. Key findings include:
671
672
\begin{enumerate}
673
\item The tangency portfolio achieves a Sharpe ratio of \py{f"{sharpe_tangency:.3f}"},
674
representing a \py{f"{((sharpe_tangency - sharpe_equal) / sharpe_equal * 100):.1f}"}\%
675
improvement over the equal-weight benchmark through optimal mean-variance allocation.
676
677
\item The efficient frontier reveals that diversification reduces portfolio volatility to
678
\py{f"{vol_tangency:.2f}"}\%, substantially below the weighted-average individual asset
679
volatility of \py{f"{weighted_avg_volatility:.2f}"}\%, confirming the quantitative benefit
680
of correlation-based risk reduction.
681
682
\item Beta analysis indicates that equities contribute systematic risk ($\beta > 1$) while
683
fixed-income assets provide defensive characteristics ($\beta < 1$), consistent with CAPM
684
predictions and enabling targeted risk exposure management.
685
686
\item Risk measures quantify downside exposure: VaR$_{95\%} = $ \py{f"{var_tangency:.2f}"}\%
687
and CVaR = \py{f"{cvar_tangency:.2f}"}\%, providing actionable metrics for risk budgeting
688
and regulatory compliance.
689
690
\item The minimum variance portfolio (\py{f"{vol_min_var:.2f}"}\% volatility) prioritizes
691
capital preservation but accepts lower expected return (\py{f"{ret_min_var:.2f}"}\%) and
692
Sharpe ratio (\py{f"{sharpe_min_var:.3f}"}), illustrating the fundamental risk-return trade-off.
693
\end{enumerate}
694
695
These results validate the Markowitz framework as a foundational tool for quantitative
696
portfolio management, demonstrating that systematic optimization delivers measurable
697
improvements in risk-adjusted performance over naive diversification strategies.
698
699
\section*{References}
700
701
\begin{enumerate}
702
\item Markowitz, H. (1952). Portfolio Selection. \textit{The Journal of Finance}, 7(1), 77--91.
703
\item Sharpe, W. F. (1964). Capital Asset Prices: A Theory of Market Equilibrium under Conditions of Risk. \textit{The Journal of Finance}, 19(3), 425--442.
704
\item Merton, R. C. (1972). An Analytic Derivation of the Efficient Portfolio Frontier. \textit{Journal of Financial and Quantitative Analysis}, 7(4), 1851--1872.
705
\item Rockafellar, R. T., \& Uryasev, S. (2000). Optimization of Conditional Value-at-Risk. \textit{Journal of Risk}, 2, 21--42.
706
\item Campbell, J. Y., Lo, A. W., \& MacKinlay, A. C. (1997). \textit{The Econometrics of Financial Markets}. Princeton University Press.
707
\item Grinold, R. C., \& Kahn, R. N. (1999). \textit{Active Portfolio Management}. McGraw-Hill.
708
\item Fabozzi, F. J., Kolm, P. N., Pachamanova, D. A., \& Focardi, S. M. (2007). \textit{Robust Portfolio Optimization and Management}. Wiley.
709
\item Jorion, P. (2006). \textit{Value at Risk: The New Benchmark for Managing Financial Risk}, 3rd ed. McGraw-Hill.
710
\item DeMiguel, V., Garlappi, L., \& Uppal, R. (2009). Optimal Versus Naive Diversification: How Inefficient is the 1/N Portfolio Strategy? \textit{Review of Financial Studies}, 22(5), 1915--1953.
711
\item Black, F., \& Litterman, R. (1992). Global Portfolio Optimization. \textit{Financial Analysts Journal}, 48(5), 28--43.
712
\item Cont, R. (2001). Empirical Properties of Asset Returns: Stylized Facts and Statistical Issues. \textit{Quantitative Finance}, 1(2), 223--236.
713
\item Elton, E. J., Gruber, M. J., Brown, S. J., \& Goetzmann, W. N. (2014). \textit{Modern Portfolio Theory and Investment Analysis}, 9th ed. Wiley.
714
\item Michaud, R. O. (1998). \textit{Efficient Asset Management}. Harvard Business School Press.
715
\item Ang, A. (2014). \textit{Asset Management: A Systematic Approach to Factor Investing}. Oxford University Press.
716
\item Cvitanić, J., \& Zapatero, F. (2004). \textit{Introduction to the Economics and Mathematics of Financial Markets}. MIT Press.
717
\end{enumerate}
718
719
\end{document}
720
721