Universal Portfolios (UP)
Relevant source files
The following files were used as context for generating this wiki page:
The Universal Portfolio (UP) is an Online Portfolio Selection (OLPS) algorithm implemented within the universal-portfolios library. Based on the work of Thomas Cover (1991), its primary goal is to maximize final wealth by choosing optimal portfolio weights in every period. It belongs to the "Follow the Winner" category of algorithms, which typically adjust weights based on the historical performance of various strategies.
Sources: README.md:21-25, universal/algos/up.py:9-14
In this implementation, the algorithm uses a performance-weighted average of all possible Constant Rebalanced Portfolios (CRPs). The library provides both a standard implementation and an enhanced version that supports "leverage," allowing the portfolio to include negative positions by stretching the underlying simplex mesh.
Sources: universal/algos/up.py:9-12, universal/algos/_up_deprecated.py:10-15
Core Architecture and Logic
The UP class inherits from the base Algo class, which defines the standard interface for online portfolio algorithms. The UP algorithm operates by creating a mesh of points on a simplex, where each point represents a specific CRP strategy.
Sources: universal/algo.py:16-25, universal/algos/up.py:9
Weight Initialization and Simplex Mesh
During initialization, the algorithm generates a set of candidate CRPs using a Monte Carlo simplex or a structured mesh. These candidates represent the universe of strategies the UP algorithm will aggregate.
| Component | Description | Implementation Details |
|---|---|---|
| Simplex Mesh | A set of points representing all possible weight distributions. | Generated via tools.mc_simplex or tools.simplex_mesh. |
| Wealth Tracker | A vector S that tracks the cumulative wealth of every candidate CRP. | Initialized as a vector of ones. |
| Leverage/Stretch | Logic to allow negative weights by expanding the simplex. | Controlled by the leverage parameter. |
Sources: universal/algos/up.py:35-46, universal/algos/_up_deprecated.py:27-35, universal/tools.py:378-400
Step Execution Logic
For every time step, the algorithm updates the wealth of all candidate CRPs based on current price relatives and computes the new portfolio weights as a weighted average.
The diagram shows the iterative update process for portfolio weights in the UP algorithm.
Sources: universal/algos/up.py:48-53, universal/algos/_up_deprecated.py:37-41
Key Implementation Details
The UP Class (universal/algos/up.py)
The primary implementation focuses on performance and the inclusion of leverage.
__init__(eval_points, leverage): Sets the number of points in the simplex mesh (complexity $O(time \cdot eval_points \cdot nr_assets^2)$) and the maximum leverage.init_step(X): Generates theWmatrix (the simplex) and theSvector (the wealth). If leverage is greater than the default ($1/m$), it stretches the simplex points.step(x, last_b, history): Performs the matrix multiplication to update cumulative wealth and returns the new distribution.
Sources: universal/algos/up.py:24-53
Integration with Results and Tools
UP results are wrapped in an AlgoResult object, which provides performance metrics and visualization tools.
This sequence shows how the UP algorithm interacts with the library's utility functions to produce analysis.
Sources: universal/algo.py:84-110, universal/result.py:34-50
Performance Metrics and Analysis
The UP algorithm is typically evaluated using several metrics provided by the AlgoResult class:
- Total Wealth: The final product of all returns.
- Sharpe Ratio: Annualized risk-adjusted return calculated from log returns.
- Turnover: The amount of rebalancing required, which is critical for UP as it updates weights every period.
- Drawdown: The longest and deepest periods of lost equity.
Sources: universal/result.py:126-170, universal/result.py:230-240
Parameters Summary
| Parameter | Type | Default | Description |
|---|---|---|---|
eval_points | int | 1e4 | Number of points to evaluate in the simplex mesh. Higher values increase accuracy and complexity. |
leverage | float | 1.0 | Maximum leverage. Value of 1.0 is a standard simplex. >1.0 allows negative weights. |
PRICE_TYPE | string | "ratio" | The expected input format for prices (usually $p_t / p_{t-1}$). |
Sources: universal/algos/up.py:24-33, universal/algos/_up_deprecated.py:23-25
Conclusion
Universal Portfolios (UP) within this repository provide a robust implementation of Cover's theoretical framework. By using a discretized simplex mesh and an extensible leverage model, the system allows for practical simulation of one of the fundamental algorithms in online portfolio selection theory. Its integration with the library's results module ensures that users can easily compare its performance against benchmarks like the Constant Rebalanced Portfolio (CRP) or Buy-and-Hold (BAH).
Sources: README.md:21-40, universal/result.py:460-485