Linear Algebra for Quantitative Finance › Systems of Linear Equations

Michael BrenndoerferOctober 23, 202511 min read
Quantitative FinanceAll chapters
Part 1 of 15Mathematical Foundations
Chapter 5Linear Algebra for Quantitative Finance › Systems of Linear Equations
Reading section 4 of 9 · Systems of Linear Equations · 11 minSection 4 of 9 · 11 min

Book contents

Section 4 of 9 · 11 min read

Linear Algebra for Quantitative Finance › Systems of Linear EquationsOne section · Sections in this chapter4 / 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

Many financial problems involve systems of linear equations. Hedge construction, factor-exposure matching, and related tasks can often be formulated as Ax=b\mathbf{A}\mathbf{x} = \mathbf{b} for unknown x\mathbf{x}, although practical versions may add constraints, approximation, or optimization.

Why is this formulation so ubiquitous? Because linear systems capture the essence of constraints and requirements. In finance, we often face situations where multiple conditions must hold simultaneously. A hedge must neutralize exposure to several risk factors at once, a replicating portfolio must match the payoffs of a target in multiple scenarios, and factor loadings must explain returns across many time periods. Each condition contributes one equation, and the unknowns are the positions or weights we need to determine. Linear algebra provides systematic machinery for finding solutions when they exist and for characterizing what's possible when they don't.

The General Problem

A system of linear equations has the form:

a11x1+a12x2+⋯+a1nxn=b1a21x1+a22x2+⋯+a2nxn=b2⋮am1x1+am2x2+⋯+amnxn=bm\begin{aligned} a_{11}x_1 + a_{12}x_2 + \cdots + a_{1n}x_n &= b_1 \\ a_{21}x_1 + a_{22}x_2 + \cdots + a_{2n}x_n &= b_2 \\ &\vdots \\ a_{m1}x_1 + a_{m2}x_2 + \cdots + a_{mn}x_n &= b_m \end{aligned}

where:

  • aija_{ij}: the coefficient in equation ii for unknown xjx_j
  • xjx_j: the jj-th unknown variable we're solving for
  • bib_i: the right-hand side constant of equation ii
  • mm: the number of equations
  • nn: the number of unknowns

In matrix form: Ax=b\mathbf{A}\mathbf{x} = \mathbf{b}, where A\mathbf{A} is m×nm \times n, x\mathbf{x} is n×1n \times 1, and b\mathbf{b} is m×1m \times 1.

The matrix A\mathbf{A} encodes the structure of the problem: how each unknown contributes to each equation. Finding x\mathbf{x} means finding the combination of unknowns that simultaneously satisfies all constraints. In financial applications, A\mathbf{A} often represents sensitivities (like Greeks or factor exposures), x\mathbf{x} represents positions or weights we're solving for, and b\mathbf{b} represents target values we want to achieve.

The geometry of linear systems provides useful intuition. Each equation with at least one nonzero coefficient defines a hyperplane in the space of unknowns (a line in 2D, a plane in 3D, and so on). Solving the system means finding the point (or points, or nothing at all) where all these hyperplanes intersect. When there are exactly as many independent equations as unknowns, and the equations aren't contradictory, the hyperplanes intersect at a single point, giving the unique solution.

Matrix Inverses and Solving Square Systems

When A\mathbf{A} is square (n×nn \times n) and invertible, the solution is x=A−1b\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}. The inverse A−1\mathbf{A}^{-1} satisfies AA−1=A−1A=I\mathbf{A}\mathbf{A}^{-1} = \mathbf{A}^{-1}\mathbf{A} = \mathbf{I}.

The inverse matrix "undoes" the transformation represented by A\mathbf{A}. If A\mathbf{A} transforms inputs to outputs, then A−1\mathbf{A}^{-1} transforms outputs back to inputs. In the context of our linear system, we know the outputs (b\mathbf{b}, the targets we want to achieve) and need to find the inputs (x\mathbf{x}, the positions that achieve those targets). Multiplying by the inverse reverses the process, revealing the required inputs.

When Does an Inverse Exist?

A square matrix is invertible (or non-singular) when its determinant is non-zero, equivalently when its rows (or columns) are linearly independent. An invertible coefficient matrix gives a unique solution for every right-hand side b\mathbf{b}. Redundancy is a property of the coefficient rows, while consistency or contradiction depends on both A\mathbf{A} and b\mathbf{b}.

In numerical work, solve Ax=b\mathbf{A}\mathbf{x}=\mathbf{b} directly rather than forming A−1\mathbf{A}^{-1} explicitly. A solver can use an appropriate factorization without forming the full inverse. For a single right-hand side, explicitly forming the inverse generally adds computation and can introduce additional rounding error. Rank and condition-number checks are still necessary when the system may be singular or ill-conditioned.

Application: Factor Replication

Consider replicating a target portfolio's factor exposures using available assets. Suppose you have three assets with known exposures to two factors (market and size), and you want to construct a portfolio with specific target exposures:

In[20]:
Code
# Factor exposures: rows are assets, columns are factors (market, size)
factor_exposures = np.array(
    [
        [1.2, 0.8],  # Asset 1: high market beta, positive size exposure
        [0.8, -0.3],  # Asset 2: moderate market beta, negative size exposure
        [1.0, 0.2],  # Asset 3: market beta 1.0, small positive size exposure
    ]
)

# Target exposures: we want these factor loadings
target_exposure = np.array([1.0, 0.0])  # Market beta of 1, size-neutral

# We have 3 assets and 2 constraints, so we need an additional constraint
# Add constraint: weights sum to 1 (fully invested)
A = np.vstack([factor_exposures.T, np.ones(3)])
b = np.append(target_exposure, 1.0)
Out[21]:
Console
Factor exposure matrix (assets × factors):
[[ 1.2  0.8]
 [ 0.8 -0.3]
 [ 1.   0.2]]

Target factor exposures: [1. 0.]
Additional constraint: weights sum to 1

Augmented system A:
[[ 1.2  0.8  1. ]
 [ 0.8 -0.3  0.2]
 [ 1.   1.   1. ]]

Target vector b: [1. 0. 1.]

We have 3 unknowns (weights) and 3 equations (2 factor constraints + 1 budget constraint). Let's solve:

In[22]:
Code
# Solve the system
weights = np.linalg.solve(A, b)

# Verify the solution
achieved_exposures = factor_exposures.T @ weights
weight_sum = np.sum(weights)
Out[23]:
Console
Solution weights: [-2. -2.  5.]

Verification:
  Factor exposures achieved: [ 1.00000000e+00 -2.99760217e-16]
  Weight sum: 1.000000

Interpretation:
  Asset 1: -200.00% of portfolio
  Asset 2: -200.00% of portfolio
  Asset 3: +500.00% of portfolio

The solution tells us exactly how to combine the three assets to achieve our target factor profile: market beta of 1 with zero size exposure, while being net fully invested. Here the weights are -200%, -200%, and +500%, so the exact match requires short positions and 900% gross exposure. In practice, leverage or short-sale limits can make the exact system infeasible; constrained optimization or regularized least squares can then trade replication error against implementability.

Application: Delta Hedging

In derivatives trading, you often need to hedge exposure to multiple risk factors. Suppose you hold a portfolio of options and want to eliminate its current modeled sensitivity to the underlying price (delta) and volatility (vega). You have two hedging instruments available. Here delta is the change in dollar value per one-dollar underlying-price change, and vega is the change in dollar value per one-percentage-point implied-volatility change. The option column refers to one modeled option unit, not an exchange contract; portfolio and instrument sensitivities use the same units. Actual contract multipliers must be applied before constructing a hedge matrix.

In[24]:
Code
# Current portfolio Greeks (what we need to hedge)
portfolio_delta = 150  # Long 150 deltas
portfolio_vega = -2000  # Short 2000 vegas

# Available hedging instruments
# Instrument 1: Stock (delta=1, vega=0)
# Instrument 2: One modeled ATM option unit (delta=0.5, vega=100)
# Vega values are dollars per one-percentage-point implied-volatility change

hedge_matrix = np.array(
    [
        [1.0, 0.5],  # Delta of each instrument
        [0.0, 100.0],  # Vega of each instrument
    ]
)

# Target: neutralize the portfolio Greeks
target = np.array([-portfolio_delta, -portfolio_vega])

# Solve for hedge quantities
hedge_quantities = np.linalg.solve(hedge_matrix, target)
Out[25]:
Console
Portfolio Greeks to hedge:
  Delta: +150
  Vega: -2000

Hedging instruments (Delta, Vega):
  Stock: (1, 0)
  ATM Option: (0.5, 100)

Required hedge quantities:
  Stock: -160 shares
  Options: +20 modeled option units

Resulting portfolio Greeks:
  Delta: 0.00
  Vega: 0.00

In this illustrative calculation, shorting 160 shares of stock and buying 20 modeled option units neutralizes both delta and vega at the stated sensitivities. Other risks and later changes in those sensitivities remain.

Least Squares: Overdetermined Systems

When we have more equations than unknowns (m>nm > n), the system is overdetermined and typically has no exact solution. This happens often in finance. We have many data points (days of returns) but few parameters to estimate (factor exposures).

The least squares solution minimizes the sum of squared residuals:

x^=arg⁡min⁡x∥b−Ax∥22\hat{\mathbf{x}} = \arg\min_{\mathbf{x}} \|\mathbf{b} - \mathbf{A}\mathbf{x}\|_2^2

where:

  • x^\hat{\mathbf{x}}: the least squares estimate of x\mathbf{x}
  • ∥⋅∥22\|\cdot\|_2^2: the squared L2 norm (sum of squared elements)
  • b−Ax\mathbf{b} - \mathbf{A}\mathbf{x}: the residual vector (observed minus fitted)

The solution is given by the normal equations (assuming ATA\mathbf{A}^T\mathbf{A} is invertible):

x^=(ATA)−1ATb\hat{\mathbf{x}} = (\mathbf{A}^T\mathbf{A})^{-1}\mathbf{A}^T\mathbf{b}

where:

  • ATA\mathbf{A}^T\mathbf{A}: the n×nn \times n Gram matrix of the explanatory-variable columns, whose entries are their pairwise inner products
  • ATb\mathbf{A}^T\mathbf{b}: a vector containing each explanatory-variable column's inner product with the target vector

Differentiating the squared residual norm gives the first-order condition AT(Ax^−b)=0\mathbf{A}^T(\mathbf{A}\hat{\mathbf{x}}-\mathbf{b})=\mathbf{0}, or ATAx^=ATb\mathbf{A}^T\mathbf{A}\hat{\mathbf{x}}=\mathbf{A}^T\mathbf{b}. When the Gram matrix is invertible, solving these normal equations yields the displayed formula. The Gram matrix captures column scale and non-orthogonality; it is not generally a correlation matrix, and its inverse is not a literal correction for "double-counting."

When ATA\mathbf{A}^T\mathbf{A} is invertible, the matrix (ATA)−1AT(\mathbf{A}^T\mathbf{A})^{-1}\mathbf{A}^T is the Moore-Penrose pseudoinverse of A\mathbf{A}.

The formula describes the mathematical solution, not a recommended floating-point algorithm. For a full-column-rank matrix, forming ATA\mathbf{A}^T\mathbf{A} squares its 2-norm condition number and can obscure weak directions numerically. Prefer a QR- or SVD-based least-squares algorithm. The example below calls np.linalg.lstsq directly rather than manually forming and inverting the Gram matrix.

Intuitively, least squares finds the x\mathbf{x} that makes Ax\mathbf{A}\mathbf{x} as close as possible to b\mathbf{b} in Euclidean distance. The residual vector b−Ax^\mathbf{b} - \mathbf{A}\hat{\mathbf{x}} is orthogonal to the column space of A\mathbf{A}. It is the component not represented by the chosen explanatory-variable columns; changing those columns or the model form can change the residual.

This geometric picture explains why least squares produces the best fit within the chosen column space. Among all possible values of x\mathbf{x}, the least squares solution generates an Ax\mathbf{A}\mathbf{x} that is the orthogonal projection of b\mathbf{b} onto the subspace spanned by the columns of A\mathbf{A}. Orthogonal projection onto a subspace always yields the closest point in that subspace. The residual is therefore the in-sample component unexplained by this span. It may contain noise, measurement error, omitted predictors, or misspecification; the projection geometry alone does not identify irreducible statistical error.

This is exactly what ordinary least-squares linear regression computes.

In[26]:
Code
# Estimate factor exposures from return data
# We have many days of returns (observations) and want to find factor betas

np.random.seed(123)
n_days = 100

# True factor betas we're trying to discover
true_betas = np.array([1.2, -0.3])  # Market beta, size beta

# Simulated factor returns
market_returns = np.random.normal(0.0005, 0.01, n_days)
size_returns = np.random.normal(0.0001, 0.008, n_days)

# Factor matrix: each row is a day, each column is a factor
factor_matrix = np.column_stack([market_returns, size_returns])

# Stock returns = factor exposures × factor returns + noise
noise = np.random.normal(0, 0.005, n_days)
stock_returns = factor_matrix @ true_betas + noise

# Estimate betas via least squares
estimated_betas = np.linalg.lstsq(factor_matrix, stock_returns, rcond=None)[0]
Out[27]:
Console
True factor betas: [ 1.2 -0.3]
Estimated betas: [ 1.1715 -0.2855]

Estimation error:
  Market beta error: -0.0285
  Size beta error: +0.0145
Out[28]:
Visualization
Scatter plot of factor-model predicted returns versus simulated stock returns, with a dashed diagonal line indicating perfect agreement.
Least squares factor estimation showing the relationship between simulated stock returns and factor-predicted returns. Points close to the diagonal line indicate accurate predictions of the simulated response.

This fit has no intercept: its only predictors are the two factor-return columns. The plot reports uncentered R2=1−SSE/∑tyt2R^2=1-\mathrm{SSE}/\sum_t y_t^2, where yty_t is the simulated stock return and SSE is the sum of squared residuals. This measures improvement over predicting zero return, rather than the mean-return baseline used in centered R2R^2. The denominator must be nonzero.

The least squares estimates are close to the true values in this seeded simulation, with small errors due to the noise in returns. More observations can support consistency when the model is correctly specified, the limiting regressor second-moment matrix has full rank, and average regressor-error products converge to zero. Exogenous noise with stable finite moments also needs an appropriate sampling condition, such as independence or suitable weak dependence, to establish that convergence; more data alone does not guarantee consistency.