From 7814ef99cdcb1f46856f705eea93bcf20fbab182 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Sat, 15 Nov 2025 22:57:27 +0400 Subject: [PATCH 01/17] Create renovate.json for automated updates Add Renovate configuration for dependency management. --- .github/renovate.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/renovate.json diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..349a7bae --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,21 @@ +{ + "extends": [ + "config:recommended", + ":enablePreCommit", + ":automergeMinor", + ":dependencyDashboard", + ":maintainLockFilesWeekly", + ":semanticCommits", + ":pinDevDependencies" + ], + "enabledManagers": [ + "pep621", + "pre-commit", + "github-actions", + "devcontainer" + ], + "timezone": "Asia/Dubai", + "schedule": [ + "before 10am on tuesday" + ] +} From 3600fa1f21ca636c7931eab72f3cb8a2a5071011 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:18:39 +0000 Subject: [PATCH 02/17] fix(deps): update dependency plotly to v6 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 12788579..8090418a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ dependencies = [ # all_extras = [ "matplotlib>=3.2.0", - "plotly>=5.0.0,<6", + "plotly>=6.4,<7", "ecos>=2.0.14,<2.1", "plotly>=5.0.0,<7", "cvxopt; python_version < '3.14'", From 57da33d8628b1c84d8d47cd371ab9ba7c567f9c7 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Sat, 15 Nov 2025 23:21:11 +0400 Subject: [PATCH 03/17] Revert merge commit d8b8958e1035a9cf4778b9605d3836661c03d4a8 --- REVERT_COMMIT.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 REVERT_COMMIT.md diff --git a/REVERT_COMMIT.md b/REVERT_COMMIT.md new file mode 100644 index 00000000..9fbaf611 --- /dev/null +++ b/REVERT_COMMIT.md @@ -0,0 +1 @@ +Revert "Merge commit d8b8958e1035a9cf4778b9605d3836661c03d4a8" \ No newline at end of file From 80fb2528e91c4e3f6ba27796a4202e1344501266 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Sun, 16 Nov 2025 17:41:12 +0400 Subject: [PATCH 04/17] Delete REVERT_COMMIT.md --- REVERT_COMMIT.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 REVERT_COMMIT.md diff --git a/REVERT_COMMIT.md b/REVERT_COMMIT.md deleted file mode 100644 index 9fbaf611..00000000 --- a/REVERT_COMMIT.md +++ /dev/null @@ -1 +0,0 @@ -Revert "Merge commit d8b8958e1035a9cf4778b9605d3836661c03d4a8" \ No newline at end of file From 5038d934593c0722a74cc6ce04a570eccb60bcda Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 12:00:41 +0000 Subject: [PATCH 05/17] chore(deps): update dependency python to 3.14 (#5) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7d1d2e5f..0cb93484 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/setup-python@v6 with: - python-version: '3.13' + python-version: '3.14' - name: install pre-commit run: python3 -m pip install pre-commit From de1ced36c2fa89581b9ba42dcb89240e2e0138de Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 13:54:16 +0400 Subject: [PATCH 06/17] Enable fork processing in Renovate config --- .github/renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json b/.github/renovate.json index 349a7bae..8b6f5dca 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,4 +1,5 @@ { + "forkProcessing": "enabled", "extends": [ "config:recommended", ":enablePreCommit", From 0650760e7db86cd4af072900ec399b67884be5a3 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 13:58:36 +0400 Subject: [PATCH 07/17] action now without installing task --- .github/renovate.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 8b6f5dca..6de8514e 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,5 +1,4 @@ { - "forkProcessing": "enabled", "extends": [ "config:recommended", ":enablePreCommit", @@ -18,5 +17,6 @@ "timezone": "Asia/Dubai", "schedule": [ "before 10am on tuesday" - ] + ], + "forkProcessing": "enabled" } From 19b34f3ba1c7013d7b7303b1ad26d50718348962 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 14:07:39 +0400 Subject: [PATCH 08/17] action now without installing task --- .github/renovate.json | 104 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 20 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 6de8514e..62b8b9b6 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,22 +1,86 @@ { - "extends": [ - "config:recommended", - ":enablePreCommit", - ":automergeMinor", - ":dependencyDashboard", - ":maintainLockFilesWeekly", - ":semanticCommits", - ":pinDevDependencies" - ], - "enabledManagers": [ - "pep621", - "pre-commit", - "github-actions", - "devcontainer" - ], - "timezone": "Asia/Dubai", - "schedule": [ - "before 10am on tuesday" - ], - "forkProcessing": "enabled" + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + + "extends": [ + "config:recommended", + ":dependencyDashboard", + ":semanticCommits", + "mergeConfidence:all-badges" + ], + + "enabledManagers": ["pip-compile", "pip_requirements", "github-actions", "pre-commit"], + + "pip": { + "lockFileMaintenance": { + "enabled": true + } + }, + + "packageRules": [ + { + "description": "Group scientific stack upgrades", + "groupName": "data-science-stack", + "matchPackagePatterns": [ + "polars", + "numpy", + "scipy", + "pandas", + "pyarrow" + ] + }, + { + "description": "Group visualisation libraries", + "groupName": "viz-stack", + "matchPackagePatterns": [ + "plotly", + "matplotlib", + "seaborn" + ] + }, + { + "description": "Group internal quant libs", + "groupName": "jquantstats-stack", + "matchPackagePatterns": [ + "jquantstats", + "tinycta" + ] + }, + { + "description": "Do not auto-upgrade polars major versions (they break APIs often)", + "matchPackageNames": ["polars"], + "major": { + "enabled": false + } + }, + { + "description": "uv-generated requirement files", + "matchPaths": [ + "requirements.txt", + "requirements-dev.txt", + "requirements/*.txt" + ], + "matchManagers": ["pip"], + "pip": { + "rangeStrategy": "bump" + } + }, + { + "description": "Group GitHub Actions updates", + "groupName": "github-actions", + "matchManagers": ["github-actions"] + } + ], + + "schedule": [ + "before 6am on Monday" + ], + + "dependencyDashboardHeader": "Renovate updates for Jebel Quant Research repositories", + + "hostRules": [ + { + "matchHost": "pypi.org", + "respectAuth": true + } + ] } From 336ffa57a5d709d2192297c72dc774b7f41ba343 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 14:11:24 +0400 Subject: [PATCH 09/17] action now without installing task --- .github/renovate.json => renovate.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/renovate.json => renovate.json (100%) diff --git a/.github/renovate.json b/renovate.json similarity index 100% rename from .github/renovate.json rename to renovate.json From 9f2bb0ebf44296c9806d5d823904994e897f5773 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 14:14:55 +0400 Subject: [PATCH 10/17] action now without installing task --- renovate.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 62b8b9b6..d9a231bb 100644 --- a/renovate.json +++ b/renovate.json @@ -82,5 +82,7 @@ "matchHost": "pypi.org", "respectAuth": true } - ] + ], + + "forkProcessing": "enabled" } From 1524028f8cbe5b8286f20577db7f2ca57b3cf800 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 14:17:46 +0400 Subject: [PATCH 11/17] action now without installing task --- renovate.json | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/renovate.json b/renovate.json index d9a231bb..41fcb897 100644 --- a/renovate.json +++ b/renovate.json @@ -10,12 +10,6 @@ "enabledManagers": ["pip-compile", "pip_requirements", "github-actions", "pre-commit"], - "pip": { - "lockFileMaintenance": { - "enabled": true - } - }, - "packageRules": [ { "description": "Group scientific stack upgrades", @@ -77,12 +71,5 @@ "dependencyDashboardHeader": "Renovate updates for Jebel Quant Research repositories", - "hostRules": [ - { - "matchHost": "pypi.org", - "respectAuth": true - } - ], - "forkProcessing": "enabled" } From 4b24b2a4b36c29d731784266986d26cb1775151b Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Wed, 26 Nov 2025 14:22:54 +0400 Subject: [PATCH 12/17] action now without installing task --- renovate.json | 73 +-------------------------------------------------- 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/renovate.json b/renovate.json index 41fcb897..3f576cbf 100644 --- a/renovate.json +++ b/renovate.json @@ -1,75 +1,4 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - - "extends": [ - "config:recommended", - ":dependencyDashboard", - ":semanticCommits", - "mergeConfidence:all-badges" - ], - - "enabledManagers": ["pip-compile", "pip_requirements", "github-actions", "pre-commit"], - - "packageRules": [ - { - "description": "Group scientific stack upgrades", - "groupName": "data-science-stack", - "matchPackagePatterns": [ - "polars", - "numpy", - "scipy", - "pandas", - "pyarrow" - ] - }, - { - "description": "Group visualisation libraries", - "groupName": "viz-stack", - "matchPackagePatterns": [ - "plotly", - "matplotlib", - "seaborn" - ] - }, - { - "description": "Group internal quant libs", - "groupName": "jquantstats-stack", - "matchPackagePatterns": [ - "jquantstats", - "tinycta" - ] - }, - { - "description": "Do not auto-upgrade polars major versions (they break APIs often)", - "matchPackageNames": ["polars"], - "major": { - "enabled": false - } - }, - { - "description": "uv-generated requirement files", - "matchPaths": [ - "requirements.txt", - "requirements-dev.txt", - "requirements/*.txt" - ], - "matchManagers": ["pip"], - "pip": { - "rangeStrategy": "bump" - } - }, - { - "description": "Group GitHub Actions updates", - "groupName": "github-actions", - "matchManagers": ["github-actions"] - } - ], - - "schedule": [ - "before 6am on Monday" - ], - - "dependencyDashboardHeader": "Renovate updates for Jebel Quant Research repositories", - + "extends": ["config:recommended"], "forkProcessing": "enabled" } From b2c9e1d360ee8d8f9bdbdcb224d3237ee6b7c975 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 10:24:25 +0000 Subject: [PATCH 13/17] chore(deps): update actions/checkout action to v6 --- .github/workflows/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0cb93484..6cc45e03 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: @@ -28,7 +28,7 @@ jobs: run: python3 -m pip install pre-commit - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -63,7 +63,7 @@ jobs: fail-fast: false # to not fail all combinations if just one fails steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install uv uses: astral-sh/setup-uv@v7 @@ -104,7 +104,7 @@ jobs: fail-fast: false # to not fail all combinations if just one fails steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install uv uses: astral-sh/setup-uv@v7 @@ -144,7 +144,7 @@ jobs: python-version: ["3.12"] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install uv uses: astral-sh/setup-uv@v7 @@ -191,7 +191,7 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install uv uses: astral-sh/setup-uv@v7 From 8baad98698b1f21e84639f22f251dfe4a372413b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 03:01:02 +0000 Subject: [PATCH 14/17] chore(deps): update github artifact actions --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ddfa9964..3cf91533 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,7 +48,7 @@ jobs: python -m build --wheel --sdist --outdir wheelhouse - name: Store wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: wheels path: wheelhouse/* @@ -102,7 +102,7 @@ jobs: id-token: write steps: - - uses: actions/download-artifact@v5 + - uses: actions/download-artifact@v6 with: name: wheels path: wheelhouse From a10ab75bb4f0430d7266d4b40f1a2ebf79a3150a Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 27 Nov 2025 07:03:19 +0400 Subject: [PATCH 15/17] Delete renovate.json --- renovate.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 renovate.json diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 3f576cbf..00000000 --- a/renovate.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": ["config:recommended"], - "forkProcessing": "enabled" -} From 4d857ebbef559a311decf90c39caef655e5d8c06 Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 27 Nov 2025 07:04:38 +0400 Subject: [PATCH 16/17] Delete pyproject.toml --- pyproject.toml | 115 ------------------------------------------------- 1 file changed, 115 deletions(-) delete mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 8090418a..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,115 +0,0 @@ -[project] -name = "pyportfolioopt" -version = "1.5.6" -description = "Financial portfolio optimization in python" -license = { file = "LICENSE" } -maintainers = [ - { name = "Robert Andrew Martin", email = "martin.robertandrew@gmail.com" }, -] -authors = [ - { name = "Robert Andrew Martin", email = "martin.robertandrew@gmail.com" }, -] -readme = "README.md" -keywords= ["finance", "portfolio", "optimization", "quant", "investing"] -classifiers=[ - "Development Status :: 4 - Beta", - "Environment :: Console", - "Intended Audience :: Financial and Insurance Industry", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Natural Language :: English", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3.14", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3 :: Only", - "Topic :: Office/Business :: Financial", - "Topic :: Office/Business :: Financial :: Investment", -] - -# core dependencies of pyportfolioopt -# this set should be kept minimal! -dependencies = [ - "cvxpy>=1.1.19", - "numpy>=1.26.0", - "pandas>=0.19", - "scikit-base<0.14.0", - "scikit-learn>=0.24.1", - "scipy>=1.3.0", -] - -[project.optional-dependencies] -# there are the following dependency sets: -# - all_extras - all soft dependencies -# - dev - the developer dependency set, for contributors -# -# soft dependencies are not required for the core functionality of pyportfolioopt - -# all soft dependencies -# -# users can install via "pip install pyportfolioopt[all_extras]" -# -all_extras = [ - "matplotlib>=3.2.0", - "plotly>=6.4,<7", - "ecos>=2.0.14,<2.1", - "plotly>=5.0.0,<7", - "cvxopt; python_version < '3.14'", -] - -# dev - the developer dependency set, for contributors and CI -dev = [ - "pytest>=9.0.0", - "pytest-cov>=7.0.0", - "yfinance>=0.2.66", -] - -# notebook tests -notebook_test = [ - "nbmake", - "pytest-rerunfailures", -] - -[project.urls] -Documentation = "https://pyportfolioopt.readthedocs.io/en/latest/" -Download = "https://pypi.org/project/pyportfolioopt/#files" -Homepage = "https://pyportfolioopt.readthedocs.io/en/latest/" -Repository = "https://github.com/pyportfolio/pyportfolioopt" -"Personal website" = "https://reasonabledeviations.com" - -[build-system] -build-backend = "setuptools.build_meta" -requires = [ - "setuptools>=78.1.1", -] - -[tool.setuptools.packages.find] -exclude = ["example", "example.*", "tests", "tests.*"] - -[tool.ruff] -line-length = 88 -# Keep Ruff aligned with project target version -target-version = "py311" -# Exclude individual files/patterns from Ruff linting/formatting -exclude = [ - "tests/test_imports.py", - "cookbook/*.ipynb", -] - -[tool.ruff.lint] -# Keep the same selected rule sets as in ruff.toml -select = ["F", "I"] - -[tool.ruff.format] -# Formatting configuration -quote-style = "double" -indent-style = "space" -line-ending = "auto" -skip-magic-trailing-comma = false - -[tool.ruff.lint.isort] -known-first-party = ["pypfopt"] -combine-as-imports = true -force-sort-within-sections = true From 6060680b8fa419de63de60fecb824d786f14a4ca Mon Sep 17 00:00:00 2001 From: Thomas Schmelzer Date: Thu, 27 Nov 2025 07:07:00 +0400 Subject: [PATCH 17/17] Create pyproject.toml --- pyproject.toml | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..4a6e4cfd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,114 @@ +[project] +name = "pyportfolioopt" +version = "1.5.6" +description = "Financial portfolio optimization in python" +license = { file = "LICENSE" } +maintainers = [ + { name = "Robert Andrew Martin", email = "martin.robertandrew@gmail.com" }, +] +authors = [ + { name = "Robert Andrew Martin", email = "martin.robertandrew@gmail.com" }, +] +readme = "README.md" +keywords= ["finance", "portfolio", "optimization", "quant", "investing"] +classifiers=[ + "Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Financial and Insurance Industry", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Office/Business :: Financial", + "Topic :: Office/Business :: Financial :: Investment", +] + +# core dependencies of pyportfolioopt +# this set should be kept minimal! +dependencies = [ + "cvxpy>=1.1.19", + "numpy>=1.26.0", + "pandas>=0.19", + "scikit-base<0.14.0", + "scikit-learn>=0.24.1", + "scipy>=1.3.0", +] + +[project.optional-dependencies] +# there are the following dependency sets: +# - all_extras - all soft dependencies +# - dev - the developer dependency set, for contributors +# +# soft dependencies are not required for the core functionality of pyportfolioopt + +# all soft dependencies +# +# users can install via "pip install pyportfolioopt[all_extras]" +# +all_extras = [ + "matplotlib>=3.2.0", + "ecos>=2.0.14,<2.1", + "plotly>=5.0.0,<7", + "cvxopt; python_version < '3.14'", +] + +# dev - the developer dependency set, for contributors and CI +dev = [ + "pytest>=9.0.0", + "pytest-cov>=7.0.0", + "yfinance>=0.2.66", +] + +# notebook tests +notebook_test = [ + "nbmake", + "pytest-rerunfailures", +] + +[project.urls] +Documentation = "https://pyportfolioopt.readthedocs.io/en/latest/" +Download = "https://pypi.org/project/pyportfolioopt/#files" +Homepage = "https://pyportfolioopt.readthedocs.io/en/latest/" +Repository = "https://github.com/pyportfolio/pyportfolioopt" +"Personal website" = "https://reasonabledeviations.com" + +[build-system] +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>=78.1.1", +] + +[tool.setuptools.packages.find] +exclude = ["example", "example.*", "tests", "tests.*"] + +[tool.ruff] +line-length = 88 +# Keep Ruff aligned with project target version +target-version = "py311" +# Exclude individual files/patterns from Ruff linting/formatting +exclude = [ + "tests/test_imports.py", + "cookbook/*.ipynb", +] + +[tool.ruff.lint] +# Keep the same selected rule sets as in ruff.toml +select = ["F", "I"] + +[tool.ruff.format] +# Formatting configuration +quote-style = "double" +indent-style = "space" +line-ending = "auto" +skip-magic-trailing-comma = false + +[tool.ruff.lint.isort] +known-first-party = ["pypfopt"] +combine-as-imports = true +force-sort-within-sections = true