Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions results/20260313_Vivaan-Atharva_darwin.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{"problem_name": "qp/mean_variance_medium", "solver_name": "CLARABEL", "compilation_time": 0.03724098205566406, "solve_time": 0.029368301, "setup_time": null, "total_time": 0.07185274499897787, "status": "optimal", "objective_value": 0.00014736059085145028, "num_iters": 9, "problem_type": "QP", "num_scalar_variables": 200, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 201, "cvxpy_version": "1.8.1", "solver_version": "CLARABEL", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:27.597102+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_medium", "solver_name": "HIGHS", "compilation_time": 0.014678955078125, "solve_time": 0.037944572992273606, "setup_time": null, "total_time": 0.06337019999955373, "status": "optimal", "objective_value": 0.00014736052948214617, "num_iters": 598, "problem_type": "QP", "num_scalar_variables": 200, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 201, "cvxpy_version": "1.8.1", "solver_version": "HIGHS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:27.728636+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_medium", "solver_name": "OSQP", "compilation_time": 0.014281988143920898, "solve_time": 0.008496627, "setup_time": null, "total_time": 0.025855489999230485, "status": "optimal", "objective_value": 0.00014736052948203284, "num_iters": 50, "problem_type": "QP", "num_scalar_variables": 200, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 201, "cvxpy_version": "1.8.1", "solver_version": "OSQP", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:27.822486+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_medium", "solver_name": "SCIPY", "compilation_time": null, "solve_time": null, "setup_time": null, "total_time": 0.0003582440003810916, "status": "solver_error", "objective_value": null, "num_iters": null, "problem_type": "QP", "num_scalar_variables": 200, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 201, "cvxpy_version": "1.8.1", "solver_version": "", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:27.891127+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_medium", "solver_name": "SCS", "compilation_time": 0.015867948532104492, "solve_time": 0.0017216689999999999, "setup_time": 0.005375016999999999, "total_time": 0.02506586699928448, "status": "optimal", "objective_value": 0.0001473605238836496, "num_iters": 25, "problem_type": "QP", "num_scalar_variables": 200, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 201, "cvxpy_version": "1.8.1", "solver_version": "SCS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:27.984579+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_small", "solver_name": "CLARABEL", "compilation_time": 0.006227970123291016, "solve_time": 0.000367496, "setup_time": null, "total_time": 0.007298979000552208, "status": "optimal", "objective_value": 0.0017934865652385655, "num_iters": 8, "problem_type": "QP", "num_scalar_variables": 20, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 21, "cvxpy_version": "1.8.1", "solver_version": "CLARABEL", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:27.996679+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_small", "solver_name": "HIGHS", "compilation_time": 0.005446195602416992, "solve_time": 0.001175248995423317, "setup_time": null, "total_time": 0.007838289999199333, "status": "optimal", "objective_value": 0.0017934865652388938, "num_iters": 61, "problem_type": "QP", "num_scalar_variables": 20, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 21, "cvxpy_version": "1.8.1", "solver_version": "HIGHS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.008957+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_small", "solver_name": "OSQP", "compilation_time": 0.005428791046142578, "solve_time": 0.000178085, "setup_time": null, "total_time": 0.007376632000159589, "status": "optimal", "objective_value": 0.0017934865652382227, "num_iters": 50, "problem_type": "QP", "num_scalar_variables": 20, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 21, "cvxpy_version": "1.8.1", "solver_version": "OSQP", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.020743+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_small", "solver_name": "SCIPY", "compilation_time": null, "solve_time": null, "setup_time": null, "total_time": 0.0003060220005863812, "status": "solver_error", "objective_value": null, "num_iters": null, "problem_type": "QP", "num_scalar_variables": 20, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 21, "cvxpy_version": "1.8.1", "solver_version": "", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.025484+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/mean_variance_small", "solver_name": "SCS", "compilation_time": 0.005944728851318359, "solve_time": 5.702e-05, "setup_time": 9.9085e-05, "total_time": 0.006940499999473104, "status": "optimal", "objective_value": 0.001793486505635041, "num_iters": 25, "problem_type": "QP", "num_scalar_variables": 20, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 21, "cvxpy_version": "1.8.1", "solver_version": "SCS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.036641+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/risk_parity_small", "solver_name": "CLARABEL", "compilation_time": 0.009557008743286133, "solve_time": 0.00189623, "setup_time": null, "total_time": 0.012374713000099291, "status": "optimal", "objective_value": 0.0012246413699866913, "num_iters": 14, "problem_type": "QP", "num_scalar_variables": 30, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 31, "cvxpy_version": "1.8.1", "solver_version": "CLARABEL", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.056804+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/risk_parity_small", "solver_name": "HIGHS", "compilation_time": null, "solve_time": null, "setup_time": null, "total_time": 0.0006085780005378183, "status": "solver_error", "objective_value": null, "num_iters": null, "problem_type": "QP", "num_scalar_variables": 30, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 31, "cvxpy_version": "1.8.1", "solver_version": "", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.065426+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/risk_parity_small", "solver_name": "OSQP", "compilation_time": null, "solve_time": null, "setup_time": null, "total_time": 0.00022551900110556744, "status": "solver_error", "objective_value": null, "num_iters": null, "problem_type": "QP", "num_scalar_variables": 30, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 31, "cvxpy_version": "1.8.1", "solver_version": "", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.073888+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/risk_parity_small", "solver_name": "SCIPY", "compilation_time": null, "solve_time": null, "setup_time": null, "total_time": 0.000545770000826451, "status": "solver_error", "objective_value": null, "num_iters": null, "problem_type": "QP", "num_scalar_variables": 30, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 31, "cvxpy_version": "1.8.1", "solver_version": "", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.082626+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "qp/risk_parity_small", "solver_name": "SCS", "compilation_time": 0.009062767028808594, "solve_time": 0.00044021500000000004, "setup_time": 0.000318183, "total_time": 0.011035745999834035, "status": "optimal", "objective_value": 0.0012253139462066462, "num_iters": 50, "problem_type": "QP", "num_scalar_variables": 30, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 31, "cvxpy_version": "1.8.1", "solver_version": "SCS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.101526+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "socp/cvar_portfolio_small", "solver_name": "CLARABEL", "compilation_time": 0.028500080108642578, "solve_time": 0.090561763, "setup_time": null, "total_time": 0.12949438199939323, "status": "infeasible", "objective_value": Infinity, "num_iters": 8, "problem_type": "LP", "num_scalar_variables": 1051, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 2051, "cvxpy_version": "1.8.1", "solver_version": "CLARABEL", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.234732+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "socp/cvar_portfolio_small", "solver_name": "HIGHS", "compilation_time": 0.020374059677124023, "solve_time": 0.10542935799458064, "setup_time": null, "total_time": 0.13965072799874179, "status": "infeasible", "objective_value": Infinity, "num_iters": null, "problem_type": "LP", "num_scalar_variables": 1051, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 2051, "cvxpy_version": "1.8.1", "solver_version": "HIGHS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.377310+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "socp/cvar_portfolio_small", "solver_name": "OSQP", "compilation_time": 0.020908832550048828, "solve_time": 0.036454654, "setup_time": null, "total_time": 0.05912847299987334, "status": "infeasible", "objective_value": Infinity, "num_iters": null, "problem_type": "LP", "num_scalar_variables": 1051, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 2051, "cvxpy_version": "1.8.1", "solver_version": "OSQP", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.439875+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "socp/cvar_portfolio_small", "solver_name": "SCIPY", "compilation_time": 0.0256650447845459, "solve_time": null, "setup_time": null, "total_time": 0.1379601080006978, "status": "infeasible", "objective_value": Infinity, "num_iters": null, "problem_type": "LP", "num_scalar_variables": 1051, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 2051, "cvxpy_version": "1.8.1", "solver_version": "SCIPY", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.580866+00:00", "contributor": "Vivaan-Atharva"}
{"problem_name": "socp/cvar_portfolio_small", "solver_name": "SCS", "compilation_time": 0.026215791702270508, "solve_time": 0.024088027, "setup_time": 0.012822304000000001, "total_time": 0.0637434630007192, "status": "infeasible", "objective_value": Infinity, "num_iters": 75, "problem_type": "LP", "num_scalar_variables": 1051, "num_scalar_eq_constr": 1, "num_scalar_leq_constr": 2051, "cvxpy_version": "1.8.1", "solver_version": "SCS", "python_version": "3.12.4", "os_info": "Darwin 25.3.0", "cpu_info": "i386", "timestamp": "2026-03-13T12:16:28.647494+00:00", "contributor": "Vivaan-Atharva"}
145 changes: 145 additions & 0 deletions src/solver_benchmarks/problems/finance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"""Finance benchmark problems using real-world inspired data."""

from __future__ import annotations

import cvxpy as cp
import numpy as np

from solver_benchmarks.problems import register_problem


@register_problem(
"qp/mean_variance_small",
tags=["qp", "small", "finance"],
description="Mean-variance portfolio optimization (20 assets)",
)
def mean_variance_small(seed: int = 0) -> cp.Problem:
"""Markowitz mean-variance portfolio optimization.

Minimizes portfolio variance subject to a minimum return target,
full investment, and no short-selling constraints.
"""
rng = np.random.default_rng(seed)
n = 20

# Simulate realistic annual returns (5-15% mean, ~20% vol)
mu = 0.08 + rng.standard_normal(n) * 0.04
# Factor model for covariance: Sigma = F @ F.T + diag(idio)
F = rng.standard_normal((n, 5)) * 0.1
idio = rng.uniform(0.01, 0.05, n)
Sigma = F @ F.T + np.diag(idio)

ret_target = 0.07
x = cp.Variable(n)
risk = cp.quad_form(x, Sigma)
constraints = [
mu @ x >= ret_target,
cp.sum(x) == 1,
x >= 0,
]
return cp.Problem(cp.Minimize(risk), constraints)


@register_problem(
"qp/mean_variance_medium",
tags=["qp", "medium", "finance"],
description="Mean-variance portfolio optimization (200 assets)",
)
def mean_variance_medium(seed: int = 0) -> cp.Problem:
"""Larger Markowitz mean-variance portfolio optimization."""
rng = np.random.default_rng(seed)
n = 200

mu = 0.08 + rng.standard_normal(n) * 0.04
F = rng.standard_normal((n, 20)) * 0.1
idio = rng.uniform(0.01, 0.05, n)
Sigma = F @ F.T + np.diag(idio)

ret_target = 0.07
x = cp.Variable(n)
risk = cp.quad_form(x, Sigma)
constraints = [
mu @ x >= ret_target,
cp.sum(x) == 1,
x >= 0,
]
return cp.Problem(cp.Minimize(risk), constraints)


@register_problem(
"socp/cvar_portfolio_small",
tags=["socp", "small", "finance"],
description="CVaR portfolio optimization (50 assets, 1000 scenarios)",
)
def cvar_portfolio_small(seed: int = 0) -> cp.Problem:
"""Conditional Value-at-Risk (CVaR) portfolio optimization.

CVaR minimization is a standard risk measure in quantitative finance,
used in place of variance when tail risk matters.
Reformulated as an LP/SOCP using the Rockafellar-Uryasev formulation.
"""
rng = np.random.default_rng(seed)
n = 50 # number of assets
S = 1000 # number of scenarios
alpha = 0.95 # confidence level (95% CVaR)

# Simulate scenario returns: factor model
F = rng.standard_normal((S, 5)) * 0.02
B = rng.standard_normal((5, n)) * 0.1
idio = rng.standard_normal((S, n)) * 0.01
R = F @ B + idio # S x n scenario return matrix

mu = R.mean(axis=0)
ret_target = 0.005 # 0.5% minimum expected return per scenario

x = cp.Variable(n) # portfolio weights
z = cp.Variable() # VaR threshold
u = cp.Variable(S) # auxiliary variables for CVaR

# CVaR = z + 1/((1-alpha)*S) * sum(u)
cvar = z + (1 / ((1 - alpha) * S)) * cp.sum(u)

constraints = [
u >= 0,
u >= -R @ x - z,
mu @ x >= ret_target,
cp.sum(x) == 1,
x >= 0,
]
return cp.Problem(cp.Minimize(cvar), constraints)


@register_problem(
"qp/risk_parity_small",
tags=["qp", "small", "finance"],
description="Risk parity portfolio approximation (30 assets)",
)
def risk_parity_small(seed: int = 0) -> cp.Problem:
"""Risk parity portfolio via quadratic approximation.

Risk parity targets equal risk contribution from each asset.
Approximated as a QP following Bruder & Roncalli (2012).
"""
rng = np.random.default_rng(seed)
n = 30

F = rng.standard_normal((n, 8)) * 0.1
idio = rng.uniform(0.01, 0.05, n)
Sigma = F @ F.T + np.diag(idio)

# Equal risk budget
b = np.ones(n) / n

x = cp.Variable(n, nonneg=True)
# Minimize variance subject to log-weight budget constraints
# (convex approximation of risk parity)
risk = cp.quad_form(x, Sigma)
constraints = [
cp.sum(x) == 1,
x >= 1e-4,
]
# Add risk budget constraint via log barrier approximation
log_constraint = cp.sum(cp.multiply(b, cp.log(x))) >= -10
constraints.append(log_constraint)

return cp.Problem(cp.Minimize(risk), constraints)