Main Content

Dynamic Portfolio Allocation in Goal-Based Wealth Management for Multiple Time Periods

This example shows a dynamic programming strategy to maximize the probability of obtaining an investor's wealth goal at the end of the investment horizon. This dynamic programming strategy is known in the literature as a goal-based wealth management (GBWM) strategy. In GBWM, risk is not necessarily measured using the standard deviation, the value-at-risk, or any other common risk metric. Instead, risk is understood as the likelihood of not attaining an investor's goal. This alternative concept of risk implies that, sometimes, in order to increase the probability of attaining an investor’s goal, the optimal portfolio’s traditional risk (that is, standard deviation) must increase if the portfolio is underfunded. In other words, for the investor’s view of risk to decrease, the traditional view of risk must increase if the portfolio’s wealth is too low.

The objective of the investment strategy is to determine a dynamic portfolio allocation such that the portfolios chosen at each rebalancing period are on the traditional mean-variance efficient frontier and these portfolios maximize the probability of achieving the wealth goal G at the time horizon T. This objective is represented as

max{A(0),A(1),,A(T-1)}  P(W(T)G),

where W(T) is the terminal portfolio wealth and A(t) are the possible actions and allocations at time t=0,1,,T-1.

The dynamic portfolio problem consists of the following parts:

  • Time periods — Portfolio rebalancing periods

  • Actions — Portfolio weights rebalancing

  • States — Wealth levels

  • Value function — Probability of achieving the goal at the end of the investment period

  • Policy or strategy — Optimal actions at each state and time period

This example follows the GBWM strategy of Das [1]. For an example of GBWM for a single time period, see the Single Period Goal-Based Wealth Management example.

Inputs for Investment Wealth Goals

Specify the initial wealth.

W0 = 100;

Specify the target wealth at the end of the investment horizon.

G = 200;

Define the time horizon.

T = 10;

Load the asset information.

load BlueChipStockMoments.mat

Rebalancing Period Actions for Efficient Portfolios

The action at each rebalancing period is to choose the weights of the investment portfolio for the next time period. In this example assume that the possible portfolio weights are associated with the portfolios on the efficient frontier. This example also assumes that the choice of possible portfolios is fixed throughout the full investment period. However, weights are not required to be on the efficient frontier. The only requirement is that the set of actions (portfolio choices) remains fixed throughout the investment period.

To simplify the computations, define a finite subset of the efficient portfolios for possible actions. Start by creating a Portfolio object with the asset information from BlueChipStockMoments.mat.

p = Portfolio(AssetList=AssetList,AssetMean=AssetMean,...

Annualize the asset returns and the variance-covariance matrix.

p.AssetMean  = 12*p.AssetMean;
p.AssetCovar = 12*p.AssetCovar;

Use setBounds to add constraints to the portfolio problem. Here, assets do not represent more than 10% of the portfolio wealth and shorting is not allowed.

p = setBounds(p,0,0.1);

Use setBudget to specify that the portfolio must be fully invested.

p = setBudget(p,1,1);

Compute the weights of 15 portfolios on the efficient frontier using estimateFrontier. These portfolios represent the possible actions at each rebalancing period.

nPortfolios = 15;
pwgt = estimateFrontier(p,nPortfolios);

Plot the efficient frontier using plotFrontier.

[prsk,pret] = plotFrontier(p,pwgt);

States for Wealth Nodes

The states are defined as the wealth values at time t. To simplify the problem, discretize the wealth values to generate a wealth grid, Wi, for i{1,,imax}.W1 corresponds to the smallest possible wealth Wmin and Wimax corresponds to the largest possible wealth Wmax. To determine Wmin and Wmax, assume that the evolution of wealth follows a geometric Brownian motion


where Z is a standard normal random variable. GBWM does not require that the wealth evolution follow a Brownian motion. However, the technique in this example requires the evolution model to be Markovian. Therefore, this example assumes that the probability of being at a certain state at time t+1 only depends on the state at time t and the action taken.

This example also assumes that Z realistically takes values between -3 and 3. When Z=-3, Wmin corresponds to the smallest value obtained in the trajectory of the Brownian motion setting, μ is the smallest possible portfolio return μmin, and σ is the largest possible portfolio risk σmax. Likewise, when Z=3, Wmax corresponds to the largest value in the trajectory, μ is the largest possible portfolio return μmax, and σ is the largest possible portfolio risk σmax. For Wmax, use σmax because the term in the exponential is increasing for all σ3/t; if σmax>3/t, use σ=3/t instead.

Define μmin, μmax, σmin, and σmax.

% Define return limits.
mu_min = pret(1);
mu_max = pret(end);

% Define volatility limits.
sigma_min = prsk(1);
sigma_max = prsk(end);

The smallest realistic value of W is


% Define the minimum possible wealth.
timeVec = 0:T;
WMinVec = W0*exp((mu_min-(sigma_max^2)/2)*timeVec- ...
WHatMin = min(WMinVec);

The largest realistic value of W is


% Define the maximum possible wealth.
WMaxVec = W0*exp((mu_max-(sigma_max^2)/2)*timeVec+ ...
WHatMax = max(WMaxVec);

Now, you can fill in the grid points between Wˆmin and Wˆmax. When you set Z=1and t=1and ignore the drift term (μ-σ2/2)t, note that σ is proportional to the logarithm of the wealth. Thus, you can work in logarithmic space and add a grid point every σmin/ρgrid units. ρgrid is an exogenous parameter that determines the density of the grid. As ρgrid grows, the number of wealth nodes increases.

% Transform to the logarithmic space.
lWHatMin = log(WHatMin);
lWHatMax = log(WHatMax);
% Define the grid in the logarithmic space.
rho = 3;
lWGrid = (lWHatMin:sigma_min/rho:lWHatMax)';

To guarantee that there exists a point in the wealth grid that matches W(0), shift the logarithmic grid downwards by the smallest shift such that one of those values matches the logarithm of the initial portfolio value.

% Compute the shift for wealth grid.
lW0 = log(W0);
difference = lWGrid-lW0;
minDownShift = min(difference(difference>=0));
% Define the wealth nodes.
WGrid = exp(lWGrid - minDownShift);
nWealthNodes = size(WGrid,1); % Number of wealth nodes

Value Function and Optimal Strategy

The problem in this example is a multi-period optimization problem. The goal is to find the action at each rebalancing period that maximizes the probability that the wealth exceeds the target goal at the end of the investment period. To solve this problem, use the Bellman equation, which in this case is given by


The value function V(Wi(t)) represents the probability of exceeding the wealth goal G at time T, given that at time t, the wealth level is Wi. Simultaneously, p(Wj(t+1)|Wi(t),π) represents the probability of moving to wealth node j at time t+1, given that at time t, you are at wealth node i and you chose portfolio π as the rebalancing action.

Compute Transition Probabilities

Since this example assumes that the wealth goal follows a geometric Brownian motion, the transition probabilities of being in wealth node Wj at time t+1, given that you are at wealth node Wi at time t, are time-homogeneous. Thus, the transition probability for a given portfolio choice π is defined as

p(Wj(t+1)|Wi(t),π)=P(WjW(t+1)<Wj+1|W(t)=Wi,π)=p(Wj+1|Wi,π)-p(Wj|Wi,π),  t{0,,T},



Φ is the cumulative distribution function of the standard normal random variable, and μπ and σπ are the return and risk of portfolio π. If j=1,

p(W1(t+1)|Wi(t),π)=p(W2|Wi,π),  t{0,,T},

and if j=imax,

p(Wimax(t+1)|Wi(t),π)=1-p(Wimax|Wi,π),  t{0,,T}.

Note that this example computes transition probabilities differently from the transition probabilities as described by Das [1], to keep a consistent mapping between W(t) and a unique wealth node index.

% Compute the transition probabilities for different portfolios:
% pTransition(i,j,k) = p(Wj|Wi,mu_k)
pTransition = zeros(nWealthNodes,nWealthNodes,nPortfolios);
for k = 1:nPortfolios
    % Get the return and variance of portfolio k.
    mu = pret(k);
    sigma = prsk(k);

    % Compute p tilde before the cdf.
    pTilde = 1/sigma*(log(WGrid'./WGrid) - (mu-(sigma^2)/2));
    % Auxiliary matrices for edge cases (j = 1 and j = i_max)
    pTildeAuxUB = [pTilde(:,2:end) inf(nWealthNodes,1)];
    pTildeAuxLB = [-inf(nWealthNodes,1) pTilde(:,2:end)];

    % Compute the transition probabilities for portfolio k.
    pTransition(:,:,k) = normcdf(pTildeAuxUB)-normcdf(pTildeAuxLB);

Maximize Probability of Achieving Investor's Goal

Since the value function is the probability of achieving the wealth investment goal G at the final time step, you know that the value function at t=T is given by


% Initialize the matrix that stores the value function at different
% wealth nodes and time periods.
V = zeros(nWealthNodes,T+1);
% Define the Value function at t = T.
V(:,end) = (WGrid >= G);

To compute the value of V(Wi(t)) for t<T, you need to go backwards in time. You start at t=T-1 to determine the portfolio that achieves the maximum in the Bellman equation and V(Wi(T-1)). Then continue with t=T-2, then t=T-3, until you reach t=0. The value of V(W(0)) is the optimal probability of attaining the wealth goal G from the initial wealth W(0).

% Compute the optimal value function and portfolio at different
% wealth nodes and time periods.
portIdx = zeros(nWealthNodes,T);
for t = T:-1:1
    pTilde = zeros(nWealthNodes,nPortfolios);
    for k = 1:nPortfolios
        % sum_j ( V(Wj(t+1)) * p(Wj|Wi,mu_k) )
        pTilde(:,k) = pTransition(:,:,k)*V(:,t+1);
    % Choose the portfolios that achieve the best probabilities.
    [V(:,t),portIdx(:,t)] = max(pTilde,[],2);

Note that V(i,t) is V(Wi(t-1)), which denotes the optimal probability of achieving the wealth goal from wealth node Wi at time period t-1. On the other hand, portIdx(i,t) defines the optimal portfolio to be chosen at time period t-1 if you are at wealth node Wi. The value of t is shifted down for V(i,t) and portIdx(i,t), given that array indices start at 1 and t starts at 0.

Use heatmap to plot the value function.

% Plot a heatmap of the value function.
xlabel("Time Period")
ylabel("Wealth Level")
title("Probability of Achieving Goal")

The figure shows how the probability of achieving the goal becomes larger as the initial wealth grows. Also, this figure demonstrates that as time passes, the current wealth must be higher than in the previous periods to get the same probability of achieving the goal.

Use heatmap to plot the optimal portfolio.

% Plot a heatmap of optimal portfolio.
xlabel("Time Period")
ylabel("Wealth Level")
title("Portfolio Aggressiveness")

This figure shows that the higher the wealth, the lower the number of the optimal portfolio. Since the number of the portfolio is directly related to the aggressiveness of the strategy, you can see that the wealthier the portfolio, the less risk is needed to achieve the final wealth goal. When the portfolio has less money, then the optimal portfolio is the one with a larger expected return, even at the cost of increasing the volatility. Also, note that the closer the time period is to the end of the investment horizon, the choice of the optimal portfolio becomes polarized, where the portfolio is either extremely aggressive or extremely conservative.

Implement Optimal Strategy

The following describes the workflow to implement the optimal strategy:

  1. At t=0, choose the optimal strategy shown in portIdx(i,j) such that i is the index associated with the wealth node that satisfies WiW(0)<Wi+1 and j=t+1. Also, let A*(0)=portIdx(i,j).

  2. Rebalance the portfolio to match the weights in pwgt(:,A*(0)). Then, define π*(0)=pwgt(:,A*(0)).

  3. Either using historical data for time period t=0 or simulating one step of a Brownian motion, obtain W(1), given that you started at W(0), and chose portfolio π*(0).

  4. Repeat steps 1 through 3 for t=1,,T-1.

% Simulate one path following the optimal strategy.
[Z,WPath,portPath,VPath] = DynamicPortSim(W0,WGrid,pret,prsk, ...

Present a table with the results of the simulation.

simulation = table((0:T)',Z,WPath,portPath,VPath,'VariableNames', ...
simulation=11×5 table
    t        Z        Wealth    OptPort    ProbOfSuccess
    __    ________    ______    _______    _____________

     0     0.53767       100       12         0.87953   
     1      1.8339    126.69       11         0.92018   
     2     -2.2588    194.27       11         0.98474   
     3     0.86217    158.68       11          0.9323   
     4     0.31877    209.52       11         0.98044   
     5     -1.3077    254.46       10         0.99184   
     6    -0.43359    241.04       10         0.98366   
     7     0.34262    260.14        8         0.99024   
     8      3.5784    311.62        5         0.99927   
     9      2.7694    566.28        1               1   
    10         NaN     894.5      NaN               1   

Note that as the probability of attaining the wealth goal (the value function) increases, the aggressiveness (number) of the optimal portfolio decreases. Now, you can plot the path of the wealth against the probability of achieving the wealth goal at the end of the investment period.


% Plot the wealth path.
yyaxis left
hold on
ylabel("Wealth Level");

% Plot the value function path.
yyaxis right
ylabel("Probability of Success");

% Specify the title, labels, and legends for the plot.
title("Optimal Strategy Outcome")
xlabel("Time Period");
legend("Wealth path","Wealth goal",Location="nw");
grid on
hold off

At t=4, the wealth goal has been achieved. However, because of the uncertainty in the problem, the probability of success is not yet 1. Furthermore, trying different paths (random seeds) shows how even a monotonic increase in the wealth does not translate to a monotonic increase in the probability of success. This behavior occurs because the wealth increase at later time periods should be higher than at earlier time periods to have the same increase in the probability of success.

Plot the cumulative distribution function (CDF) of attaining the goal wealth at different time periods.

% Plot the cumulative distribution function (CDF) of success at
% different time periods.
nWN = 60;
xline(W0,'--k','LineWidth',2); % Initial wealth
xline(G,'-.r','LineWidth',2); % Goal wealth

% Specify the title, labels, and legends.
title('Success CDF at Different Time Periods')
xlabel('Wealth Level')
ylabel('Probability of Success')
legend("t = "+num2str((0:T-1)'),Location="se")
grid on

This figure shows how as the time period approaches the investment horizon, the CDF shifts to the right and becomes steeper. This shift demonstrates that changes in the wealth level have a higher impact toward the end of the investment horizon. For example, an increase of 100 to 110 wealth points at t=0 only increases the probability of success by 3%, while the same wealth increase at t=4 increases the probability of success by 7%.

Local Functions

function [Z,WPath,portPath,VPath] = DynamicPortSim(W0,WGrid,...
% Define time periods.
T = size(V,2)-1;

% Define standard normal random variables for the Brownian motion.
Z = randn(T,1);
Z = [Z;nan]; % No randomness at the final time period

% Find the wealth node index of the initial wealth.
tol = 1e-8; % Account for numerical inaccuracies
difference = WGrid-W0;
% Assign to wealth node j such that W_j <= W(0) < W_{j+1}
WNodeIdx = find(difference<=tol,1,'last');

% Run the simulation.
WPath = [W0; zeros(T,1)];
portPath = [portIdx(WNodeIdx,1); zeros(T,1)];
VPath = [V(WNodeIdx,1); zeros(T,1)];
for t = 1:T
    % Get the return and variance of optimal portfolio at time t.
    mu = pret(portIdx(WNodeIdx,t));
    sigma = prsk(portIdx(WNodeIdx,t));

    % Compute the wealth at time t+1 following the Browninan motion.
    WPath(t+1) = WPath(t)*exp(mu-(sigma^2)/2+sigma*Z(t));

    % Compute the wealth node index corresponding to the current wealth.
    difference = WGrid-WPath(t+1);
    % Assign to wealth node j such that W_j <= W(t+1) < W_{j+1}
    WNodeIdx = find(difference <= tol,1,'last');

    % Store the optimum strategy and value function.
    if t<T
        portPath(t+1) = portIdx(WNodeIdx,t+1);
        portPath(t+1) = nan;
    VPath(t+1) = V(WNodeIdx,t+1);


[1] Das, Sanjiv R., Daniel Ostrov, Anand Radhakrishnan, and Deep Srivastav. “Dynamic Portfolio Allocation in Goals-Based Wealth Management.” Computational Management Science 17, no. 4 (December 2020): 613–40. Available at:

See Also

| | | |

Related Examples

More About