Linear Algebra for Quantitative Finance › Matrices in Finance
Quantitative FinanceAll chapters Linear Algebra for Quantitative Finance › Matrices in FinanceOne section · Sections in this chapter3 / 9 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
A matrix is a rectangular array of numbers. While vectors represent single entities (one portfolio, one day of returns), matrices represent collections and relationships. These include return history across time, covariances between assets, and transformations between coordinate systems.
The jump from vectors to matrices is conceptually significant. A vector captures one snapshot, such as today's returns or a single portfolio's weights. A matrix can store an entire dataset or a specified set of pairwise summaries. When we write down a covariance matrix, we're encoding each asset's variance and every pairwise covariance in the investment universe. When we write down a return matrix, we're capturing the complete history of how multiple assets performed over multiple time periods. This compression of information into a structured rectangular array is what makes quantitative finance computationally tractable.
Matrix Fundamentals
An matrix has rows and columns. In finance, we commonly organize data with rows as time periods and columns as assets:
Here is the return of asset on day . This matrix contains 4 days of returns for 3 assets.
This chapter uses time as rows and assets as columns. Under that convention, each row represents the cross-section of the represented asset universe at one moment, while each column represents the complete time series of one asset. Extracting a row gives you all represented assets' returns on a specific day; extracting a column gives you one asset's return history. Other sources and libraries may use the transpose, so check the documented orientation before applying a matrix operation.
# Simulated return matrix: 4 days, 3 assets
# Each row is a day, each column is an asset
return_matrix = np.array(
[
[0.02, -0.01, 0.015], # Day 1
[0.01, 0.02, -0.005], # Day 2
[-0.015, 0.005, 0.01], # Day 3
[0.005, -0.005, 0.02], # Day 4
]
)Return matrix (4 days × 3 assets): [[ 0.02 -0.01 0.015] [ 0.01 0.02 -0.005] [-0.015 0.005 0.01 ] [ 0.005 -0.005 0.02 ]] Shape: (4, 3) Day 2 returns (row 1): [ 0.01 0.02 -0.005] Asset 3 returns (column 2): [ 0.015 -0.005 0.01 0.02 ]
Matrix Multiplication
Matrix multiplication is the workhorse operation of linear algebra. For matrices (size ) and (size ), the product is an matrix where:
where:
- : element in row , column of the result matrix
- : element in row , column of matrix
- : element in row , column of matrix
Each element of the result is a dot product of a row from with a column from .
Each element of the result shows how much the -th row of aligns with the -th column of . In financial terms, when multiplying a return matrix by a weight vector, each resulting element aggregates the weighted contributions of all assets for that time period. You can think of matrix multiplication as performing many dot products simultaneously. The entry of the product answers the question "how does row of the first matrix relate to column of the second?"
This interpretation illuminates why matrix multiplication has the dimensional requirements it does. The dot product requires vectors of equal length, so for each row-column pair to produce a dot product, the row length (number of columns in ) must equal the column length (number of rows in ). The result matrix takes its row count from and its column count from because we compute one number for each possible row-column pairing.
For matrix multiplication to be valid, the number of columns in must equal the number of rows in . The result has the number of rows from and columns from : .
A financial application is computing portfolio returns across multiple days. If is a matrix of simple returns ( days, assets) and is an weight vector, then performs one dot product per day. These are portfolio simple returns when the stated weights apply at the beginning of every day, as in a portfolio rebalanced between days without modeled trading costs. A buy-and-hold allocation generally has different beginning weights after prices change, so its weights must be updated for each period. The result has shape in this column-vector notation:
# Portfolio returns across multiple days via matrix multiplication
weights = np.array([0.4, 0.35, 0.25])
# Matrix-vector multiplication: (4×3) @ (3,) = (4,)
portfolio_returns = return_matrix @ weightsDaily portfolio returns: Day 1: +0.0083 (+0.83%) Day 2: +0.0097 (+0.97%) Day 3: -0.0018 (-0.18%) Day 4: +0.0053 (+0.53%) Mean portfolio return: 0.0054 Portfolio volatility: 0.0044
The Covariance Matrix
For real-valued asset returns with finite second moments, the covariance matrix captures how assets move together. For assets, it's an symmetric matrix where element is the covariance between assets and :
where:
- : the element of the covariance matrix
- : returns of assets and
- : expected (mean) returns of assets and
- : the expectation operator
The formula shows what covariance measures: we're looking at the product of deviations from the mean. When asset is above its average and asset is also above its average, the product is positive. When both are below average, the product is again positive. But when one is above and the other below, the product is negative. By averaging these products across many observations, covariance measures positive or negative linear co-movement. Its absolute magnitude depends on the return scale, so a small covariance alone does not establish weak linear association; compare it with the product of the standard deviations, or use correlation. Zero covariance does not imply independence without additional assumptions; for example, a variable and its square can be dependent while having zero covariance under a symmetric distribution.
The diagonal elements are variances of individual assets. The off-diagonal elements measure co-movement. Positive covariance means assets tend to move together. Negative covariance means they move oppositely.
# Compute covariance matrix from return data
# Use one trading year of simulated observations for a more stable illustration
np.random.seed(42)
n_days = 252 # One trading year
n_assets = 3
# Generate correlated returns
mean_returns = np.array([0.0005, 0.0003, 0.0004]) # Daily means
volatilities = np.array([0.02, 0.015, 0.025]) # Daily vols
# True correlation structure
correlation = np.array([[1.0, 0.6, 0.3], [0.6, 1.0, 0.4], [0.3, 0.4, 1.0]])
# Convert correlation to covariance
true_cov = np.outer(volatilities, volatilities) * correlation
# Generate returns from multivariate normal
returns_data = np.random.multivariate_normal(mean_returns, true_cov, n_days)
# Estimate covariance matrix from data
sample_cov = np.cov(returns_data, rowvar=False)The output uses the conventional annualized daily-volatility proxy: daily standard deviation multiplied by . This equals the standard deviation of an additive 252-day return sum when daily variance is constant and cross-day covariances are zero, as in this independent simulation. It is not the exact standard deviation of compounded annual simple returns.
Sample covariance matrix (×10,000 for readability): [[3.4765 1.4642 0.9198] [1.4642 2.1172 0.8783] [0.9198 0.8783 5.4973]] Volatilities (annualized): Asset 1: 29.60% Asset 2: 23.10% Asset 3: 37.22% Correlation matrix: [[1. 0.54 0.21 ] [0.54 1. 0.257] [0.21 0.257 1. ]]

Portfolio Variance: The Quadratic Form
Portfolio variance demonstrates the power of matrix notation. For portfolio weights fixed over the modeled return distribution and an asset covariance matrix for that same distribution, the portfolio variance is:
where:
- : the variance of the portfolio's returns
- : the vector of portfolio weights
- : the transpose of (a row vector)
- : the covariance matrix of asset returns
This compact formula packs a lot of computation: it accounts for each asset's variance and all pairwise covariances, weighted by the portfolio allocations. The expression is called a quadratic form because if you expand it, you get a polynomial where each term involves products of two weights. It's quadratic in the portfolio allocations.
Expanding for two assets:
where:
- : the variances of assets 1 and 2
- : the covariance between assets 1 and 2
The first two terms are variance contributions from each asset. The third term is , so its sign depends on both covariance and weights. Negative covariance lowers variance relative to zero covariance when the nonzero weights have the same sign; for opposite-sign positions, that effect reverses.
For nonnegative weights summing to one, portfolio variance is no greater than the weighted average of the individual variances. With both weights positive and covariance below the geometric mean of positive individual variances, this inequality is strict. The code below uses a different benchmark: the weighted average of individual volatilities. That is the portfolio volatility when all positively weighted, nonzero-volatility assets are perfectly positively correlated. Actual portfolio volatility is no greater than this benchmark, and is strictly lower if at least one such pair has correlation below one. The variance and volatility comparisons should not be interchanged.
The matrix formula has the same form for any number of assets. For 500 stocks, it remains while the ordered double sum contains 250,000 terms: 500 variance terms and 249,500 off-diagonal terms. Because the covariance matrix is symmetric, only 125,250 entries are unique. Compact notation keeps the calculation manageable as a portfolio grows from a toy example to a production system.
# Portfolio variance calculation
weights = np.array([0.4, 0.35, 0.25])
# Using the quadratic form
portfolio_variance = weights @ sample_cov @ weights
portfolio_volatility = np.sqrt(portfolio_variance)
# Conventional annualized daily-volatility proxy, as defined above
annual_vol = portfolio_volatility * np.sqrt(252)Portfolio weights: [0.4 0.35 0.25] Daily portfolio variance: 0.00019068 Daily portfolio volatility: 1.3809% Annualized volatility: 21.92% Weighted average volatility (no diversification): 29.23% Diversification benefit: 7.31 percentage points

The portfolio volatility is lower than the weighted average of individual volatilities because the assets are imperfectly correlated. This is the mathematical basis of diversification.
Matrix Transpose and Special Matrices
The transpose of matrix , written , flips rows and columns: .
Several special matrix types appear frequently in finance:
- Symmetric matrices: . Covariance matrices are always symmetric. This property reflects a fundamental reality: the covariance between assets A and B must equal the covariance between B and A, since we're measuring the same relationship from both directions.
- Diagonal matrices: Non-zero elements only on the diagonal. Used to represent variance contributions when assets are uncorrelated, or to scale different variables by different amounts.
- Identity matrix: Diagonal matrix with 1s on the diagonal. Acts as the "1" of matrix multiplication: . It's the matrix equivalent of multiplying by one, leaving any matrix unchanged.
- Positive definite matrices: A real symmetric matrix is positive definite when for every non-zero real vector . Valid covariance matrices must be positive semi-definite (allowing zero). This ensures that every portfolio variance is non-negative, as variance must be by definition.
The eigenvalue calculation below previews Eigenvalue Decomposition, where we explain these values and their connection to variance. For now, use the nonnegative quadratic-form condition above as the definition of positive semi-definiteness.
# Verify covariance matrix properties
# 1. Symmetric
is_symmetric = np.allclose(sample_cov, sample_cov.T)
# 2. Positive semi-definite (all eigenvalues ≥ 0)
eigenvalues = np.linalg.eigvalsh(sample_cov)
is_psd = np.all(eigenvalues >= -1e-10) # Small tolerance for numerical precisionCovariance matrix is symmetric: True Eigenvalues: [0.0001167 0.00036008 0.00063233] Covariance matrix is positive semi-definite: True
The sample covariance is symmetric and positive semi-definite by its centered-data construction. The numerical checks are consistent with these properties to the chosen tolerance; permitting tiny negative computed eigenvalues is a numerical diagnostic, not proof that every exact quadratic form of an arbitrary matrix is nonnegative. Symmetry means that covariance between assets A and B equals covariance between B and A. Positive semi-definiteness guarantees nonnegative portfolio variance.