# Compact-RIEnet: A Compact Rotational Invariant Estimator Network for GMV Optimization
[](https://pypi.org/project/compact-rienet/)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
Compact-RIEnet implements a **parameter-efficient, end-to-end neural estimator** for **Global Minimum-Variance (GMV)** portfolios. The architecture couples a **five-parameter lag-kernel** with a **bidirectional GRU spectral denoiser** and a **marginal-volatility head** to produce cleaned inverse covariances and analytic GMV weights. By design, the number of learnable parameters is **independent of the look-back window length and the asset-universe size**, enabling immediate transfer across universes and sampling frequencies without retraining. The model can be trained directly on a realized-variance objective and can export its cleaned covariance for constrained optimizations.
## Key Features
- **End-to-End Variance Objective** – Trains on the realized out-of-sample variance, yielding GMV weights analytically from the learned inverse covariance.
- **Parameter Efficiency** – Fixed-size modules (5-parameter lag kernel; BiGRU eigencleaning; lightweight volatility head) keep the model at ≈2k parameters.
- **Size-Invariant Design** – Complexity does not scale with look-back length or cross-sectional dimension; deploy on new universes without architecture changes.
- **RIE-Style Covariance Cleaning** – Rotation-invariant mapping of the correlation spectrum with a BiGRU (16 units per direction by default).
- **Practical Outputs** – Retrieve GMV weights and the cleaned precision/covariance; the latter can be plugged into long-only QP solvers when needed.
- **Reproducible Defaults** – TensorFlow/Keras reference implementation with paper-consistent hyperparameters and tests.
## Installation
Install from PyPI:
```bash
pip install compact-rienet
```
Or install from source:
```bash
git clone https://github.com/bongiornoc/Compact-RIEnet.git
cd Compact-RIEnet
pip install -e .
```
## Quick Start
### Basic Usage
```python
import tensorflow as tf
from compact_rienet import CompactRIEnetLayer, variance_loss_function
# Defaults reproduce the compact GMV architecture (bidirectional GRU with 16 units)
rienet_layer = CompactRIEnetLayer(output_type=['weights', 'precision'])
# Sample data: (batch_size, n_stocks, n_days)
returns = tf.random.normal((32, 10, 60), stddev=0.02)
# Retrieve GMV weights and cleaned precision in one pass
outputs = rienet_layer(returns)
weights = outputs['weights'] # (32, 10, 1)
precision = outputs['precision'] # (32, 10, 10)
# GMV training objective
covariance = tf.random.normal((32, 10, 10))
covariance = tf.matmul(covariance, covariance, transpose_b=True)
loss = variance_loss_function(covariance, weights)
print(loss.shape) # (32, 1, 1)
```
### Training with the GMV Variance Loss
```python
import tensorflow as tf
from compact_rienet import CompactRIEnetLayer, variance_loss_function
def create_portfolio_model():
inputs = tf.keras.Input(shape=(None, None))
weights = CompactRIEnetLayer(output_type='weights')(inputs)
return tf.keras.Model(inputs=inputs, outputs=weights)
model = create_portfolio_model()
# Synthetic training data
X_train = tf.random.normal((1000, 10, 60), stddev=0.02)
Sigma_train = tf.random.normal((1000, 10, 10))
Sigma_train = tf.matmul(Sigma_train, Sigma_train, transpose_b=True)
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4, clipnorm=1.0)
model.compile(optimizer=optimizer, loss=variance_loss_function)
model.fit(X_train, Sigma_train, epochs=10, batch_size=32, verbose=True)
```
> **Tip:** When you intend to deploy Compact-RIEnet on portfolios of varying size, train on batches that span different asset universes. The RIE-based architecture is dimension agnostic and benefits from heterogeneous training shapes.
### Using Different Output Types
```python
# GMV weights only
weights = CompactRIEnetLayer(output_type='weights')(returns)
# Precision matrix only
precision_matrix = CompactRIEnetLayer(output_type='precision')(returns)
# Precision, covariance, and the lag-transformed inputs in one pass
outputs = CompactRIEnetLayer(
output_type=['precision', 'covariance', 'input_transformed']
)(returns)
precision_matrix = outputs['precision']
covariance_matrix = outputs['covariance']
lagged_inputs = outputs['input_transformed']
# Optional: disable variance normalisation (do not use it with end-to-end GMV training)
raw_covariance = CompactRIEnetLayer(
output_type='covariance',
normalize_transformed_variance=False
)(returns)
```
> ⚠️ When Compact-RIEnet is trained end-to-end on the GMV variance loss, leave
> `normalize_transformed_variance=True` (the default). The loss is invariant to global
> covariance rescalings and the layer keeps the implied variance scale centred
> around one. Disable the normalisation only when using alternative objectives
> where the absolute volatility scale must be preserved.
## Loss Function
### Variance Loss Function
```python
from compact_rienet import variance_loss_function
loss = variance_loss_function(
covariance_true=true_covariance, # (batch_size, n_assets, n_assets)
weights_predicted=predicted_weights # (batch_size, n_assets, 1)
)
```
**Mathematical Formula:**
```
Loss = n_assets × wᵀ Σ w
```
Where `w` are the portfolio weights and `Σ` is the realised covariance matrix.
## Architecture Details
The Compact-RIEnet pipeline consists of:
1. **Input Scaling** – Annualise returns by 252
2. **Lag Transformation** – Five-parameter memory kernel for temporal weighting
3. **Covariance Estimation** – Sample covariance across assets
4. **Eigenvalue Decomposition** – Spectral analysis of the covariance matrix
5. **Recurrent Cleaning** – Bidirectional GRU/LSTM processing of eigen spectra
6. **Marginal Volatility Head** – Dense network forecasting inverse standard deviations
7. **Matrix Reconstruction** – RIE-based synthesis of Σ⁻¹ and GMV weight normalisation
Paper defaults use a single bidirectional GRU layer with 16 units per direction and a marginal-volatility head with 8 hidden units, matching the compact network described in Bongiorno et al. (2025).
## Requirements
- Python ≥ 3.8
- TensorFlow ≥ 2.10.0
- Keras ≥ 2.10.0
- NumPy ≥ 1.21.0
## Development
```bash
git clone https://github.com/bongiornoc/Compact-RIEnet.git
cd Compact-RIEnet
pip install -e ".[dev]"
pytest tests/
```
## Citation
Please cite the following references when using Compact-RIEnet:
```bibtex
@inproceedings{bongiorno2025compact,
title={Neural Network-Driven Volatility Drag Mitigation under Aggressive Leverage},
author={Bongiorno, Christian and Manolakis, Efstratios and Mantegna, Rosario N.},
booktitle={Proceedings of the 6th ACM International Conference on AI in Finance (ICAIF '25)},
year={2025}
}
@article{bongiorno2025covariance,
title={End-to-End Large Portfolio Optimization for Variance Minimization with Neural Networks through Covariance Cleaning},
author={Bongiorno, Christian and Manolakis, Efstratios and Mantegna, Rosario N.},
journal={arXiv preprint arXiv:2507.01918},
year={2025}
}
```
For software citation:
```bibtex
@software{compact_rienet2025,
title={Compact-RIEnet: A Compact Rotational Invariant Estimator Network for Global Minimum-Variance Optimisation},
author={Bongiorno, Christian},
year={2025},
version={1.1.3},
url={https://github.com/bongiornoc/Compact-RIEnet}
}
```
You can print citation information programmatically:
```python
import compact_rienet
compact_rienet.print_citation()
```
## Support
For questions, issues, or contributions, please:
- Open an issue on [GitHub](https://github.com/bongiornoc/Compact-RIEnet/issues)
- Check the documentation
- Contact Prof. Christian Bongiorno (<christian.bongiorno@centralesupelec.fr>) for calibrated model weights or collaboration requests
Raw data
{
"_id": null,
"home_page": "https://github.com/bongiornoc/Compact-RIEnet",
"name": "compact-rienet",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Christian Bongiorno <christian.bongiorno@centralesupelec.fr>",
"keywords": "portfolio optimization, neural networks, finance, machine learning, tensorflow, eigenvalue decomposition, recurrent neural networks, covariance estimation",
"author": "Christian Bongiorno",
"author_email": "Christian Bongiorno <christian.bongiorno@centralesupelec.fr>",
"download_url": "https://files.pythonhosted.org/packages/af/52/34035d95b679062794ed2659e813e0d1cda727f03ab6f07b4bdd78ccee9d/compact_rienet-1.1.7.tar.gz",
"platform": null,
"description": "# Compact-RIEnet: A Compact Rotational Invariant Estimator Network for GMV Optimization\n\n[](https://pypi.org/project/compact-rienet/)\n[](https://www.python.org/downloads/)\n[](https://opensource.org/licenses/MIT)\n\nCompact-RIEnet implements a **parameter-efficient, end-to-end neural estimator** for **Global Minimum-Variance (GMV)** portfolios. The architecture couples a **five-parameter lag-kernel** with a **bidirectional GRU spectral denoiser** and a **marginal-volatility head** to produce cleaned inverse covariances and analytic GMV weights. By design, the number of learnable parameters is **independent of the look-back window length and the asset-universe size**, enabling immediate transfer across universes and sampling frequencies without retraining. The model can be trained directly on a realized-variance objective and can export its cleaned covariance for constrained optimizations.\n\n## Key Features\n\n- **End-to-End Variance Objective** \u2013 Trains on the realized out-of-sample variance, yielding GMV weights analytically from the learned inverse covariance.\n- **Parameter Efficiency** \u2013 Fixed-size modules (5-parameter lag kernel; BiGRU eigencleaning; lightweight volatility head) keep the model at \u22482k parameters.\n- **Size-Invariant Design** \u2013 Complexity does not scale with look-back length or cross-sectional dimension; deploy on new universes without architecture changes.\n- **RIE-Style Covariance Cleaning** \u2013 Rotation-invariant mapping of the correlation spectrum with a BiGRU (16 units per direction by default).\n- **Practical Outputs** \u2013 Retrieve GMV weights and the cleaned precision/covariance; the latter can be plugged into long-only QP solvers when needed.\n- **Reproducible Defaults** \u2013 TensorFlow/Keras reference implementation with paper-consistent hyperparameters and tests.\n\n## Installation\n\nInstall from PyPI:\n\n```bash\npip install compact-rienet\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/bongiornoc/Compact-RIEnet.git\ncd Compact-RIEnet\npip install -e .\n```\n\n## Quick Start\n\n### Basic Usage\n\n```python\nimport tensorflow as tf\nfrom compact_rienet import CompactRIEnetLayer, variance_loss_function\n\n# Defaults reproduce the compact GMV architecture (bidirectional GRU with 16 units)\nrienet_layer = CompactRIEnetLayer(output_type=['weights', 'precision'])\n\n# Sample data: (batch_size, n_stocks, n_days)\nreturns = tf.random.normal((32, 10, 60), stddev=0.02)\n\n# Retrieve GMV weights and cleaned precision in one pass\noutputs = rienet_layer(returns)\nweights = outputs['weights'] # (32, 10, 1)\nprecision = outputs['precision'] # (32, 10, 10)\n\n# GMV training objective\ncovariance = tf.random.normal((32, 10, 10))\ncovariance = tf.matmul(covariance, covariance, transpose_b=True)\nloss = variance_loss_function(covariance, weights)\nprint(loss.shape) # (32, 1, 1)\n```\n\n### Training with the GMV Variance Loss\n\n```python\nimport tensorflow as tf\nfrom compact_rienet import CompactRIEnetLayer, variance_loss_function\n\ndef create_portfolio_model():\n inputs = tf.keras.Input(shape=(None, None))\n weights = CompactRIEnetLayer(output_type='weights')(inputs)\n return tf.keras.Model(inputs=inputs, outputs=weights)\n\nmodel = create_portfolio_model()\n\n# Synthetic training data\nX_train = tf.random.normal((1000, 10, 60), stddev=0.02)\nSigma_train = tf.random.normal((1000, 10, 10))\nSigma_train = tf.matmul(Sigma_train, Sigma_train, transpose_b=True)\n\noptimizer = tf.keras.optimizers.Adam(learning_rate=1e-4, clipnorm=1.0)\nmodel.compile(optimizer=optimizer, loss=variance_loss_function)\n\nmodel.fit(X_train, Sigma_train, epochs=10, batch_size=32, verbose=True)\n```\n\n> **Tip:** When you intend to deploy Compact-RIEnet on portfolios of varying size, train on batches that span different asset universes. The RIE-based architecture is dimension agnostic and benefits from heterogeneous training shapes.\n\n### Using Different Output Types\n\n```python\n# GMV weights only\nweights = CompactRIEnetLayer(output_type='weights')(returns)\n\n# Precision matrix only\nprecision_matrix = CompactRIEnetLayer(output_type='precision')(returns)\n\n# Precision, covariance, and the lag-transformed inputs in one pass\noutputs = CompactRIEnetLayer(\n output_type=['precision', 'covariance', 'input_transformed']\n)(returns)\nprecision_matrix = outputs['precision']\ncovariance_matrix = outputs['covariance']\nlagged_inputs = outputs['input_transformed']\n\n# Optional: disable variance normalisation (do not use it with end-to-end GMV training)\nraw_covariance = CompactRIEnetLayer(\n output_type='covariance',\n normalize_transformed_variance=False\n)(returns)\n```\n\n> \u26a0\ufe0f When Compact-RIEnet is trained end-to-end on the GMV variance loss, leave\n> `normalize_transformed_variance=True` (the default). The loss is invariant to global\n> covariance rescalings and the layer keeps the implied variance scale centred\n> around one. Disable the normalisation only when using alternative objectives\n> where the absolute volatility scale must be preserved.\n\n## Loss Function\n\n### Variance Loss Function\n\n```python\nfrom compact_rienet import variance_loss_function\n\nloss = variance_loss_function(\n covariance_true=true_covariance, # (batch_size, n_assets, n_assets)\n weights_predicted=predicted_weights # (batch_size, n_assets, 1)\n)\n```\n\n**Mathematical Formula:**\n```\nLoss = n_assets \u00d7 w\u1d40 \u03a3 w\n```\n\nWhere `w` are the portfolio weights and `\u03a3` is the realised covariance matrix.\n\n## Architecture Details\n\nThe Compact-RIEnet pipeline consists of:\n\n1. **Input Scaling** \u2013 Annualise returns by 252\n2. **Lag Transformation** \u2013 Five-parameter memory kernel for temporal weighting\n3. **Covariance Estimation** \u2013 Sample covariance across assets\n4. **Eigenvalue Decomposition** \u2013 Spectral analysis of the covariance matrix\n5. **Recurrent Cleaning** \u2013 Bidirectional GRU/LSTM processing of eigen spectra\n6. **Marginal Volatility Head** \u2013 Dense network forecasting inverse standard deviations\n7. **Matrix Reconstruction** \u2013 RIE-based synthesis of \u03a3\u207b\u00b9 and GMV weight normalisation\n\nPaper defaults use a single bidirectional GRU layer with 16 units per direction and a marginal-volatility head with 8 hidden units, matching the compact network described in Bongiorno et al. (2025).\n\n## Requirements\n\n- Python \u2265 3.8\n- TensorFlow \u2265 2.10.0\n- Keras \u2265 2.10.0\n- NumPy \u2265 1.21.0\n\n## Development\n\n```bash\ngit clone https://github.com/bongiornoc/Compact-RIEnet.git\ncd Compact-RIEnet\npip install -e \".[dev]\"\npytest tests/\n```\n\n## Citation\n\nPlease cite the following references when using Compact-RIEnet:\n\n```bibtex\n@inproceedings{bongiorno2025compact,\n title={Neural Network-Driven Volatility Drag Mitigation under Aggressive Leverage},\n author={Bongiorno, Christian and Manolakis, Efstratios and Mantegna, Rosario N.},\n booktitle={Proceedings of the 6th ACM International Conference on AI in Finance (ICAIF '25)},\n year={2025}\n}\n\n@article{bongiorno2025covariance,\n title={End-to-End Large Portfolio Optimization for Variance Minimization with Neural Networks through Covariance Cleaning},\n author={Bongiorno, Christian and Manolakis, Efstratios and Mantegna, Rosario N.},\n journal={arXiv preprint arXiv:2507.01918},\n year={2025}\n}\n```\n\nFor software citation:\n\n```bibtex\n@software{compact_rienet2025,\n title={Compact-RIEnet: A Compact Rotational Invariant Estimator Network for Global Minimum-Variance Optimisation},\n author={Bongiorno, Christian},\n year={2025},\n version={1.1.3},\n url={https://github.com/bongiornoc/Compact-RIEnet}\n}\n```\n\nYou can print citation information programmatically:\n\n```python\nimport compact_rienet\ncompact_rienet.print_citation()\n```\n\n## Support\n\nFor questions, issues, or contributions, please:\n\n- Open an issue on [GitHub](https://github.com/bongiornoc/Compact-RIEnet/issues)\n- Check the documentation\n- Contact Prof. Christian Bongiorno (<christian.bongiorno@centralesupelec.fr>) for calibrated model weights or collaboration requests\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Compact Recurrent-Invariant Eigenvalue Network for Portfolio Optimization",
"version": "1.1.7",
"project_urls": {
"Bug Tracker": "https://github.com/bongiornoc/Compact-RIEnet/issues",
"Documentation": "https://github.com/bongiornoc/Compact-RIEnet",
"Homepage": "https://github.com/bongiornoc/Compact-RIEnet",
"Source Code": "https://github.com/bongiornoc/Compact-RIEnet"
},
"split_keywords": [
"portfolio optimization",
" neural networks",
" finance",
" machine learning",
" tensorflow",
" eigenvalue decomposition",
" recurrent neural networks",
" covariance estimation"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "7537cad336a50b43c95a2a2444e19a477f083cef13fa6713792017135d08fa56",
"md5": "c923f8502f7a6bd6ecbb3ccde6bbd92f",
"sha256": "99444700730620d71db081847ece6b6b48b7587d5115bf2accc91850fa6b5f8b"
},
"downloads": -1,
"filename": "compact_rienet-1.1.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c923f8502f7a6bd6ecbb3ccde6bbd92f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 23105,
"upload_time": "2025-10-26T07:56:52",
"upload_time_iso_8601": "2025-10-26T07:56:52.073092Z",
"url": "https://files.pythonhosted.org/packages/75/37/cad336a50b43c95a2a2444e19a477f083cef13fa6713792017135d08fa56/compact_rienet-1.1.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "af5234035d95b679062794ed2659e813e0d1cda727f03ab6f07b4bdd78ccee9d",
"md5": "5e791cfdf6f66925a89c5acda4dd5832",
"sha256": "82b1e56ef6a278e80d072032de8c9f537e115f4e7e0a342482365212f0c71acc"
},
"downloads": -1,
"filename": "compact_rienet-1.1.7.tar.gz",
"has_sig": false,
"md5_digest": "5e791cfdf6f66925a89c5acda4dd5832",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 29116,
"upload_time": "2025-10-26T07:56:53",
"upload_time_iso_8601": "2025-10-26T07:56:53.640641Z",
"url": "https://files.pythonhosted.org/packages/af/52/34035d95b679062794ed2659e813e0d1cda727f03ab6f07b4bdd78ccee9d/compact_rienet-1.1.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-26 07:56:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bongiornoc",
"github_project": "Compact-RIEnet",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "compact-rienet"
}