Test
BrandtSolver.AssetSV — Type
Static Vector of size (N,) representing N assets.
BrandtSolver.AssetVec — Type
Vector of size (N,) representing values across N assets.
BrandtSolver.RegressionStrategy — Type
Abstract parent type for all regression strategies.
BrandtSolver.SimAssetMat — Type
Matrix of size (sim x N) representing asset values for each simulation.
BrandtSolver.SimTimeMat — Type
Matrix of size (sim x Time) representing scalar values over time for each simulation.
BrandtSolver.SimTimeSV — Type
Matrix of size (Sims x Time) where each entry is an AssetSV.
BrandtSolver.SimVec — Type
Vector of size (sim,) representing values across simulations.
BrandtSolver.SolverParams — Type
struct SolverParamsConfiguration parameters for the Brandt portfolio solver.
Arguments
W_grid::Vector{Float64}: Grid of wealth values at initial time t=0 used to evaluate and interpolate the policy function.poly_order::Int64: Order of the polynomial used for expanding state variables in the cross-sectional regression.max_taylor_order::Int64: The truncation order for the Taylor expansion of the value function.trimming_α::Float64: The α value used if a trimmed regression strategy is applied.
BrandtSolver.StandardOLS — Type
Standard Ordinary Least Squares. Fastest method. Uses QR factorization.
BrandtSolver.TrimmedOLS — Type
Trimmed OLS (robust to outliers). Removes the top and bottom α probability mass before regressing.
Arguments
α::Float64: The fraction of data to trim from both tails (e.g., 0.05 for 5% trimming).
BrandtSolver.UtilityFunctions — Type
struct UtilityFunctionsA container for the utility function, its derivatives, and its inverse.
Arguments
u::Function: The base utility functionU(W).nth_derivative::Function: A functionf(n)that returns a function for then-th derivative ofU(W).inverse::Function: The inverse utility function, used to calculate Certainty Equivalents.
Typically, you do not construct this manually. Instead, use create_utility_from_ad to generate it automatically from a base utility function.
BrandtSolver.calculate_expected_utility — Method
calculate_expected_utility(
Re_all_paths::AbstractMatrix{<:SVector},
X_all_paths::AbstractMatrix{Float64},
Y_all_paths::AbstractMatrix{Float64},
future_policies::Vector{Vector{Any}},
t_start::Int,
W_start::Float64,
ω_force::Union{Vector{<:SVector}, <:SVector},
utility_struct::UtilityFunctions
)Evaluates the expected utility and Certainty Equivalent (CE) of a specific portfolio allocation (ω_force) at time t_start for a given starting wealth (W_start).
It calculates this by forward-simulating the wealth trajectories from t_start to terminal time T, assuming the agent applies the forced weights at t_start and then follows the optimal future_policies for all subsequent periods.
Paths that result in bankruptcy (wealth $\leq 10^{-9}$) are filtered out to prevent numerical explosion (e.g., utility approaching $-\infty$ for CRRA) before computing the final mean.
Arguments
Re_all_paths::AbstractMatrix{<:SVector}: A matrix(sims × steps)ofSVectors representing excess returns.X_all_paths::AbstractMatrix{Float64}: A matrix(sims × steps)of gross risk-free returns.Y_all_paths::AbstractMatrix{Float64}: A matrix(sims × steps)of non-tradable income yields.future_policies::Vector{Vector{Any}}: A nested vector structure containing the interpolated policy rules for $t > t_{start}$.t_start::Int: The time step from which to begin the forward simulation.W_start::Float64: The starting wealth level applied uniformly across all simulation paths.ω_force::Union{Vector{<:SVector}, <:SVector}: The portfolio allocation to force att_start. Can be a singleSVector(applied to all paths) or aVectorofSVectors (path-dependent weights).utility_struct::UtilityFunctions: The configuredUtilityFunctionscontaining the base utilityuand itsinverse.
Returns
- A tuple
(J_0, CE_0):J_0::Float64: The conditionally expected utility across all valid, non-bankrupt simulated paths.CE_0::Float64: The Certainty Equivalent of that expected utility (the guaranteed, risk-free wealth level that yields identical utility).
BrandtSolver.calculate_next_wealth — Method
calculate_next_wealth(W_current, ω_t, Re_next, R_free)The core physics kernel that advances wealth...
Arguments
W_current: The wealth at time $t$.ω_t: The chosen portfolio weight(s) for the risky assets at time $t$.Re_next: The realized excess return(s) of the risky assets at time $t+1$.R_free: The gross risk-free return between $t$ and $t+1$.
BrandtSolver.calculate_realized_term — Method
calculate_realized_term(
n::Int,
k_vec::Vector{Int},
W_t_plus_1::Vector{Float64},
W_T::Vector{Float64},
Re_next_svec::AbstractVector{<:SVector},
utility::UtilityFunctions,
)Computes the realized marginal utility integrand ($Y_n$) for the $n$-th order term of the Taylor-expanded equation across all simulation paths.
The realized integrand for the Taylor expansion evaluates to: math Y_n = U^{(n)}(W_T) \left(\frac{W_T}{W_{t+1}}\right)^n \left(\prod_{j=1}^{N} R_{e, j, t+1}^{k_j}\right) R_{e, t+1}`
Arguments
n::Int: The specific derivative order in the Taylor expansion (e.g., 2 for the variance term).k_vec::Vector{Int}: A vector of integers representing the cross-asset monomial exponents $k_j$ for the multivariate expansion.W_t_plus_1::Vector{Float64}: Simulated wealth at time $t+1$.W_T::Vector{Float64}: Simulated terminal wealth at time $T$.Re_next_svec::AbstractVector{<:SVector}: A vector ofSVectorexcess returns at time $t+1$.utility::UtilityFunctions: TheUtilityFunctionsstruct containing the $n$-th derivative generator.
Returns
- A
Matrix{Float64}of size(sims × N_assets)containing the evaluated integrand for each simulation path and each asset.
BrandtSolver.compute_and_regress_moments — Method
compute_and_regress_moments(t_decision, poly_order, max_taylor_order, Z_all_paths, W_t_plus_1,
W_T, Re_next_svec, utility, reg_strategy)Orchestrates the calculation of conditionally expected marginal utility moments for the Taylor-expanded equation.
For each term in the Taylor expansion up to max_taylor_order and for all cross-asset combinations (generated via multiexponents), this function calculates the realized ex-post integrand and then projects it onto the space of available information at t_decision using a cross-sectional regression.
Arguments
t_decision::Int: The current time step in the backward recursion.poly_order::Int: The polynomial degree used to construct the basis functions (design matrix) from the state variables.max_taylor_order::Int: The highest order of the Taylor expansion to compute.Z_all_paths::Vector{<:AbstractMatrix{Float64}}: A vector containing the full simulated paths of all state variables.W_t_plus_1::Vector{Float64}: The simulated wealth across all paths at time $t+1$.W_T::Vector{Float64}: The simulated terminal wealth across all paths at time $T$.Re_next_svec::AbstractVector{<:SVector}: A vector ofSVectors representing realized excess returns at time $t+1$.utility::UtilityFunctions: The configured utility container with automatic differentiation.reg_strategy::RegressionStrategy: The chosen regression strategy (e.g.,StandardOLSorTrimmedOLS).
Returns
Dict{Vector{Int}, Matrix{Float64}}: A dictionary mapping the cross-asset monomial exponent vectors (k_vec) to their conditionally expected values (asims × N_assetsmatrix).
BrandtSolver.compute_conditional_expectation — Method
compute_conditional_expectation(t_decision, reg_strategy, reg_context, φ, integrand)Performs the cross-sectional regression to map realized future quantities to present expectations, conditional on current state variables.
At $t > 1$, it uses the pre-computed regression context (e.g., a QR factorization) to rapidly project the realized integrand onto the basis matrix φ. At $t = 1$, since all agents share the exact same starting state, the conditional expectation is mathematically identical to the unconditional cross-sectional mean.
Arguments
t_decision::Int: The current time step.reg_strategy::RegressionStrategy: The specific algorithm used to estimate coefficients.reg_context::Any: The pre-computed regression context (e.g., aFactorizationobject forStandardOLSor a raw matrix forTrimmedOLS).φ::Union{Nothing, AbstractMatrix{Float64}}: The polynomial expansion of the state variables (design matrix). Will benothingat $t = 1$.integrand::Matrix{Float64}: The realized future values ($Y_n$) to be projected onto the state space.
Returns
Matrix{Float64}: The predicted (conditionally expected) values for each simulation path and each asset.
BrandtSolver.compute_expectations_and_policy — Method
compute_expectations_and_policy(
t_decision::Int,
poly_order::Int,
max_taylor_order::Int,
W_at_t::Float64,
Z_all_paths::Vector{<:AbstractMatrix{Float64}},
R_free_base::AbstractMatrix{Float64},
income_component::AbstractMatrix{Float64},
Re_all_paths::AbstractMatrix{<:SVector},
T_steps::Int,
utility::UtilityFunctions,
future_policies::Vector,
reg_strategy::RegressionStrategy,
)Calculates the conditional expectations of utility moments and solves the First Order Conditions (FOCs) for the optimal portfolio weights across all simulation paths at a specific decision time and a single starting wealth level.
Arguments
t_decision::Int: The current time step in the backward recursion.poly_order::Int: The polynomial degree for the cross-sectional regression basis.max_taylor_order::Int: The Taylor expansion order of the value function.W_at_t::Float64: The specific wealth level being evaluated across all paths.Z_all_paths::Vector{<:AbstractMatrix{Float64}}: A vector of matrices representing the state variables.R_free_base::AbstractMatrix{Float64}: A matrix of gross risk-free returns.income_component::AbstractMatrix{Float64}: A matrix of the non-tradable income yields.Re_all_paths::AbstractMatrix{<:SVector}: A matrix of SVector excess returns for the risky assets.T_steps::Int: The total number of simulation time steps.utility::UtilityFunctions: The utility struct containinguand its derivatives.future_policies::Vector: The optimal policy interpolators for time periodst > t_decision.reg_strategy::RegressionStrategy: The OLS strategy (Standard or Trimmed).
Returns
ω_t_svec: A vector ofSVectors containing the optimal weights for each simulation path.expected_moments_all: A dictionary mapping exponent vectors to their conditionally expected matrices.W_t_plus_1: The simulated wealth at the next time step.W_T: The simulated terminal wealth.
BrandtSolver.create_policy_interpolators — Method
create_policy_interpolators(
t_decision::Int,
W_grid::Vector{Float64},
poly_order::Int,
Z_all_paths::Vector{<:AbstractMatrix{Float64}},
R_free_base::AbstractMatrix{Float64},
income_component::AbstractMatrix{Float64},
Re_all_paths::AbstractMatrix{<:SVector},
T_steps::Int,
utility::UtilityFunctions,
future_policies::Vector{Vector{Any}},
max_taylor_order::Int,
reg_strategy::RegressionStrategy,
recorder::AbstractSolverRecorder
)Constructs state-contingent policy rules for a given decision time by evaluating optimal portfolio weights across a specified grid of wealth values (W_grid) and interpolating the results.
Arguments
t_decision::Int: Current time step in the backward recursion.W_grid::Vector{Float64}: The grid of wealth values to evaluate.poly_order::Int: Polynomial degree for the cross-sectional regression.Z_all_paths::Vector{<:AbstractMatrix{Float64}}: Vector of state variable matrices.R_free_base::AbstractMatrix{Float64}: Gross risk-free return matrix.income_component::AbstractMatrix{Float64}: Non-tradable income matrix.Re_all_paths::AbstractMatrix{<:SVector}: Matrix ofSVectorexcess returns.T_steps::Int: Total number of time steps.utility::UtilityFunctions: TheUtilityFunctionsstruct.future_policies::Vector{Vector{Any}}: A vector of previously computed future policies.max_taylor_order::Int: Expansion order for the Euler equation.reg_strategy::RegressionStrategy: The OLS strategy (Standard or Trimmed).recorder::AbstractSolverRecorder: The logging mechanism for debugging data.
Returns
- A
Vectorof linear interpolation objects (one for each simulation path). Each interpolator takes a wealth valueWand returns the optimal portfolio allocation vectorω.
BrandtSolver.create_utility_from_ad — Method
create_utility_from_ad(base_utility_func::Function)Wraps a user-provided base utility function into a UtilityFunctions struct, automatically generating its exact higher-order derivatives and an inverse function.
Details
- Derivatives: Uses
ForwardDiff.derivativerecursively to compute any $n$-th order derivative. Results are aggressively cached in a closure dictionary so that re-evaluating the same derivative order carries zero compilation or setup overhead. - Inverse: Generates an inverse utility function $W = U^{-1}(J)$ using Newton's method (
Roots.find_zero), relying on the automatically computed first derivative for fast convergence.
Arguments
base_utility_func::Function: A standard scalar function representing utility, e.g., $W \mapsto \frac{W^{1-γ}}{1-γ}$
Returns
- A populated
UtilityFunctionsstruct.
BrandtSolver.estimate_coefficients — Method
estimate_coefficients(::StandardOLS, qrΦ::Factorization, Y::AbstractVector{Float64})Estimates regression coefficients using Standard Ordinary Least Squares (OLS).
This method dispatches on the StandardOLS strategy type. It utilizes a pre-computed QR factorization (qrΦ) for maximum performance, avoiding the need to re-factorize the design matrix at every step.
Arguments
::StandardOLS: The strategy selector. The variable name is omitted (anonymous argument) because the struct contains no data needed for the calculation.qrΦ::Factorization: The QR factorization of the design matrix Φ (fromqr(Φ)).Y::AbstractVector{Float64}: The dependent variable (response vector).
Returns
Vector{Float64}: The estimated coefficients θ minimizing ||Φθ - Y||².
BrandtSolver.estimate_coefficients — Method
estimate_coefficients(strat::TrimmedOLS, Φ::AbstractMatrix, Y::AbstractVector{Float64})Estimates regression coefficients using α-Trimmed OLS (Least Trimmed Squares).
This method dispatches on the TrimmedOLS strategy. It is designed to be robust against outliers (e.g., extreme wealth paths in long-horizon simulations) by physically removing the top and bottom α fraction of the data distribution before regressing.
Arguments
strategy::TrimmedOLS: The strategy struct containing the trimming parameterstrat.alpha.Φ::AbstractMatrix: The raw design matrix. Note: Unlike Standard OLS, we cannot use a pre-computed QR factorization because the rows included in the regression change dynamically based on the sorting ofY.Y::AbstractVector{Float64}: The dependent variable (response vector).
Algorithm
- Calculates integer indices corresponding to the
αand1-αquantiles. - Sorts
Yto identify the "body" of the distribution. - Subsets both
YandΦto exclude the extreme tails. - Solves standard OLS on the remaining subset.
Returns
Vector{Float64}: The estimated coefficients θ based on the trimmed dataset.
BrandtSolver.plot_policy_rules — Method
plot_policy_rules(future_policies, solver_params, t_idx, asset_names; samples=50)Plots the optimal portfolio allocation (weights) as a function of wealth ($W$) for a specific decision time t_idx.
It plots a subset of individual simulation paths to show cross-sectional dispersion (due to varying state variables) and overlays a thick red line representing the mean policy across all simulations.
Arguments
future_policies: The nested vector of interpolated policy functions returned by the solver.solver_params: The configuration parameters, specifically used to extract theW_grid.t_idx: The decision time step to evaluate.asset_names: A list of strings representing the asset names, used to generate subplots.samples: (Keyword) The number of individual simulation paths to plot as semi-transparent lines (defaults to 50).
Returns
- A
Makie.Figureobject containing the generated plot.
BrandtSolver.plot_policy_surface — Method
plot_policy_surface(future_policies, solver_params, t_idx, state_values::AbstractVector, state_name::String, asset_names)Generates a 3D surface plot visualizing the optimal portfolio weight as a joint function of both Wealth ($W$) and a specific state variable at decision time t_idx.
This provides a comprehensive view of the agent's full policy rule, showing how intertemporal hedging demands (driven by the state variable) interact with risk aversion (driven by wealth).
Arguments
future_policies: The nested vector of interpolated policy functions.solver_params: The configuration parameters used to extractW_grid.t_idx: The decision time step to evaluate.state_values: A vector containing the cross-sectional values of the state variable att_idx.state_name: A string label for the state variable used for the y-axis.asset_names: A list of strings representing the asset names.
Returns
- A
Makie.Figureobject containing the generated 3D surface plot.
BrandtSolver.plot_realized_weights — Method
plot_realized_weights(Re_all_paths, X_all_paths, Y_all_paths, times, future_policies,
asset_names; W_init=100.0)Simulates wealth paths forward in time using the computed optimal future_policies and plots the realized trajectories of the portfolio weights over the lifecycle.
It overlays the mean realized weight and a 90% confidence interval band. Paths where wealth falls to zero (bankruptcy) are dynamically filtered out.
Arguments
Re_all_paths: A matrix(sims × steps)ofSVectors representing excess returns.X_all_paths: A matrix(sims × steps)of gross risk-free returns.Y_all_paths: A matrix(sims × steps)of non-tradable income yields.times: An iterable of time points corresponding to the decision steps.future_policies: The nested vector of interpolated policy functions.asset_names: A list of strings representing the asset names.W_init: (Keyword) The initial wealth to start the forward simulation (defaults to 100.0).
Returns
- A
Makie.Figureobject containing the generated plot.
BrandtSolver.plot_state_dependence — Method
plot_state_dependence(future_policies, solver_params, t_idx, state_values::AbstractVector,
state_name::String, asset_names; fix_W=100.0)Plots the sensitivity of the optimal portfolio weights to a specific state variable (e.g., interest rate or dividend yield), holding wealth strictly constant at fix_W.
Arguments
future_policies: The nested vector of interpolated policy functions.solver_params: The configuration parameters.t_idx: The decision time step to evaluate.state_values: A vector containing the cross-sectional values of the state variable att_idx.state_name: A string label for the state variable used for the x-axis.asset_names: A list of strings representing the asset names.fix_W: (Keyword) The constant wealth level at which to evaluate the policy (defaults to 100.0).
Returns
- A
Makie.Figureobject containing the generated plot.
BrandtSolver.plot_value_vs_utility — Method
plot_value_vs_utility(Re_all_paths, X_all_paths, Y_all_paths, solver_params, future_policies,
utility_struct; t_check=nothing)Serves as an economic validity check by plotting the forward-simulated expected utility (the Value function, $J(W)$) against the theoretical terminal utility function $U(W)$.
If the solver is working correctly, the expected utility $J(W)$ evaluated at $T - 1$ should be equal to $U(W)$, representing the value added by optimal dynamic trading.
Arguments
Re_all_paths: A matrix ofSVectors representing excess returns.X_all_paths: A matrix of gross risk-free returns.Y_all_paths: A matrix of non-tradable income yields.solver_params: The configuration parameters used to extractW_grid.future_policies: The nested vector of interpolated policy functions.utility_struct: The utility container.t_check: (Keyword) The specific time step to evaluate. Defaults toT-1.
Returns
- A
Makie.Figureobject containing the generated plot.
BrandtSolver.power_matrix — Method
power_matrix(Z::Vector{Vector{Float64}}, p::Int)Constructs a design matrix (feature matrix) for a polynomial regression model.
It generates power terms (e.g., x, x^2, ..., x^p) for each predictor variable in Z and prepends a column of ones to serve as the intercept term.
The final column order is: [intercept, Z[1]^1, Z[1]^2, ..., Z[1]^p, Z[2]^1, Z[2]^2, ..., Z[2]^p, ...]
Arguments
Z::Vector{Vector{Float64}}: A vector of predictor variables.n = length(Z)is the number of distinct predictor variables, andsim = length(Z[1])is the number of observations (rows). All inner vectors must have the same length.p::Int: The maximum polynomial degree to compute for each predictor.
Returns
Matrix{Float64}: A design matrix of sizesim × (n*p + 1).
Examples
julia> X1 = [1.0, 2.0, 3.0];
julia> X2 = [4.0, 5.0, 6.0];
julia> Z = [X1, X2]; # n=2 predictors, sim=3 observations
julia> p = 2; # Max degree
julia> BrandtSolver.power_matrix(Z, p)
3×5 Matrix{Float64}:
1.0 1.0 1.0 4.0 16.0
1.0 2.0 4.0 5.0 25.0
1.0 3.0 9.0 6.0 36.0BrandtSolver.record_step! — Method
record_step!(recorder, t, w_idx, label, value)Hooks into the solver to save data.
BrandtSolver.simulate_wealth_trajectory — Method
simulate_wealth_trajectory(
W_start_vec::Vector{Float64},
t_start_idx::Int,
T_end_idx::Int,
X_full::AbstractMatrix{Float64},
Y_full::AbstractMatrix{Float64},
Re_full::AbstractMatrix{<:SVector},
future_policies::Vector{Vector{Any}};
forced_policy_at_t_start=nothing,
recorder::AbstractPathRecorder = NoOpPathRecorder()
)Simulates wealth trajectories forward in time across all simulation paths from t_start_idx to T_end_idx.
At each time step, the function determines the portfolio weights (either using forced_policy_at_t_start for the initial step or querying the interpolated future_policies for subsequent steps). It then advances wealth using the calculate_next_wealth physics kernel.
Arguments
W_start_vec::Vector{Float64}: Initial wealth values for all simulation paths att_start_idx.t_start_idx::Int: The starting time step index.T_end_idx::Int: The terminal time step index.X_full::AbstractMatrix{Float64}: Abstract matrix(sims × steps)of gross risk-free returns.Y_full::AbstractMatrix{Float64}: Abstract matrix(sims × steps)of non-tradable income yields.Re_full::AbstractMatrix{<:SVector}: Abstract matrix(sims × steps)ofSVectorexcess returns.future_policies::Vector{Vector{Any}}: A nested vector of interpolated policies for future time steps.forced_policy_at_t_start: Optional portfolio weight(s) to strictly apply att_start_idx. Can be a singleSVectoror aVectorofSVectors.recorder::AbstractPathRecorder: A logging mechanism to record the simulated wealth paths (defaults toNoOpPathRecorder()).
Returns
- A tuple
(W_t_plus_1, W_T):W_t_plus_1::Vector{Float64}: Wealth at the immediate next time step (t_start_idx + 1). This is captured and returned because it acts as the base expansion point in the denominator of the Brandt equation.W_T::Vector{Float64}: Terminal wealth atT_end_idx.
BrandtSolver.solve_2nd_order_policy — Method
solve_2nd_order_policy(expected_moments_i, W_t, N_assets)Solves for the optimal portfolio weights using a 2nd-order Taylor expansion of the value function.
By truncating at the second order, the First Order Conditions (FOCs) reduce to a standard system of linear equations. A dynamic regularization term (jitter) is automatically scaled and added to the diagonal of the covariance-like matrix B_mat to guarantee numerical stability and invertibility, especially when dealing with nearly perfectly correlated assets or zero-variance states.
Arguments
expected_moments_i::Dict{Vector{Int}, Vector{Float64}}: A dictionary mapping the cross-asset monomial exponent vectors to their conditionally expected values for a specific simulation path.W_t::Float64: The agent's specific wealth level at the current decision time.N_assets::Int: The total number of tradable risky assets in the market.
Returns
Vector{Float64}: The optimal allocation weights for the risky assets.
BrandtSolver.solve_higher_order_policy — Method
solve_higher_order_policy(expected_moments_i, W_t, N_assets, max_taylor_order)Solves for the optimal portfolio weights using an arbitrary max_taylor_order expansion of the FOC.
If max_taylor_order == 2, it bypasses the non-linear solver entirely and efficiently returns the analytical linear solution via solve_2nd_order_policy. For orders strictly greater than 2, it dynamically generates the non-linear First Order Conditions (FOCs) using multiexponents and solves for the roots using NonlinearSolve.jl.
The analytical 2nd-order solution is injected as the initial guess to ensure rapid and stable convergence of the non-linear solver.
Arguments
expected_moments_i::Dict{Vector{Int}, Vector{Float64}}: A dictionary mapping the cross-asset monomial exponent vectors to their conditionally expected values for a specific simulation path.W_t::Float64: The agent's specific wealth level at the current decision time.N_assets::Int: The total number of tradable risky assets in the market.max_taylor_order::Int: The highest degree of the Taylor expansion to compute (e.g., 4 computes up to the 4th-order expansion).
Returns
Vector{Float64}: The optimal allocation weights for the risky assets. If the non-linear solver fails to converge, the algorithm safely falls back to returning the 2nd-order analytical solution.
BrandtSolver.solve_portfolio_problem — Method
solve_portfolio_problem(
Re_all_paths::AbstractMatrix{<:SVector},
Z_all_paths::Vector{<:AbstractMatrix{Float64}},
X_all_paths::AbstractMatrix{Float64},
Y_all_paths::AbstractMatrix{Float64},
solver_params::SolverParams,
utility::UtilityFunctions;
recorder::AbstractSolverRecorder = NoOpRecorder()
)The primary entry point for solving the dynamic portfolio choice problem.
It orchestrates the backward recursion (dynamic programming) by iterating backwards from the period before terminal time, T-1, to period 1. At each step, it calculates the optimal policies conditionally based on the optimal future_policies derived in the previous iterations.
Arguments
Re_all_paths::AbstractMatrix{<:SVector}: A matrix(sims × steps)ofSVectors representing excess returns.Z_all_paths::Vector{<:AbstractMatrix{Float64}}: A vector containing the state variable matrices.X_all_paths::AbstractMatrix{Float64}: The base gross risk-free return matrix.Y_all_paths::AbstractMatrix{Float64}: The non-tradable income return matrix.solver_params::SolverParams: Configuration parameters (e.g.,W_grid, polynomial orders).utility::UtilityFunctions: The configured utility and derivatives functions.recorder::AbstractSolverRecorder: An optional recorder to log intermediate steps (defaults toNoOpRecorder()).
Returns
future_policies: A nested vector structure[time_step][simulation_path](Wealth)that holds the full interpolated policy rules for every path at every time step.