From 2c321a7c729430762668f6caaf28e7046ee9eed8 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:26:39 +0200 Subject: [PATCH 01/26] Adding shell script to run black and isort and to commit changes if present --- scripts/auto-format-commit.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 scripts/auto-format-commit.sh diff --git a/scripts/auto-format-commit.sh b/scripts/auto-format-commit.sh new file mode 100644 index 00000000..bbc6f019 --- /dev/null +++ b/scripts/auto-format-commit.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# Code formatting with isort and black +isort $(git ls-files '*.py') +black $(git ls-files '*.py') + +git add $(git ls-files) + +# Check Git diff-index +git diff-index --quiet HEAD -- + +if [ $? -eq 0 ]; then + echo "No changes found, nothing to see/do here." +else + echo "Changes found. Preparing commit." + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git commit -m "Automated formatting changes" +fi + +git log | head +exit 0 \ No newline at end of file From 88ef2598841ed2a204bf61f42951bc12e34fd3d2 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:34:23 +0200 Subject: [PATCH 02/26] editing requirements --- requirements_dev.txt | 2 +- requirements_test.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index d50a4b6d..e4d01882 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ -black==23.1.0 +black mypy isort jupyter diff --git a/requirements_test.txt b/requirements_test.txt index da5b1675..5260e7d3 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,2 +1,5 @@ pytest>=7.3.2 +black +mypy +isort pylint \ No newline at end of file From af23ea0575b2dad4295d1d4609f293abd3eda935 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:36:04 +0200 Subject: [PATCH 03/26] edit setup --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 578803f0..bb76ab19 100644 --- a/setup.py +++ b/setup.py @@ -21,10 +21,10 @@ def read_requirements(file_path): install_requires = read_requirements("requirements.txt") extras_require = { - "test": read_requirements("requirements_test.txt"), + "cd": read_requirements("requirements_cd.txt"), "dev": read_requirements("requirements_dev.txt"), "docs": read_requirements("requirements_docs.txt"), - "cd": read_requirements("requirements_cd.txt"), + "test": read_requirements("requirements_test.txt"), } setuptools.setup( From 42c93dd90313ee88a7b6ee999f3d419268e8ffa0 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:37:21 +0200 Subject: [PATCH 04/26] adding workflow without push --- .github/workflows/auto-format.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/auto-format.yml diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml new file mode 100644 index 00000000..76aa0d49 --- /dev/null +++ b/.github/workflows/auto-format.yml @@ -0,0 +1,28 @@ +name: AutoFormatting +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + code-formatting: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' # Specify the desired Python version + + - name: Install dependencies + run: | + pip install -r requirements_ci.txt + + - name: Code formatting and committing changes + run: | + sh scripts/auto-format-commit.sh From 3e96b533f80ec241967bd09574c1689b26e2e28b Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:41:25 +0200 Subject: [PATCH 05/26] fixing workflow --- .github/workflows/auto-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 76aa0d49..2322ed79 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -21,7 +21,7 @@ jobs: - name: Install dependencies run: | - pip install -r requirements_ci.txt + pip install -r requirements_test.txt - name: Code formatting and committing changes run: | From 6e2293e190b86259a39e50c12b27a4d4aaf892f8 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:48:24 +0200 Subject: [PATCH 06/26] test print github.ref --- .github/workflows/auto-format.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 2322ed79..4b0e0cf2 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -26,3 +26,8 @@ jobs: - name: Code formatting and committing changes run: | sh scripts/auto-format-commit.sh + + - name: Print github.ref + run: | + echo "github.ref:" + echo ${{ github.ref }} From fdd7fa3d3c28cdb2d11364697b9ee65d56dbecee Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:50:24 +0200 Subject: [PATCH 07/26] print git branch --- .github/workflows/auto-format.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 4b0e0cf2..ff48dcc1 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -31,3 +31,4 @@ jobs: run: | echo "github.ref:" echo ${{ github.ref }} + git branch From fa6135cbc4a94147f74f157db1c4512e999d90f7 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:52:59 +0200 Subject: [PATCH 08/26] another test --- .github/workflows/auto-format.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index ff48dcc1..82ad26a6 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -31,4 +31,7 @@ jobs: run: | echo "github.ref:" echo ${{ github.ref }} + echo "git branch:" git branch + echo "github.head_ref" + echo ${{ github.head_ref }} From 0187ce58ea3f31680a27480fc6c9542cb4177371 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:55:08 +0200 Subject: [PATCH 09/26] test to push changes to the (PR) branch --- .github/workflows/auto-format.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 82ad26a6..5b4ca3f6 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -35,3 +35,9 @@ jobs: git branch echo "github.head_ref" echo ${{ github.head_ref }} + + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: ${{ github.head_ref }} From c3cae13f4e763983ea6857c7fd328a7fe8ce84d5 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 19:58:29 +0200 Subject: [PATCH 10/26] test github.ref --- .github/workflows/auto-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 5b4ca3f6..6dd58f85 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -40,4 +40,4 @@ jobs: uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - branch: ${{ github.head_ref }} + branch: ${{ github.ref }} From 30bbf83f6d616ebcd0dcd3fea800ec20304bdf26 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:06:18 +0200 Subject: [PATCH 11/26] fixing workflow --- .github/workflows/auto-format.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 6dd58f85..05c6151d 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -13,6 +13,9 @@ jobs: steps: - name: Check out code uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v4 @@ -40,4 +43,4 @@ jobs: uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - branch: ${{ github.ref }} + branch: ${{ github.head_ref }} From 92ca47cd108bb519047e5e00713bfa8f1216e832 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:07:48 +0200 Subject: [PATCH 12/26] test --- .github/workflows/auto-format.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 05c6151d..69ea3dd0 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -42,5 +42,4 @@ jobs: - name: Push changes uses: ad-m/github-push-action@master with: - github_token: ${{ secrets.GITHUB_TOKEN }} branch: ${{ github.head_ref }} From bfe1d2bc1095d436218dee35f4edd79925ed672d Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:28:31 +0200 Subject: [PATCH 13/26] merging both scripts to update readmes --- scripts/update_readme.tex.md.sh | 27 --------------------------- scripts/update_version_readme.sh | 27 ++++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 30 deletions(-) delete mode 100644 scripts/update_readme.tex.md.sh diff --git a/scripts/update_readme.tex.md.sh b/scripts/update_readme.tex.md.sh deleted file mode 100644 index 441d0347..00000000 --- a/scripts/update_readme.tex.md.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -replace_patterns() { - local file_path="$1" - - # Copy README.md to README.tex.md - cp README.md "$file_path" - - # Read the contents of README.tex.md - local content=$(<"$file_path") - - # Replace patterns - content=$(echo "$content" | sed -E "s//\$\\\\displaystyle\\\\dfrac{\\\\text{price}_{t_i} - \\\\text{price}_{t_0} + \\\\text{dividend}}{\\\\text{price}_{t_0}}\$/") - - content=$(echo "$content" | sed -E "s//\$\\\\displaystyle\\\\dfrac{\\\\text{price}_{t_i} - \\\\text{price}_{t_{i-1}}}{\\\\text{price}_{t_{i-1}}}\$/") - - content=$(echo "$content" | sed -E "s//\$\\\\displaystyle\\\\log\\\\left(1 + \\\\dfrac{\\\\text{price}_{t_i} - \\\\text{price}_{t_{i-1}}}{\\\\text{price}_{t_{i-1}}}\\\\right)\$/") - - # Write the updated contents back to README.tex.md - echo "$content" > "$file_path" -} - -# Specify the file path for README.tex.md -tex_file_path="README.tex.md" - -# Call the function to perform the replacements -replace_patterns "$tex_file_path" \ No newline at end of file diff --git a/scripts/update_version_readme.sh b/scripts/update_version_readme.sh index 0f1b3357..014a7dc7 100644 --- a/scripts/update_version_readme.sh +++ b/scripts/update_version_readme.sh @@ -2,7 +2,7 @@ update_version_readme() { local version_file="version" - local readme_md="README.md" + local readme_md="$1" # Read the current version from the "version" file local current_version=$(grep -Eo 'version=([0-9]+\.){2}[0-9]+' "$version_file" | cut -d'=' -f2) @@ -17,5 +17,26 @@ update_version_readme() { update_file "$readme_md" } -# Call the update_version function -update_version_readme \ No newline at end of file +update_readme_tex() { + local file_path="$1" + + # Copy README.md to README.tex.md + cp README.md "$file_path" + + # Read the contents of README.tex.md + local content=$(<"$file_path") + + # Replace patterns + content=$(echo "$content" | sed -E "s//\$\\\\displaystyle\\\\dfrac{\\\\text{price}_{t_i} - \\\\text{price}_{t_0} + \\\\text{dividend}}{\\\\text{price}_{t_0}}\$/") + + content=$(echo "$content" | sed -E "s//\$\\\\displaystyle\\\\dfrac{\\\\text{price}_{t_i} - \\\\text{price}_{t_{i-1}}}{\\\\text{price}_{t_{i-1}}}\$/") + + content=$(echo "$content" | sed -E "s//\$\\\\displaystyle\\\\log\\\\left(1 + \\\\dfrac{\\\\text{price}_{t_i} - \\\\text{price}_{t_{i-1}}}{\\\\text{price}_{t_{i-1}}}\\\\right)\$/") + + # Write the updated contents back to README.tex.md + echo "$content" > "$file_path" +} + +# Update both readme files: +update_version_readme "README.md" +update_readme_tex "README.tex.md" \ No newline at end of file From 918a5475e97ba2e1b48d1cdb78528cc1b6b72879 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:29:02 +0200 Subject: [PATCH 14/26] renaming script to update readme --- scripts/{update_version_readme.sh => update_readme.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{update_version_readme.sh => update_readme.sh} (100%) diff --git a/scripts/update_version_readme.sh b/scripts/update_readme.sh similarity index 100% rename from scripts/update_version_readme.sh rename to scripts/update_readme.sh From 5b9463f81e7dfc35ff4aec61055a7fd17eaf5117 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:31:04 +0200 Subject: [PATCH 15/26] updating script --- scripts/auto-format-commit.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/auto-format-commit.sh b/scripts/auto-format-commit.sh index bbc6f019..a69789bc 100644 --- a/scripts/auto-format-commit.sh +++ b/scripts/auto-format-commit.sh @@ -1,10 +1,19 @@ #!/bin/sh +echo "Updating README files:" +# Update version number in README files: +scripts/update_version_readme.sh +# Update README.tex.md +scripts/update_readme.tex.md.sh + # Code formatting with isort and black +echo "Code formatting with isort and black:" isort $(git ls-files '*.py') black $(git ls-files '*.py') -git add $(git ls-files) +# Stage changes +#git add $(git ls-files) +git add --udpate # Check Git diff-index git diff-index --quiet HEAD -- From 9d9276b775e19d750553e3fcdb933b4e42bb386b Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:37:10 +0200 Subject: [PATCH 16/26] adding new script to commit changes (if present), and removing that code from other scripts --- .github/workflows/auto-format.yml | 15 +++++------ .../{auto-format-commit.sh => auto-commit.sh} | 18 ++++++------- scripts/auto-format.sh | 25 +++++++++++++++++++ .../{update_readme.sh => update-readme.sh} | 3 ++- 4 files changed, 40 insertions(+), 21 deletions(-) rename scripts/{auto-format-commit.sh => auto-commit.sh} (52%) create mode 100644 scripts/auto-format.sh rename scripts/{update_readme.sh => update-readme.sh} (96%) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 69ea3dd0..47485c7e 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -26,18 +26,15 @@ jobs: run: | pip install -r requirements_test.txt - - name: Code formatting and committing changes + - name: Updating README files run: | - sh scripts/auto-format-commit.sh + sh scripts/update-readme.sh + sh scripts/auto-commit.sh "Updating README files" - - name: Print github.ref + - name: Code formatting and committing changes run: | - echo "github.ref:" - echo ${{ github.ref }} - echo "git branch:" - git branch - echo "github.head_ref" - echo ${{ github.head_ref }} + sh scripts/auto-format-commit.sh + sh scripts/auto-commit.sh "Automated formatting changes" - name: Push changes uses: ad-m/github-push-action@master diff --git a/scripts/auto-format-commit.sh b/scripts/auto-commit.sh similarity index 52% rename from scripts/auto-format-commit.sh rename to scripts/auto-commit.sh index a69789bc..3e2cfc34 100644 --- a/scripts/auto-format-commit.sh +++ b/scripts/auto-commit.sh @@ -1,15 +1,11 @@ #!/bin/sh -echo "Updating README files:" -# Update version number in README files: -scripts/update_version_readme.sh -# Update README.tex.md -scripts/update_readme.tex.md.sh +COMMITMSG=$1 -# Code formatting with isort and black -echo "Code formatting with isort and black:" -isort $(git ls-files '*.py') -black $(git ls-files '*.py') +if [ -z $COMMITMSG ]; then + COMMITMSG="Automated formatting changes" +fi +echo "COMMITMSG: $COMMITMSG" # Stage changes #git add $(git ls-files) @@ -24,8 +20,8 @@ else echo "Changes found. Preparing commit." git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - git commit -m "Automated formatting changes" + git commit -m "${COMMITMSG}" fi git log | head -exit 0 \ No newline at end of file +exit 0 diff --git a/scripts/auto-format.sh b/scripts/auto-format.sh new file mode 100644 index 00000000..442ad4e1 --- /dev/null +++ b/scripts/auto-format.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# Code formatting with isort and black +echo "Code formatting with isort and black:" +isort $(git ls-files '*.py') +black $(git ls-files '*.py') + +## Stage changes +##git add $(git ls-files) +#git add --udpate +# +## Check Git diff-index +#git diff-index --quiet HEAD -- +# +#if [ $? -eq 0 ]; then +# echo "No changes found, nothing to see/do here." +#else +# echo "Changes found. Preparing commit." +# git config --local user.email "github-actions[bot]@users.noreply.github.com" +# git config --local user.name "github-actions[bot]" +# git commit -m "Automated formatting changes" +#fi +# +#git log | head +#exit 0 diff --git a/scripts/update_readme.sh b/scripts/update-readme.sh similarity index 96% rename from scripts/update_readme.sh rename to scripts/update-readme.sh index 014a7dc7..6f92f16a 100644 --- a/scripts/update_readme.sh +++ b/scripts/update-readme.sh @@ -38,5 +38,6 @@ update_readme_tex() { } # Update both readme files: +echo "Updating README files:" update_version_readme "README.md" -update_readme_tex "README.tex.md" \ No newline at end of file +update_readme_tex "README.tex.md" From 3ca21a8d1021b25d9912d499c4bd40cfdc8b0832 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 20:52:05 +0200 Subject: [PATCH 17/26] fixing workflow and script --- .github/workflows/auto-format.yml | 7 ++++++- scripts/auto-commit.sh | 6 ++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 47485c7e..7a42c81f 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -27,16 +27,21 @@ jobs: pip install -r requirements_test.txt - name: Updating README files + id: update_readme run: | sh scripts/update-readme.sh sh scripts/auto-commit.sh "Updating README files" + continue-on-error: true - name: Code formatting and committing changes + id: code_format run: | - sh scripts/auto-format-commit.sh + sh scripts/auto-format.sh sh scripts/auto-commit.sh "Automated formatting changes" + continue-on-error: true - name: Push changes + if: ${{ steps.update_readme.outcome == 'success' || steps.code_format.outcome == 'success' }} uses: ad-m/github-push-action@master with: branch: ${{ github.head_ref }} diff --git a/scripts/auto-commit.sh b/scripts/auto-commit.sh index 3e2cfc34..33b03781 100644 --- a/scripts/auto-commit.sh +++ b/scripts/auto-commit.sh @@ -9,19 +9,17 @@ echo "COMMITMSG: $COMMITMSG" # Stage changes #git add $(git ls-files) -git add --udpate +git add --update # Check Git diff-index git diff-index --quiet HEAD -- if [ $? -eq 0 ]; then echo "No changes found, nothing to see/do here." + exit 1 else echo "Changes found. Preparing commit." git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" git commit -m "${COMMITMSG}" fi - -git log | head -exit 0 From b9381c27efbb9dc8f023437fdc93c12d7fced1f3 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 21:01:40 +0200 Subject: [PATCH 18/26] fixing scripts and workflow again --- .github/workflows/auto-format.yml | 8 ++++---- scripts/auto-commit.sh | 4 ++-- scripts/auto-format.sh | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 7a42c81f..128745f8 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -29,15 +29,15 @@ jobs: - name: Updating README files id: update_readme run: | - sh scripts/update-readme.sh - sh scripts/auto-commit.sh "Updating README files" + bash scripts/update-readme.sh + bash scripts/auto-commit.sh "Updating README files" continue-on-error: true - name: Code formatting and committing changes id: code_format run: | - sh scripts/auto-format.sh - sh scripts/auto-commit.sh "Automated formatting changes" + bash scripts/auto-format.sh + bash scripts/auto-commit.sh "Automated formatting changes" continue-on-error: true - name: Push changes diff --git a/scripts/auto-commit.sh b/scripts/auto-commit.sh index 33b03781..e1fba355 100644 --- a/scripts/auto-commit.sh +++ b/scripts/auto-commit.sh @@ -1,8 +1,8 @@ -#!/bin/sh +#!/bin/bash COMMITMSG=$1 -if [ -z $COMMITMSG ]; then +if [ -z "$COMMITMSG" ]; then COMMITMSG="Automated formatting changes" fi echo "COMMITMSG: $COMMITMSG" diff --git a/scripts/auto-format.sh b/scripts/auto-format.sh index 442ad4e1..da6e64d9 100644 --- a/scripts/auto-format.sh +++ b/scripts/auto-format.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Code formatting with isort and black echo "Code formatting with isort and black:" From 4667c11d020c843f9608b239b44eedaae221a2b4 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 21:05:04 +0200 Subject: [PATCH 19/26] Echo appropriate message when executing auto-commit.sh --- scripts/auto-commit.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/auto-commit.sh b/scripts/auto-commit.sh index e1fba355..c61c9e3a 100644 --- a/scripts/auto-commit.sh +++ b/scripts/auto-commit.sh @@ -1,5 +1,7 @@ #!/bin/bash +echo "Running auto commit" + COMMITMSG=$1 if [ -z "$COMMITMSG" ]; then From d9074f89bdb750ceb4697007fa55bf612d49fffe Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 21:11:47 +0200 Subject: [PATCH 20/26] updating scripts --- scripts/auto-commit.sh | 1 - scripts/auto-format.sh | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/scripts/auto-commit.sh b/scripts/auto-commit.sh index c61c9e3a..ac0279e4 100644 --- a/scripts/auto-commit.sh +++ b/scripts/auto-commit.sh @@ -10,7 +10,6 @@ fi echo "COMMITMSG: $COMMITMSG" # Stage changes -#git add $(git ls-files) git add --update # Check Git diff-index diff --git a/scripts/auto-format.sh b/scripts/auto-format.sh index da6e64d9..ed107031 100644 --- a/scripts/auto-format.sh +++ b/scripts/auto-format.sh @@ -4,22 +4,3 @@ echo "Code formatting with isort and black:" isort $(git ls-files '*.py') black $(git ls-files '*.py') - -## Stage changes -##git add $(git ls-files) -#git add --udpate -# -## Check Git diff-index -#git diff-index --quiet HEAD -- -# -#if [ $? -eq 0 ]; then -# echo "No changes found, nothing to see/do here." -#else -# echo "Changes found. Preparing commit." -# git config --local user.email "github-actions[bot]@users.noreply.github.com" -# git config --local user.name "github-actions[bot]" -# git commit -m "Automated formatting changes" -#fi -# -#git log | head -#exit 0 From 0e741b86f115641a4a6a646faa7a2fc0578d09e0 Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 21:18:11 +0200 Subject: [PATCH 21/26] minor changes and reverting test changes --- README.md | 1 - scripts/auto-commit.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/README.md b/README.md index ab9e0606..78fea24a 100644 --- a/README.md +++ b/README.md @@ -267,4 +267,3 @@ Furthermore, it is also shown how the entire *Efficient Frontier* and the optima Also, the optimisation of a portfolio and its visualisation based on a *Monte Carlo* is shown. Finally, *FinQuant*'s visualisation methods allow for overlays, if this is desired. Thus, with only the following few lines of code, one can create an overlay of the *Monte Carlo* run, the *Efficient Frontier*, its optimised portfolios for *Minimum Volatility* and *Maximum Sharpe Ratio*, as well as the portfolio's individual stocks. - diff --git a/scripts/auto-commit.sh b/scripts/auto-commit.sh index ac0279e4..84d57b84 100644 --- a/scripts/auto-commit.sh +++ b/scripts/auto-commit.sh @@ -7,7 +7,6 @@ COMMITMSG=$1 if [ -z "$COMMITMSG" ]; then COMMITMSG="Automated formatting changes" fi -echo "COMMITMSG: $COMMITMSG" # Stage changes git add --update From e7379a4b848278282f13085501d4d070cc78cfef Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sat, 22 Jul 2023 21:22:23 +0200 Subject: [PATCH 22/26] only run new workflow when pushed to master or develop --- .github/workflows/auto-format.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 128745f8..59fb7383 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -1,11 +1,9 @@ -name: AutoFormatting +name: AutoUpdateFormatting on: push: branches: - master - pull_request: - branches: - - master + - develop jobs: code-formatting: From 27888790a23501a370a7f628a208ded48737ce50 Mon Sep 17 00:00:00 2001 From: Pietropaolo Frisoni Date: Sun, 23 Jul 2023 21:39:16 +0200 Subject: [PATCH 23/26] New feature: Value at Risk (VaR) (#106) The Value at Risk (VaR) is a way to evaluate the risk of a portfolio. It measures the potential loss that a portfolio can have over a certain period with a specified confidence level. With respect to the beta parameter, variance, etc., VaR uses a probability distribution, and it assumes that returns are normally distributed. Using the variance-covariance method, we want to compute the portfolio's value at risk (VaR) over the selected period (the 'freq' variable). The Monte Carlo approach is left for further development. --------- Co-authored-by: Frank Milthaler --- README.md | 3 ++- example/Example-Analysis.py | 12 ++++++++--- finquant/portfolio.py | 40 ++++++++++++++++++++++++++++++++++++- finquant/quants.py | 29 +++++++++++++++++++++++++++ finquant/stock.py | 6 +++--- tests/test_quants.py | 34 +++++++++++++++++++++++++++++++ version | 4 ++-- 7 files changed, 118 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 78fea24a..e74a8c9f 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,8 @@ look at the examples provided in `./example`. `./example/Example-Analysis.py`: This example shows how to use an instance of `finquant.portfolio.Portfolio`, get the portfolio's quantities, such as - Expected Returns, - Volatility, - - Sharpe Ratio. + - Sharpe Ratio, + - Value at Risk. It also shows how to extract individual stocks from the given portfolio. Moreover it shows how to compute and visualise: - the different Returns provided by the module `finquant.returns`, diff --git a/example/Example-Analysis.py b/example/Example-Analysis.py index 4904e7e5..b012961c 100644 --- a/example/Example-Analysis.py +++ b/example/Example-Analysis.py @@ -49,9 +49,10 @@ # -# ## Expected Return, Volatility and Sharpe Ratio of Portfolio -# The annualised expected return and volatility as well as the Sharpe Ratio are automatically computed. They are obtained as shown below. -# The expected return and volatility are based on 252 trading days by default. The Sharpe Ratio is computed with a risk free rate of 0.005 by default. +# ## Expected Return, Volatility, Sharpe Ratio and Value at Risk of Portfolio +# The annualised expected return and volatility, as well as the Sharpe Ratio and Value at Risk are automatically computed. They are obtained as shown below. +# The expected return and volatility are based on 252 trading days by default. +# The Sharpe Ratio is computed with a risk free rate of 0.005 by default. The Value at Risk is computed with a confidence level of 0.95 by default. # @@ -68,6 +69,11 @@ # Sharpe ratio (computed with a risk free rate of 0.005 by default) print(pf.sharpe) +# + +# Value at Risk (computed with a confidence level of 0.95 by default) +print(pf.var) + # # ## Getting Skewness and Kurtosis of the stocks diff --git a/finquant/portfolio.py b/finquant/portfolio.py index fbc423dc..210ca307 100644 --- a/finquant/portfolio.py +++ b/finquant/portfolio.py @@ -18,6 +18,7 @@ - Expected (annualised) Return, - Volatility, - Sharpe Ratio, +- Value at Risk, - Beta parameter (optional), - skewness of the portfolio's stocks, - Kurtosis of the portfolio's stocks, @@ -58,7 +59,7 @@ from finquant.efficient_frontier import EfficientFrontier from finquant.market import Market from finquant.monte_carlo import MonteCarloOpt -from finquant.quants import sharpe_ratio, weighted_mean, weighted_std +from finquant.quants import sharpe_ratio, value_at_risk, weighted_mean, weighted_std from finquant.returns import ( cumulative_returns, daily_log_returns, @@ -85,9 +86,11 @@ def __init__(self): self.expected_return = None self.volatility = None self.sharpe = None + self.var = None self.skew = None self.kurtosis = None self.totalinvestment = None + self.var_confidence_level = 0.95 self.risk_free_rate = 0.005 self.freq = 252 # instance variables for Efficient Frontier and @@ -154,6 +157,20 @@ def market_index(self, index: Market) -> None: """ self.__market_index = index + @property + def var_confidence_level(self): + return self.__var_confidence_level + + @var_confidence_level.setter + def var_confidence_level(self, val): + if not isinstance(val, float): + raise ValueError("confidence level is expected to be a float.") + if val >= 1 or val <= 0: + raise ValueError("confidence level is expected to be between 0 and 1.") + self.__var_confidence_level = val + # now that this changed, update VaR + self._update() + def add_stock(self, stock: Stock) -> None: """Adds a stock of type ``Stock`` to the portfolio. Each time ``add_stock`` is called, the following instance variables are updated: @@ -210,6 +227,7 @@ def _update(self): self.expected_return = self.comp_expected_return(freq=self.freq) self.volatility = self.comp_volatility(freq=self.freq) self.sharpe = self.comp_sharpe() + self.var = self.comp_var() self.skew = self._comp_skew() self.kurtosis = self._comp_kurtosis() if self.market_index is not None: @@ -355,6 +373,22 @@ def comp_sharpe(self): self.sharpe = sharpe return sharpe + def comp_var(self): + """Compute and return the Value at Risk of the portfolio. + + :Output: + :VaR: ``float``, the Value at Risk of the portfolio + """ + # compute the Value at Risk of the portfolio + var = value_at_risk( + investment=self.totalinvestment, + mu=self.expected_return, + sigma=self.volatility, + conf_level=self.var_confidence_level, + ) + self.var = var + return var + def comp_beta(self) -> float: """Compute and return the Beta parameter of the portfolio. @@ -631,6 +665,7 @@ def properties(self): - Expected Return, - Volatility, - Sharpe Ratio, + - Value at Risk, - Beta (optional), - skewness, - Kurtosis @@ -648,6 +683,9 @@ def properties(self): string += f"\nPortfolio Expected Return: {self.expected_return:0.3f}" string += f"\nPortfolio Volatility: {self.volatility:0.3f}" string += f"\nPortfolio Sharpe Ratio: {self.sharpe:0.3f}" + string += f"\nPortfolio Value at Risk: {self.var:0.3f}" + string += f"\nConfidence level of Value at Risk: " + string += f"{self.var_confidence_level * 100:0.2f} %" if self.beta is not None: string += f"\nPortfolio Beta: {self.beta:0.3f}" string += "\n\nSkewness:" diff --git a/finquant/quants.py b/finquant/quants.py index afa2c9e6..95e33bcf 100644 --- a/finquant/quants.py +++ b/finquant/quants.py @@ -6,6 +6,7 @@ import numpy as np import pandas as pd +from scipy.stats import norm def weighted_mean(means, weights): @@ -74,6 +75,34 @@ def sharpe_ratio(exp_return, volatility, risk_free_rate=0.005): return (exp_return - risk_free_rate) / float(volatility) +def value_at_risk(investment, mu, sigma, conf_level=0.95) -> float: + """Computes and returns the expected value at risk of an investment/assets. + + :Input: + :investment: ``float``/``int``, total value of the investment + :mu: ``float``/``int`` average/mean return of the investment + :sigma: ``float``/``int`` standard deviation of the investment + :conf_level: ``float`` (default= ``0.95``), confidence level of the VaR + + :Output: + :Value at Risk: ``float``, VaR of the investment + """ + if not isinstance( + investment, (int, float, np.int32, np.int64, np.float32, np.float64) + ): + raise ValueError("investment is expected to be an integer or float.") + if not isinstance(mu, (int, float, np.int32, np.int64, np.float32, np.float64)): + raise ValueError("mu is expected to be an integer or float") + if not isinstance(sigma, (int, float, np.int32, np.int64, np.float32, np.float64)): + raise ValueError("sigma is expected to be an integer or float") + if not isinstance(conf_level, float): + raise ValueError("confidence level is expected to be a float.") + if conf_level >= 1 or conf_level <= 0: + raise ValueError("confidence level is expected to be between 0 and 1.") + + return investment * (mu - sigma * norm.ppf(1 - conf_level)) + + def annualised_portfolio_quantities( weights, means, cov_matrix, risk_free_rate=0.005, freq=252 ): diff --git a/finquant/stock.py b/finquant/stock.py index b67b75b2..f0ed1d51 100644 --- a/finquant/stock.py +++ b/finquant/stock.py @@ -78,7 +78,7 @@ def comp_beta(self, market_daily_returns: pd.Series) -> float: def properties(self): """Nicely prints out the properties of the stock: Expected Return, - Volatility, Skewness, Kurtosis as well as the ``Allocation`` (and other + Volatility, Beta (optional), Skewness, Kurtosis as well as the ``Allocation`` (and other information provided in investmentinfo.) """ # nicely printing out information and quantities of the stock @@ -86,10 +86,10 @@ def properties(self): string += f"\n{self.asset_type}: {self.name}" string += f"\nExpected Return: {self.expected_return:0.3f}" string += f"\nVolatility: {self.volatility:0.3f}" - string += f"\nSkewness: {self.skew:0.5f}" - string += f"\nKurtosis: {self.kurtosis:0.5f}" if self.beta is not None: string += f"\n{self.asset_type} Beta: {self.beta:0.3f}" + string += f"\nSkewness: {self.skew:0.5f}" + string += f"\nKurtosis: {self.kurtosis:0.5f}" string += "\nInformation:" string += "\n" + str(self.investmentinfo.to_frame().transpose()) string += "\n" + "-" * 50 diff --git a/tests/test_quants.py b/tests/test_quants.py index 3232d234..99422bc0 100644 --- a/tests/test_quants.py +++ b/tests/test_quants.py @@ -1,8 +1,10 @@ import numpy as np +import pytest from finquant.quants import ( annualised_portfolio_quantities, sharpe_ratio, + value_at_risk, weighted_mean, weighted_std, ) @@ -32,6 +34,38 @@ def test_sharpe_ratio(): assert sharpe_ratio(0.5, 0.22, 0.005) == 2.25 +def test_value_at_risk(): + assert abs(value_at_risk(1e2, 0.5, 0.25, 0.95) - 91.12) <= 1e-1 + assert abs(value_at_risk(1e3, 0.8, 0.5, 0.99) - 1963.17) <= 1e-1 + assert abs(value_at_risk(1e4, -0.1, 0.25, 0.9) - 2203.88) <= 1e-1 + assert abs(value_at_risk(1e4, 0.1, -0.25, 0.9) - (-2203.88)) <= 1e-1 + assert abs(value_at_risk(1e4, -0.1, -0.25, 0.9) - (-4203.88)) <= 1e-1 + assert value_at_risk(0, 0.1, 0.5, 0.9) == 0 + assert abs(value_at_risk(1e4, 0, 0.5, 0.9) - 6407.76) <= 1e-1 + assert abs(value_at_risk(1e4, 0.1, 0, 0.9) - 1000) <= 1e-1 + assert value_at_risk(1e4, 0, 0, 0.9) == 0 + + +def test_value_at_risk_invalid_types(): + with pytest.raises(ValueError): + value_at_risk("10000", 0.05, 0.02, 0.95) + + with pytest.raises(ValueError): + value_at_risk(10000, 0.05, "0.02", 0.95) + + with pytest.raises(ValueError): + value_at_risk(10000, [0.05], 0.02, 0.95) + + with pytest.raises(ValueError): + value_at_risk(10000, 0.05, 0.02, "0.95") + + with pytest.raises(ValueError): + value_at_risk(10000, 0.05, 0.02, 1.5) + + with pytest.raises(ValueError): + value_at_risk(10000, 0.05, 0.02, -0.5) + + def test_annualised_portfolio_quantities(): x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) y = np.array([9, 8, 7, 6, 5, 4, 3, 2, 1]) diff --git a/version b/version index f8832652..228945eb 100644 --- a/version +++ b/version @@ -1,2 +1,2 @@ -version=0.3.2 -release=0.3.2 +version=0.4.0 +release=0.4.0 From 101ee7f9ca160969cd5352f04add12275b0fdeda Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Sun, 23 Jul 2023 21:49:22 +0200 Subject: [PATCH 24/26] Updating README files (#110) --- README.md | 2 +- README.tex.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e74a8c9f..41d29515 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ pypi - pypi + pypi GitHub Actions diff --git a/README.tex.md b/README.tex.md index c4c956a5..f7fba6be 100644 --- a/README.tex.md +++ b/README.tex.md @@ -7,7 +7,7 @@ pypi - pypi + pypi GitHub Actions @@ -249,7 +249,8 @@ look at the examples provided in `./example`. `./example/Example-Analysis.py`: This example shows how to use an instance of `finquant.portfolio.Portfolio`, get the portfolio's quantities, such as - Expected Returns, - Volatility, - - Sharpe Ratio. + - Sharpe Ratio, + - Value at Risk. It also shows how to extract individual stocks from the given portfolio. Moreover it shows how to compute and visualise: - the different Returns provided by the module `finquant.returns`, From a4dc9eefab98d1447fde3ec2a23d7b9bae04ffed Mon Sep 17 00:00:00 2001 From: Frank Milthaler Date: Mon, 24 Jul 2023 19:08:44 +0200 Subject: [PATCH 25/26] enabling auto-format on PRs --- .github/workflows/auto-format.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 59fb7383..4b1e0632 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -4,6 +4,10 @@ on: branches: - master - develop + pull_request: + branches: + - master + - develop jobs: code-formatting: From 5a6ad6eb88bb2835ca04a0a0895835f9354310ec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Jul 2023 17:17:44 +0000 Subject: [PATCH 26/26] Automated formatting changes --- example/Example-Analysis.py | 3 ++- example/Example-Build-Portfolio-from-file.py | 3 ++- example/Example-Build-Portfolio-from-web.py | 3 ++- example/Example-Optimisation.py | 3 ++- finquant/asset.py | 6 ++++-- finquant/market.py | 3 ++- finquant/portfolio.py | 2 +- finquant/stock.py | 1 + 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/example/Example-Analysis.py b/example/Example-Analysis.py index b012961c..ba0f4682 100644 --- a/example/Example-Analysis.py +++ b/example/Example-Analysis.py @@ -9,10 +9,11 @@ # +import datetime import pathlib + import matplotlib.pyplot as plt import pandas as pd -import datetime # importing FinQuant's function to automatically build the portfolio from finquant.portfolio import build_portfolio diff --git a/example/Example-Build-Portfolio-from-file.py b/example/Example-Build-Portfolio-from-file.py index 1bc856b9..1f61118e 100644 --- a/example/Example-Build-Portfolio-from-file.py +++ b/example/Example-Build-Portfolio-from-file.py @@ -9,9 +9,10 @@ # +import datetime import pathlib + import pandas as pd -import datetime # importing FinQuant's function to automatically build the portfolio from finquant.portfolio import build_portfolio diff --git a/example/Example-Build-Portfolio-from-web.py b/example/Example-Build-Portfolio-from-web.py index 18f2e701..f2406c24 100644 --- a/example/Example-Build-Portfolio-from-web.py +++ b/example/Example-Build-Portfolio-from-web.py @@ -9,9 +9,10 @@ # -import pandas as pd import datetime +import pandas as pd + # importing some custom functions/objects from finquant.portfolio import build_portfolio diff --git a/example/Example-Optimisation.py b/example/Example-Optimisation.py index 566d54bb..5646e300 100644 --- a/example/Example-Optimisation.py +++ b/example/Example-Optimisation.py @@ -26,11 +26,12 @@ # +import datetime import pathlib + import matplotlib.pyplot as plt import numpy as np import pandas as pd -import datetime # importing FinQuant's function to automatically build the portfolio from finquant.portfolio import build_portfolio diff --git a/finquant/asset.py b/finquant/asset.py index 7baba64b..ea51c50d 100644 --- a/finquant/asset.py +++ b/finquant/asset.py @@ -45,7 +45,9 @@ class Asset: """ - def __init__(self, data: pd.Series, name: str, asset_type: str = 'Market index') -> None: + def __init__( + self, data: pd.Series, name: str, asset_type: str = "Market index" + ) -> None: """ :Input: :data: ``pandas.Series``, of asset prices @@ -119,4 +121,4 @@ def properties(self): def __str__(self): # print short description string = f"Contains information about {self.asset_type}: {self.name}." - return string \ No newline at end of file + return string diff --git a/finquant/market.py b/finquant/market.py index b4652591..426bbe20 100644 --- a/finquant/market.py +++ b/finquant/market.py @@ -14,6 +14,7 @@ import numpy as np import pandas as pd + from finquant.asset import Asset from finquant.returns import daily_returns, historical_mean_return @@ -43,4 +44,4 @@ def comp_daily_returns(self) -> pd.Series: """Computes the daily returns (percentage change) of the market index. See ``finquant.returns.daily_returns``. """ - return daily_returns(self.data) \ No newline at end of file + return daily_returns(self.data) diff --git a/finquant/portfolio.py b/finquant/portfolio.py index 210ca307..1401de60 100644 --- a/finquant/portfolio.py +++ b/finquant/portfolio.py @@ -49,8 +49,8 @@ - Individual stocks of the portfolio (Expected Return over Volatility) """ -from typing import List import datetime +from typing import List import matplotlib.pylab as plt import numpy as np diff --git a/finquant/stock.py b/finquant/stock.py index a0f2da37..c47b32b7 100644 --- a/finquant/stock.py +++ b/finquant/stock.py @@ -25,6 +25,7 @@ import numpy as np import pandas as pd + from finquant.asset import Asset from finquant.returns import daily_returns, historical_mean_return