Portfolio Optimization: Factor Model#
Description: Mean-Variance Portfolio Optimization model where the risk estimator is not given explicitly but is instead represented by a factor model, as is common in US equity models [1]. The original notebook is [3].
Tags: finance, portfolio optimization, mean variance, factor model, AMPL conditonal instantiation, cardinality constraint
Notebook author: Gleb Belov <gleb@ampl.com>
References:
[1] Menchero, J., Orr, D., Wang, J.: The Barra US equity model (USE4), methodology notes. English, MSCI. May 2011.
[2] Gérard Cornuéjols, Javier Peña, and Reha Tütüncü. Optimization Methods in Finance. Cambridge University Press, 2 edition, 2018. doi:10.1017/9781107297340.
[3] Gurobi. Factor Model as Objective. https://gurobi-finance.readthedocs.io/en/latest/modeling_notebooks/factor_models_objective.html, accessed Nov 3, 2025.
[4] Mosek ApS. Ferrari, factorizing, and portfolios in conic form. https://themosekblog.blogspot.com/2024/03/ferrari-factorizing-and-portfolios-in.html, accessed Nov 4, 2025.
# Install dependencies
%pip install -q amplpy pandas numpy matplotlib
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook
ampl = ampl_notebook(
modules=["gurobi", "mosek", "highs"], # modules to install
license_uuid="default", # license to use
) # instantiate AMPL object and register magics
# Import extras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
Background#
The standard mean-variance (Markowitz) portfolio selection model determines optimal investments that balance risk and expected return. In this notebook, we maximize utility, which is defined as a weighted linear function of return and risk that can be adjusted by varying the risk-aversion coefficient \(\gamma\).
The standard formulation of this problem on \(n\) assets reads
where \(\mu \in \mathbf{R}^n\) is the return estimator, \(\Sigma \in \mathbf{R}^{n,n}\) is used as an estimator for the variance, and \(1_n\) is the vector of \(n\) ones. While it is certainly possible that the matrix \(\Sigma\) is given explicitly (e.g., as the covariance matrix of a time series), it is often expressed implicitly through a factor model. In that case, the matrix \(\Sigma\) takes the form
where
\(X \in \mathbf{R}^{n,k}\) is the factor exposure matrix,
\(\Sigma_0 \in \mathbf{R}^{k,k}\) is the symmetric positive definite (SPD) factor covariance matrix, and
\(D \in \mathbf{R}^{n,n}\) is the diagonal matrix of specific risks with \(d_{ii} > 0\) for all \(i\).
Effectively, this splits the risk into two sources: One that arises from common risk factors (macroeconomic conditions, market trends, etc.) and a specific risk that is uncorrelated among the assets. The number of factors, \(k\), is typically much smaller than the number \(n\) of assets.
The important observation from a computational point of view is the following: The factor model data is of size \(nk + n\) (with \(k \ll n\)), while the covariance matrix \(\Sigma\) is on the order of \(n^2\). As we will see, optimization models using the factor model admit a smaller representation and typically offer improved computational performance.
A synthetic factor model#
Leading industry factor models are commercial products that are not necessary for our demonstration purposes. We are more interested in a qualitative comparison of solver performance using some factor model than in the actual economic meaning. For this reason, our first step will be to create a simple, synthetic multivariate factor model that we can use in the study that follows.
The following function uses an uncorrelated factor covariance matrix \(\Sigma_0\) that is used for sampling a multivariate normal distribution on num_factors factors along time_steps sampling points for num_assets assets:
def factor_model(num_assets, num_factors, timesteps):
# Generate random factor model, risk is X * sigma0 * X.T + cov(u)
sigma0 = np.diag(1 + np.arange(num_factors) + np.random.rand(num_factors))
X = np.random.normal(size=(num_assets, num_factors))
alpha = np.random.normal(loc=1, size=(num_assets, 1))
u = np.random.multivariate_normal(
np.zeros(num_assets), np.eye(num_assets), timesteps
).T
d = np.diag(np.cov(u)) # NOTE: This is the _diagonal_ of D!
# Time series in factor space
TS_factor = np.random.multivariate_normal(
np.zeros(num_factors), sigma0, timesteps
).T
# Estimate mu from time series in full space
mu = np.mean(alpha + X @ TS_factor + u, axis=1)
return X, sigma0, d, mu
We skip the details of this statistical procedure for constructing \(X\), \(\Sigma_0\), \(D\), and \(\mu\); more background and details can be found in [2, Sect. 6.6]. The essential point is that we now have a synthetic factor model that acts similarly to a commercial factor model regarding solver performance.
Taking advantage of the factor model structure#
Ignoring the constant factor \(\frac{1}{2}\gamma\) for a moment, the objective function we want to maximize includes
The first term, \(x^T X \Sigma_0 X^T x\), would result in a quadratic function having \((n+1)\frac n2\) terms. Since \(\Sigma_0\) is SPD, it admits a Cholesky factorization \(\Sigma_0 = LL^T\) where \(L \in \mathbf{R}^{k,k}\) is a triangular matrix. This allows us to rewrite the first term as
where we have substituted \(y = B^T x\) in the last step. Also, note that \(B = X L \in \mathbf{R}^{n, k}\) comprises only \(nk\) elements.
The second term, \(x^T D x\), comprises only \(n\) terms (i.e., \(\sum_i d_{ii} x_{i}^2\)) and can be used as is. Putting this together, the standard optimization model (1) can be rewritten as
Note that the \(k\) variables \(y\) do not have bound constraints. Model (2) contains the much smaller matrix \(B\) instead of \(\Sigma\) in model (1), at the expense of \(k\) additional optimization variables. Generally, form (2) is advantageous for solver performance; we shall compare both in the next step.
Comparing the two optimization models#
In order to compare the solution times for models (1) and (2) above, we will define an AMPL model translating into either (1) or (2) depending on parameter want_factor_model.
Use %%writefile to save AMPL model (see AMPLPY Best Practices)#
%%writefile portfolio_sigma_factors.mod
set ASSETS;
set FACTORS default {};
# Parameters
param want_factor_model default 1; # Model (1) or (2)
param expected_return {ASSETS};
param risk_free_rate; # gamma
# The below parameters are needed depending on want_factor_model
param factor_loadings {ASSETS, FACTORS};
param asset_specific_risks {ASSETS};
param asset_cov {ASSETS, ASSETS}; # The full matrix
# Variables
var weight {ASSETS} >=0 <=1; # Asset weights
var portfolio_return = sum {i in ASSETS} weight[i] * expected_return[i];
# factor_exposure should be non-defined variables.
# Only instantiate if want_factor_model!=0
var factor_exposure {FACTORS: want_factor_model};
var portfolio_variance =
if want_factor_model
then
sum {f in FACTORS} factor_exposure[f]^2
+ sum {a in ASSETS} asset_specific_risks[a] * weight[a]^2
else
sum {a1 in ASSETS, a2 in ASSETS}
asset_cov[a1, a2] * weight[a1] * weight[a2];
# Objective: Minimize utility: expected return + portfolio variance
maximize Utility:
portfolio_return - risk_free_rate / 2.0 * portfolio_variance;
# Constraints
subject to BudgetConstraint:
sum{i in ASSETS} weight[i] == 1;
# This definition constraint only instantiates
# if want_factor_model!=0
subject to FactorExposureDefinition{f in FACTORS: want_factor_model}:
factor_exposure[f] == sum{i in ASSETS} weight[i] * factor_loadings[i, f];
Overwriting portfolio_sigma_factors.mod
Now we define two auxiliary functions to build an optimization model in either form using AMPLPY. Let’s start with a function for the traditional form (1):
def build_sigma_model(gamma, sigma, mu):
ampl.reset()
ampl.read("portfolio_sigma_factors.mod")
ampl.param["want_factor_model"] = 0
ampl.set["ASSETS"] = range(1, mu.shape[0] + 1)
ampl.param["expected_return"] = mu
ampl.param["factor_loadings"] = []
ampl.param["asset_specific_risks"] = []
ampl.param["asset_cov"] = sigma
ampl.param["risk_free_rate"] = gamma
The second function builds the equivalent model (2):
def build_factor_model(gamma, B, d, mu):
ampl.reset()
ampl.read("portfolio_sigma_factors.mod")
ampl.param["want_factor_model"] = 1
ampl.set["ASSETS"] = range(1, mu.shape[0] + 1)
ampl.set["FACTORS"] = range(1, B.shape[1] + 1)
ampl.param["expected_return"] = mu
ampl.param["factor_loadings"] = B
ampl.param["asset_specific_risks"] = d
ampl.param["asset_cov"] = []
ampl.param["risk_free_rate"] = gamma
We are now ready to run a small benchmark. We will keep a fixed risk aversion coefficient \(\gamma\), and solve both models over a range of data with an increasing number of assets:
def RunBenchmark(
ampl_options={"solver": "gurobi", "gurobi_options": {"numericfocus": 3}}
):
np.random.seed(0xACAC) # Fix seed for reproducibility
num_factors = 72 # USE4 has 72 factors, too (see [1])
timesteps = 700
gamma = 0.025
problem_dims = np.linspace(100, 750, 16, endpoint=True, dtype=int)
time_sigma = []
time_factor = []
if "mp_options" not in ampl_options:
ampl_options["mp_options"] = {}
ampl_options["mp_options"]["tech:timing"] = 2 # For Initial.time_solver
ampl.option = ampl_options
for num_assets in problem_dims:
X, sigma0, d, mu = factor_model(num_assets, num_factors, timesteps)
print("Running with", num_assets, "of", problem_dims[-1], "assets: sigma...")
sigma = X @ sigma0 @ X.T + np.diag(d)
build_sigma_model(gamma, sigma, mu)
ampl.snapshot("portfolio_sigma.run")
ampl.solve()
time_sigma.append(ampl.get_value("Initial.time_solver"))
print(
"Running with",
num_assets,
"of",
problem_dims[-1],
"assets: factor model...",
)
L = np.linalg.cholesky(sigma0)
B = X @ L
build_factor_model(gamma, B, d, mu)
ampl.snapshot("portfolio_factors.run")
ampl.solve()
time_factor.append(ampl.get_value("Initial.time_solver"))
print(" ...done ---------------------------------------")
return problem_dims, time_sigma, time_factor
Graphical output code#
def Plot(problem_dims, time_sigma, time_factor, caption):
fig, ax = plt.subplots()
ax.plot(problem_dims, time_sigma, c="blue", marker="o", label="sigma")
ax.plot(problem_dims, time_factor, c="red", marker="o", label="factor")
ax.legend()
plt.title(caption)
plt.xlabel("No. assets")
plt.ylabel("Solution time (sec.)")
plt.grid(True)
plt.close(fig)
return fig
Runner wrapper#
def BenchmarkSolver(solver, options={"gurobi_options": {"outlev": 0, "timing": 2}}):
options["solver"] = solver
p_dims, time_sigma, time_factor = RunBenchmark(options)
fig = Plot(p_dims, time_sigma, time_factor, solver.capitalize() + " benchmark")
return fig
Run with different solvers#
fig = BenchmarkSolver("gurobi")
Running with 100 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
/Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/massage.h:98:34: runtime error: signed integer overflow: 33 * 489929840339196788 cannot be represented in type 'long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/massage.h:98:34
/Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/massage.h:98:37: runtime error: signed integer overflow: 7842240797665118548 + 6386558351771823828 cannot be represented in type 'long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/massage.h:98:37
/Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/massage.h:98:34: runtime error: signed integer overflow: 33 * 556558325256565636 cannot be represented in type 'long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/massage.h:98:34
/Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/collect.c:1424:9: runtime error: applying non-zero offset 8 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/collect.c:1424:9
NL model read time = 0.022245s
NL model conversion time = 0.045357s
Gurobi 13.0.0: optimal solution; objective 2.889499366
0 simplex iterations
11 barrier iterations
Setup time = 0.081387s
Solver time = 0.007210s
Output time = 0.000009s
Total time = 0.088606s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 100 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.006218s
NL model conversion time = 0.008540s
Gurobi 13.0.0: optimal solution; objective 2.889499372
0 simplex iterations
14 barrier iterations
Setup time = 0.016534s
Solver time = 0.004845s
Output time = 0.000010s
Total time = 0.021390s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 143 of 750 assets: sigma...
Gurobi 13.0.0:
/Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/func.c:1375:14: runtime error: member access within null pointer of type 'Library'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Users/gb5/Documents/prj/AMPL/escrow/cmake/acl/func.c:1375:14
tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.014339s
NL model conversion time = 0.082731s
Gurobi 13.0.0: optimal solution; objective 3.050585815
0 simplex iterations
12 barrier iterations
Setup time = 0.098607s
Solver time = 0.012008s
Output time = 0.000016s
Total time = 0.110631s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 143 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.006343s
NL model conversion time = 0.011266s
Gurobi 13.0.0: optimal solution; objective 3.050585815
0 simplex iterations
15 barrier iterations
Setup time = 0.019190s
Solver time = 0.006760s
Output time = 0.000010s
Total time = 0.025960s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 186 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.020559s
NL model conversion time = 0.139035s
Gurobi 13.0.0: optimal solution; objective 3.285445494
0 simplex iterations
13 barrier iterations
Setup time = 0.161120s
Solver time = 0.019432s
Output time = 0.000018s
Total time = 0.180570s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 186 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.006181s
NL model conversion time = 0.014015s
Gurobi 13.0.0: optimal solution; objective 3.285445494
0 simplex iterations
15 barrier iterations
Setup time = 0.021770s
Solver time = 0.008381s
Output time = 0.000008s
Total time = 0.030159s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 230 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.028753s
NL model conversion time = 0.212300s
Gurobi 13.0.0: optimal solution; objective 3.256968483
0 simplex iterations
13 barrier iterations
Setup time = 0.242593s
Solver time = 0.026633s
Output time = 0.000015s
Total time = 0.269241s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 230 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.007897s
NL model conversion time = 0.016968s
Gurobi 13.0.0: optimal solution; objective 3.256968498
0 simplex iterations
16 barrier iterations
Setup time = 0.026446s
Solver time = 0.011402s
Output time = 0.000009s
Total time = 0.037857s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 273 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.038867s
NL model conversion time = 0.299201s
Gurobi 13.0.0: optimal solution; objective 3.405238096
0 simplex iterations
12 barrier iterations
Setup time = 0.339594s
Solver time = 0.035039s
Output time = 0.000016s
Total time = 0.374648s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 273 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.007107s
NL model conversion time = 0.019740s
Gurobi 13.0.0: optimal solution; objective 3.405238098
0 simplex iterations
16 barrier iterations
Setup time = 0.028442s
Solver time = 0.011731s
Output time = 0.000009s
Total time = 0.040182s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 316 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.049610s
NL model conversion time = 0.400795s
Gurobi 13.0.0: optimal solution; objective 3.382498578
0 simplex iterations
14 barrier iterations
Setup time = 0.451923s
Solver time = 0.060313s
Output time = 0.000012s
Total time = 0.512249s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 316 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.007126s
NL model conversion time = 0.022612s
Gurobi 13.0.0: optimal solution; objective 3.382498581
0 simplex iterations
17 barrier iterations
Setup time = 0.031235s
Solver time = 0.016410s
Output time = 0.000015s
Total time = 0.047659s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 360 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.063799s
NL model conversion time = 0.523210s
Gurobi 13.0.0: optimal solution; objective 3.727943459
0 simplex iterations
14 barrier iterations
Setup time = 0.588579s
Solver time = 0.073050s
Output time = 0.000014s
Total time = 0.661644s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 360 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.007188s
NL model conversion time = 0.025309s
Gurobi 13.0.0: optimal solution; objective 3.727943459
0 simplex iterations
15 barrier iterations
Setup time = 0.033992s
Solver time = 0.012820s
Output time = 0.000014s
Total time = 0.046825s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 403 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.077972s
NL model conversion time = 0.656408s
Gurobi 13.0.0: optimal solution; objective 3.991145637
0 simplex iterations
13 barrier iterations
Setup time = 0.735927s
Solver time = 0.088037s
Output time = 0.000019s
Total time = 0.823982s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 403 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.008917s
NL model conversion time = 0.028200s
Gurobi 13.0.0: optimal solution; objective 3.991145637
0 simplex iterations
15 barrier iterations
Setup time = 0.038662s
Solver time = 0.013863s
Output time = 0.000015s
Total time = 0.052541s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 446 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.092709s
NL model conversion time = 0.798175s
Gurobi 13.0.0: optimal solution; objective 3.951770561
0 simplex iterations
14 barrier iterations
Setup time = 0.892443s
Solver time = 0.099403s
Output time = 0.000016s
Total time = 0.991862s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 446 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.007758s
NL model conversion time = 0.031332s
Gurobi 13.0.0: optimal solution; objective 3.951770564
0 simplex iterations
16 barrier iterations
Setup time = 0.040668s
Solver time = 0.015293s
Output time = 0.000008s
Total time = 0.055970s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 490 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.114746s
NL model conversion time = 0.969103s
Gurobi 13.0.0: optimal solution; objective 4.481524759
0 simplex iterations
14 barrier iterations
Setup time = 1.085351s
Solver time = 0.124003s
Output time = 0.000025s
Total time = 1.209378s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 490 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.007727s
NL model conversion time = 0.033897s
Gurobi 13.0.0: optimal solution; objective 4.481524758
0 simplex iterations
16 barrier iterations
Setup time = 0.043120s
Solver time = 0.015872s
Output time = 0.000013s
Total time = 0.059006s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 533 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.132315s
NL model conversion time = 1.140990s
Gurobi 13.0.0: optimal solution; objective 3.468383937
0 simplex iterations
13 barrier iterations
Setup time = 1.274868s
Solver time = 0.136554s
Output time = 0.000016s
Total time = 1.411439s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 533 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.008151s
NL model conversion time = 0.036704s
Gurobi 13.0.0: optimal solution; objective 3.468383954
0 simplex iterations
16 barrier iterations
Setup time = 0.046366s
Solver time = 0.016214s
Output time = 0.000016s
Total time = 0.062596s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 576 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.152646s
NL model conversion time = 1.332237s
Gurobi 13.0.0: optimal solution; objective 3.947223252
0 simplex iterations
13 barrier iterations
Setup time = 1.486423s
Solver time = 0.158098s
Output time = 0.000018s
Total time = 1.644538s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 576 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.008146s
NL model conversion time = 0.039494s
Gurobi 13.0.0: optimal solution; objective 3.947223235
0 simplex iterations
14 barrier iterations
Setup time = 0.049155s
Solver time = 0.015858s
Output time = 0.000014s
Total time = 0.065027s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 620 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.174984s
NL model conversion time = 1.538655s
Gurobi 13.0.0: optimal solution; objective 3.757197193
0 simplex iterations
14 barrier iterations
Setup time = 1.715182s
Solver time = 0.199303s
Output time = 0.000024s
Total time = 1.914509s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 620 of 750 assets: factor model...
tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.008704s
NL model conversion time = 0.042515s
Gurobi 13.0.0: optimal solution; objective 3.757197179
0 simplex iterations
15 barrier iterations
Setup time = 0.052794s
Solver time = 0.018532s
Output time = 0.000014s
Total time = 0.071340s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 663 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.200310s
NL model conversion time = 1.754369s
Gurobi 13.0.0: optimal solution; objective 3.890282998
0 simplex iterations
13 barrier iterations
Setup time = 1.956225s
Solver time = 0.219335s
Output time = 0.000021s
Total time = 2.175581s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 663 of 750 assets: factor model...
tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.008458s
NL model conversion time = 0.045424s
Gurobi 13.0.0: optimal solution; objective 3.890282997
0 simplex iterations
14 barrier iterations
Setup time = 0.055427s
Solver time = 0.017867s
Output time = 0.000014s
Total time = 0.073307s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 706 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.254625s
NL model conversion time = 2.012921s
Gurobi 13.0.0: optimal solution; objective 4.216462571
0 simplex iterations
14 barrier iterations
Setup time = 2.269083s
Solver time = 0.258094s
Output time = 0.000026s
Total time = 2.527203s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 706 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.008560s
NL model conversion time = 0.048164s
Gurobi 13.0.0: optimal solution; objective 4.216462566
0 simplex iterations
15 barrier iterations
Setup time = 0.058285s
Solver time = 0.018849s
Output time = 0.000011s
Total time = 0.077146s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 750 of 750 assets: sigma...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.330849s
NL model conversion time = 2.289885s
Gurobi 13.0.0: optimal solution; objective 4.084297931
0 simplex iterations
14 barrier iterations
Setup time = 2.622394s
Solver time = 0.303686s
Output time = 0.000023s
Total time = 2.926103s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 750 of 750 assets: factor model...
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 0
tech:timing = 2
NL model read time = 0.009082s
NL model conversion time = 0.050856s
Gurobi 13.0.0: optimal solution; objective 4.08429793
0 simplex iterations
15 barrier iterations
Setup time = 0.061465s
Solver time = 0.020074s
Output time = 0.000015s
Total time = 0.081554s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
fig
fig = BenchmarkSolver("mosek")
Running with 100 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.003649s
NL model conversion time = 0.002614s
MOSEK 11.0.29: optimal, termination reason unknown; objective 2.889499379
0 simplex iterations
11 barrier iterations
Setup time = 0.010774s
Solver time = 0.008641s
Output time = 0.000004s
Total time = 0.019419s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 100 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.000780s
NL model conversion time = 0.000380s
MOSEK 11.0.29: optimal, termination reason unknown; objective 2.889499604
0 simplex iterations
10 barrier iterations
Setup time = 0.001513s
Solver time = 0.005062s
Output time = 0.000008s
Total time = 0.006583s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 143 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.003460s
NL model conversion time = 0.002965s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.050585172
0 simplex iterations
11 barrier iterations
Setup time = 0.006790s
Solver time = 0.008689s
Output time = 0.000005s
Total time = 0.015484s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 143 of 750 assets: factor model...
tech:timing = 2
NL model read time = 0.000856s
NL model conversion time = 0.000481s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.05058624
0 simplex iterations
10 barrier iterations
Setup time = 0.001751s
Solver time = 0.006116s
Output time = 0.000008s
Total time = 0.007875s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 186 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.005474s
NL model conversion time = 0.004833s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.285445494
0 simplex iterations
10 barrier iterations
Setup time = 0.010676s
Solver time = 0.012178s
Output time = 0.000012s
Total time = 0.022865s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 186 of 750 assets: factor model...
tech:timing = 2
NL model read time = 0.000863s
NL model conversion time = 0.000555s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.2854455
0 simplex iterations
9 barrier iterations
Setup time = 0.001781s
Solver time = 0.006979s
Output time = 0.000006s
Total time = 0.008766s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 230 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.008205s
NL model conversion time = 0.007580s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.256964287
0 simplex iterations
9 barrier iterations
Setup time = 0.016167s
Solver time = 0.017687s
Output time = 0.000008s
Total time = 0.033861s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 230 of 750 assets: factor model...
tech:timing = 2
NL model read time = 0.000922s
NL model conversion time = 0.000612s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.25696976
0 simplex iterations
10 barrier iterations
Setup time = 0.001891s
Solver time = 0.008455s
Output time = 0.000006s
Total time = 0.010353s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 273 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.011388s
NL model conversion time = 0.011301s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.405237857
0 simplex iterations
8 barrier iterations
Setup time = 0.023060s
Solver time = 0.025908s
Output time = 0.000008s
Total time = 0.048976s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 273 of 750 assets: factor model...
tech:timing = 2
NL model read time = 0.000905s
NL model conversion time = 0.000682s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.405238099
0 simplex iterations
10 barrier iterations
Setup time = 0.001956s
Solver time = 0.009566s
Output time = 0.000004s
Total time = 0.011527s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 316 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.014528s
NL model conversion time = 0.015442s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.38248968
0 simplex iterations
10 barrier iterations
Setup time = 0.030343s
Solver time = 0.035470s
Output time = 0.000006s
Total time = 0.065819s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 316 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.000993s
NL model conversion time = 0.000745s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.382499869
0 simplex iterations
10 barrier iterations
Setup time = 0.002138s
Solver time = 0.010682s
Output time = 0.000006s
Total time = 0.012826s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 360 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.019554s
NL model conversion time = 0.022926s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.727936326
0 simplex iterations
12 barrier iterations
Setup time = 0.042850s
Solver time = 0.047704s
Output time = 0.000009s
Total time = 0.090563s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 360 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001012s
NL model conversion time = 0.000845s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.727944316
0 simplex iterations
10 barrier iterations
Setup time = 0.002222s
Solver time = 0.011362s
Output time = 0.000004s
Total time = 0.013588s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 403 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.041465s
NL model conversion time = 0.027353s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.991143579
0 simplex iterations
9 barrier iterations
Setup time = 0.069183s
Solver time = 0.051676s
Output time = 0.000008s
Total time = 0.120867s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 403 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.000940s
NL model conversion time = 0.000907s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.991146675
0 simplex iterations
9 barrier iterations
Setup time = 0.002206s
Solver time = 0.012241s
Output time = 0.000004s
Total time = 0.014452s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 446 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.045737s
NL model conversion time = 0.033300s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.95175699
0 simplex iterations
9 barrier iterations
Setup time = 0.079407s
Solver time = 0.064274s
Output time = 0.000009s
Total time = 0.143690s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 446 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001058s
NL model conversion time = 0.000995s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.951770947
0 simplex iterations
11 barrier iterations
Setup time = 0.002405s
Solver time = 0.014635s
Output time = 0.000004s
Total time = 0.017043s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 490 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.058614s
NL model conversion time = 0.043068s
MOSEK 11.0.29: optimal, termination reason unknown; objective 4.481523355
0 simplex iterations
11 barrier iterations
Setup time = 0.102066s
Solver time = 0.082781s
Output time = 0.000012s
Total time = 0.184858s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 490 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001046s
NL model conversion time = 0.001072s
MOSEK 11.0.29: optimal, termination reason unknown; objective 4.481525298
0 simplex iterations
11 barrier iterations
Setup time = 0.002477s
Solver time = 0.015577s
Output time = 0.000004s
Total time = 0.018058s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 533 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.071716s
NL model conversion time = 0.050574s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.46836678
0 simplex iterations
10 barrier iterations
Setup time = 0.122670s
Solver time = 0.094526s
Output time = 0.000007s
Total time = 0.217203s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 533 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001089s
NL model conversion time = 0.001127s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.468384663
0 simplex iterations
11 barrier iterations
Setup time = 0.002579s
Solver time = 0.016884s
Output time = 0.000006s
Total time = 0.019469s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 576 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.076802s
NL model conversion time = 0.059633s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.94722303
0 simplex iterations
11 barrier iterations
Setup time = 0.136805s
Solver time = 0.111880s
Output time = 0.000010s
Total time = 0.248694s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 576 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001123s
NL model conversion time = 0.001195s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.94722337
0 simplex iterations
11 barrier iterations
Setup time = 0.002676s
Solver time = 0.017649s
Output time = 0.000014s
Total time = 0.020338s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 620 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.086316s
NL model conversion time = 0.065536s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.757192416
0 simplex iterations
12 barrier iterations
Setup time = 0.152226s
Solver time = 0.128890s
Output time = 0.000015s
Total time = 0.281131s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 620 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001188s
NL model conversion time = 0.001231s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.757199199
0 simplex iterations
10 barrier iterations
Setup time = 0.002776s
Solver time = 0.018406s
Output time = 0.000008s
Total time = 0.021189s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 663 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.105038s
NL model conversion time = 0.079371s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.890277622
0 simplex iterations
10 barrier iterations
Setup time = 0.184798s
Solver time = 0.135437s
Output time = 0.000009s
Total time = 0.320245s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 663 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001127s
NL model conversion time = 0.001332s
MOSEK 11.0.29: optimal, termination reason unknown; objective 3.890283607
0 simplex iterations
10 barrier iterations
Setup time = 0.002824s
Solver time = 0.019196s
Output time = 0.000013s
Total time = 0.022033s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 706 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.116002s
NL model conversion time = 0.089312s
MOSEK 11.0.29: optimal, termination reason unknown; objective 4.216458356
0 simplex iterations
11 barrier iterations
Setup time = 0.205695s
Solver time = 0.168408s
Output time = 0.000015s
Total time = 0.374118s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 706 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001140s
NL model conversion time = 0.001385s
MOSEK 11.0.29: optimal, termination reason unknown; objective 4.216462746
0 simplex iterations
12 barrier iterations
Setup time = 0.002885s
Solver time = 0.021844s
Output time = 0.000005s
Total time = 0.024734s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 750 of 750 assets: sigma...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.134174s
NL model conversion time = 0.097466s
MOSEK 11.0.29: optimal, termination reason unknown; objective 4.084297436
0 simplex iterations
11 barrier iterations
Setup time = 0.232026s
Solver time = 0.188301s
Output time = 0.000007s
Total time = 0.420334s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 750 of 750 assets: factor model...
MOSEK 11.0.29: tech:timing = 2
NL model read time = 0.001184s
NL model conversion time = 0.001489s
MOSEK 11.0.29: optimal, termination reason unknown; objective 4.084300161
0 simplex iterations
11 barrier iterations
Setup time = 0.003049s
Solver time = 0.021503s
Output time = 0.000005s
Total time = 0.024557s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
fig
fig = BenchmarkSolver("highs", {"highs_options": "tech:threads=8"})
Running with 100 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.002179s
NL model conversion time = 0.002870s
HiGHS 1.11.0: optimal solution; objective 2.889499379
0 simplex iterations
0 barrier iterations
Setup time = 0.010177s
Solver time = 0.002539s
Output time = 0.000006s
Total time = 0.012722s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 100 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000258s
NL model conversion time = 0.000458s
HiGHS 1.11.0: optimal solution; objective 2.889499379
0 simplex iterations
0 barrier iterations
Setup time = 0.001204s
Solver time = 0.004149s
Output time = 0.000004s
Total time = 0.005357s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 143 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.002907s
NL model conversion time = 0.002895s
HiGHS 1.11.0: optimal solution; objective 3.050585816
0 simplex iterations
0 barrier iterations
Setup time = 0.006295s
Solver time = 0.001572s
Output time = 0.000005s
Total time = 0.007873s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 143 of 750 assets: factor model...
tech:timing = 2
tech:threads = 8
NL model read time = 0.000271s
NL model conversion time = 0.000594s
HiGHS 1.11.0: optimal solution; objective 3.050585816
0 simplex iterations
0 barrier iterations
Setup time = 0.001342s
Solver time = 0.005852s
Output time = 0.000004s
Total time = 0.007198s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 186 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.004934s
NL model conversion time = 0.005013s
HiGHS 1.11.0: optimal solution; objective 3.285445494
0 simplex iterations
0 barrier iterations
Setup time = 0.010425s
Solver time = 0.002246s
Output time = 0.000007s
Total time = 0.012678s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 186 of 750 assets: factor model...
tech:timing = 2
tech:threads = 8
NL model read time = 0.000318s
NL model conversion time = 0.000692s
HiGHS 1.11.0: optimal solution; objective 3.285445494
0 simplex iterations
0 barrier iterations
Setup time = 0.001543s
Solver time = 0.007006s
Output time = 0.000003s
Total time = 0.008553s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 230 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.007705s
NL model conversion time = 0.007924s
HiGHS 1.11.0: optimal solution; objective 3.256968502
0 simplex iterations
0 barrier iterations
Setup time = 0.016122s
Solver time = 0.003050s
Output time = 0.000006s
Total time = 0.019178s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 230 of 750 assets: factor model...
tech:timing = 2
tech:threads = 8
NL model read time = 0.000337s
NL model conversion time = 0.000793s
HiGHS 1.11.0: optimal solution; objective 3.256968502
0 simplex iterations
0 barrier iterations
Setup time = 0.001596s
Solver time = 0.009040s
Output time = 0.000003s
Total time = 0.010639s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 273 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.010946s
NL model conversion time = 0.011876s
HiGHS 1.11.0: optimal solution; objective 3.405238098
0 simplex iterations
0 barrier iterations
Setup time = 0.023306s
Solver time = 0.003764s
Output time = 0.000005s
Total time = 0.027075s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 273 of 750 assets: factor model...
tech:timing = 2
tech:threads = 8
NL model read time = 0.000359s
NL model conversion time = 0.000871s
HiGHS 1.11.0: optimal solution; objective 3.405238098
0 simplex iterations
0 barrier iterations
Setup time = 0.001703s
Solver time = 0.009902s
Output time = 0.000004s
Total time = 0.011609s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 316 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.014008s
NL model conversion time = 0.016255s
HiGHS 1.11.0: optimal solution; objective 3.382498583
0 simplex iterations
0 barrier iterations
Setup time = 0.030740s
Solver time = 0.004803s
Output time = 0.000006s
Total time = 0.035548s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 316 of 750 assets: factor model...
tech:timing = 2
tech:threads = 8
NL model read time = 0.000385s
NL model conversion time = 0.001004s
HiGHS 1.11.0: optimal solution; objective 3.382498583
0 simplex iterations
0 barrier iterations
Setup time = 0.001901s
Solver time = 0.011957s
Output time = 0.000004s
Total time = 0.013862s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 360 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.033494s
NL model conversion time = 0.024397s
HiGHS 1.11.0: optimal solution; objective 3.727943459
0 simplex iterations
0 barrier iterations
Setup time = 0.058378s
Solver time = 0.005600s
Output time = 0.000007s
Total time = 0.063985s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 360 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000469s
NL model conversion time = 0.001069s
HiGHS 1.11.0: optimal solution; objective 3.727943459
0 simplex iterations
0 barrier iterations
Setup time = 0.002028s
Solver time = 0.012977s
Output time = 0.000004s
Total time = 0.015010s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 403 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.037225s
NL model conversion time = 0.028047s
HiGHS 1.11.0: optimal solution; objective 3.991145637
0 simplex iterations
0 barrier iterations
Setup time = 0.065760s
Solver time = 0.006812s
Output time = 0.000006s
Total time = 0.072578s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 403 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000438s
NL model conversion time = 0.001169s
HiGHS 1.11.0: optimal solution; objective 3.991145637
0 simplex iterations
0 barrier iterations
Setup time = 0.002109s
Solver time = 0.014813s
Output time = 0.000004s
Total time = 0.016926s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 446 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.049512s
NL model conversion time = 0.036083s
HiGHS 1.11.0: optimal solution; objective 3.951770573
0 simplex iterations
0 barrier iterations
Setup time = 0.086111s
Solver time = 0.007070s
Output time = 0.000008s
Total time = 0.093190s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 446 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000501s
NL model conversion time = 0.001277s
HiGHS 1.11.0: optimal solution; objective 3.951770573
0 simplex iterations
0 barrier iterations
Setup time = 0.002260s
Solver time = 0.015186s
Output time = 0.000005s
Total time = 0.017451s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 490 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.053276s
NL model conversion time = 0.046047s
HiGHS 1.11.0: optimal solution; objective 4.481524759
0 simplex iterations
0 barrier iterations
Setup time = 0.099799s
Solver time = 0.009082s
Output time = 0.000006s
Total time = 0.108887s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 490 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000515s
NL model conversion time = 0.001459s
HiGHS 1.11.0: optimal solution; objective 4.481524759
0 simplex iterations
0 barrier iterations
Setup time = 0.002452s
Solver time = 0.016788s
Output time = 0.000004s
Total time = 0.019245s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 533 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.074192s
NL model conversion time = 0.051626s
HiGHS 1.11.0: optimal solution; objective 3.468383954
0 simplex iterations
0 barrier iterations
Setup time = 0.126318s
Solver time = 0.010799s
Output time = 0.000006s
Total time = 0.137123s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 533 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000585s
NL model conversion time = 0.001549s
HiGHS 1.11.0: optimal solution; objective 3.468383954
0 simplex iterations
0 barrier iterations
Setup time = 0.002632s
Solver time = 0.020002s
Output time = 0.000004s
Total time = 0.022639s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 576 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.078626s
NL model conversion time = 0.063165s
HiGHS 1.11.0: optimal solution; objective 3.947223253
0 simplex iterations
0 barrier iterations
Setup time = 0.142292s
Solver time = 0.012429s
Output time = 0.000009s
Total time = 0.154730s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 576 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000559s
NL model conversion time = 0.001648s
HiGHS 1.11.0: optimal solution; objective 3.947223253
0 simplex iterations
0 barrier iterations
Setup time = 0.002708s
Solver time = 0.020986s
Output time = 0.000005s
Total time = 0.023699s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 620 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.098946s
NL model conversion time = 0.072297s
HiGHS 1.11.0: optimal solution; objective 3.757197201
0 simplex iterations
0 barrier iterations
Setup time = 0.171777s
Solver time = 0.012940s
Output time = 0.000007s
Total time = 0.184723s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 620 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000605s
NL model conversion time = 0.001706s
HiGHS 1.11.0: optimal solution; objective 3.757197201
0 simplex iterations
0 barrier iterations
Setup time = 0.002788s
Solver time = 0.022418s
Output time = 0.000005s
Total time = 0.025210s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 663 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.120306s
NL model conversion time = 0.086194s
HiGHS 1.11.0: optimal solution; objective 3.890282998
0 simplex iterations
0 barrier iterations
Setup time = 0.207005s
Solver time = 0.015977s
Output time = 0.000008s
Total time = 0.222990s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 663 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000679s
NL model conversion time = 0.001769s
HiGHS 1.11.0: optimal solution; objective 3.890282998
0 simplex iterations
0 barrier iterations
Setup time = 0.002942s
Solver time = 0.025320s
Output time = 0.000006s
Total time = 0.028268s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 706 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.130317s
NL model conversion time = 0.098204s
HiGHS 1.11.0: optimal solution; objective 4.216462576
0 simplex iterations
0 barrier iterations
Setup time = 0.229061s
Solver time = 0.016780s
Output time = 0.000009s
Total time = 0.245850s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 706 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000682s
NL model conversion time = 0.001949s
HiGHS 1.11.0: optimal solution; objective 4.216462576
0 simplex iterations
0 barrier iterations
Setup time = 0.003114s
Solver time = 0.023971s
Output time = 0.000005s
Total time = 0.027091s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
Running with 750 of 750 assets: sigma...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.146603s
NL model conversion time = 0.105291s
HiGHS 1.11.0: optimal solution; objective 4.084297931
0 simplex iterations
0 barrier iterations
Setup time = 0.252424s
Solver time = 0.020016s
Output time = 0.000010s
Total time = 0.272450s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
Running with 750 of 750 assets: factor model...
HiGHS 1.11.0: tech:timing = 2
tech:threads = 8
NL model read time = 0.000674s
NL model conversion time = 0.001997s
HiGHS 1.11.0: optimal solution; objective 4.084297931
0 simplex iterations
0 barrier iterations
Setup time = 0.003151s
Solver time = 0.028221s
Output time = 0.000005s
Total time = 0.031376s
suffix time OUT;
suffix time_read OUT;
suffix time_setup OUT;
suffix time_output OUT;
suffix time_solver OUT;
suffix time_conversion OUT;
...done ---------------------------------------
fig
For Gurobi and Mosek, it is clear that the solve times of (2) are much smaller both in absolute and asymptotic terms. The data may appear somewhat nonsmooth over the problem dimensions. These are artifacts from multi-threading and different code paths in the computational kernels used for dense matrix multiplication. However HiGHS runs about 10x faster overall and the sigma model works better, which might be due to HiGHS presolve.
However, HiGHS cannot currently solve MIQP which would arise when adding discrete entities to the model, for example, a cardinality constraint (see the MP Modeling Guide):
n_positive = ampl.get_value("count {a in ASSETS} (weight[a] > 1e-4)")
n_pos_new = round(0.7 * n_positive)
print("Constrain to", n_pos_new, "assets from currently", n_positive)
ampl.eval(
"s.t. Cardinality: atmost {} {{a in ASSETS}} (weight[a] > 0);".format(n_pos_new)
)
ampl.solve(solver="gurobi", gurobi_options="outlev=1", verbose=True)
print()
print(
"New number of positive assets:",
ampl.get_value("count {a in ASSETS} (weight[a] > 1e-4)"),
)
Constrain to 30 assets from currently 43
Gurobi 13.0.0: tech:timing = 2
tech:outlev = 1
Set parameter WLSAccessID
Set parameter WLSSecret
Set parameter LicenseID to value 2719854
Gurobi 13.0.0beta1 - expires 2025-12-02
WLS license 2719854 - registered to AMPL Optimization
NL model read time = 0.023518s
AMPL MP initial flat model has 822 variables (0 integer, 0 binary);
Objectives: 1 quadratic;
Constraints: 74 linear;
Algebraic expressions: 1 count;
Logical expressions: 750 conditional (in)equalitie(s); 750 not;
AMPL MP final model has 2324 variables (2 integer, 1500 binary);
Objectives: 1 quadratic;
Constraints: 825 linear;
Logical expressions: 750 indeq;
NL model conversion time = 0.079990s
Set parameter InfUnbdInfo to value 1
Gurobi Optimizer version 13.0.0 build v13.0.0beta1 (mac64[arm] - Darwin 24.6.0 24G90)
CPU model: Apple M1 Pro
Thread count: 8 physical cores, 8 logical processors, using up to 8 threads
Non-default parameters:
InfUnbdInfo 1
WLS license 2719854 - registered to AMPL Optimization
Optimize a model with 74 rows, 2324 columns and 54823 nonzeros (Max)
Model fingerprint: 0x537c43b5
Model has 750 linear objective coefficients
Model has 822 quadratic objective terms
Model has 750 simple general constraints
750 INDICATOR
Model has 1 general nonlinear constraint (0 nonlinear terms)
Variable types: 1573 continuous, 751 integer (0 binary)
Coefficient statistics:
Matrix range [6e-05, 3e+01]
Objective range [5e-03, 8e+00]
QObjective range [2e-02, 3e-02]
Bounds range [1e+00, 3e+01]
RHS range [1e+00, 3e+01]
GenCon coe range [1e+00, 1e+00]
NLCon coe range [1e+00, 1e+00]
Warning: Completing partial solution with 751 unfixed non-continuous variables out of 751
User MIP start did not produce a new incumbent solution
Presolve added 750 rows and 0 columns
Presolve removed 0 rows and 752 columns
Presolve time: 0.19s
Presolved: 824 rows, 1572 columns, 57004 nonzeros
Presolved model has 822 quadratic objective terms
Variable types: 822 continuous, 750 integer (750 binary)
Found heuristic solution: objective 1.6199186
Root relaxation: objective 4.084298e+00, 2267 iterations, 0.16 seconds (0.47 work units)
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 4.08430 0 40 1.61992 4.08430 152% - 0s
Another try with MIP start
H 0 0 1.8121056 4.08430 125% - 0s
H 0 0 2.0275529 4.08430 101% - 0s
H 0 0 2.1425597 4.08430 90.6% - 0s
H 0 0 2.1535301 4.08430 89.7% - 0s
H 0 0 2.6971230 4.08430 51.4% - 0s
H 0 0 2.7334972 4.08430 49.4% - 0s
H 0 0 2.7361581 4.08430 49.3% - 0s
0 0 4.08430 0 40 2.73616 4.08430 49.3% - 0s
H 0 0 3.2979051 4.08430 23.8% - 0s
H 0 0 3.3367343 4.08430 22.4% - 0s
H 0 0 3.3986239 4.08430 20.2% - 0s
H 0 0 3.4457379 4.08430 18.5% - 0s
H 0 0 3.4670127 4.08430 17.8% - 0s
H 0 0 3.4767013 4.08430 17.5% - 0s
H 0 0 3.4828032 4.08430 17.3% - 0s
H 0 0 3.4864062 4.08430 17.1% - 0s
H 0 0 3.6915189 4.08430 10.6% - 1s
0 2 4.08430 0 40 3.69152 4.08430 10.6% - 1s
H 26 32 3.7699421 4.08430 8.34% 20.6 1s
H 32 45 3.9224948 4.08430 4.13% 22.0 1s
H 35 45 4.0223700 4.08430 1.54% 20.6 1s
H 135 103 4.0247193 4.08430 1.48% 8.7 1s
H 138 103 4.0391176 4.08430 1.12% 8.6 1s
* 363 261 33 4.0496462 4.08420 0.85% 6.8 1s
* 373 267 31 4.0690503 4.08420 0.37% 6.9 1s
* 402 274 32 4.0690704 4.08412 0.37% 7.1 1s
* 659 390 37 4.0715829 4.08405 0.31% 6.7 1s
* 989 444 32 4.0718249 4.08318 0.28% 6.3 1s
* 1009 444 33 4.0727540 4.08318 0.26% 6.3 1s
* 1093 431 44 4.0752095 4.08310 0.19% 6.3 1s
Cutting planes:
Implied bound: 20
Explored 4556 nodes (28440 simplex iterations) in 2.89 seconds (4.71 work units)
Thread count was 8 (of 8 available processors)
Solution count 10: 4.07521 4.07275 4.07182 ... 4.02237
Optimal solution found (tolerance 1.00e-04)
Best objective 4.075209453893e+00, best bound 4.075209453893e+00, gap 0.0000%
Gurobi 13.0.0: optimal solution; objective 4.075209454
28440 simplex iterations
4556 branching nodes
Setup time = 0.118529s
Solver time = 2.893763s
Output time = 0.000019s
Total time = 3.012311s
New number of positive assets: 30
Takeaways#
Incorporating explicit factors to model risk in an AMPL model is straightforward.
AMPL allows easy switching between state-of-the-art solvers.
Using factor risk models instead of the derived full covariance matrix can greatly improve solution time.