Thinking One Move Ahead: Multi-Period Portfolio Optimization
In the earlier article Portfolio Optimization for Long-Only Multi-Factor Equity Strategies, I gave a fairly complete introduction to how the problem of solving single-period portfolio weights can be transformed into a quadratic program. This article summarizes the key ideas of the Stanford and BlackRock collaboration paper Multi-Period Trading via Convex Optimization. Published in 2017, that paper offered one of the first systematic treatments of multi-period optimization in portfolio management.
This article includes AI-assisted writing.
Model
Assets and Cash
Consider a portfolio consisting of \(n\) assets and one cash account over a finite horizon of \(T\) discrete time periods. Let \(h_t \in \mathbb{R}^{n+1}\) denote the holdings at time \(t\), where \((h_t)i\) is the dollar value of asset \(i\) and \((h_t){n+1}\) is the cash balance. The total portfolio value is \(v_t = 1^T h_t\), and the portfolio weights are \(w_t = h_t / v_t\).
Trading
Assume all trades occur at the beginning of each period. The trade vector \(u_t \in \mathbb{R}^n\) represents dollar trades at time \(t\), where \(u_{ti} > 0\) means buying asset \(i\) and \(u_{ti} < 0\) means selling asset \(i\). The post-trade holdings satisfy \(h_{t+1} = h_t + u_t\), and post-trade cash is
$$ (h_{t+1})_{n+1} = (h_t)_{n+1} - 1^T u_t $$
Transaction Costs
For example, transaction costs can be modeled as a combination of linear and fixed costs:
$$ \text{transaction cost} = \gamma^T |u_t| + \delta^T \mathbf{1}_{|u_t| > 0} $$
where \(\gamma\) is the per-unit trading cost vector and \(\delta\) is the fixed cost vector for each trade.
Holding Costs
Holding costs can include borrowing costs and management fees:
$$ \text{holding cost} = \lambda^T h_t + \mu^T \mathbf{1}_{h_t < 0} $$
where \(\lambda\) is the per-unit holding cost and \(\mu\) is the per-unit borrowing cost.
Self-Financing Constraint
The self-financing condition requires that the cash balance remain nonnegative in each period:
$$ (h_{t+1})_{n+1} = (h_t)_{n+1} - 1^T u_t \geq 0 $$
Single-Period Optimization (SPO)
Single-period optimization (SPO) is a common portfolio optimization approach that seeks to maximize expected return over one period while controlling risk and trading costs. Its defining feature is that the decision is made only for the current period, without explicitly modeling future periods.
Objective Function
In SPO, the objective is typically to maximize risk-adjusted return. A representative formulation is
$$ \max_{w_t} \left( r_t^T w_t - \gamma_t \psi_t(w_t) - \phi_{\text{hold}, t} (w_t) - \phi_{\text{trade}, t} (w_t - w_{t-1}) \right) $$
where:
- \(w_t\) is the asset weight vector at time \(t\).
- \(r_t\) is the expected return vector at time \(t\).
- \(\gamma_t\) is the risk-aversion parameter.
- \(\psi_t(w_t)\) is the risk function at time \(t\).
- \(\phi_{\text{hold}, t}(w_t)\) is the holding cost.
- \(\phi_{\text{trade}, t}(w_t - w_{t-1})\) is the trading cost.
Constraints
The SPO problem must satisfy a set of constraints to ensure feasibility and portfolio discipline. Common constraints include:
The weights sum to one:
$$ \sum_{i=1}^{n} (w_{t})_i = 1 $$
The weights are nonnegative:
$$ w_t \geq 0 $$
These ensure the portfolio is a valid long-only allocation.
Solving the Problem
Single-period optimization is usually solved by convex optimization tools such as cvxpy. A simple example is shown below:
1 | import cvxpy as cp |
Summary
SPO is a portfolio optimization method tailored to a single time period. Its goal is to maximize current-period risk-adjusted return. While it can produce effective allocation decisions for the next step, it does not account for future periods or the impact of today’s decision on tomorrow’s position. For long-horizon investing, that is a real limitation.
Multi-Period Optimization (MPO)
Multi-period optimization explicitly considers asset allocation and trading decisions across multiple future periods. By planning over a longer horizon, it can improve total portfolio performance. For example, suppose we expect short-term returns to be positive but long-term returns to be negative. SPO may chase the next-period gain and leave the portfolio trapped in an unfavorable future position, forcing a costly exit. MPO can do better by accounting for both transaction costs and the changing return outlook.
Objective Function
The multi-period problem is typically solved over a planning horizon extending several periods into the future. At each time step we choose a trade vector \(z_t\), and use an optimization problem to plan over the next \(H\) periods:
$$ t, t+1, \ldots, t+H-1 $$
The objective is to maximize risk-adjusted return over the full horizon. For the planning range from \(t\) to \(t+H-1\), the problem can be written as
$$ \sum_{\tau=t}^{t+H-1} \left( r_{\tau|t}^T (w_\tau + z_\tau) - \gamma_\tau \psi_\tau(w_\tau + z_\tau) - \phi_{\text{hold}, \tau} (w_\tau + z_\tau) - \phi_{\text{trade}, \tau} (z_\tau) \right) $$
where:
- \(r_{\tau|t}\) is the estimate made at time \(t\) of return in period \(\tau\).
- \(w_\tau\) is the asset weight vector at period \(\tau\).
- \(z_\tau\) is the trade vector at period \(\tau\).
- \(\gamma_\tau\) is the risk-aversion parameter.
- \(\psi_\tau\) is the risk function.
- \(\phi_{\text{hold}, \tau}\) is the holding-cost function.
- \(\phi_{\text{trade}, \tau}\) is the trading-cost function.
The dynamics of portfolio weights can be written as
$$ w_{t+1} = \frac{1}{1 + R_t^p} (1 + r_t) \circ (w_t + z_t) $$
where \(R_t^p\) is the risk-free rate, \(r_t\) is the asset return vector, and \(\circ\) denotes elementwise multiplication.
Under a simplifying assumption, we ignore changes in weights caused by price movements:
$$ w_{\tau+1} = w_\tau + z_\tau, \quad \tau = t, \ldots, t+H-1 $$
The problem is then equivalent to
$$ \max \sum_{\tau=t+1}^{t+H} \left( r_{\tau|t}^T w_\tau - \gamma_\tau \psi_\tau (w_\tau) - \phi_{\text{hold}, \tau} (w_\tau) - \phi_{\text{trade}, \tau} (w_\tau - w_{\tau-1}) \right) $$
with decision variables given by the future weights \(w_{t+1}, \ldots, w_{t+H}\).
Solving the Problem
Below is a simple example showing how to implement multi-period optimization in cvxpy:
1 | import cvxpy as cp |
Code notes
Parameter setup
nis the number of assets.Tis the number of periods.His the planning horizon.
Random data generation
ris the matrix of asset returns with shape(T, n).gammais the risk-aversion parameter.phi_holdandphi_tradeare holding-cost and trading-cost matrices with shape(T, n).Sigmais the risk tensor with shape(T, n, n).
Initial weights
w0is the initial portfolio, assumed to be equally weighted.
Decision variables
wstores the asset weights in each period.zstores the trade vectors in each period.
Objective
- The goal is to maximize risk-adjusted return over the full horizon.
Constraints
w[t]is the weight vector in periodt.z[t]is the trade vector in periodt.- The constraints enforce full investment and nonnegative weights.
Optimization
- The problem is defined and solved with
cvxpy.
- The problem is defined and solved with
Output
- The code prints the optimal weights and trade vectors.
This example illustrates how cvxpy can be used to implement MPO. The approach can handle allocation and trading decisions across multiple future periods and thereby improve overall portfolio behavior.
Thinking One Move Ahead: Multi-Period Portfolio Optimization