Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d695eaa
chore: add refs.bib with Duchi et al. (2008) entry
tschm Jun 5, 2026
0387d69
test: add test suite for proximal module
tschm Jun 5, 2026
fa82490
feat: add solve_proximal to _BaseProblem
tschm Jun 5, 2026
da448ba
test: add TestSolveProximal to test_proximal and test_base
tschm Jun 5, 2026
21ced49
feat: add proximal solver to make_minvar_figures benchmarks and plots
tschm Jun 5, 2026
3842052
chore: add proximal.py implementation and regenerated scaling figures
tschm Jun 5, 2026
d4eb3ed
docs: add Section 4.5 on proximal gradient solver to minvar_paper
tschm Jun 5, 2026
47b6ca6
docs: split sec:kkt into Positive-Definite Reduction and Primal-Dual …
tschm Jun 5, 2026
e5da546
docs: add closing sentence to Section 3 stating the SPD + inequality …
tschm Jun 5, 2026
7b39fdb
feat: matrix-free proximal gradient via power iteration
tschm Jun 5, 2026
3553351
docs: rewrite Section 4 to introduce both active-set and simplex-proj…
tschm Jun 5, 2026
ac31b98
refs: add Condat (2016) and cite alongside Duchi for simplex projection
tschm Jun 5, 2026
74a5826
paper: move LW shrinkage section before computational methods
tschm Jun 5, 2026
35b0e0f
paper: fix LaTeX compilation errors
tschm Jun 5, 2026
52d06dd
paper: rewrite abstract to include proximal/simplex-projection strategy
tschm Jun 5, 2026
accf858
paper: extract abstract into abstract.tex, \input from main file
tschm Jun 5, 2026
79f05ab
paper: extract Introduction into s1_introduction.tex
tschm Jun 5, 2026
68abde3
paper: extract Sections 2-3 into s2s3_problem.tex
tschm Jun 5, 2026
d6f4cf0
paper: add Algorithm 2 (proximal gradient) in Section 4
tschm Jun 5, 2026
32316f9
paper: extract Section 4 into s4_nonneg.tex
tschm Jun 5, 2026
1852f82
paper: collapse NNLS subsection to a single paragraph
tschm Jun 5, 2026
09cc2ce
paper: remove trailing dots from all \paragraph{} headings
tschm Jun 5, 2026
f907cda
chore: bump rhiza to v0.18.8
tschm Jun 6, 2026
6bad42f
chore: apply rhiza sync v0.18.8
tschm Jun 6, 2026
031e586
bib file for paper
tschm Jun 8, 2026
2e45111
further cleaning
tschm Jun 8, 2026
02a9b2a
further cleaning
tschm Jun 8, 2026
a04ed4c
package + tests
tschm Jun 8, 2026
0a7a2b1
package + tests
tschm Jun 8, 2026
19e2364
package + tests
tschm Jun 8, 2026
7794928
package + tests
tschm Jun 8, 2026
e284c6e
package + tests
tschm Jun 9, 2026
69b447e
package + tests
tschm Jun 9, 2026
b034da5
scripts for downloading the data
tschm Jun 9, 2026
a5bdfc8
shrinkage utils
tschm Jun 9, 2026
ddb2c5d
tests
tschm Jun 9, 2026
aa023fe
tests
tschm Jun 9, 2026
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
2 changes: 1 addition & 1 deletion .rhiza/template.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
repository: "jebel-quant/rhiza"
ref: "v0.18.4"
ref: "v0.18.8"

profiles:
- github-project
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ from fast_minimum_variance import Problem
# 500 daily returns, 20 assets
X = np.random.default_rng(42).standard_normal((500, 20))

w, iters = Problem(X).solve_cg() # matrix-free CG — recommended
w, outer, inner = Problem(X).solve_cg() # matrix-free CG — recommended
w, iters = Problem(X).solve_kkt() # direct dense solve — exact baseline

assert abs(w.sum() - 1.0) < 1e-8
Expand All @@ -48,16 +48,17 @@ it compresses the eigenvalue spectrum and directly cuts CG iteration counts. Use

```python
T, N = X.shape
w, iters = Problem(X, alpha=N / (N + T)).solve_cg()
w, outer, inner = Problem(X, alpha=N / (N + T)).solve_cg()
```

On S&P 500 equity data (495 assets, 1192 days), shrinkage cuts CG iterations from 685 to
205 and makes the matrix-free solver the fastest option by a wide margin.

## Solvers

All solvers are methods on `Problem` and return `(w, iters)` where
All solvers are methods on `Problem` and return `(w, ...)` where
$w \in \mathbb{R}^N$, $\sum_i w_i = 1$, $w_i \geq 0$.
`solve_cg` returns `(w, outer_steps, inner_iters)`; all others return `(w, iters)`.

| Method | Approach | When to use |
|---|---|---|
Expand Down Expand Up @@ -151,12 +152,12 @@ The same solver handles a range of portfolio construction problems by choosing $
```python
# Mean-variance
mu = np.random.default_rng(0).standard_normal(N) # expected returns, shape (N,)
w, _ = Problem(X, rho=1.0, mu=mu).solve_cg()
w, *_ = Problem(X, rho=1.0, mu=mu).solve_cg()

# Minimum tracking error to benchmark b
b = np.ones(N) / N # equal-weight benchmark
mu_te = X.T @ (X @ b)
w, _ = Problem(X, rho=2.0, mu=mu_te).solve_cg()
w, *_ = Problem(X, rho=2.0, mu=mu_te).solve_cg()
```

When `rho != 0`, two SPD solves are performed per outer step: $\Sigma_a v_1 = \mathbf{1}$
Expand Down
Binary file not shown.
Binary file modified book/marimo/notebooks/data/sp500_pct_returns.parquet
Binary file not shown.
83 changes: 0 additions & 83 deletions book/marimo/notebooks/fetch_sp500.py

This file was deleted.

Binary file removed book/marimo/notebooks/graphs/markowitz_scaling.png
Binary file not shown.
Binary file added book/marimo/notebooks/graphs/minvar_frontier.pdf
Binary file not shown.
Binary file added book/marimo/notebooks/graphs/minvar_frontier.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added book/marimo/notebooks/graphs/minvar_iters.pdf
Binary file not shown.
Binary file added book/marimo/notebooks/graphs/minvar_iters.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed book/marimo/notebooks/graphs/minvar_loglog.png
Binary file not shown.
Binary file modified book/marimo/notebooks/graphs/minvar_scaling.pdf
Binary file not shown.
Binary file modified book/marimo/notebooks/graphs/minvar_scaling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
193 changes: 0 additions & 193 deletions book/marimo/notebooks/make_minvar_figures.py

This file was deleted.

6 changes: 6 additions & 0 deletions experiment/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
load_data:
uv run fetch_sp500.py
uv run fetch_ftse100.py

experiment:
uv run experiment.py
Binary file added experiment/data/ftse100_pct_returns.parquet
Binary file not shown.
Binary file added experiment/data/sp500_pct_returns.parquet
Binary file not shown.
Loading
Loading