# Regret Optimizer¶

The RegretOptimizer inherits the DiscreteUncertaintyOptimizer. The minimum regret optimization is a technique under decision theory on making decisions under uncertainty.

class allopy.optimize.RegretOptimizer(num_assets, num_scenarios, prob=None, algorithm=40, c_eps=None, xtol_abs=None, xtol_rel=None, ftol_abs=None, ftol_rel=None, max_eval=None, verbose=False, sum_to_1=True, max_attempts=5)[source]
__init__(num_assets, num_scenarios, prob=None, algorithm=40, c_eps=None, xtol_abs=None, xtol_rel=None, ftol_abs=None, ftol_rel=None, max_eval=None, verbose=False, sum_to_1=True, max_attempts=5)[source]

The RegretOptimizer is a convenience class for scenario based optimization.

Notes

The term regret refers to the instance where after having decided on one alternative, the choice of a different alternative would have led to a more optimal (better) outcome when the eventual scenario transpires.

The RegretOptimizer employs a 2 stage optimization process. In the first step, the optimizer calculates the optimal weights for each scenario. In the second stage, the optimizer minimizes the regret function to give the final optimal portfolio weights.

Assuming the objective is to maximize returns subject to some volatility constraints, the first stage optimization will be as listed

$\begin{split}\begin{gather*} \underset{w_s}{\max} R_s(w_s) \forall s \in S \\ s.t. \\ \sigma_s(w_s) \leq \Sigma \end{gather*}\end{split}$

where $$R_s(\cdot)$$ is the returns function for scenario $$s$$, $$\sigma_s(\cdot)$$ is the volatility function for scenario $$s$$ and $$\Sigma$$ is the volatility threshold. Subsequently, to minimize the regret across all scenarios, $$S$$,

$\begin{gather*} \underset{w}{\min} \sum_{s \in S} p_s \cdot D(R_s(w_s) - R_s(w)) \end{gather*}$

Where $$D(\cdot)$$ is a distance function (usually quadratic) and $$p_s$$ is the discrete probability of scenario $$s$$ occurring.

Parameters
• num_assets (int) – Number of assets

• num_scenarios (int) – Number of scenarios

• prob (Union[Iterable[float], Iterable[int], ndarray, None]) – Vector containing probability of each scenario occurring

• algorithm – The optimization algorithm. Default algorithm is Sequential Least Squares Quadratic Programming.

• c_eps (float, optional) – Constraint epsilon is the tolerance for the inequality and equality constraints functions. Any value that is less than the constraint epsilon is considered to be within the boundary.

• xtol_abs (float or np.ndarray, optional) – Set absolute tolerances on optimization parameters. tol is an array giving the tolerances: stop when an optimization step (or an estimate of the optimum) changes every parameter x[i] by less than tol[i]. For convenience, if a scalar tol is given, it will be used to set the absolute tolerances in all n optimization parameters to the same value. Criterion is disabled if tol is non-positive.

• xtol_rel (float or np.ndarray, optional) – Set relative tolerance on optimization parameters: stop when an optimization step (or an estimate of the optimum) causes a relative change the parameters x by less than tol, i.e. $$\|\Delta x\|_w < tol \cdot \|x\|_w$$ measured by a weighted $$L_1$$ norm $$\|x\|_w = \sum_i w_i |x_i|$$, where the weights $$w_i$$ default to 1. (If there is any chance that the optimal $$\|x\|$$ is close to zero, you might want to set an absolute tolerance with code:xtol_abs as well.) Criterion is disabled if tol is non-positive.

• ftol_abs (float, optional) – Set absolute tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the function value by less than tol. Criterion is disabled if tol is non-positive.

• ftol_rel (float, optional) – Set relative tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the objective function value by less than tol multiplied by the absolute value of the function value. (If there is any chance that your optimum function value is close to zero, you might want to set an absolute tolerance with ftol_abs as well.) Criterion is disabled if tol is non-positive.

• max_eval (int, optional) – Stop when the number of function evaluations exceeds maxeval. (This is not a strict maximum: the number of function evaluations may exceed maxeval slightly, depending upon the algorithm.) Criterion is disabled if maxeval is non-positive.

• verbose (bool) – If True, the optimizer will report its operations

• sum_to_1 (bool) – If true, the optimal weights for each first level scenario must sum to 1.

• max_attempts (int) – Number of times to retry optimization. This is useful when optimization is in a highly unstable or non-convex space.

DiscreteUncertaintyOptimizer

Discrete Uncertainty Optimizer

add_equality_constraint(functions)[source]

Adds the equality constraint function in standard form, A = b. If the gradient of the constraint function is not specified and the algorithm used is a gradient-based one, the optimizer will attempt to insert a smart numerical gradient for it.

The list of functions needs to match the number of scenarios. The function at index 0 will be assigned as a constraint function to the first optimization regime.

Parameters

functions (Callable or List of Callable) – Constraint function. The function signature should be such that the first argument takes in a weight vector and outputs a numeric (float). The second argument is optional and contains the gradient. If given, the user must put adjust the gradients inplace. If only a single function is given, the same function will be used for all the scenarios

add_equality_matrix_constraint(Aeq, beq)[source]

Sets equality constraints in standard matrix form.

For equality, $$\mathbf{A} \cdot \mathbf{x} = \mathbf{b}$$

Parameters
• Aeq ({iterable float, ndarray}) – Equality matrix. Must be 2 dimensional

• beq ({scalar, ndarray}) – Equality vector or scalar. If scalar, it will be propagated

add_inequality_constraint(functions)[source]

Adds the equality constraint function in standard form, A <= b. If the gradient of the constraint function is not specified and the algorithm used is a gradient-based one, the optimizer will attempt to insert a smart numerical gradient for it.

The list of functions needs to match the number of scenarios. The function at index 0 will be assigned as a constraint function to the first optimization regime.

Parameters

functions (Callable or List of Callable) – Constraint functions. The function signature should be such that the first argument takes in a weight vector and outputs a numeric (float). The second argument is optional and contains the gradient. If given, the user must put adjust the gradients inplace. If only a single function is given, the same function will be used for all the scenarios

add_inequality_matrix_constraint(A, b)[source]

Sets inequality constraints in standard matrix form.

For inequality, $$\mathbf{A} \cdot \mathbf{x} \leq \mathbf{b}$$

Parameters
• A ({iterable float, ndarray}) – Inequality matrix. Must be 2 dimensional.

• b ({scalar, ndarray}) – Inequality vector or scalar. If scalar, it will be propagated.

property lower_bounds

Lower bound of each variable for all the optimization models in the first and second stages

optimize(x0_first_level=None, x0_prop=None, initial_solution='random', approx=True, dist_func=<ufunc 'square'>, random_state=None)[source]

Finds the minimal regret solution across the range of scenarios

Notes

The exact (actual) objective function to minimize regret is given below,

$\begin{gather*} \underset{w}{\min} \sum_{s \in S} p_s \cdot D(R_s(w_s) - R_s(w)) \end{gather*}$

However, given certain problem formulations where the objective and constraint functions are linear and convex, the problem can be transformed to

$\begin{gather*} \underset{a}{\min} \sum_{s \in S} p_s \cdot D(R_s(w_s) - R_s(W \cdot a)) \end{gather*}$

where $$W$$ is a matrix where each rows represents a single scenario, $$s$$ and each column represents an asset class. This formulation solves for $$a$$ which represents the proportion of each scenario that contributes to the final portfolio weights. Thus if there are 3 scenarios and $$a$$ is [0.3, 0.5, 0.2], it means that the final portfolio took 30% from scenario 1, 50% from scenario 2 and 20% from scenario 3.

This formulation makes a strong assumption that the final minimal regret portfolio is a linear combination of the weights from each scenario’s optimal.

The following lists the options for finding an initial solution for the optimization problem. It is best if the user supplies an initial value instead of using the heuristics provided if the user already knows the region to search.

random

Randomly generates “bound-feasible” starting points for the decision variables. Note that these variables may not fulfil the other constraints. For problems where the bounds have been tightly defined, this often yields a good solution.

min_constraint_norm

Solves the optimization problem listed below. The objective is to minimize the $$L_2$$ norm of the constraint functions while keeping the decision variables bounded by the original problem’s bounds.

$\begin{split}\min | constraint |^2 \\ s.t. \\ LB \leq x \leq UB\end{split}$
Parameters
• x0_first_level (list of list of floats or ndarray, optional) – List of initial solution vector for each scenario optimization. If provided, the list must have the same length at the first dimension as the number of solutions.

• x0_prop (list of floats, optional) – Initial solution vector for the regret optimization (2nd level). This can either be the final optimization weights if approx is False or the scenario proportion otherwise.

• initial_solution (str, optional) – The method to find the initial solution if the initial vector x0 is not specified. Set as None to disable. However, if disabled, the initial vector must be supplied. See notes on Initial Solution for more information

• approx (bool) – If True, a linear approximation will be used to calculate the regret optimal. See Notes.

• dist_func (Callable) – A callable function that will be applied as a distance metric for the regret function. The default is a quadratic function. See Notes.

• random_state (int, optional) – Random seed. Applicable if initial_solution is “random”

Returns

Regret optimal solution weights

Return type

np.ndarray

property prob

Vector containing probability of each scenario occurring

set_bounds(lb, ub)[source]

Sets the lower and upper bound

Parameters
• lb ({int, float, ndarray}) – Vector of lower bounds. If array, must be same length as number of free variables. If float or int, value will be propagated to all variables.

• ub ({int, float, ndarray}) – Vector of upper bounds. If array, must be same length as number of free variables. If float or int, value will be propagated to all variables.

set_epsilon_constraint(eps)[source]

Sets the tolerance for the constraint functions

Parameters

eps (float) – Tolerance

set_ftol_abs(tol)[source]

Set absolute tolerance on objective function value.

The absolute tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the function value by less than tol. Criterion is disabled if tol is non-positive.

Parameters

tol (float) – absolute tolerance of objective function value

set_ftol_rel(tol)[source]

Set relative tolerance on objective function value.

Set relative tolerance on function value: stop when an optimization step (or an estimate of the optimum) changes the objective function value by less than tol multiplied by the absolute value of the function value. (If there is any chance that your optimum function value is close to zero, you might want to set an absolute tolerance with ftol_abs as well.) Criterion is disabled if tol is non-positive.

Parameters

tol (float, optional) – Absolute relative of objective function value

set_max_objective(functions)[source]

Sets the optimizer to maximize the objective function. If gradient of the objective function is not set and the algorithm used to optimize is gradient-based, the optimizer will attempt to insert a smart numerical gradient for it.

The list of functions needs to match the number of scenarios. The function at index 0 will be assigned as the objective function to the first optimization regime.

Parameters

functions (Callable or List of Callable) – Objective function. The function signature should be such that the first argument takes in a weight vector and outputs a numeric (float). The second argument is optional and contains the gradient. If given, the user must put adjust the gradients inplace. If only a single function is given, the same function will be used for all the scenarios

set_maxeval(n)[source]

Sets maximum number of objective function evaluations.

Stop when the number of function evaluations exceeds maxeval. (This is not a strict maximum: the number of function evaluations may exceed maxeval slightly, depending upon the algorithm.) Criterion is disabled if maxeval is non-positive.

Parameters

n (int) – maximum number of evaluations

set_meta(*, assets=None, scenarios=None)[source]

Sets meta data which will be used for result summary

Parameters
• assets (list of str, optional) – Names of each asset class

• scenarios (list of str, optional) – Names of each scenario

set_min_objective(functions)[source]

Sets the optimizer to minimize the objective function. If gradient of the objective function is not set and the algorithm used to optimize is gradient-based, the optimizer will attempt to insert a smart numerical gradient for it.

The list of functions needs to match the number of scenarios. The function at index 0 will be assigned as the objective function to the first optimization regime.

Parameters

functions (Callable or List of Callable) – Objective function. The function signature should be such that the first argument takes in a weight vector and outputs a numeric (float). The second argument is optional and contains the gradient. If given, the user must put adjust the gradients inplace. If only a single function is given, the same function will be used for all the scenarios

set_xtol_abs(tol)[source]

Sets absolute tolerances on optimization parameters.

The absolute tolerances on optimization parameters. tol is an array giving the tolerances: stop when an optimization step (or an estimate of the optimum) changes every parameter x[i] by less than tol[i]. For convenience, if a scalar tol is given, it will be used to set the absolute tolerances in all n optimization parameters to the same value. Criterion is disabled if tol is non-positive.

Parameters

tol (float or np.ndarray) – Absolute tolerance for each of the free variables

set_xtol_rel(tol)[source]

Sets relative tolerances on optimization parameters.

Set relative tolerance on optimization parameters: stop when an optimization step (or an estimate of the optimum) causes a relative change the parameters x by less than tol, i.e. $$\|\Delta x\|_w < tol \cdot \|x\|_w$$ measured by a weighted $$L_1$$ norm $$\|x\|_w = \sum_i w_i |x_i|$$, where the weights $$w_i$$ default to 1. (If there is any chance that the optimal $$\|x\|$$ is close to zero, you might want to set an absolute tolerance with code:xtol_abs as well.) Criterion is disabled if tol is non-positive.

Parameters

tol (float or np.ndarray) – relative tolerance for each of the free variables

property upper_bounds

Upper bound of each variable for all the optimization models in the first and second stages