|
1 | 1 | # factorlasso |
2 | 2 |
|
| 3 | +**`factorlasso` estimates sparse multi-output factor models with sign constraints, prior-centred |
| 4 | +shrinkage, data-driven grouped penalties, and consistent factor covariance assembly.** |
| 5 | + |
| 6 | +It provides LASSO, Hierarchical Clustering Group LASSO (HCGL), Factor-Clustering Group LASSO |
| 7 | +(FCGL), sparse-group, UniLasso, and cooperative penalties through auditable CVXPY formulations. |
| 8 | + |
| 9 | +**Install:** `pip install factorlasso` · **Import:** `factorlasso` · **Status:** Beta |
| 10 | + |
3 | 11 | [](https://pypi.org/project/factorlasso/) |
4 | 12 | [](https://pypi.org/project/factorlasso/) |
5 | | -[](LICENSE) |
6 | 13 | [](https://github.com/ArturSepp/factorlasso/actions/workflows/ci.yml) |
7 | 14 | [](https://factorlasso.readthedocs.io/en/latest/) |
| 15 | +[](LICENSE) |
8 | 16 | [](https://pepy.tech/project/factorlasso) |
9 | 17 | [](https://pepy.tech/project/factorlasso) |
10 | 18 |
|
11 | | -**`factorlasso` is a Python library for sparse multi-output factor-model estimation with sign |
12 | | -constraints, prior-centred shrinkage, data-driven grouped penalties, and consistent factor |
13 | | -covariance assembly.** |
14 | | - |
15 | | -It provides LASSO, Hierarchical Clustering Group LASSO (HCGL), Factor-Clustering Group LASSO |
16 | | -(FCGL), sparse-group, UniLasso, and cooperative penalties through auditable CVXPY formulations. |
17 | | - |
18 | 19 | **Paper:** Sepp, A. and Kastenholz, M. (2026), *factorlasso: Hierarchical |
19 | 20 | Clustering Group LASSO (HCGL) with Cluster-Pooled Sign Derivation for |
20 | 21 | Multi-Asset Factor Models in Python*, submitted to the *Journal of Statistical |
@@ -68,6 +69,49 @@ It is written in pure numpy/pandas/scipy/cvxpy. No numba, no custom |
68 | 69 | coordinate descent. The solver is CVXPY (default `CLARABEL`), so problem |
69 | 70 | formulation is explicit and auditable. |
70 | 71 |
|
| 72 | +## Installation |
| 73 | + |
| 74 | +```bash |
| 75 | +pip install factorlasso |
| 76 | +``` |
| 77 | + |
| 78 | +Requires Python ≥ 3.10, CVXPY ≥ 1.3, and numpy / pandas / scipy / openpyxl. |
| 79 | + |
| 80 | +## Five-minute quickstart |
| 81 | + |
| 82 | +```python |
| 83 | +import numpy as np |
| 84 | +import pandas as pd |
| 85 | +from factorlasso import LassoModel, LassoModelType |
| 86 | + |
| 87 | +rng = np.random.default_rng(0) |
| 88 | +T, M, N = 200, 4, 10 |
| 89 | +X = pd.DataFrame(rng.standard_normal((T, M)), columns=[f"f{i}" for i in range(M)]) |
| 90 | +Y = pd.DataFrame(rng.standard_normal((T, N)), columns=[f"y{i}" for i in range(N)]) |
| 91 | + |
| 92 | +model = LassoModel(model_type=LassoModelType.LASSO, reg_lambda=1e-5).fit(x=X, y=Y) |
| 93 | + |
| 94 | +print(model.coef_.shape) # (N, M) estimated β |
| 95 | +print(model.intercept_.shape) # (N,) estimated α |
| 96 | +print(model.predict(X).shape) # fitted response panel |
| 97 | +``` |
| 98 | + |
| 99 | +```text |
| 100 | +(10, 4) |
| 101 | +(10,) |
| 102 | +(200, 10) |
| 103 | +``` |
| 104 | + |
| 105 | +The API mirrors scikit-learn: `fit(x, y)`, `predict(x)`, `score(x, y)`, |
| 106 | +`get_params()`, `set_params()`. Fitted attributes carry a trailing underscore. |
| 107 | +`fit`/`predict`/`score` accept NumPy arrays as well as pandas objects, and the |
| 108 | +estimator declares `__sklearn_tags__`, so it composes directly with |
| 109 | +`sklearn.pipeline.Pipeline`, `GridSearchCV`, and `cross_val_score`. A fitted |
| 110 | +model also exposes `summary()`. The `plot_signs()` heatmap requires Matplotlib, |
| 111 | +which is not a runtime dependency and must be installed separately. |
| 112 | + |
| 113 | +--- |
| 114 | + |
71 | 115 | ## Offline cluster lineage |
72 | 116 |
|
73 | 117 | `analyze_cluster_lineage` turns independently estimated per-date risk clusters in a |
@@ -119,47 +163,7 @@ preserves the pre-0.16 flat-window calculation exactly. |
119 | 163 |
|
120 | 164 | --- |
121 | 165 |
|
122 | | -## Installation |
123 | | - |
124 | | -```bash |
125 | | -pip install factorlasso |
126 | | -``` |
127 | | - |
128 | | -Requires Python ≥ 3.10, CVXPY ≥ 1.3, and numpy / pandas / scipy / openpyxl. |
129 | | - |
130 | | ---- |
131 | | - |
132 | | -## Quickstart |
133 | | - |
134 | | -```python |
135 | | -import numpy as np |
136 | | -import pandas as pd |
137 | | -from factorlasso import LassoModel, LassoModelType |
138 | | - |
139 | | -rng = np.random.default_rng(0) |
140 | | -T, M, N = 200, 4, 10 |
141 | | -X = pd.DataFrame(rng.standard_normal((T, M)), columns=[f"f{i}" for i in range(M)]) |
142 | | -Y = pd.DataFrame(rng.standard_normal((T, N)), columns=[f"y{i}" for i in range(N)]) |
143 | | - |
144 | | -model = LassoModel(model_type=LassoModelType.LASSO, reg_lambda=1e-5).fit(x=X, y=Y) |
145 | | - |
146 | | -model.coef_ # (N, M) estimated β |
147 | | -model.intercept_ # (N,) estimated α |
148 | | -model.predict(X) # Ŷ |
149 | | -model.score(X, Y) # mean R² |
150 | | -``` |
151 | | - |
152 | | -The API mirrors scikit-learn: `fit(x, y)`, `predict(x)`, `score(x, y)`, |
153 | | -`get_params()`, `set_params()`. Fitted attributes carry a trailing underscore. |
154 | | -`fit`/`predict`/`score` accept NumPy arrays as well as pandas objects, and the |
155 | | -estimator declares `__sklearn_tags__`, so it composes directly with |
156 | | -`sklearn.pipeline.Pipeline`, `GridSearchCV`, and `cross_val_score`. A fitted |
157 | | -model also exposes `summary()` (a text fit report) and `plot_signs()` (a |
158 | | -heatmap of the derived sign matrix). |
159 | | - |
160 | | ---- |
161 | | - |
162 | | -## Motivation |
| 166 | +## Why factorlasso |
163 | 167 |
|
164 | 168 | Factor models are central to quantitative finance, underpinning the |
165 | 169 | commercial risk systems in industry use (among others, MSCI Barra, Axioma, |
@@ -192,7 +196,7 @@ under [Citation](#citation). |
192 | 196 |
|
193 | 197 | --- |
194 | 198 |
|
195 | | -## What makes it different |
| 199 | +## Key differentiators |
196 | 200 |
|
197 | 201 | ### 1. Per-element sign constraints |
198 | 202 |
|
@@ -373,7 +377,7 @@ References: |
373 | 377 | * Zou, H. (2006). The adaptive Lasso and its oracle properties. |
374 | 378 | *J. Amer. Stat. Assoc.* 101(476), 1418–1429. |
375 | 379 |
|
376 | | -### 3. Prior-centered regularisation |
| 380 | +### 3. Prior-centred regularisation |
377 | 381 |
|
378 | 382 | Pass a `(N × M)` DataFrame `factors_beta_prior` to penalise `‖β − β₀‖` instead |
379 | 383 | of `‖β‖`. The prior is a soft target, not a hard constraint — the penalty |
@@ -882,35 +886,41 @@ Four runnable examples in [`examples/`](examples/): |
882 | 886 | ## Testing |
883 | 887 |
|
884 | 888 | ```bash |
885 | | -pip install -e ".[dev]" |
886 | | -pytest |
| 889 | +uv sync --locked --group test |
| 890 | +uv run --no-sync pytest |
| 891 | +uv run --locked --only-group lint ruff check src/factorlasso tests |
887 | 892 | ``` |
888 | 893 |
|
889 | | -The suite currently collects 500 tests and reports 92.67% line coverage, including numerical parity |
890 | | -tests against `qis` for the EWMA primitives and against `scikit-learn` for the |
891 | | -LASSO path. |
| 894 | +The suite covers estimator contracts, independent EWMA references, covariance assembly, cluster |
| 895 | +diagnostics, and numerical parity with scikit-learn and skglm on their shared LASSO surface. |
892 | 896 |
|
893 | 897 | --- |
894 | 898 |
|
895 | 899 | ## Ecosystem |
896 | 900 |
|
897 | | -This package is part of an open-source Python stack for quantitative finance — full catalogue at [github.com/ArturSepp](https://github.com/ArturSepp): |
| 901 | +This package is part of an open-source Python stack for quantitative finance. The |
| 902 | +[ArturSepp profile](https://github.com/ArturSepp) is the canonical full catalogue: |
898 | 903 |
|
899 | 904 | | Package | Purpose | |
900 | 905 | |---|---| |
901 | 906 | | [`qis`](https://github.com/ArturSepp/QuantInvestStrats) | Performance analytics, factsheets, and visualisation | |
902 | 907 | | [`optimalportfolios`](https://github.com/ArturSepp/OptimalPortfolios) | Portfolio construction and backtesting | |
903 | 908 | | [`factorlasso`](https://github.com/ArturSepp/factorlasso) *(this package)* | Sparse factor models and factor covariance estimation | |
904 | 909 | | [`bbg-fetch`](https://github.com/ArturSepp/BloombergFetch) | Bloomberg data fetching | |
| 910 | +| [`option-chain-analytics`](https://github.com/ArturSepp/OptionChainAnalytics) | Point-in-time option-chain normalisation, reconstruction, querying, and visualisation | |
| 911 | +| [`vanilla-option-pricers`](https://github.com/ArturSepp/VanillaOptionPricers) | Vectorised vanilla option pricers and implied volatility fitters | |
| 912 | +| [`stochvolmodels`](https://github.com/ArturSepp/StochVolModels) | Stochastic volatility pricing analytics | |
905 | 913 | | [`trendfollowing`](https://github.com/ArturSepp/TrendFollowingSystems) | Trend-following systems: closed-form theory and replication | |
| 914 | +| [`privateassets`](https://github.com/ArturSepp/privateassets) | Money-weighted multi-factor alpha from private-asset cash flows | |
906 | 915 | | [`goal-based-allocation`](https://github.com/ArturSepp/GoalBasedAllocation) | Dynamic MV allocation under regime-switching jump-diffusions | |
907 | | -| [`stochvolmodels`](https://github.com/ArturSepp/StochVolModels) | Stochastic volatility pricing analytics | |
908 | | -| [`vanilla-option-pricers`](https://github.com/ArturSepp/VanillaOptionPricers) | Vectorised vanilla option pricers and implied volatility fitters | |
909 | 916 |
|
910 | | -Dependency links within the stack: `optimalportfolios` builds on `qis` and `factorlasso`; `trendfollowing` builds on `qis`. |
| 917 | +`factorlasso` has no runtime dependency on another package in the stack. It is consumed by |
| 918 | +`optimalportfolios` and, through its optional `factors` extra, by `privateassets`. |
911 | 919 |
|
912 | 920 | ## Citation |
913 | 921 |
|
| 922 | +A machine-readable citation is available in [`CITATION.cff`](CITATION.cff). |
| 923 | + |
914 | 924 | If you use `factorlasso` in academic work, please cite the software |
915 | 925 | paper describing the package (submitted to the *Journal of Statistical |
916 | 926 | Software*), the methodology paper for the cluster-pooled sign derivation |
@@ -940,8 +950,8 @@ software itself: |
940 | 950 |
|
941 | 951 | @article{SeppHansenKastenholz2026MATF, |
942 | 952 | author = {Sepp, Artur and Hansen, Emilie and Kastenholz, Mika}, |
943 | | - title = {Capital Market Assumptions Using Multi-Asset Tradable Factors: |
944 | | - The {MATF-CMA} Framework}, |
| 953 | + title = {Capital Market Assumptions and Strategic Asset Allocation Using |
| 954 | + Multi-Asset Tradable Factors}, |
945 | 955 | journal = {Journal of Portfolio Management}, |
946 | 956 | year = {2026}, |
947 | 957 | note = {Forthcoming.} |
@@ -970,10 +980,12 @@ software itself: |
970 | 980 |
|
971 | 981 | --- |
972 | 982 |
|
973 | | -## Contributing & feedback |
| 983 | +## Feedback & contributing |
974 | 984 |
|
975 | | -Issues and pull requests welcome at |
976 | | -<https://github.com/ArturSepp/factorlasso>. |
| 985 | +- **Bug:** use the [bug-report form](https://github.com/ArturSepp/factorlasso/issues/new?template=bug_report.yml) with the version, Python/platform, a minimal reproducer, and expected versus actual output. |
| 986 | +- **Feature:** use the [feature-request form](https://github.com/ArturSepp/factorlasso/issues/new?template=feature_request.yml) and describe the estimation goal, current workaround, and smallest useful API. In particular: which grouping, constraint, or covariance diagnostic is missing? |
| 987 | +- **Question or methodology:** search or open an [issue](https://github.com/ArturSepp/factorlasso/issues) and identify the estimator, paper section, or convention involved. |
| 988 | +- **Contribution:** follow [CONTRIBUTING.md](CONTRIBUTING.md) and look for [`good first issue`](https://github.com/ArturSepp/factorlasso/labels/good%20first%20issue) or [`help wanted`](https://github.com/ArturSepp/factorlasso/labels/help%20wanted) work. |
977 | 989 |
|
978 | 990 | See [`CHANGELOG.md`](CHANGELOG.md) for release history and |
979 | 991 | [`COMPATIBILITY.md`](COMPATIBILITY.md) for the API stability policy |
|
0 commit comments