Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved examples #118

Merged
merged 18 commits into from
Dec 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ BUILDDIR = build
ENVDIR = env
BINDIR = $(ENVDIR)/bin
EXTRA_SCRIPTS = bumpversion.py
EXAMPLES = examples/*.py
EXAMPLES = examples

ifeq ($(OS), Windows_NT)
BINDIR=$(ENVDIR)/Scripts
Expand All @@ -34,10 +34,11 @@ test: ## run tests w/ cov report
$(BINDIR)/coverage xml
$(BINDIR)/diff-cover coverage.xml --config-file pyproject.toml
# disabled for now, we need to change pickle as default on-disk cache
# $(BINDIR)/bandit $(PROJECT)/*.py $(PROJECT)/tests/*.py
# $(BINDIR)/bandit $(PROJECT)/*.py $(TESTS)/*.py

lint: ## run linter
$(BINDIR)/pylint $(PROJECT)
$(BINDIR)/pylint $(PROJECT) $(EXTRA_SCRIPTS) $(EXAMPLES)
$(BINDIR)/diff-quality --violations=pylint --config-file pyproject.toml

docs: ## build docs
$(BINDIR)/sphinx-build -E docs $(BUILDDIR)
Expand All @@ -51,10 +52,10 @@ coverage: ## open html cov report

fix: ## auto-fix code
# selected among many code auto-fixers, tweaked in pyproject.toml
$(BINDIR)/autopep8 -i $(PROJECT)/*.py $(TESTS)/*.py
$(BINDIR)/isort $(PROJECT)/*.py $(TESTS)/*.py
$(BINDIR)/autopep8 -i -r $(PROJECT) $(EXAMPLES) $(EXTRA_SCRIPTS)
$(BINDIR)/isort $(PROJECT) $(EXAMPLES) $(EXTRA_SCRIPTS)
# this is the best found for the purpose
$(BINDIR)/docformatter --in-place $(PROJECT)/*.py $(TESTS)/*.py
$(BINDIR)/docformatter -r --in-place $(PROJECT) $(EXAMPLES) $(EXTRA_SCRIPTS)

release: update lint test ## update version, publish to pypi
$(BINDIR)/python bumpversion.py
Expand All @@ -64,8 +65,8 @@ release: update lint test ## update version, publish to pypi
$(BINDIR)/twine upload --skip-existing dist/*

examples: ## run examples for docs
for example in hello_world case_shiller dow30_example; \
do env CVXPORTFOLIO_SAVE_PLOTS=1 $(BINDIR)/python examples/"$$example".py > docs/_static/"$$example"_output.txt; \
for example in hello_world case_shiller universes dow30; \
do env CVXPORTFOLIO_SAVE_PLOTS=1 $(BINDIR)/python -m examples."$$example" > docs/_static/"$$example"_output.txt; \
done
mv *.png docs/_static/

Expand Down
17 changes: 9 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Installation
Cvxportolio is written in Python and can easily installed in any Python
environment by simple:

.. code:: console
.. code:: bash

pip install -U cvxportfolio

Expand All @@ -43,7 +43,7 @@ Test

After installing you can run our unit test suite in you local environment by

.. code:: console
.. code:: bash

python -m cvxportfolio.tests

Expand Down Expand Up @@ -109,8 +109,9 @@ are available in the code repository.
`The original examples from the paper
<https://github.com/cvxgrp/cvxportfolio/tree/0.0.X/examples>`_
are visible in a dedicated branch,
and are being translated to run with the stable versions (``1.0.*``) of the
library.
and are being translated to run with the stable versions (``1.0.0`` and above) of the
library. The translations are visible at `this documentation page
<https://www.cvxportfolio.com/en/latest/examples/paper_examples.html>_`.

We show in the example on `user-provided
forecasters <https://github.com/cvxgrp/cvxportfolio/blob/master/examples/user_provided_forecasters.py>`__
Expand Down Expand Up @@ -156,7 +157,7 @@ repository (or, `fork on
Github <https://docs.github.com/en/get-started/quickstart/fork-a-repo>`__
and then clone your fork)

.. code:: console
.. code:: bash

git clone https://github.com/cvxgrp/cvxportfolio.git
cd cvxportfolio
Expand All @@ -166,7 +167,7 @@ Then, you should have a look at our
and possibly change the ``PYTHON`` variable to match your system’s
python interpreter. Once you have done that,

.. code:: console
.. code:: bash

make env
make test
Expand All @@ -178,7 +179,7 @@ test suite.
You activate the shell environment with one of scripts in ``env/bin``
(or ``env\Scripts`` on Windows), for example if you use bash on POSIX

.. code:: console
.. code:: bash

source env/bin/activate

Expand All @@ -192,7 +193,7 @@ Windows) like we do in the Makefile.
Additionally, to match our CI/CD pipeline, you may set the following
`git hooks <https://git-scm.com/docs/githooks>`__

.. code:: console
.. code:: bash

echo "make lint" > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Expand Down
23 changes: 21 additions & 2 deletions TODOs_ROADMAP.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,27 @@ their planned release.
``cvxportfolio.risks``
----------------------

``cvxportfolio.hyperparameters``
-------------------------

- [ ] Clean up interface w/ ``MarketSimulator``, right now it calls private
methods, maybe enough to make them public. Target ``1.0.4``.
- [ ] Add risk/fine default ``GammaTrade``, ``GammaRisk`` (which are
``RangeHyperParameter``) modeled after original examples from paper.
Target ``1.1.0``.

``cvxportfolio.policies``
-------------------------

- [ ] Add `AllIn` policy, which allocates all to a single name (like
``AllCash``). Target ``1.1.0``.

Optimization policies
~~~~~~~~~~~~~~~~~~~~~

- [ ] Improve behavior for infeasibility/unboundedness/solver error. Target
``1.1.0``.
- [ ] Improve ``__repr__`` method, now hard to read. Target ``1.0.4``.

``cvxportfolio.constraints``
----------------------------
Expand All @@ -85,6 +98,10 @@ Optimization policies

- [ ] Make ``BackTestResult`` interface methods with ``MarketSimulator``
public.
- [ ] Add a ``backruptcy`` property (boolean). Amend ``sharpe_ratio``
and other aggregate statistics (as best as possible) to return ``-np.inf``
if back-test ended in backruptcy. This is needed specifically for
hyper-parameter optimization. Target ``1.0.4``.


Development & testing
Expand All @@ -99,8 +116,10 @@ Development & testing
Documentation
-------------

- Manual
- Quickstart
- [ ] Improve examples section, also how "Hello world" is mentioned in readme.
Target ``1.0.4``, PR #118.
- [ ] Manual.
- [ ] Quickstart, probably to merge into manual.

Examples
--------
Expand Down
48 changes: 38 additions & 10 deletions bumpversion.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,68 @@
"""Look for __version__ in any __init__.py recursively and upgrade.

Additionally, look for version string in any setup.py and (Sphinx) conf.py
and do the same. Version is assumed to be in the format X.Y.Z, where X, Y,
and Z are integers. Take argument revision (Z -> Z+1),
# Copyright 2023 Enzo Busseti
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Find __version__ in __init__.py in file tree (BFS) and upgrade.

Additionally, look for version string in any setup.py, pyproject.toml,
and conf.py and do the same. Version is in the format X.Y.Z,
where X, Y, and Z are integers. Take argument revision (Z -> Z+1),
minor (Y -> Y+1, Z -> 0), or major (X -> X+1, Y -> 0, Z -> 0).
Return the updated version string."""

Add the modifications to git staging, commit with version number and
editable message (opens git configured text editor), tag with version number,
push everything to origin.
"""

import subprocess
from ast import literal_eval
from pathlib import Path


def findversion(root='.'):
"""Find version number. Skip [env, venv, .*].

We use the first __init__.py with a __version__ that we find.

:param root: Root folder of the project.
:type root: Pathlib.Path or str

:raises ValueError: No version found.

:returns: Found version string.
:rtype: str
"""
p = Path(root)

for fname in p.iterdir():

if fname.name == '__init__.py':
with open(fname) as f:
with open(fname, encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
if '__version__' in line:
return eval(line.split('=')[1])
return literal_eval(line.split('=')[1])
if fname.is_dir():
if not (fname.name in ['env', 'venv'] or fname.name[0] == '.'):
result = findversion(fname)
if result:
return result

raise ValueError('Not found any!')


def replaceversion(new_version, version, root='.'):
"""Replace version number. Skip [env, venv, .*].

We replace in all __init__.py, conf.py, setup.py, and pyproject.toml
"""

Expand Down
10 changes: 5 additions & 5 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ Examples
Many `example scripts are available in the code repository. <https://github.com/cvxgrp/cvxportfolio/tree/master/examples>`_
We show some of them, along with their results, in the following pages:

.. - :doc:`Hello World example <hello_world>`
.. - :doc:`Case-Shiller example <examples/case_shiller>`


.. toctree::
:maxdepth: 2

hello_world
examples/case_shiller
examples/dow30
examples/dow30
examples/timing
examples/universes
examples/etfs
examples/paper_examples
8 changes: 5 additions & 3 deletions docs/examples/case_shiller.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Case-Shiller Example
====================
Case-Shiller multi-period
=========================

This is an example that shows that Cvxportfolio can work as well with
different asset classes, in this case a real estate portfolio. We use
Expand All @@ -9,10 +9,12 @@ are comparable to the annual return on the asset, and we show
that multi-period optimization is useful to correctly balance transaction cost
and expected risk-adjusted return.
This example script is
`available in the repository <https://github.com/cvxgrp/cvxportfolio/blob/master/examples/case_shiller.py>`_.
`available in the repository
<https://github.com/cvxgrp/cvxportfolio/blob/master/examples/case_shiller.py>`_.

.. literalinclude:: ../../examples/case_shiller.py
:language: python
:lines: 14-

This is the output printed to screen when executing this script. You can see
many statistics of the back-tests.
Expand Down
7 changes: 4 additions & 3 deletions docs/examples/dow30.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
DOW30 Example
DOW30 monthly
=============

This example script is
`available in the repository <https://github.com/cvxgrp/cvxportfolio/blob/master/examples/dow30_example.py>`_.
`available in the repository <https://github.com/cvxgrp/cvxportfolio/blob/master/examples/dow30.py>`_.
See the docstring below for its explanation.

.. literalinclude:: ../../examples/dow30_example.py
.. literalinclude:: ../../examples/dow30.py
:language: python
:lines: 14-

This is the output printed to screen when executing this script. You can see
many statistics of the back-tests.
Expand Down
9 changes: 9 additions & 0 deletions docs/examples/etfs.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Wide asset classes ETFs
=======================

This example script is
`available in the repository <https://github.com/cvxgrp/cvxportfolio/blob/master/examples/etfs.py>`_.

.. literalinclude:: ../../examples/etfs.py
:language: python
:lines: 14-
32 changes: 32 additions & 0 deletions docs/examples/paper_examples.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Original examples from the paper
================================

*Work in progress.*

These are the original examples, which were also used to generate plots
and results in :paper:`chapter 7 of the paper <chapter.7>`. They were
originally written as IPython notebook, and have been translated into Python
code using the stable API of Cvxportfolio (*i.e.*, version ``1.0.0`` and
above).

The original notebooks are `available on this branch of the repository
<https://github.com/cvxgrp/cvxportfolio/blob/0.0.X/examples/>`_.

.. note::

Currently some of them are *work in progress*, refer to the linked notebook
if in doubt.

.. toctree::
:maxdepth: 2

paper_examples/hello_world
paper_examples/data_risk_model
paper_examples/multi_period_opt
paper_examples/portfolio_simulation
paper_examples/rank_and_spo
paper_examples/real_time_optimization
paper_examples/single_period_opt
paper_examples/single_period_opt_lin_tcost
paper_examples/solution_time

15 changes: 15 additions & 0 deletions docs/examples/paper_examples/data_risk_model.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Data and risk model estimates
=============================

This example script is
`available in the repository
<https://github.com/cvxgrp/cvxportfolio/blob/master/examples/paper_examples/data_risk_model.py>`_.
See the docstring below for its explanation.

This is a translation of the `original IPython notebook
<https://github.com/cvxgrp/cvxportfolio/blob/0.0.X/examples/DataEstimatesRiskModel.ipynb>`_
which doesn't run any more for reasons explained below.

.. literalinclude:: ../../../examples/paper_examples/data_risk_model.py
:language: python
:lines: 14-
15 changes: 15 additions & 0 deletions docs/examples/paper_examples/hello_world.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Hello World (original)
======================

This example script is
`available in the repository
<https://github.com/cvxgrp/cvxportfolio/blob/master/examples/paper_examples/hello_world.py>`_.
See the docstring below for its explanation.

This is a translation of the `original IPython notebook
<https://github.com/cvxgrp/cvxportfolio/blob/0.0.X/examples/HelloWorld.ipynb>`_
using Cvxportfolio's stable API.

.. literalinclude:: ../../../examples/paper_examples/hello_world.py
:language: python
:lines: 14-
15 changes: 15 additions & 0 deletions docs/examples/paper_examples/multi_period_opt.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Multi-period Optimization
=========================

This example script is
`available in the repository
<https://github.com/cvxgrp/cvxportfolio/blob/master/examples/paper_examples/multi_period_opt.py>`_.
See the docstring below for its explanation.

This is a translation of the `original IPython notebook
<https://github.com/cvxgrp/cvxportfolio/blob/0.0.X/examples/MultiPeriodOptimization.ipynb>`_
using Cvxportfolio's stable API.

.. literalinclude:: ../../../examples/paper_examples/multi_period_opt.py
:language: python
:lines: 14-
Loading
Loading