Returns, Diversification, and Portfolio Risk
A price rises from 100 to 110, then falls to 99. The two returns are 10% and −10%, yet the investment loses 1% overall. Put two assets into a portfolio and a second distinction appears: returns combine using beginning-of-period weights, but volatility does not. These distinctions let us turn prices into returns and calculate the risk of a portfolio.
All prices, returns, and portfolio parameters below are hypothetical; amounts use one currency unit. We ignore trading costs and taxes until the section on costs, and assume no external deposits or withdrawals during a holding period. For option payoffs and pricing assumptions, see Financial Markets and Mathematical Modeling; for worked replication examples, continue to No-Arbitrage and Binomial Option Pricing.
From prices to returns
Let be the initial price and the final price. Without distributions, the simple return and log return are:
A log return requires . When an asset becomes worthless, its simple return is −100% and its log return has no finite value. Prices must use consistent units after changes such as stock splits, or a mechanical adjustment can be mistaken for a gain or loss.
Across periods, multiply growth factors. If each period's proceeds remain invested, wealth after periods is:
For 100 → 110 → 99, . The arithmetic mean return is 0%, but the geometric mean per period is , and the sum of log returns is approximately −0.010050. The arithmetic mean describes the average single-period return; the geometric mean describes compounded growth along this path. Two periods need not mean two years: specify their length before calling a result annualized.
Log returns add across time, while simple portfolio returns are weighted across assets. A portfolio's log return generally differs from the weighted average of its assets' log returns. The two shortcuts cannot be used interchangeably.
Total return, distributions, and purchasing power
Stock returns can come from both price appreciation and dividends. The SEC's investor education page also explains that nominal growth can lag inflation. Comparing investments requires accounting for distributions and purchasing power.
Let be a distribution per unit received at the end of the period, with no other cash flows during that period. Total return is:
Buy at 100, finish at 98, and receive a dividend of 5. The price return is −2%, but total return is . If a distribution arrives earlier and is reinvested immediately, calculate wealth using the actual timing and reinvestment price. Do not add dividends again to a total-return series that already includes their reinvestment.
For inflation over the same period, so that the price index remains positive, the real return measures the change in purchasing power:
At 2% inflation, the example's real return is . Subtracting 2% from 3% gives 1%, an approximation for small changes. Multi-period comparisons likewise need total returns and price-index changes for the same currency and interval.
Weight drift and rebalancing
The weight is the fraction of initial portfolio value invested in asset . A fully invested, long-only portfolio has and . With no transfers between asset positions or external cash flows during the period, and distributions reinvested in their respective assets, portfolio simple return uses asset total returns measured consistently:
If distributions are held as cash, include cash as a separate position when calculating the next period's weights.
Suppose initial wealth is 10000, with 60% in A and 40% in B. Over one year, A returns 10% and B returns −5%:
Portfolio return is . Without trading, A starts the next year at of wealth. Its weight is no longer 60% when calculating the next period's return.
The SEC's explanation of rebalancing describes adjustments to restore an asset allocation. Here that means selling 360 of A and buying 360 of B. A calendar schedule and a weight-deviation threshold are different trading rules. Specify the rule before comparing net returns and risk; restoring weights alone does not guarantee a higher return next period.
Covariance and diversification
Markowitz's Portfolio Selection (1952) frames portfolio choice as a trade-off between expected return and return variance. The original paper, available as a readable PDF, explains why diversification depends on covariance, not just the number of securities held. For the statistical definitions, see Statistics and Probability.
Let the random return vector be , its mean , and its covariance matrix . For weights chosen before the period:
Volatility is the standard deviation of returns, . When both assets have positive standard deviations, , where is their correlation. Thus:
Keep the 60/40 weights, but now use hypothetical forward-looking model inputs, all for one year:
These are not estimates from the realized returns in the previous section. Set , so covariance is :
Expected return is 6.4% and volatility approximately 13.5647%. Directly weighting the two volatilities gives 16%, which is correct here only under perfect positive correlation. Hold the weights and individual volatilities fixed and change correlation:
Diversification lowers volatility below the weighted 16%, but the result can still exceed B's standalone 10%. Even perfect negative correlation does not remove risk at these weights, because the weighted volatility exposures do not cancel.
Keep the sampling interval explicit when estimating volatility. If log returns have equal variances and zero covariance between every pair of periods, the standard deviation of their sum over periods equals the single-period standard deviation times . These conditions are sufficient, not necessary: temporal covariances can also cancel. This scaling does not directly give the exact annual volatility of compounded simple returns.
Volatility, drawdown, and downside losses
Volatility counts deviations both above and below the mean. It does not describe the maximum loss or the order of losses, and mean and variance alone do not generally determine the probability of losing money.
Drawdown measures the distance below a previous wealth peak. For a total-return wealth path starting at without external cash flows, let . Express drawdown as a nonnegative loss fraction:
Wealth finishes 12% above its starting value, yet maximum drawdown along the way is 20%. Recovering from 88 to the old peak of 110 requires a 25% gain, rather than 20%. Deposits mechanically increase an account balance; with external cash flows, use a return index that removes their effect when calculating drawdown.
A stress scenario makes downside exposure explicit. If A loses 30% and B loses 10% in the same year, a 60/40 portfolio returns −22%, losing 2200 on initial wealth of 10000. This calculation assigns no probability to the scenario. Nor does model volatility of 13.5647% put a ceiling on losses. Estimating loss probabilities or average losses beyond a threshold requires further assumptions about the tail distribution or scenario probabilities.
Mean–variance optimization and estimation sensitivity
The CVX portfolio-optimization course gives a single-period mean–variance objective: expected return minus a variance penalty. Its long-only version is:
The parameter controls the model's trade-off between return and variance. Mean and covariance must use the same horizon, with returns expressed as decimals. Changing to percentage units changes the relative scale of the two terms, so the same cannot simply be retained. With a positive-semidefinite covariance matrix, the objective is concave and these constraints form a convex feasible set; convex optimization can find a global optimum. The mean–variance efficient frontier consists of feasible portfolios that no other feasible portfolio dominates in expected return and variance. It changes with inputs and constraints.
For the covariance matrix above, write and . Expanding variance gives:
To minimize variance alone, set the derivative . This gives : 12.5% in A and 87.5% in B. Expected returns do not enter this solution.
To maximize the return-minus-variance objective instead, set , differentiate with respect to , and enforce :
Reducing only A's expected return by 2 percentage points changes the allocation by 25 percentage points. An accurate solution does not make the inputs accurate. Sample means, covariances, and correlations change with the observation window; relationships under a common shock can differ from those in ordinary periods. Perturb expected returns, change the covariance-estimation window, and add position caps to see whether allocations remain stable. Minimum variance avoids estimating means but still depends on estimated covariance.
Costs, liquidity, and model boundaries
The course also includes transaction-cost penalties based on changes in weights. A linear version is:
Use the already-drifted, pre-trade weights for . Each is the cost per unit of value bought or sold. Both weight vectors here are normalized by pre-trade wealth, so is a fraction of that wealth and target amounts are before fees. Subtracting from the return objective, or constraining total trading, can change the original optimal weights. Targets defined as weights of wealth after fees also require costs in the budget constraint.
The rebalancing example buys and sells 360 each. At a fee of 0.1% on each side, estimated cost is . This charges on the sum of purchases and sales. Halving the total traded value before applying the same fee rate would count only half the cost. The table's targets of 6240 and 4160 are before fees; when fees come out of the portfolio, recompute targets and trades using wealth after costs.
A fixed linear rate does not capture changing bid–ask spreads, market impact, or an inability to execute promptly. The SEC's liquidity explanation highlights trading speed and price impact; its order guide also notes that the last-traded price need not be a market order's execution price. In illiquid markets, a quoted price may not be available for the whole order. A requirement to sell soon calls for limits on positions and tradable amounts. Taxes, financing costs, and cash needs over multiple periods also change the feasible plan.
Mean–variance retains the first two moments over one horizon. Tail losses, drawdown paths, changing parameters, and execution constraints need further modeling. Compare a portfolio's total-return path, correlation assumptions, stress losses, and trading plan after costs together. The Quantitative Finance overview leads onward to options and macro scenarios.
Reproduce the calculations in Python
Save the code as portfolio_example.py and run python3 portfolio_example.py with Python 3.8 or later. The standard-library documentation records that math.prod was added in Python 3.8. The optimization uses the analytical solution with the fixed covariance matrix above; the remaining calculations reproduce compounding, real returns, rebalancing, diversification, drawdown, and stress losses.
returns must be a nonempty sequence of equal-length periods' returns, all finite and greater than −1, so that log returns are finite; otherwise the code raises ValueError. Positive trade amounts mean purchases and negative amounts mean sales. Estimated fees use absolute traded amounts.
from math import isfinite, log1p, prod, sqrt
returns = [0.10, -0.10]
if not returns or any(not isfinite(r) or r <= -1 for r in returns):
raise ValueError("returns must be nonempty and finite, with each return > -1")
growth = prod(1 + r for r in returns)
print(f"compound={growth - 1:.4%}; log_sum={sum(log1p(r) for r in returns):.6f}")
print(f"arithmetic={sum(returns) / len(returns):.4%}; geometric={growth**(1 / len(returns)) - 1:.4%}")
total_return = (98 + 5) / 100 - 1
print(f"total={total_return:.4%}; real={(1 + total_return) / 1.02 - 1:.4%}")
holdings = [6000 * 1.10, 4000 * 0.95]
wealth = sum(holdings)
trade_a = 0.60 * wealth - holdings[0]
trade_b = -trade_a
print(f"wealth={wealth:.2f}; return={wealth / 10000 - 1:.4%}; weight_A={holdings[0] / wealth:.4%}")
print(f"trade_A={trade_a:.2f}; trade_B={trade_b:.2f}; estimated_fee={(abs(trade_a) + abs(trade_b)) * 0.001:.2f}")
sigma_a, sigma_b = 0.20, 0.10
w = 0.60
for rho in [1.0, 0.25, 0.0, -1.0]:
variance = (w * sigma_a)**2 + ((1 - w) * sigma_b)**2
variance += 2 * w * (1 - w) * rho * sigma_a * sigma_b
print(f"rho={rho:.2f}; variance={variance:.6f}; volatility={sqrt(variance):.4%}")
cov = 0.25 * sigma_a * sigma_b
den = sigma_a**2 + sigma_b**2 - 2 * cov
x_min = (sigma_b**2 - cov) / den
print(f"min_variance_weight_A={x_min:.4%}")
for mu_a in [0.08, 0.06]:
mu_b, gamma = 0.04, 1.0
x = ((mu_a - mu_b) / (2 * gamma) + sigma_b**2 - cov) / den
x = min(1.0, max(0.0, x))
print(f"mu_A={mu_a:.2%}; optimal_weight_A={x:.4%}")
path = [100, 110, 88, 99, 112]
peak, max_drawdown = path[0], 0.0
for value in path:
peak = max(peak, value)
max_drawdown = max(max_drawdown, 1 - value / peak)
print(f"max_drawdown={max_drawdown:.4%}; recovery={110 / 88 - 1:.4%}")
stress = 0.60 * (-0.30) + 0.40 * (-0.10)
print(f"stress_return={stress:.4%}; stress_loss={-10000 * stress:.2f}")
compound=-1.0000%; log_sum=-0.010050
arithmetic=0.0000%; geometric=-0.5013%
total=3.0000%; real=0.9804%
wealth=10400.00; return=4.0000%; weight_A=63.4615%
trade_A=-360.00; trade_B=360.00; estimated_fee=0.72
rho=1.00; variance=0.025600; volatility=16.0000%
rho=0.25; variance=0.018400; volatility=13.5647%
rho=0.00; variance=0.016000; volatility=12.6491%
rho=-1.00; variance=0.006400; volatility=8.0000%
min_variance_weight_A=12.5000%
mu_A=8.00%; optimal_weight_A=62.5000%
mu_A=6.00%; optimal_weight_A=37.5000%
max_drawdown=20.0000%; recovery=25.0000%
stress_return=-22.0000%; stress_loss=2200.00