Skip to main content

Algorithms for finding maximally diversified portfolios using the log-determinant objective.

Project description

Diversifind

Diversifind is a Python toolkit for finding the most diversified subset of assets from a large universe.

Given a correlation matrix and a target portfolio size $k$, the library searches for the portfolio that maximizes the determinant of the correlation matrix, which corresponds to selecting the most independent return streams.

This approach is particularly useful for systematic trading and strategy portfolios, where the goal is to combine independent signals rather than minimize variance.


Quick Example

import numpy as np
from diversifind import beam

# Example: random correlation matrix
np.random.seed(0)
n_assets = 20

A = np.random.randn(n_assets, n_assets)
cov = A @ A.T
std = np.sqrt(np.diag(cov))
corr = cov / np.outer(std, std)

symbols = [f"Asset_{i}" for i in range(n_assets)]

# Find the most diversified portfolio of size 5
results = beam(corr, symbols, k=5)

print(results.pretty())

Example output:

Top diversified portfolios:

Rank      LogDet  Symbols
-------------------------
1      -0.092668  Asset_8, Asset_9, Asset_12, Asset_16, Asset_19
2      -0.132573  Asset_2, Asset_4, Asset_11, Asset_14, Asset_15
3      -0.141984  Asset_1, Asset_2, Asset_4, Asset_16, Asset_17

The Problem

Suppose you have $M$ assets and want to choose $k$ assets such that the portfolio contains the most independent return streams.

A natural objective is to maximize the determinant of the correlation matrix:

$$ \max_{S \subseteq {1..M}, |S|=k} \det(C_S) $$

where $C_S$ is the correlation matrix of the selected assets.

A larger determinant implies:

  • lower pairwise correlations
  • higher effective rank
  • more independent sources of return

However, this becomes a combinatorial search problem:

$$ \binom{M}{k} $$

which grows extremely quickly.

For example:

Universe Portfolio size Combinations
50 5 2,118,760
50 10 10,272,278,170
100 10 17,310,309,456,440

Exhaustive search quickly becomes infeasible.


Algorithms Included

Diversifind implements several search strategies.

Greedy Search

A fast heuristic:

  1. Start with the best pair
  2. Iteratively add the asset that maximizes the log-determinant increase

Very fast but not guaranteed optimal.


Beam Search (Recommended)

Beam search maintains a pool of the best partial portfolios at each step.

Instead of exploring all possibilities, it expands only the most promising candidates.

Advantages:

  • dramatically faster than brute force
  • near-optimal results in practice
  • tunable accuracy via beam_width

Example:

results = beam(corr, symbols, k=10, beam_width=5000)

Brute Force (Benchmark)

The library also includes a multiprocessing brute-force search used for benchmarking.

from diversifind import bruteforce_mp

results = bruteforce_mp(corr, symbols, k=5)

This guarantees the optimal portfolio but becomes infeasible for large universes.


Analytics Tools

Diversifind includes tools to analyze the diversification properties of portfolios.

Example:

from diversifind import analyze_portfolio

best = results.best()

analysis = analyze_portfolio(
    corr=corr,
    combo=best.combo_indices,
    symbols=symbols
)

print(analysis["effective_rank"])
print(analysis["max_abs_corr"])

Diagnostics include:

  • effective rank
  • eigenvalue spectrum
  • max / mean correlations
  • correlation pair inspection

Installation

Install from PyPI (recommended)

Once the package is published, you will be able to install it directly with:

pip install diversifind

Install from source (development)

If you want the latest development version:

git clone https://github.com/Varltia/diversifind.git
cd diversifind
pip install -e .

The -e flag installs the package in editable mode, so local code changes immediately affect the installed package.


Example Scripts

The repository includes examples:

examples/basic_usage.py

Additional examples are available in the repository, including a real data notebook demonstrating the workflow on historical market data:

examples/real_data_example.ipynb

This notebook walks through loading price data, computing returns and correlations, running the search algorithms, and analyzing the resulting diversified portfolios.


Research Report

This project began as an exploration of how to efficiently solve the maximum determinant portfolio selection problem.

The full write-up including experiments comparing greedy, beam search, and brute-force approaches is available here:

docs/research_report.md

For a reference of the public API and analytics utilities, see:

docs/api_guide.md

Project Structure

diversifind/
    analytics.py
    results.py
    search_methods.py
    utils.py

tests/
    test_beam.py
    test_bruteforce.py
    test_greedy.py
    test_results.py
    test_utils.py
    test_analytics.py

examples/
    basic_usage.py
    real_data_example.ipynb
    data/
        sample_closes.csv

docs/
    research_report.md
    api_guide.md

Use Cases

Diversifind can be useful for:

  • systematic trading portfolios
  • alpha stream diversification
  • factor portfolio construction
  • signal selection
  • machine learning ensemble diversification

License

MIT License

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

diversifind-0.1.0.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

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

diversifind-0.1.0-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file diversifind-0.1.0.tar.gz.

File metadata

  • Download URL: diversifind-0.1.0.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for diversifind-0.1.0.tar.gz
Algorithm Hash digest
SHA256 50d66d1b58ca6ca5d14118d0313233ba05d1ddcde9ebb456cfaf2efa5408ca0a
MD5 4194d622e39d795943824a61766dfc53
BLAKE2b-256 f7cc83acd9e41faa2c985cc68127b1b54e384c83654cf3d8cf365c1af6c4c504

See more details on using hashes here.

File details

Details for the file diversifind-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: diversifind-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for diversifind-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3b065f5356d6a714b68ae12e9cff9545a0327afd542f6f0265fc2dcf85fd1ec5
MD5 6d0adac08e4200b83f6a6ec82f0bca74
BLAKE2b-256 07f387c4482fbda5276306054a3d42df5fbd48a15a4a21b6108089f0651f988a

See more details on using hashes here.

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