Skip to main content

A Compact Recurrent-Invariant Eigenvalue Network for Portfolio Optimization

Project description

Compact-RIEnet: A Compact Rotational Invariant Estimator Network for GMV Optimization

PyPI version Python 3.8+ License: 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:

pip install compact-rienet

Or install from source:

git clone https://github.com/bongiornoc/Compact-RIEnet.git
cd Compact-RIEnet
pip install -e .

Quick Start

Basic Usage

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

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

# GMV weights only
weights = CompactRIEnetLayer(output_type='weights')(returns)

# Precision matrix only
precision_matrix = CompactRIEnetLayer(output_type='precision')(returns)

# Both precision and covariance in one pass
outputs = CompactRIEnetLayer(output_type=['precision', 'covariance'])(returns)
precision_matrix = outputs['precision']
covariance_matrix = outputs['covariance']

Loss Function

Variance Loss Function

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

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:

@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:

@software{compact_rienet2025,
  title={Compact-RIEnet: A Compact Rotational Invariant Estimator Network for Global Minimum-Variance Optimisation},
  author={Bongiorno, Christian},
  year={2025},
  version={1.0.6},
  url={https://github.com/bongiornoc/Compact-RIEnet}
}

You can print citation information programmatically:

import compact_rienet
compact_rienet.print_citation()

Support

For questions, issues, or contributions, please:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

compact_rienet-1.0.6.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

compact_rienet-1.0.6-py3-none-any.whl (19.9 kB view details)

Uploaded Python 3

File details

Details for the file compact_rienet-1.0.6.tar.gz.

File metadata

  • Download URL: compact_rienet-1.0.6.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for compact_rienet-1.0.6.tar.gz
Algorithm Hash digest
SHA256 f30353e7d2e517e32cb953bbcb3e57d51b2245715509d2cfcc0fa5ab8d7ed28a
MD5 cde90ff9b111a46ad12102d4ccb0d511
BLAKE2b-256 0fb19c7b689d624e275b962623d383e2b9198e481b3b088fe7fac3b45dcc1960

See more details on using hashes here.

Provenance

The following attestation bundles were made for compact_rienet-1.0.6.tar.gz:

Publisher: publish.yml on bongiornoc/Compact-RIEnet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file compact_rienet-1.0.6-py3-none-any.whl.

File metadata

  • Download URL: compact_rienet-1.0.6-py3-none-any.whl
  • Upload date:
  • Size: 19.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for compact_rienet-1.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 50298fdee18f773ea28f4452ff780d9a8e647ef7485a06066dbe2fd90c1b0ca7
MD5 4e2d0a576624c6b660c979c3f930b237
BLAKE2b-256 877cacb85ab94436162a6f1e1e96753953d594bb479af6925df1057f200f7a98

See more details on using hashes here.

Provenance

The following attestation bundles were made for compact_rienet-1.0.6-py3-none-any.whl:

Publisher: publish.yml on bongiornoc/Compact-RIEnet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page