Skip to content

About

Collection of algorithms for online portfolio selection

Resources

Stars

868 stars

Watchers

30 watching

Forks

Repository files navigation

Universal Portfolios

PyPi Version PyPi License PyPi Downloads

Open PRs Contributors Repo size

This Python package brings together Online Portfolio Selection (OLPS) algorithms from the literature, implemented faithfully to their papers and run under one interface, so that they can be compared and their claims checked.

In short, OLPS algorithms choose portfolio weights in every period to maximize final wealth. Examples include the Markowitz portfolio and the Universal portfolio. Many papers in this field report spectacular backtests. The point of this package is to make it easy to see how much of that survives a closer look. Contributions and corrections are more than welcome.

⚠️ Read this before trusting any backtest

The results you get from these algorithms on the bundled datasets say very little about how they would do with real money.

  • The datasets only contain survivors. NYSE(O), NYSE(N), DJIA, SP500 and TSE are the standard stock benchmarks of the OLPS literature (MSCI holds country indices). They include only stocks that traded every day of the period: none went bankrupt or was delisted. Some are also picked in hindsight. SP500 is the 25 stocks with the largest market cap in April 2003, after the period ends, and NYSE(N) keeps 23 of NYSE(O)'s 36 stocks. The Anticor paper (p. 592), CWMR (§5.5) and OLMAR (§5.5) acknowledge this. Many later papers, such as PPT and SSPO, don't mention it.
  • Survivor-only data hides the main risk of "follow the loser" algorithms. OLMAR, PAMR, PPT, SSPO and the like move money into stocks that just fell. Survivor-only data still has stocks that fall a long way, but none that fall all the way and get delisted, so these algorithms never meet one. examples/survivorship_bias.ipynb simulates this on random walks. Survivorship alone doesn't make these algorithms beat uniform CRP. But once stocks can go bankrupt, they keep buying into the collapsing ones. Even when only 1–7% of the stocks go bankrupt, OLMAR, PAMR and PPT end with 46–76% of CRP's wealth, against 84–94% on survivors, while buy-and-hold loses less than CRP.
  • Transaction costs. Most headline numbers assume rebalancing for free at the daily close. The mean-reversion algorithms trade most of their wealth every day. PPT, for example, falls behind uniform CRP at fees of 0.14–0.6% per unit traded on the bundled datasets, and SSPO at 0.5% round trip ends below CRP on SP500. Set result.fee before believing any number.
  • Parameters are often tuned on the same data. PPT's step size and four of SSPO's five parameters were chosen by final wealth on the same five datasets the papers then report, with no out-of-sample period.
  • Independent re-tests are discouraging. On recent S&P 500 stocks, Moon et al. (2019) find that OLMAR and PAMR lose almost everything at 0.25% costs.

Use this package to study the algorithms and their failure modes, not to pick a trading strategy.

Outline of this package

  • Python notebooks:

    • Online Portfolios: explains the basic use of the library. Script sequence, various options, method arguments, and a strategy template to get you started.
    • Modern Portfolio Theory: goes deeper into the OLPS principle and the tools developed in this library to approach it.
    • Survivorship bias: what survivor-only datasets hide about mean-reversion algorithms, on simulated data.
  • universal.data contains various datasets to help you in your journey.

  • universal.algos hosts the implementations of various OLPS algorithms from the literature:

  • universal.algo provides a general class inherited by all the individual algos' subclasses. Algo computes the weights at every timestep.

  • universal.result computes the portfolio wealth from the weights and various metrics on the strategy's performance.

Quick Start

from universal import tools
from universal.algos import CRP

if __name__ == '__main__':
  # Run CRP on a computer-generated portfolio of 3 stocks and plot the results
  tools.quickrun(CRP())

Additional Resources

If you do not know what an online portfolio is, look at Ernest Chan's blog, CASTrader, or a recent survey by Bin Li and Steven C. H. Hoi.

Paul Perry followed up on this and made a comparison of all algorithms on more recent ETF datasets. The original authors of some of the algorithms recently published their own implementation on GitHub - Online Portfolio Selection Toolbox in MATLAB.

If you are more into R or just looking for a good resource about Universal Portfolios, check out the blog and package logopt by Marc Delvaux.

Note: If you don't want to install the package locally, you can run both notebooks with Binder - modern-portfolio-theory.ipynb Binder or On-line portfolios.ipynb Binder

Installation

pip install universal-portfolios

Development

Set up .venv, install dependencies and run tests with:

make test

Contributors

Creator: Marigold

Thank you for your contributions!

Alexander Myltsev | angonyfox | booxter | dexhunter | DrPaprikaa | paulorodriguesxv | stergnator | Xander Dunn

Disclaimer

This software is for educational purposes only and is far from any production environment. Do not risk money you are afraid to lose. Use the software at your own risk. The authors assume no responsibility for your trading results.

About

Collection of algorithms for online portfolio selection

Resources

Stars

868 stars

Watchers

30 watching

Forks

Releases

Packages

Used by

Contributors

Languages