Test

BrandtSolver.SolverParamsType
struct SolverParams

Configuration 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.

source
BrandtSolver.TrimmedOLSType

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).
source
BrandtSolver.UtilityFunctionsType
struct UtilityFunctions

A container for the utility function, its derivatives, and its inverse.

Arguments

  • u::Function: The base utility function U(W).

  • nth_derivative::Function: A function f(n) that returns a function for the n-th derivative of U(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.

source
BrandtSolver.calculate_expected_utilityMethod
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) of SVectors 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 at t_start. Can be a single SVector (applied to all paths) or a Vector of SVectors (path-dependent weights).
  • utility_struct::UtilityFunctions: The configured UtilityFunctions containing the base utility u and its inverse.

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).
source
BrandtSolver.calculate_next_wealthMethod
 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$.
source
BrandtSolver.calculate_realized_termMethod
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 of SVector excess returns at time $t+1$.
  • utility::UtilityFunctions: The UtilityFunctions struct 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.
source
BrandtSolver.compute_and_regress_momentsMethod
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 of SVectors 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., StandardOLS or TrimmedOLS).

Returns

  • Dict{Vector{Int}, Matrix{Float64}}: A dictionary mapping the cross-asset monomial exponent vectors (k_vec) to their conditionally expected values (a sims × N_assets matrix).
source
BrandtSolver.compute_conditional_expectationMethod
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., a Factorization object for StandardOLS or a raw matrix for TrimmedOLS).
  • φ::Union{Nothing, AbstractMatrix{Float64}}: The polynomial expansion of the state variables (design matrix). Will be nothing at $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.
source
BrandtSolver.compute_expectations_and_policyMethod
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 containing u and its derivatives.
  • future_policies::Vector: The optimal policy interpolators for time periods t > t_decision.
  • reg_strategy::RegressionStrategy: The OLS strategy (Standard or Trimmed).

Returns

  • ω_t_svec: A vector of SVectors 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.
source
BrandtSolver.create_policy_interpolatorsMethod
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 of SVector excess returns.
  • T_steps::Int: Total number of time steps.
  • utility::UtilityFunctions: The UtilityFunctions struct.
  • 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 Vector of linear interpolation objects (one for each simulation path). Each interpolator takes a wealth value W and returns the optimal portfolio allocation vector ω.
source
BrandtSolver.create_utility_from_adMethod
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.derivative recursively 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 UtilityFunctions struct.
source
BrandtSolver.estimate_coefficientsMethod
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 Φ (from qr(Φ)).
  • Y::AbstractVector{Float64}: The dependent variable (response vector).

Returns

  • Vector{Float64}: The estimated coefficients θ minimizing ||Φθ - Y||².
source
BrandtSolver.estimate_coefficientsMethod
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 parameter strat.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 of Y.
  • Y::AbstractVector{Float64}: The dependent variable (response vector).

Algorithm

  1. Calculates integer indices corresponding to the α and 1-α quantiles.
  2. Sorts Y to identify the "body" of the distribution.
  3. Subsets both Y and Φ to exclude the extreme tails.
  4. Solves standard OLS on the remaining subset.

Returns

  • Vector{Float64}: The estimated coefficients θ based on the trimmed dataset.
source
BrandtSolver.plot_policy_rulesMethod
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 the W_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.Figure object containing the generated plot.
source
BrandtSolver.plot_policy_surfaceMethod
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 extract W_grid.
  • t_idx: The decision time step to evaluate.
  • state_values: A vector containing the cross-sectional values of the state variable at t_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.Figure object containing the generated 3D surface plot.
source
BrandtSolver.plot_realized_weightsMethod
 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) of SVectors 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.Figure object containing the generated plot.
source
BrandtSolver.plot_state_dependenceMethod
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 at t_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.Figure object containing the generated plot.
source
BrandtSolver.plot_value_vs_utilityMethod
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 of SVectors 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 extract W_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 to T-1.

Returns

  • A Makie.Figure object containing the generated plot.
source
BrandtSolver.power_matrixMethod
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, and sim = 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 size sim × (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.0
source
BrandtSolver.simulate_wealth_trajectoryMethod
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 at t_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) of SVector excess 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 at t_start_idx. Can be a single SVector or a Vector of SVectors.
  • recorder::AbstractPathRecorder: A logging mechanism to record the simulated wealth paths (defaults to NoOpPathRecorder()).

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 at T_end_idx.
source
BrandtSolver.solve_2nd_order_policyMethod
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.
source
BrandtSolver.solve_higher_order_policyMethod
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.
source
BrandtSolver.solve_portfolio_problemMethod
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) of SVectors 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 to NoOpRecorder()).

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.
source