- Authors

- Name
- Youngju Kim
- @fjvbn20031
Table of Contents
- Foundations of Asset Allocation
- Asset Class Characteristics
- Asset Allocation Strategy Types
- ETF-Based Portfolio Implementation
- Rebalancing Strategies
- Python Portfolio Optimization
- Quiz and Self-Assessment
1. Foundations of Asset Allocation
What Is Asset Allocation?
Asset allocation is the process of dividing an investment portfolio among different asset categories — such as stocks, bonds, real estate, and cash — based on an investor's goals, risk tolerance, and time horizon. It is one of the most consequential decisions any investor makes.
Research by Brinson, Hood, and Beebower (1986) famously concluded that over 90% of the variability in a portfolio's returns is explained by its asset allocation policy — not by security selection or market timing. This finding underscores why getting allocation right matters far more than picking the "best" individual stocks.
Modern Portfolio Theory (MPT)
Harry Markowitz introduced Modern Portfolio Theory in his landmark 1952 paper "Portfolio Selection." MPT provides the mathematical framework for constructing portfolios that maximize expected return for a given level of risk.
The Mathematics of Diversification
For a two-asset portfolio with assets A and B:
- Expected portfolio return:
E(Rp) = wA * E(RA) + wB * E(RB) - Portfolio variance:
Var(Rp) = wA^2 * Var(RA) + wB^2 * Var(RB) + 2 * wA * wB * Cov(RA, RB)
The covariance term is the key insight. When the correlation coefficient (ρ) between two assets is less than 1.0, combining them reduces overall portfolio risk below the weighted average of individual risks. When ρ = -1.0, risk can be eliminated entirely through a specific weighting.
Practical Implication
You do not need to find uncorrelated assets to benefit from diversification — any correlation below 1.0 provides some benefit. This is why mixing stocks and bonds, which tend to have low or negative correlations during equity bear markets, is so powerful.
The Efficient Frontier
The efficient frontier is the set of portfolios that offer the highest expected return for each level of risk (standard deviation). Any portfolio not on the efficient frontier is suboptimal — it either takes on more risk for the same return, or earns less return for the same risk.
Capital Market Line (CML)
When a risk-free asset (such as Treasury bills) is added to the opportunity set, investors can construct portfolios along the Capital Market Line — a straight line from the risk-free rate tangent to the efficient frontier at the Market Portfolio. The tangency point is called the Market Portfolio, and the slope of the CML is the maximum achievable Sharpe ratio in the market.
Key Takeaways from MPT
- Diversification reduces risk without necessarily reducing expected return
- The efficient frontier is curved — there are diminishing marginal benefits to diversification
- Correlation is the critical variable; lower correlations mean greater diversification benefits
- The Market Portfolio (all investable assets held in market-cap proportion) sits on the efficient frontier
Risk-Return Tradeoff
No investment provides high returns without taking on risk. This fundamental relationship is called the risk-return tradeoff. Understanding it is crucial for setting realistic expectations.
Types of Risk
- Systematic risk (market risk): Cannot be diversified away. Examples include recession risk, interest rate risk, and geopolitical events.
- Unsystematic risk (idiosyncratic risk): Specific to individual companies or sectors. Can be largely eliminated through diversification.
Risk Measures
- Standard deviation: Measures total volatility (both upside and downside)
- Beta: Sensitivity to market movements (beta = 1.0 means moves in line with market)
- Maximum drawdown: Largest peak-to-trough decline
- Value at Risk (VaR): Maximum expected loss at a given confidence level over a time horizon
2. Asset Class Characteristics
Equities (Stocks)
Stocks represent ownership in companies and have historically delivered the highest long-run returns of the major asset classes. The S&P 500 has returned approximately 10% annually before inflation over the past century.
Domestic US Equities
- Large-cap blend: S&P 500, low volatility, reliable earnings base (examples: Apple, Microsoft, Amazon)
- Small-cap: Higher long-run return premium historically, higher volatility
- Growth vs Value: Growth stocks trade at high valuations; value stocks trade at discounts to fundamentals
International Developed Market Equities
- Europe: Lower valuations than US, dividend-focused culture, slower growth
- Japan: Corporate governance reforms underway, yen exposure
- Australia/Canada: Resource-heavy economies, commodity exposure
- Key ETFs: VEA (Vanguard Developed Markets), EFA (iShares)
Emerging Market Equities
- China: World's second-largest economy, regulatory and geopolitical risk
- India: Demographic tailwinds, fast-growing middle class
- Southeast Asia: Vietnam, Indonesia, Thailand — manufacturing shift from China
- Key ETFs: VWO (Vanguard), EEM (iShares), IEMG (iShares)
Historical Return Expectations (annualized, before inflation)
| Asset | Historical Return | Volatility |
|---|---|---|
| US Large-Cap | ~10% | ~15% |
| International Developed | ~8% | ~17% |
| Emerging Markets | ~9% | ~22% |
| Small-Cap Value | ~12% | ~20% |
Fixed Income (Bonds)
Bonds provide portfolio stability, income, and diversification benefits relative to equities. They tend to rise in value during equity market downturns (flight to safety), making them valuable portfolio stabilizers.
Government Bonds
- US Treasuries: The global risk-free benchmark. Short-term (T-bills), intermediate (notes), long-term (T-bonds, 20-30 years)
- TIPS (Treasury Inflation-Protected Securities): Principal adjusted for CPI, real yield guaranteed
- International government bonds: Currency risk adds complexity
Corporate Bonds
- Investment-grade (BBB and above): Low default risk, modest yield premium over Treasuries
- High-yield/Junk bonds (BB and below): Higher default risk, equity-like behavior during stress
Bond Duration and Interest Rate Risk
Duration measures a bond's price sensitivity to interest rate changes. A bond with duration of 8 years falls approximately 8% in price when yields rise 1%. Long-term bonds carry more interest rate risk but offer higher yields.
Key ETFs:
- BND: Vanguard Total Bond Market (all US investment-grade bonds)
- AGG: iShares Core US Aggregate Bond
- TLT: iShares 20+ Year Treasury Bond
- IEF: iShares 7-10 Year Treasury Bond
- TIP: iShares TIPS Bond
Alternative Investments
Real Estate Investment Trusts (REITs)
REITs own income-producing real estate (offices, retail, apartments, warehouses, data centers, healthcare). They must distribute 90% of taxable income as dividends, making them attractive income investments.
- Low correlation with stocks and bonds over full market cycles
- Inflation hedge: Rental income tends to rise with inflation
- Sub-sectors: residential, commercial, industrial, healthcare, data center, hotel
- Key ETFs: VNQ (Vanguard US REIT), VNQI (International REIT), REM (Mortgage REIT)
Gold
Gold is the quintessential safe-haven asset. Its appeal lies in:
- Store of value over millennia
- Negative or low correlation with equities during crises
- Inflation hedge (though imperfect)
- No counterparty risk (unlike bonds or stocks)
- No yield, which means opportunity cost during bull markets
Key ETFs: GLD (SPDR), IAU (iShares, lower expense ratio at 0.25% vs GLD's 0.40%)
Commodities
Commodities provide inflation protection and low correlation with financial assets.
- Energy: WTI crude oil, natural gas (via USO, UNG)
- Metals: Gold, silver, copper
- Agriculture: Corn, wheat, soybeans
- Broad commodities: DJP, PDBC, COMT
Infrastructure
Infrastructure assets (toll roads, airports, utilities, energy pipelines) provide:
- Long-term contracted cash flows
- Inflation linkage (often regulated pricing)
- Low correlation with equities over full cycles
- Access via ETFs like IFRA, IGF, or PAVE
Cash and Cash Equivalents
Cash equivalents include money market funds, Treasury bills, and short-term certificates of deposit. Their role in a portfolio:
- Capital preservation
- Liquidity for rebalancing and opportunistic investing
- Dry powder for bear market purchases
- Drawback: Real returns are near zero or negative during inflationary periods
3. Asset Allocation Strategy Types
Strategic Asset Allocation (SAA)
Strategic Asset Allocation establishes a long-term target mix based on the investor's goals, risk tolerance, and time horizon. The portfolio is periodically rebalanced back to target.
Defining Your Policy Portfolio
The policy portfolio is the investor's long-term benchmark — the allocation that best matches their objectives. It is derived from:
- Investment horizon (longer = more equity capacity)
- Risk tolerance (subjective willingness to bear losses)
- Risk capacity (objective ability to absorb losses)
- Return requirements (needed to meet goals)
- Liquidity needs (upcoming cash flow requirements)
Classic SAA Examples
Aggressive (long horizon, high tolerance):
- 90% stocks (60% US, 20% international, 10% emerging)
- 10% bonds
Balanced (medium horizon):
- 60% stocks (40% US, 15% international, 5% emerging)
- 35% bonds
- 5% alternatives (gold, REITs)
Conservative (short horizon, low tolerance):
- 30% stocks
- 50% bonds
- 10% REITs
- 10% cash/short-term
Tactical Asset Allocation (TAA)
TAA allows dynamic adjustments around the strategic target based on market conditions, valuations, or economic outlook. The strategic target serves as the anchor, with tactical tilts typically limited to ±5 to 20%.
Common TAA Signals
- Cyclically adjusted P/E (CAPE/Shiller PE): High CAPE suggests lower future returns; underweight equities
- Credit spreads: Widening spreads signal stress; reduce risk
- Yield curve: Inverted curve historically precedes recession; reduce duration
- Momentum: Assets with recent outperformance tend to continue near-term
The Case Against TAA
Studies consistently show that most active managers and tactical allocators underperform simple strategic allocation over long periods. Timing is notoriously difficult. For most investors, a disciplined SAA with low-cost index funds outperforms tactical maneuvering after fees and taxes.
Life-Cycle Asset Allocation
Life-cycle (or age-based) allocation systematically reduces equity exposure as the investor ages, reflecting:
- Shorter time horizon to recover from losses
- Greater dependence on portfolio for income
- Reduced human capital (future earning power)
Age-Based Rules of Thumb
Traditional rule: Stock % = 100 - Age
Modern rule (longer lifespans): Stock % = 110 - Age or 120 - Age
Sample glide path:
- Age 25: 90% stocks, 10% bonds
- Age 40: 80% stocks, 20% bonds
- Age 55: 65% stocks, 35% bonds
- Age 65: 50% stocks, 50% bonds
- Age 75: 35% stocks, 65% bonds
Target Date Funds (TDFs)
TDFs automate the glide path. An investor choosing a 2050 Target Date Fund will hold an aggressive allocation today that automatically becomes more conservative as 2050 approaches. Major providers include Vanguard (Target Retirement series), Fidelity (Freedom series), and Schwab (Target Date Index series).
The Permanent Portfolio
Devised by investment analyst Harry Browne, the Permanent Portfolio divides assets equally among four quadrants, each designed to thrive in a different economic environment.
| Asset | Weight | Thrives When... |
|---|---|---|
| Stocks | 25% | Economy is growing |
| Long-term government bonds | 25% | Deflation / recession |
| Gold | 25% | Inflation / dollar weakness |
| Cash (T-bills) | 25% | Recession / tight monetary policy |
Performance Characteristics
- Very low volatility (often under 7% annualized)
- Positive returns in most years
- Significantly lags 100% equity portfolios in bull markets
- Ideal for risk-averse investors who prioritize sleep-well-at-night investing
The All-Weather Portfolio
Ray Dalio and Bridgewater Associates developed the All-Weather strategy based on the observation that four economic environments drive asset returns: growth rising/falling and inflation rising/falling.
Standard All-Weather Allocation
| Asset | Weight |
|---|---|
| US Stocks | 30% |
| Long-term US Treasuries (20+ yr) | 40% |
| Intermediate US Treasuries (7-10 yr) | 15% |
| Gold | 7.5% |
| Commodities | 7.5% |
The heavy bond allocation (55%) is counterintuitive but intentional: since stocks are ~3x more volatile than bonds, you need ~3x more bonds to achieve equal risk contribution. This is the Risk Parity principle.
Caveat: The All-Weather portfolio struggled in 2022's simultaneous rate hike and equity decline environment, demonstrating that no strategy works in all conditions.
Core-Satellite Strategy
The core-satellite approach divides the portfolio into two distinct components.
Core Portfolio (60-80% of assets)
- Low-cost, passive index funds tracking broad market benchmarks
- Goal: capture market returns efficiently
- Typical instruments: VTI (US total market), VXUS (international), BND (bonds)
- Expected to stay constant regardless of market conditions
Satellite Portfolio (20-40% of assets)
- Active or semi-active investments seeking alpha
- Factor tilts (value, momentum, small-cap, quality)
- Sector ETFs (technology, healthcare, energy)
- Thematic ETFs (clean energy, AI, robotics)
- Individual stocks the investor has high conviction in
- Alternative assets (private equity, hedge funds if accessible)
4. ETF-Based Portfolio Implementation
Selecting ETFs: Key Criteria
Expense Ratio The single most important factor for passive index ETFs. Even a 0.1% annual difference compounds dramatically over decades.
| ETF | Index | Expense Ratio |
|---|---|---|
| VOO | S&P 500 | 0.03% |
| SPY | S&P 500 | 0.09% |
| IVV | S&P 500 | 0.03% |
| VTI | US Total Market | 0.03% |
| VXUS | International ex-US | 0.07% |
| BND | US Aggregate Bond | 0.03% |
| IAU | Gold | 0.25% |
| GLD | Gold | 0.40% |
| VNQ | US REITs | 0.12% |
| VWO | Emerging Markets | 0.08% |
| QQQ | NASDAQ 100 | 0.20% |
Other Selection Criteria
- Assets under management (AUM): Larger funds have tighter spreads
- Tracking error: How closely the ETF follows its index
- Liquidity (bid-ask spread): Tighter spreads reduce transaction costs
- Issuer reputation: Vanguard, iShares (BlackRock), State Street (SPDR) are top tier
Sample Portfolio Constructions
Three-Fund Portfolio (Classic Simplicity)
- VTI: 60% (US Total Market)
- VXUS: 30% (International Total Market)
- BND: 10% (US Aggregate Bond)
Pros: Extreme simplicity, maximum diversification, ultra-low cost Cons: No explicit alternatives exposure, bond-light for conservative investors
Five-Asset Portfolio (Balanced)
- VTI: 40% (US stocks)
- VXUS: 20% (International stocks)
- BND: 25% (US bonds)
- IAU: 7.5% (Gold)
- VNQ: 7.5% (US REITs)
All-Weather ETF Implementation
- SPY / VOO: 30% (US Large-Cap)
- TLT: 40% (20+ Year Treasury)
- IEF: 15% (7-10 Year Treasury)
- GLD / IAU: 7.5% (Gold)
- DJP / PDBC: 7.5% (Commodities)
Permanent Portfolio ETF Implementation
- VTI: 25% (US stocks)
- TLT: 25% (Long-term Treasury)
- GLD: 25% (Gold)
- SHV / BIL: 25% (Short-term T-bills / Cash)
Tax-Efficient Asset Location
Different account types have different tax treatment. Optimal asset location places each investment in the most tax-efficient account.
Taxable Account (brokerage account) Best for: Tax-efficient assets
- Total market index ETFs (low turnover, qualified dividends)
- Municipal bonds (tax-exempt interest)
- Individual stocks (control over when to realize gains)
- Buy-and-hold positions
Tax-Deferred Account (Traditional IRA, 401k) Best for: High-income, high-turnover assets
- REITs (dividends taxed as ordinary income, deferred until withdrawal)
- Corporate bonds (interest income fully taxable)
- High-yield bonds
- Actively managed funds with high turnover
Tax-Free Account (Roth IRA) Best for: Highest expected growth assets
- Small-cap growth stocks
- Emerging market equities
- High-conviction individual stocks
- Assets you expect to grow most aggressively
5. Rebalancing Strategies
Why Rebalancing Matters
Without rebalancing, a portfolio drifts from its target allocation. After a prolonged equity bull market, an investor with a 60/40 target might find themselves holding 75% equities — far more risk than intended. Rebalancing restores the intended risk profile.
Rebalancing also enforces a contrarian discipline: selling outperforming assets and buying underperformers. While psychologically difficult, this systematically implements "buy low, sell high."
Calendar-Based Rebalancing
Rebalance at fixed time intervals regardless of drift.
Monthly rebalancing
- Pro: Closely maintains target allocation
- Con: High transaction costs and tax drag from frequent trading
- Best for: Tax-advantaged accounts with zero-commission trading
Quarterly rebalancing
- Pro: Good balance of precision and cost
- Con: Misses sharp intra-quarter moves
Annual rebalancing
- Pro: Lowest transaction costs and capital gains taxes
- Con: Portfolio can drift significantly between checkpoints
- Best for: Taxable accounts, buy-and-hold investors
Research Finding: Studies (Vanguard, Schwab) show annual or semi-annual rebalancing performs nearly as well as monthly rebalancing at far lower cost.
Threshold-Based (Band) Rebalancing
Rebalance only when an asset class drifts beyond a defined threshold.
Absolute bands Example: Target 60% stocks with ±5% band (55-65% range). Rebalance when stocks fall below 55% or exceed 65%.
Relative bands Example: Rebalance when any asset drifts more than 20% from target in relative terms. If stock target is 60%, rebalance when stocks fall below 48% or exceed 72% (60% ± 20% of 60%).
Choosing Band Width
| Band Width | Trade Frequency | Transaction Cost | Target Precision |
|---|---|---|---|
| ±5% | High | High | High |
| ±10% | Medium | Medium | Medium |
| ±20% | Low | Low | Low |
Most practitioners recommend ±5% absolute or ±20% relative as reasonable defaults.
Hybrid Approach
Combine calendar and threshold methods: check quarterly but only rebalance if a threshold has been breached. This prevents both neglect and over-trading.
Rebalancing with New Contributions
For investors regularly adding money, the most tax-efficient rebalancing method is directing new contributions to underweight asset classes. This achieves rebalancing without any selling — therefore no capital gains tax in taxable accounts.
Example: Monthly investing 1,000 to bonds until allocation is restored.
Tax-Loss Harvesting
Tax-loss harvesting (TLH) sells securities at a loss to offset capital gains elsewhere, reducing current-year taxes. The proceeds are immediately reinvested in a similar (but not identical) security to maintain market exposure.
Example
- You hold VTI down 12% in a taxable account
- Sell VTI, immediately buy ITOT (iShares Core S&P Total US Market ETF) — similar exposure
- Book the loss to offset other gains
- After 31 days (to avoid wash-sale rule), you may switch back to VTI if desired
Wash-Sale Rule: You cannot repurchase the same or "substantially identical" security within 30 days before or after the sale and still claim the loss.
6. Python Portfolio Optimization
Environment Setup
# Install required packages
# pip install numpy pandas yfinance scipy matplotlib seaborn
import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from scipy.optimize import minimize
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
# Configure plot style
plt.style.use('seaborn-v0_8-whitegrid')
TRADING_DAYS = 252
RISK_FREE_RATE = 0.04 # 4% annual risk-free rate (approximate 2024 T-bill rate)
Downloading Historical Data
# Define our portfolio universe
TICKERS = {
'SPY': 'S&P 500',
'QQQ': 'NASDAQ 100',
'VEA': 'Intl Developed',
'VWO': 'Emerging Markets',
'BND': 'US Bonds',
'TLT': 'Long-Term Treasuries',
'GLD': 'Gold',
'VNQ': 'US REITs',
'PDBC': 'Commodities',
}
def download_data(tickers, start='2015-01-01', end='2024-01-01'):
"""Download adjusted close prices for a list of tickers."""
print(f"Downloading data for {len(tickers)} tickers...")
raw = yf.download(list(tickers.keys()), start=start, end=end)
prices = raw['Adj Close'].dropna(how='all')
prices = prices.dropna() # Keep only complete rows
print(f"Downloaded {len(prices)} days of data ({prices.index[0].date()} to {prices.index[-1].date()})")
return prices
prices = download_data(TICKERS)
returns = prices.pct_change().dropna()
print(f"\nReturn matrix shape: {returns.shape}")
Asset Class Analysis
def analyze_assets(returns, tickers, trading_days=252, risk_free=0.04):
"""
Compute annualized statistics for each asset.
Returns a DataFrame with return, volatility, Sharpe ratio, and max drawdown.
"""
stats = []
for ticker in tickers:
if ticker not in returns.columns:
continue
r = returns[ticker]
ann_return = r.mean() * trading_days
ann_vol = r.std() * np.sqrt(trading_days)
sharpe = (ann_return - risk_free) / ann_vol
# Maximum drawdown
cum = (1 + r).cumprod()
rolling_max = cum.cummax()
drawdown = (cum - rolling_max) / rolling_max
max_dd = drawdown.min()
stats.append({
'Asset': tickers[ticker],
'Ann. Return': ann_return,
'Ann. Volatility': ann_vol,
'Sharpe Ratio': sharpe,
'Max Drawdown': max_dd
})
df = pd.DataFrame(stats).set_index('Asset')
return df
asset_stats = analyze_assets(returns, TICKERS, TRADING_DAYS, RISK_FREE_RATE)
print("\n=== Asset Class Statistics (Annualized) ===")
print(asset_stats.to_string(
float_format=lambda x: f"{x:.2%}" if abs(x) < 10 else f"{x:.2f}"
))
Efficient Frontier via Monte Carlo Simulation
def simulate_portfolios(returns, num_portfolios=10_000, risk_free=0.04):
"""
Generate random portfolios to approximate the efficient frontier.
Returns arrays of (volatility, return, sharpe) and a matrix of weights.
"""
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_assets = len(mean_returns)
port_returns = np.zeros(num_portfolios)
port_vols = np.zeros(num_portfolios)
port_sharpes = np.zeros(num_portfolios)
all_weights = np.zeros((num_portfolios, num_assets))
np.random.seed(42)
for i in range(num_portfolios):
# Random weights (long-only, sum to 1)
w = np.random.dirichlet(np.ones(num_assets))
all_weights[i] = w
ret = np.dot(w, mean_returns) * TRADING_DAYS
vol = np.sqrt(np.dot(w, np.dot(cov_matrix * TRADING_DAYS, w)))
sharpe = (ret - risk_free) / vol
port_returns[i] = ret
port_vols[i] = vol
port_sharpes[i] = sharpe
return port_returns, port_vols, port_sharpes, all_weights
port_ret, port_vol, port_sharpe, port_weights = simulate_portfolios(
returns, num_portfolios=10_000, risk_free=RISK_FREE_RATE
)
print(f"\nSimulated {len(port_ret):,} random portfolios")
print(f"Best Sharpe ratio found: {port_sharpe.max():.3f}")
print(f"Return at best Sharpe: {port_ret[np.argmax(port_sharpe)]:.2%}")
print(f"Volatility at best Sharpe: {port_vol[np.argmax(port_sharpe)]:.2%}")
Sharpe Ratio Optimization
def portfolio_metrics(weights, mean_returns, cov_matrix, risk_free=0.04):
"""Return annualized (return, volatility, Sharpe) for a weight vector."""
w = np.array(weights)
ret = np.dot(w, mean_returns) * TRADING_DAYS
vol = np.sqrt(np.dot(w, np.dot(cov_matrix * TRADING_DAYS, w)))
sharpe = (ret - risk_free) / vol
return ret, vol, sharpe
def maximize_sharpe(returns, risk_free=0.04):
"""Find the maximum Sharpe ratio portfolio using scipy optimization."""
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_assets = len(mean_returns)
tickers = returns.columns.tolist()
def neg_sharpe(weights):
_, _, sharpe = portfolio_metrics(weights, mean_returns, cov_matrix, risk_free)
return -sharpe
constraints = [{'type': 'eq', 'fun': lambda w: w.sum() - 1.0}]
bounds = [(0.0, 1.0)] * num_assets
x0 = np.array([1.0 / num_assets] * num_assets)
result = minimize(
neg_sharpe, x0,
method='SLSQP',
bounds=bounds,
constraints=constraints,
options={'maxiter': 2000, 'ftol': 1e-9}
)
return result.x, tickers
opt_weights, opt_tickers = maximize_sharpe(returns, RISK_FREE_RATE)
mean_ret = returns.mean()
cov_mat = returns.cov()
opt_ret, opt_vol, opt_sharpe = portfolio_metrics(
opt_weights, mean_ret, cov_mat, RISK_FREE_RATE
)
print("\n=== Maximum Sharpe Ratio Portfolio ===")
print(f"Expected Annual Return: {opt_ret:.2%}")
print(f"Annual Volatility: {opt_vol:.2%}")
print(f"Sharpe Ratio: {opt_sharpe:.3f}")
print("\nWeights:")
for ticker, w in zip(opt_tickers, opt_weights):
if w > 0.001:
label = TICKERS.get(ticker, ticker)
print(f" {label:22s}: {w:.1%}")
Minimum Variance Portfolio
def minimize_variance(returns):
"""Find the minimum variance portfolio."""
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_assets = len(mean_returns)
def portfolio_vol(weights):
w = np.array(weights)
return np.sqrt(np.dot(w, np.dot(cov_matrix * TRADING_DAYS, w)))
constraints = [{'type': 'eq', 'fun': lambda w: w.sum() - 1.0}]
bounds = [(0.0, 1.0)] * num_assets
x0 = np.array([1.0 / num_assets] * num_assets)
result = minimize(
portfolio_vol, x0,
method='SLSQP',
bounds=bounds,
constraints=constraints
)
return result.x
minvar_weights = minimize_variance(returns)
mv_ret, mv_vol, mv_sharpe = portfolio_metrics(
minvar_weights, mean_ret, cov_mat, RISK_FREE_RATE
)
print("\n=== Minimum Variance Portfolio ===")
print(f"Expected Annual Return: {mv_ret:.2%}")
print(f"Annual Volatility: {mv_vol:.2%}")
print(f"Sharpe Ratio: {mv_sharpe:.3f}")
print("\nWeights:")
for ticker, w in zip(opt_tickers, minvar_weights):
if w > 0.001:
label = TICKERS.get(ticker, ticker)
print(f" {label:22s}: {w:.1%}")
Plotting the Efficient Frontier
def plot_efficient_frontier(port_ret, port_vol, port_sharpe,
opt_w, mv_w, mean_ret, cov_mat, risk_free=0.04):
"""Visualize the efficient frontier with key portfolios marked."""
fig, ax = plt.subplots(figsize=(12, 8))
# Scatter of random portfolios, colored by Sharpe ratio
scatter = ax.scatter(
port_vol, port_ret,
c=port_sharpe, cmap='viridis', alpha=0.4, s=8
)
cbar = plt.colorbar(scatter, ax=ax)
cbar.set_label('Sharpe Ratio', fontsize=12)
# Mark the maximum Sharpe ratio portfolio
ret_o, vol_o, _ = portfolio_metrics(opt_w, mean_ret, cov_mat, risk_free)
ax.scatter(vol_o, ret_o, marker='*', color='red', s=600, zorder=5,
label=f'Max Sharpe ({ret_o:.1%} / {vol_o:.1%})')
# Mark the minimum variance portfolio
ret_m, vol_m, _ = portfolio_metrics(mv_w, mean_ret, cov_mat, risk_free)
ax.scatter(vol_m, ret_m, marker='D', color='orange', s=200, zorder=5,
label=f'Min Variance ({ret_m:.1%} / {vol_m:.1%})')
# Individual assets
for i, ticker in enumerate(returns.columns):
a_ret = mean_ret[ticker] * TRADING_DAYS
a_vol = returns[ticker].std() * np.sqrt(TRADING_DAYS)
ax.scatter(a_vol, a_ret, marker='s', color='gray', s=80, zorder=4)
ax.annotate(TICKERS.get(ticker, ticker),
(a_vol, a_ret), textcoords='offset points',
xytext=(5, 5), fontsize=8)
ax.xaxis.set_major_formatter(mticker.PercentFormatter(xmax=1, decimals=0))
ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1, decimals=0))
ax.set_xlabel('Annual Volatility (Risk)', fontsize=13)
ax.set_ylabel('Annual Expected Return', fontsize=13)
ax.set_title('Efficient Frontier (Monte Carlo Simulation)', fontsize=15)
ax.legend(fontsize=11)
plt.tight_layout()
plt.savefig('efficient_frontier_en.png', dpi=150)
plt.show()
print("Efficient frontier plot saved.")
plot_efficient_frontier(
port_ret, port_vol, port_sharpe,
opt_weights, minvar_weights,
mean_ret, cov_mat, RISK_FREE_RATE
)
Monte Carlo Retirement Simulation
def monte_carlo_retirement(
initial_investment: float,
monthly_contribution: float,
weights: np.ndarray,
mean_returns: pd.Series,
cov_matrix: pd.DataFrame,
years: int = 30,
num_simulations: int = 1000,
annual_withdrawal: float = 0.0
) -> dict:
"""
Simulate portfolio growth over a retirement horizon.
Supports both accumulation (monthly_contribution > 0) and
distribution (annual_withdrawal > 0) phases.
"""
days = years * TRADING_DAYS
port_daily_mean = np.dot(weights, mean_returns)
port_daily_std = np.sqrt(np.dot(weights, np.dot(cov_matrix, weights)))
daily_withdrawal = annual_withdrawal / TRADING_DAYS
results = np.zeros((days + 1, num_simulations))
results[0] = initial_investment
np.random.seed(0)
for sim in range(num_simulations):
for day in range(1, days + 1):
daily_ret = np.random.normal(port_daily_mean, port_daily_std)
monthly_add = monthly_contribution if (day % 21 == 0) else 0
results[day, sim] = (
results[day - 1, sim] * (1 + daily_ret)
+ monthly_add
- daily_withdrawal
)
if results[day, sim] < 0:
results[day, sim] = 0 # Ruin — portfolio depleted
final = results[-1]
ruin_rate = (final == 0).mean()
return {
'simulation_paths': results,
'final_values': final,
'median': np.median(final),
'p25': np.percentile(final, 25),
'p75': np.percentile(final, 75),
'p5': np.percentile(final, 5),
'p95': np.percentile(final, 95),
'ruin_rate': ruin_rate,
}
# Accumulation phase: invest $10,000 today + $500/month for 30 years
sim_result = monte_carlo_retirement(
initial_investment=10_000,
monthly_contribution=500,
weights=opt_weights,
mean_returns=mean_ret,
cov_matrix=cov_mat,
years=30,
num_simulations=1000
)
print("\n=== 30-Year Retirement Accumulation Simulation ===")
print(f"Initial Investment: $10,000 + $500/month")
print(f"Median outcome: ${sim_result['median']:>12,.0f}")
print(f"75th percentile: ${sim_result['p75']:>12,.0f}")
print(f"25th percentile: ${sim_result['p25']:>12,.0f}")
print(f"5th percentile: ${sim_result['p5']:>12,.0f}")
print(f"95th percentile: ${sim_result['p95']:>12,.0f}")
# Visualization
fig, axes = plt.subplots(1, 2, figsize=(16, 7))
# Simulation paths
ax1 = axes[0]
paths = sim_result['simulation_paths']
years_axis = np.linspace(0, 30, paths.shape[0])
for i in range(0, min(200, paths.shape[1])):
ax1.plot(years_axis, paths[:, i] / 1e6, alpha=0.07, color='steelblue', lw=0.8)
ax1.plot(years_axis, np.median(paths, axis=1) / 1e6,
color='red', lw=2.5, label='Median')
ax1.plot(years_axis, np.percentile(paths, 5, axis=1) / 1e6,
color='orange', lw=1.5, linestyle='--', label='5th percentile')
ax1.set_xlabel('Years', fontsize=12)
ax1.set_ylabel('Portfolio Value ($M)', fontsize=12)
ax1.set_title('Monte Carlo Simulation Paths (30 Years)', fontsize=13)
ax1.legend()
# Distribution of final values
ax2 = axes[1]
ax2.hist(sim_result['final_values'] / 1e6, bins=60,
color='steelblue', edgecolor='white', alpha=0.8)
ax2.axvline(sim_result['median'] / 1e6, color='red',
linestyle='--', lw=2, label='Median')
ax2.axvline(sim_result['p5'] / 1e6, color='orange',
linestyle='--', lw=2, label='5th percentile')
ax2.set_xlabel('Final Portfolio Value ($M)', fontsize=12)
ax2.set_ylabel('Frequency', fontsize=12)
ax2.set_title('Distribution of 30-Year Final Values', fontsize=13)
ax2.legend()
plt.tight_layout()
plt.savefig('monte_carlo_retirement.png', dpi=150)
plt.show()
Correlation Heatmap
fig, ax = plt.subplots(figsize=(10, 8))
corr = returns.corr()
labels = [TICKERS.get(t, t) for t in corr.columns]
corr.columns = labels
corr.index = labels
mask = np.triu(np.ones_like(corr, dtype=bool), k=1)
sns.heatmap(
corr, annot=True, fmt='.2f', cmap='RdYlGn',
vmin=-1, vmax=1, center=0, ax=ax,
linewidths=0.5, annot_kws={'size': 9}
)
ax.set_title('Asset Class Correlation Matrix', fontsize=14)
plt.tight_layout()
plt.savefig('correlation_heatmap_en.png', dpi=150)
plt.show()
print("Correlation heatmap saved.")
7. Quiz and Self-Assessment
Quiz 1: What is the primary benefit of diversification according to Modern Portfolio Theory?
Answer: Combining assets with correlations below 1.0 reduces overall portfolio risk below the weighted average of individual asset risks — without necessarily reducing expected return.
Explanation: MPT mathematically proves that as long as two assets are not perfectly correlated (ρ less than 1.0), combining them in a portfolio reduces total variance. This is called the diversification effect or the "free lunch" of investing. The lower the correlation, the greater the risk reduction. When ρ = -1.0, it is theoretically possible to construct a zero-risk portfolio. In practice, most asset pairs have correlations between 0 and 0.7, providing meaningful but incomplete diversification benefits.
Quiz 2: Why does the All-Weather Portfolio hold 55% in bonds? Isn't that excessively conservative?
Answer: The 55% bond allocation is intentional and based on risk parity. Since stocks are roughly 3 times more volatile than bonds, you need about 3 times as much in bonds to achieve equal risk contribution from each asset. The goal is balanced risk, not balanced capital.
Explanation: Risk parity allocates based on risk contribution, not dollar amount. If stocks have 15% annual volatility and bonds have 5%, a 50/50 dollar split means stocks contribute ~90% of total portfolio risk. To balance risk contributions equally, you need roughly 75% bonds to 25% stocks. The All-Weather portfolio blends four economic quadrants, not just two asset classes, but the same logic applies. Critics point out that this heavy bond allocation caused significant losses in 2022 when both stocks and bonds fell simultaneously — a rare scenario the model underweighted.
Quiz 3: What is the wash-sale rule and how does it affect tax-loss harvesting?
Answer: The wash-sale rule (IRS rule) prohibits claiming a tax loss if you repurchase the same or "substantially identical" security within 30 days before or after the sale. It prevents investors from booking artificial losses while maintaining the same market exposure.
Explanation: To harvest a loss while maintaining market exposure, investors must buy a different but similar fund. For example, selling VTI (Vanguard Total Market) and buying ITOT (iShares Total US Market) maintains essentially the same economic exposure but avoids the wash-sale rule because they track different indexes. After 31 days, you can switch back to the original security. Important: The wash-sale rule applies within the same taxpayer's accounts, including IRAs. It does not apply to gains — you can always sell for a gain and immediately repurchase.
Quiz 4: What are the key limitations of the Sharpe ratio as a portfolio performance measure?
Answer: The Sharpe ratio assumes normally distributed returns (symmetric), uses standard deviation which penalizes upside volatility equally with downside, can be manipulated through leverage or option strategies, and fails to capture tail risk and drawdown magnitude.
Explanation: Real asset returns exhibit fat tails (kurtosis) and negative skewness — extreme negative returns occur far more often than a normal distribution would predict. A strategy that earns steady small gains but suffers rare catastrophic losses can have a high Sharpe ratio despite being very risky. Alternative measures include: (1) Sortino ratio — uses only downside deviation, better for asymmetric strategies; (2) Calmar ratio — return divided by maximum drawdown; (3) Omega ratio — probability-weighted ratio of gains to losses above/below a threshold. No single metric fully captures portfolio quality.
Quiz 5: For a 35-year-old long-term investor, is calendar-based or threshold-based rebalancing generally more tax-efficient?
Answer: Threshold-based rebalancing is generally more tax-efficient because it only triggers trades when drift is large enough to matter, resulting in fewer taxable events. The optimal approach combines directing new contributions to underweight assets with threshold rebalancing.
Explanation: Calendar rebalancing trades on schedule regardless of whether allocation has meaningfully drifted, creating unnecessary taxable events. Threshold rebalancing only rebalances when drift exceeds a predefined band (e.g., ±5%), so in a year with limited drift, no taxable trades occur. Additionally, for accumulation-phase investors, directing all new contributions toward underweight asset classes can often restore balance without any selling. Vanguard research found that for most investors, annual or threshold-triggered rebalancing achieves 90%+ of the theoretical benefit of monthly rebalancing at a fraction of the cost.
Conclusion
Asset allocation is the master decision of investing. The key principles to remember:
- Diversify across asset classes: Combine assets with low correlations to reduce risk without sacrificing expected return.
- Match allocation to your situation: Time horizon, risk tolerance, income stability, and goals should drive your policy portfolio.
- Minimize costs: Every basis point saved in fees compounds into significantly more wealth over decades.
- Rebalance systematically: Restore target weights periodically using the most tax-efficient method available.
- Use tax-advantaged accounts: Maximize IRA, 401(k), and other tax-sheltered accounts before investing in taxable accounts.
- Stay the course: The biggest threat to long-term investing is emotional decision-making during market downturns.
The best portfolio is one you can stick with through market cycles — not the theoretically optimal one you abandon during a crash. Start simple, stay consistent, and let compounding do the heavy lifting.
Disclaimer: This article is for educational purposes only and does not constitute investment advice. All investments involve risk, including the possible loss of principal. Consult a qualified financial advisor before making investment decisions.