< Home
← Posts
Bar chart of median solve time on a synthetic 1,000-security problem: CVXPY with Clarabel 1,165.3 milliseconds, hand-built sparse Clarabel 87.9, factored interior point 23.6.

Fast Portfolio Optimisation: Interior-Point Methods That Keep the Structure

Two interior-point kernels, for factor-risk QPs and scenario-based models such as CVaR and drawdown, with exact scenario screening, machine-checked bounds, benchmarks against CVXPY, Clarabel, and Riskfolio-Lib, and the cases where the method falls short.

Portfolio research solves the same convex problem thousands of times, across gross targets, risk measures, and formation dates. These problems have structure that general-purpose modelling tools discard. In factor-risk QPs, the covariance is a low-rank term plus a diagonal. In scenario models such as CVaR and drawdown, a small dense block of weights couples to a large sparse block of per-scenario variables.

This note describes two interior-point kernels QUARCC built to keep that structure through the solve. A synthetic 1,000-security factor-risk problem takes 23.6 ms in one thread, against 87.9 ms for a hand-built sparse Clarabel model and 1,165.3 ms for CVXPY with Clarabel. At 360,000 scenarios, CVaR models solve 12–17× faster than Riskfolio-Lib. The gain is much smaller on drawdown measures, and some risk-capped problems at that scale fail to converge. The full derivations and every benchmark are in the paper (PDF).

Factor-risk QPs

The first kernel handles a QP in weights x∈Rn\mathbf{x} \in \mathbb{R}^n with box bounds, two-sided exposure bands, and linear equalities:

min⁡x  12x⊤Px+q⊤xs.t.ℓ≤x≤u,    gℓ≤Gx≤gu,    Ax=b.\min_{\mathbf{x}} \; \tfrac{1}{2}\mathbf{x}^\top \mathbf{P}\mathbf{x} + \mathbf{q}^\top \mathbf{x} \quad \text{s.t.} \quad \boldsymbol{\ell} \le \mathbf{x} \le \mathbf{u},\;\; \mathbf{g}_\ell \le \mathbf{G}\mathbf{x} \le \mathbf{g}_u,\;\; \mathbf{A}\mathbf{x} = \mathbf{b}.

With factor risk, the Hessian is a low-rank term plus a diagonal, P=U diag(c) U⊤+diag(pd)\mathbf{P} = \mathbf{U}\,\mathrm{diag}(\mathbf{c})\,\mathbf{U}^\top + \mathrm{diag}(\mathbf{p}_d). We use a Mehrotra (1992) predictor-corrector. Eliminating slacks leaves a matrix M=H+Uaug diag(caug) Uaug⊤\mathbf{M} = \mathbf{H} + \mathbf{U}_{\text{aug}}\,\mathrm{diag}(\mathbf{c}_{\text{aug}})\,\mathbf{U}_{\text{aug}}^\top, where H\mathbf{H} is diagonal and each band adds one column. By the Woodbury identity,

M−1V=H−1V−H−1UaugK−1Uaug⊤H−1V,K=diag(caug)−1+Uaug⊤H−1Uaug.\mathbf{M}^{-1}\mathbf{V} = \mathbf{H}^{-1}\mathbf{V} - \mathbf{H}^{-1}\mathbf{U}_{\text{aug}}\mathbf{K}^{-1}\mathbf{U}_{\text{aug}}^\top\mathbf{H}^{-1}\mathbf{V}, \qquad \mathbf{K} = \mathrm{diag}(\mathbf{c}_{\text{aug}})^{-1} + \mathbf{U}_{\text{aug}}^\top\mathbf{H}^{-1}\mathbf{U}_{\text{aug}}.

Per-iteration linear algebra falls from O(n3)O(n^3) to O(nr2+r3)O(nr^2 + r^3) for rank rr. Across a rebalance ladder U\mathbf{U}, G\mathbf{G}, and A\mathbf{A} do not change, so setup is done once.

Scenario models

The second kernel covers CVaR, worst realisation, mean absolute deviation, semi-deviation, lower partial moments, and drawdown measures, under minimum-risk, utility, maximum-return, and maximum-Sharpe objectives. These share a form with a small dense block x\mathbf{x} of size mm and a large auxiliary block v\mathbf{v}:

min⁡x,v  12x⊤Px+cx⊤x+12v⊤diag(qv)v+cv⊤vs.t.Gxx+Gvv≤h,    Ex=e.\min_{\mathbf{x},\mathbf{v}} \; \tfrac{1}{2}\mathbf{x}^\top \mathbf{P}\mathbf{x} + \mathbf{c}_x^\top \mathbf{x} + \tfrac{1}{2}\mathbf{v}^\top \mathrm{diag}(\mathbf{q}_v)\mathbf{v} + \mathbf{c}_v^\top \mathbf{v} \quad \text{s.t.} \quad \mathbf{G}_x\mathbf{x} + \mathbf{G}_v\mathbf{v} \le \mathbf{h},\;\; \mathbf{E}\mathbf{x} = \mathbf{e}.

The auxiliaries can be eliminated exactly at each Newton step. With barrier weights W\mathbf{W}, Svv=diag(qv)+Gv⊤WGv\mathbf{S}_{vv} = \mathrm{diag}(\mathbf{q}_v) + \mathbf{G}_v^\top\mathbf{W}\mathbf{G}_v and B=Gv⊤WGx\mathbf{B} = \mathbf{G}_v^\top\mathbf{W}\mathbf{G}_x, what remains is a dense system in Δx\Delta\mathbf{x}:

P+Gx⊤WGx−B⊤Svv−1B.\mathbf{P} + \mathbf{G}_x^\top\mathbf{W}\mathbf{G}_x - \mathbf{B}^\top\mathbf{S}_{vv}^{-1}\mathbf{B}.

Nothing of size T×TT \times T is formed. When Svv\mathbf{S}_{vv} is diagonal, an iteration costs O(Tm2+m3)O(Tm^2 + m^3). Drawdown auxiliaries form a chain, so Svv\mathbf{S}_{vv} becomes banded and needs a triangular solve. Risk caps touch many auxiliaries at once, so they enter through a bordered system instead.

Solving CVaR on a subset of scenarios

CVaR depends only on the tail, so most scenarios play no part in the optimum. Write the Rockafellar-Uryasev objective on a subset SS of scenarios as FS(x,t)=t+c∑i∈Smax⁡(0,ℓi(x)−t)F_S(\mathbf{x}, t) = t + c \sum_{i \in S} \max(0, \ell_i(\mathbf{x}) - t). If (x,t)(\mathbf{x}, t) minimises FSF_S and no dropped scenario has a loss above tt, then (x,t)(\mathbf{x}, t) also minimises the objective on all scenarios: the dropped terms are nonnegative everywhere and zero at this point.

The algorithm starts from the worst scenarios of two simple portfolios, solves the restricted problem, adds any violated scenarios, and repeats. The same argument applies to worst realisation.

Certificates and proofs

Each solve reports whether it converged, and returns no weights if it did not. An early-stopped solve can still carry a bound. For convex ff and multipliers λ≥0\boldsymbol{\lambda} \ge 0 and y\mathbf{y} at any iterate z\mathbf{z}, with dual residual rd\mathbf{r}_d, every feasible z⋆\mathbf{z}^\star satisfies

f(z)−f(z⋆)≤λ⊤(h−Gz)+y⊤(e−Ez)+∥rd∥∞∥z−z⋆∥1.f(\mathbf{z}) - f(\mathbf{z}^\star) \le \boldsymbol{\lambda}^\top(\mathbf{h} - \mathbf{G}\mathbf{z}) + \mathbf{y}^\top(\mathbf{e} - \mathbf{E}\mathbf{z}) + \|\mathbf{r}_d\|_\infty \|\mathbf{z} - \mathbf{z}^\star\|_1.

This bound and the screening result are machine-checked in Lean 4. The link between those statements and the numerical code is tested but not formally verified.

Benchmarks

All problems are synthetic. Runs use one thread on one core of an Intel Core i5-7300U, and times for our method and the factor-risk baselines are medians of repeated runs. Riskfolio-Lib times are single runs.

Factor-risk QPs, at tolerance 10−810^{-8}, with gaps measured against the first row of each group. The ladder has 36 rungs, and its gaps are for the first rung.

WorkloadSolver pathMedian (ms)SpeedupObjective gapWeight gap
n=300n = 300, r=43r = 43CVXPY + Clarabel92.9baseline00
Sparse Clarabel25.23.7×2.1e-91.2e-5
This method8.810.6×2.1e-64.4e-4
n=1000n = 1000, r=43r = 43CVXPY + Clarabel1,165.3baseline00
Sparse Clarabel87.913.3×2.1e-102.3e-7
This method23.649.4×5.3e-65.3e-4
Ladder, n=500n = 500, per solveCVXPY rebuild275.4baseline00
Sparse Clarabel43.36.4×
This method, prepared12.122.8×3.2e-65.5e-4

The 49× headline mostly measures modelling overhead. Against the sparse model, the fairer comparison, the gain is 3.7× at n=1000n = 1000 and 3.6× on the ladder.

Scenario models against Riskfolio-Lib, which uses Clarabel through CVXPY. Each range covers minimum-risk and maximum-Sharpe solves. Process A has four common factors and no position cap. Process B has five weaker factors and a 25% cap. Both have T=10,000T = 10{,}000 and n=50n = 50, and every solve reached optimal status.

MeasureOurs, A (s)Riskfolio-Lib, A (s)Speedup, ASpeedup, B
CVaR0.19–0.202.43–2.7012.6–13.4×3.5–5.0×
Worst realisation0.041.47–1.8435.5–47.8×5.5–9.5×
Mean absolute deviation0.22–0.232.29–2.7410.6–11.8×9.7–13.6×
Semi-deviation0.22–0.233.50–3.9315.5–18.1×17.7–18.3×
Variance0.010.054.8–5.0×5.7–5.8×
CDaR2.24–2.603.79–4.531.5–2.0×1.2–2.3×
Maximum drawdown0.72–0.853.11–3.313.7–4.6×2.3–5.0×
Average drawdown0.52–0.612.61–2.624.3–5.0×2.8–5.2×

The two columns of speedups show how much the gain depends on the data. Worst realisation falls from up to 48× to under 10× with no change in the method. On process A, relative objective differences are at most 2.2×10−82.2 \times 10^{-8}.

Screening at scale: 8 assets, 2,000 block-bootstrapped 15-year monthly paths, 360,000 scenarios, and a 40% position cap.

ModelOurs (s)Riskfolio-Lib (s)SpeedupScenarios keptWeight gap
CVaR, minimum risk2.1525.011.7×83,9101.1e-8
CVaR, maximum Sharpe1.1119.217.4×47,4665.7e-9
Worst realisation, minimum risk0.0357.13203×1282.8e-8
Worst realisation, maximum Sharpe0.0347.59225×1283.5e-10
Mean absolute deviation, maximum Sharpe4.3114.63.4×no screening6.5e-6

Limitations

  • Risk caps at large scale can fail. On a 20-point CVaR frontier at 360,000 scenarios, 4 of the 19 capped problems reach optimal status, 13 end optimal but inaccurate, and 2 stall and return no weights. The same construction completes on the first 200,000 scenarios. The failures are detected and reported, but they mean a full frontier does not complete at this scale.
  • Drawdown measures gain least. CDaR is only 1.2–2.3× faster, with up to 63 iterations.
  • Synthetic data, one machine. Absolute times and ratios will differ elsewhere, and they vary with the data, as the table above shows.
  • Computation, not investment results. The QUARCC Purple and US Long-Short results were both solved with Clarabel, not with this method.
  • Factor-risk weights differ slightly. Gaps near 5×10−45 \times 10^{-4} come mainly from the default quadratic soft-band penalty. Stopping at six iterations is 2.7–4.9× faster but leaves gaps up to 1.9×10−21.9 \times 10^{-2}, which suits screening and warm starts only.
  • Signs must be fixed in the factor-risk kernel. Free-sign support selection with minimum positions still needs an outer ladder or a first-stage sign assignment.
  • Coverage is partial. Entropic value at risk, tracking-error constraints, and other measures that need exponential, power, or second-order cones are not supported, nor are integer constraints.

The solver code is not publicly available.

Read more

More From The Archive