Skip to content

Commit

Permalink
Numpy 2.0 Compatibiilty (#36)
Browse files Browse the repository at this point in the history
* gha update
* fix input syntax
* bump up dependencies
* np.INF removed
* update tests for numpy 2.0
* new tox setup
* readme update
  • Loading branch information
stefan-jansen authored Sep 25, 2024
1 parent 9465db2 commit 31173cf
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 59 deletions.
38 changes: 25 additions & 13 deletions .github/workflows/build_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ name: PyPI
on:
workflow_dispatch:
inputs:
publish_to_pypi:
description: 'Publish to PyPI?'
target:
type: choice
description: 'Package Index'
required: true
type: boolean
default: 'false'
default: 'PYPI'
options: [ 'TESTPYPI', 'PYPI' ]
version:
description: 'Version to publish'
required: true
default: '0.5.11'

jobs:
dist:
Expand All @@ -16,11 +21,14 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
python-version: [ 3.8 ]
python-version: [ "3.10" ]

steps:
- name: Checkout empyrical
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.version }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
Expand All @@ -41,24 +49,28 @@ jobs:
upload_pypi:
needs: [ dist ]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags')
permissions:
contents: read
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: artifact
path: dist

- name: publish to testpypi
- name: Publish to PyPI
if: ${{ github.event.inputs.target == 'PYPI' }}
uses: pypa/gh-action-pypi-publish@release/v1
if: inputs.publish_to_pypi == 'false'
with:
user: __token__
password: ${{ secrets.TESTPYPI_TOKEN }}
repository_url: https://test.pypi.org/legacy/
password: ${{ secrets.PYPI_TOKEN }}

- name: publish to pypi
- name: Publish to PyPI - Test
if: ${{ github.event.inputs.target == 'TESTPYPI' }}
uses: pypa/gh-action-pypi-publish@release/v1
if: inputs.publish_to_pypi == 'true'
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
password: ${{ secrets.TESTPYPI_TOKEN }}
repository-url: https://test.pypi.org/legacy/
skip-existing: true
verbose: true
4 changes: 4 additions & 0 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ name: CI Tests

on:
workflow_dispatch:
schedule:
- cron: "0 8 * * 6"
push:
branches:
- main
pull_request:
branches:
- main
Expand Down
23 changes: 18 additions & 5 deletions .github/workflows/test_wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,21 @@ jobs:
- name: Checkout empyrical
uses: actions/checkout@v4

- name: Install wheel & run tests
run: |
pip install -U pip wheel tox-gh-actions
pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple your-package empyrical-reloaded[test]
tox -p auto -q
# - name: Install wheel & run tests
# run: |
# pip install -U pip wheel tox-gh-actions
# pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple empyrical-reloaded[test]
# tox -p auto -q

- name: Unittests with tox & pytest
uses: nick-fields/retry@v3
with:
timeout_minutes: 90
max_attempts: 3
retry_on: error
new_command_on_retry: |
python -m pip install -U pip wheel tox tox-gh-actions
python -m pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple empyrical-reloaded[test]
tox -p auto -q
command: tox
78 changes: 65 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ conda install empyrical-reloaded -c conda-forge

empyrical requires and installs the following packages while executing the above commands:

- numpy>=1.9.2
- pandas>=1.0.0
- numpy>=1.23.5
- pandas>=1.3.0
- scipy>=0.15.1

> Note that Numpy>=2.0 requires pandas>=2.2.2. If you are using an older version of pandas, you may need to upgrade
> accordingly, otherwise you may encounter compatibility issues.
Optional dependencies include [yfinance](https://github.com/ranaroussi/yfinance) to download price data
from [Yahoo! Finance](https://finance.yahoo.com/)
and [pandas-datareader](https://pandas-datareader.readthedocs.io/en/latest/) to
Expand Down Expand Up @@ -129,18 +132,67 @@ risk_factors = emp.utils.get_fama_french()

pd.concat([risk_factors.head(), risk_factors.tail()])

Mkt-RF SMB HML RF Mom
Mkt - RF
SMB
HML
RF
Mom
Date
1970-01-02 00:00:00+00:00 0.0118 0.0129 0.0101 0.00029 -0.0340
1970-01-05 00:00:00+00:00 0.0059 0.0067 0.0072 0.00029 -0.0153
1970-01-06 00:00:00+00:00 -0.0074 0.0010 0.0021 0.00029 0.0038
1970-01-07 00:00:00+00:00 -0.0015 0.0040 -0.0033 0.00029 0.0011
1970-01-08 00:00:00+00:00 0.0004 0.0018 -0.0017 0.00029 0.0033
2024-03-22 00:00:00+00:00 -0.0023 -0.0087 -0.0053 0.00021 0.0043
2024-03-25 00:00:00+00:00 -0.0026 -0.0024 0.0088 0.00021 -0.0034
2024-03-26 00:00:00+00:00 -0.0026 0.0009 -0.0013 0.00021 0.0009
2024-03-27 00:00:00+00:00 0.0088 0.0104 0.0091 0.00021 -0.0134
2024-03-28 00:00:00+00:00 0.0010 0.0029 0.0048 0.00021 -0.0044
1970 - 01 - 02
00: 00:00 + 00: 00
0.0118
0.0129
0.0101
0.00029 - 0.0340
1970 - 01 - 05
00: 00:00 + 00: 00
0.0059
0.0067
0.0072
0.00029 - 0.0153
1970 - 01 - 06
00: 00:00 + 00: 00 - 0.0074
0.0010
0.0021
0.00029
0.0038
1970 - 01 - 07
00: 00:00 + 00: 00 - 0.0015
0.0040 - 0.0033
0.00029
0.0011
1970 - 01 - 0
8
00: 00:00 + 00: 00
0.0004
0.0018 - 0.0017
0.00029
0.0033
2024 - 03 - 22
00: 00:00 + 00: 00 - 0.0023 - 0.0087 - 0.0053
0.00021
0.0043
2024 - 03 - 25
00: 00:00 + 00: 00 - 0.0026 - 0.0024
0.0088
0.00021 - 0.0034
2024 - 03 - 26
00: 00:00 + 00: 00 - 0.0026
0.0009 - 0.0013
0.00021
0.0009
2024 - 03 - 27
00: 00:00 + 00: 00
0.0088
0.0104
0.0091
0.00021 - 0.0134
2024 - 03 - 28
00: 00:00 + 00: 00
0.0010
0.0029
0.0048
0.00021 - 0.0044
```

### Asset Prices and Benchmark Returns
Expand Down
42 changes: 32 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,32 @@ maintainers = [
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"License :: OSI Approved :: Apache Software License",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Mathematics",
"Operating System :: OS Independent"
]

requires-python = ">=3.7"
requires-python = ">=3.9"
dynamic = ["version"]


license = { file = "LICENSE" }

dependencies = [
"numpy >=1.9.2",
# following pandas
"numpy>=1.23.5; python_version<'3.12'",
"numpy>=1.26.0; python_version>='3.12'",
# "numpy>=2.0; python_version>='3.12'",
"pandas >=1.3.0; python_version<'3.12'",
"pandas>=2.2.2; python_version>='3.12'",
"bottleneck >=1.3.0",
"pandas >=1.0.0",
"pandas >=1.3.0",
"scipy >=0.15.1",
"peewee<3.17.4" # awwaiting bugfix in latest version: https://github.com/coleifer/peewee/issues/2891
]
Expand All @@ -49,8 +54,9 @@ repository = 'https://github.com/stefan-jansen/empyrical-reloaded'
requires = [
"setuptools>=54.0.0",
"setuptools_scm[toml]>=6.2",
"wheel>=0.31.0",
"oldest-supported-numpy; python_version>='3.7'"
# "wheel>=0.31.0",
# "numpy>=2.0rc1; python_version>='3.9'",
# "oldest-supported-numpy; python_version>='3.9'"
]
build-backend = "setuptools.build_meta"

Expand Down Expand Up @@ -102,7 +108,8 @@ write_to = "src/empyrical/_version.py"
version_scheme = 'guess-next-dev'
local_scheme = 'dirty-tag'

[tool.pytest]
[tool.pytest.ini_options]
pythonpath = 'src'
testpaths = 'tests'
addopts = '-v'

Expand Down Expand Up @@ -138,7 +145,17 @@ exclude = '''
[tool.tox]
legacy_tox_ini = """
[tox]
envlist = py39-pandas12, py{39,310}-pandas{13,14,15}, py311-pandas15, py312-pandas20
envlist =
py39-pandas{13,14,15}-numpy1
py310-pandas{13,14,15,20,21,22}-numpy1
py311-pandas{13,14,15,20,21,22}-numpy1
py312-pandas{13,14,15,20,21,22}-numpy1
py39-pandas222-numpy2
py310-pandas222-numpy2
py311-pandas222-numpy2
py312-pandas222-numpy2
isolated_build = True
skip_missing_interpreters = True
minversion = 3.23.0
Expand All @@ -158,11 +175,16 @@ setenv =
changedir = tmp
extras = test
deps =
pandas12: pandas>=1.2.0,<1.3
pandas13: pandas>=1.3.0,<1.4
pandas14: pandas>=1.4.0,<1.5
pandas15: pandas>=1.5.0,<1.6
pandas20: pandas>=2.0.0
pandas20: pandas>=2.0,<2.1
pandas21: pandas>=2.1,<2.2
pandas22: pandas>=2.2,<2.3
pandas222: pandas>=2.2.2,<2.3
numpy1: numpy>=1.23.5,<2.0
numpy2: numpy>=2.0,<2.1
commands =
pytest --cov={toxinidir}/src --cov-report term --cov-report=xml --cov-report=html:htmlcov {toxinidir}/tests
Expand Down
2 changes: 1 addition & 1 deletion src/empyrical/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ def downside_risk(
np.asanyarray(returns),
np.asanyarray(required_return),
),
np.NINF,
-np.inf,
0,
)

Expand Down
15 changes: 10 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import pytest
import pandas as pd
import numpy as np
from packaging.version import Version

PANDAS22 = Version(pd.__version__) >= Version("2.2.0")
monthly = "ME" if PANDAS22 else "M"
annual = "YE" if PANDAS22 else "A"


@pytest.fixture(scope="function")
Expand All @@ -11,12 +16,12 @@ def set_helpers(request):

request.cls.returns = pd.Series(
rand.randn(1, 120)[0] / 100.0,
index=pd.date_range("2000-1-30", periods=120, freq="M"),
index=pd.date_range("2000-1-30", periods=120, freq=monthly),
)

request.cls.factor_returns = pd.Series(
rand.randn(1, 120)[0] / 100.0,
index=pd.date_range("2000-1-30", periods=120, freq="M"),
index=pd.date_range("2000-1-30", periods=120, freq=monthly),
)


Expand Down Expand Up @@ -85,7 +90,7 @@ def input_data():

df_index_simple = pd.date_range("2000-1-30", periods=8, freq="D")
df_index_week = pd.date_range("2000-1-30", periods=8, freq="W")
df_index_month = pd.date_range("2000-1-30", periods=8, freq="M")
df_index_month = pd.date_range("2000-1-30", periods=8, freq=monthly)

df_week = pd.DataFrame(
{
Expand Down Expand Up @@ -176,7 +181,7 @@ def input_data():
# Monthly returns
"monthly_returns": pd.Series(
np.array([0.0, 1.0, 10.0, -4.0, 2.0, 3.0, 2.0, 1.0, -10.0]) / 100,
index=pd.date_range("2000-1-30", periods=9, freq="M"),
index=pd.date_range("2000-1-30", periods=9, freq=monthly),
),
# Series of length 1
"one_return": pd.Series(
Expand Down Expand Up @@ -214,7 +219,7 @@ def input_data():
),
"flat_line_yearly": pd.Series(
np.array([3.0, 3.0, 3.0]) / 100,
index=pd.date_range("2000-1-30", periods=3, freq="A"),
index=pd.date_range("2000-1-30", periods=3, freq=annual),
),
# Positive line
"pos_line": pd.Series(
Expand Down
Loading

0 comments on commit 31173cf

Please sign in to comment.