Skip to content

Commit

Permalink
New version 1.3.9 with type/mypy & docstring cleanup (#52)
Browse files Browse the repository at this point in the history
* Dependencies update and fixes of FBT001 & FBT001 ruff codes

* update dependencies

* fixed openpyxl.worksheet type issue

* dependencies update of numpy and pandas

* minor mypy fix

* consolidated simulation for tests even further

* ruff dev dependency update

* ruff pre-commit update

* standardized datetime import

* misc on types and doc strings

* renamed job in github action and updated black

* New version 1.3.9 with type & docstring cleanup
  • Loading branch information
karrmagadgeteer2 authored Oct 24, 2023
1 parent c86f115 commit f16bcd2
Show file tree
Hide file tree
Showing 16 changed files with 442 additions and 409 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ env:
POETRY_VER: 1.6.1

jobs:
codecheck:
run_checks:
runs-on: ubuntu-latest
defaults:
run:
Expand Down
10 changes: 6 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.292'
rev: 'v0.1.1'
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
- repo: https://github.com/psf/black
rev: 23.9.1
rev: 23.10.1
hooks:
- id: black
language: system
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.6.0
rev: v1.6.1
hooks:
- id: mypy
additional_dependencies:
- types-all
- pydantic>=2.4.2
- types-openpyxl>=3.1.0.22
- types-openpyxl>=3.1.0.24
- pandas-stubs>=2.1.1.230928
- types-python-dateutil>=2.8.19.14
- types-requests>=2.31.0.10
- types-toml>=0.10.8.7
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ this log will cover all changes, and I will not attempt to go back very far in h
At some point I will also start documenting changes in release documentation instead.


## Version [1.3.9] - 2023-10-24

- Mainly type/mypy and docstring cleanup
- Updated numpy and pandas which may affect users downstream

## Version [1.3.8] - 2023-10-15

- tightened .to_json() and .to_xlsx() methods. File path now defaults to homepath/Documents and if it does not exist it will save in the directory of the calling function
Expand Down
1 change: 1 addition & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Without an x next to a version below you can assume that it works as intended.

| Version | Supported |
|---------|--------------------|
| 1.3.9 | :white_check_mark: |
| 1.3.8 | :white_check_mark: |
| 1.3.7 | :white_check_mark: |
| 1.3.6 | :white_check_mark: |
Expand Down
96 changes: 52 additions & 44 deletions openseries/common_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
from typing import Any, Optional, Union, cast

from numpy import log, sqrt
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.workbook.workbook import Workbook
from openpyxl.worksheet.worksheet import Worksheet
from pandas import DataFrame, DatetimeIndex, Series
from plotly.graph_objs import Figure # type: ignore[import-untyped]
from plotly.offline import plot # type: ignore[import-untyped]
Expand All @@ -24,6 +25,7 @@
from openseries.load_plotly import load_plotly_dict
from openseries.risk import cvar_down_calc, drawdown_series, var_down_calc
from openseries.types import (
DaysInYearType,
LiteralBarPlotMode,
LiteralLinePlotMode,
LiteralNanMethod,
Expand Down Expand Up @@ -503,7 +505,8 @@ def to_xlsx(
filename: str,
sheet_title: Optional[str] = None,
directory: Optional[DirectoryPath] = None,
overwrite: bool = True, # noqa: FBT001, FBT002
*,
overwrite: bool = True,
) -> str:
"""
Save .tsdf DataFrame to an Excel spreadsheet file.
Expand Down Expand Up @@ -541,10 +544,10 @@ def to_xlsx(
wrksheet = wrkbook.active

if sheet_title:
wrksheet.title = sheet_title # type: ignore[union-attr]
cast(Worksheet, wrksheet).title = sheet_title

for row in dataframe_to_rows(df=self.tsdf, index=True, header=True):
wrksheet.append(row) # type: ignore[union-attr]
cast(Worksheet, wrksheet).append(row)

if not overwrite and Path(sheetfile).exists():
msg = f"{sheetfile!s} already exists."
Expand All @@ -561,9 +564,10 @@ def plot_bars(
filename: Optional[str] = None,
directory: Optional[DirectoryPath] = None,
labels: Optional[list[str]] = None,
auto_open: bool = True, # noqa: FBT001, FBT002
add_logo: bool = True, # noqa: FBT001, FBT002
output_type: LiteralPlotlyOutput = "file",
*,
auto_open: bool = True,
add_logo: bool = True,
) -> tuple[Figure, str]:
"""
Create a Plotly Bar Figure.
Expand All @@ -583,12 +587,12 @@ def plot_bars(
labels: list[str], optional
A list of labels to manually override using the names of
the input self.tsdf
output_type: LiteralPlotlyOutput, default: "file"
Determines output type
auto_open: bool, default: True
Determines whether to open a browser window with the plot
add_logo: bool, default: True
If True a Captor logo is added to the plot
output_type: LiteralPlotlyOutput, default: "file"
Determines output type
Returns
-------
Expand Down Expand Up @@ -655,10 +659,11 @@ def plot_series(
filename: Optional[str] = None,
directory: Optional[DirectoryPath] = None,
labels: Optional[list[str]] = None,
auto_open: bool = True, # noqa: FBT001, FBT002
add_logo: bool = True, # noqa: FBT001, FBT002
show_last: bool = False, # noqa: FBT001, FBT002
output_type: LiteralPlotlyOutput = "file",
*,
auto_open: bool = True,
add_logo: bool = True,
show_last: bool = False,
) -> tuple[Figure, str]:
"""
Create a Plotly Scatter Figure.
Expand All @@ -678,14 +683,14 @@ def plot_series(
labels: list[str], optional
A list of labels to manually override using the names of
the input self.tsdf
output_type: LiteralPlotlyOutput, default: "file"
Determines output type
auto_open: bool, default: True
Determines whether to open a browser window with the plot
add_logo: bool, default: True
If True a Captor logo is added to the plot
show_last: bool, default: False
If True the last self.tsdf point is highlighted as red dot with a label
output_type: LiteralPlotlyOutput, default: "file"
Determines output type
Returns
-------
Expand Down Expand Up @@ -765,7 +770,7 @@ def arithmetic_ret_func(
months_from_last: Optional[int] = None,
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
) -> Union[float, Series[type[float]]]:
"""
https://www.investopedia.com/terms/a/arithmeticmean.asp.
Expand All @@ -779,7 +784,7 @@ def arithmetic_ret_func(
Specific from date
to_date : datetime.date, optional
Specific to date
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
Expand Down Expand Up @@ -825,8 +830,8 @@ def vol_func(
months_from_last: Optional[int] = None,
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
periods_in_a_year_fixed: Optional[int] = None,
) -> Union[float, Series]: # type: ignore[type-arg]
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
) -> Union[float, Series[type[float]]]:
"""
Annualized volatility.
Expand All @@ -842,7 +847,7 @@ def vol_func(
Specific from date
to_date : datetime.date, optional
Specific to date
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and comparisons
Returns
Expand All @@ -865,9 +870,9 @@ def vol_func(
)
time_factor = how_many / fraction

result = self.tsdf.loc[cast(int, earlier) : cast(int, later)]
result = result.ffill()
result = result.pct_change().std() * sqrt(time_factor)
data = self.tsdf.loc[cast(int, earlier) : cast(int, later)]
data = data.ffill()
result = data.pct_change().std().mul(sqrt(time_factor))

if self.tsdf.shape[1] == 1:
return float(result.iloc[0])
Expand All @@ -885,8 +890,9 @@ def vol_from_var_func(
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
interpolation: LiteralQuantileInterp = "lower",
drift_adjust: bool = False, # noqa: FBT001, FBT002
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
*,
drift_adjust: bool = False,
) -> Union[float, Series[type[float]]]:
"""
Implied annualized volatility.
Expand All @@ -907,11 +913,11 @@ def vol_from_var_func(
Specific to date
interpolation: LiteralQuantileInterp, default: "lower"
type of interpolation in Pandas.DataFrame.quantile() function.
drift_adjust: bool, default: False
An adjustment to remove the bias implied by the average return
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
drift_adjust: bool, default: False
An adjustment to remove the bias implied by the average return
Returns
-------
Expand Down Expand Up @@ -940,8 +946,9 @@ def target_weight_from_var(
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
interpolation: LiteralQuantileInterp = "lower",
drift_adjust: bool = False, # noqa: FBT001, FBT002
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
*,
drift_adjust: bool = False,
) -> Union[float, Series[type[float]]]:
"""
Target weight from VaR.
Expand All @@ -968,11 +975,11 @@ def target_weight_from_var(
Specific to date
interpolation: LiteralQuantileInterp, default: "lower"
type of interpolation in Pandas.DataFrame.quantile() function.
drift_adjust: bool, default: False
An adjustment to remove the bias implied by the average return
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
drift_adjust: bool, default: False
An adjustment to remove the bias implied by the average return
Returns
-------
Expand Down Expand Up @@ -1064,7 +1071,7 @@ def downside_deviation_func(
months_from_last: Optional[int] = None,
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
) -> Union[float, Series[type[float]]]:
"""
Downside Deviation.
Expand All @@ -1084,7 +1091,7 @@ def downside_deviation_func(
Specific from date
to_date : datetime.date, optional
Specific to date
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
Expand Down Expand Up @@ -1424,7 +1431,7 @@ def ret_vol_ratio_func(
months_from_last: Optional[int] = None,
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
) -> Union[float, Series[type[float]]]:
"""
Ratio between arithmetic mean of returns and annualized volatility.
Expand All @@ -1446,7 +1453,7 @@ def ret_vol_ratio_func(
Specific from date
to_date : datetime.date, optional
Specific to date
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
Expand Down Expand Up @@ -1484,7 +1491,7 @@ def sortino_ratio_func(
months_from_last: Optional[int] = None,
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
) -> Union[float, Series[type[float]]]:
"""
Sortino Ratio.
Expand All @@ -1508,7 +1515,7 @@ def sortino_ratio_func(
Specific from date
to_date : datetime.date, optional
Specific to date
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
Expand Down Expand Up @@ -1889,7 +1896,7 @@ def rolling_vol(
self: CommonModel,
column: int = 0,
observations: int = 21,
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
) -> DataFrame:
"""
Calculate rolling annualised volatilities.
Expand All @@ -1900,7 +1907,7 @@ def rolling_vol(
Position as integer of column to calculate
observations: int, default: 21
Number of observations in the overlapping window.
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
Expand Down Expand Up @@ -1940,8 +1947,9 @@ def _var_implied_vol_and_target_func(
from_date: Optional[dt.date] = None,
to_date: Optional[dt.date] = None,
interpolation: LiteralQuantileInterp = "lower",
drift_adjust: bool = False, # noqa: FBT001, FBT002
periods_in_a_year_fixed: Optional[int] = None,
periods_in_a_year_fixed: Optional[DaysInYearType] = None,
*,
drift_adjust: bool = False,
) -> Union[float, Series[type[float]]]:
"""
Volatility implied from VaR or Target Weight.
Expand Down Expand Up @@ -1972,11 +1980,11 @@ def _var_implied_vol_and_target_func(
Specific to date
interpolation: LiteralQuantileInterp, default: "lower"
type of interpolation in Pandas.DataFrame.quantile() function.
drift_adjust: bool, default: False
An adjustment to remove the bias implied by the average return
periods_in_a_year_fixed : int, optional
periods_in_a_year_fixed : DaysInYearType, optional
Allows locking the periods-in-a-year to simplify test cases and
comparisons
drift_adjust: bool, default: False
An adjustment to remove the bias implied by the average return
Returns
-------
Expand Down
13 changes: 7 additions & 6 deletions openseries/datefixer.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ def date_fix(
def date_offset_foll(
raw_date: DateType,
months_offset: int = 12,
adjust: bool = False, # noqa: FBT001, FBT002
following: bool = True, # noqa: FBT001, FBT002
countries: CountriesType = "SE",
custom_holidays: Optional[HolidayType] = None,
*,
adjust: bool = False,
following: bool = True,
) -> dt.date:
"""
Offset dates according to a given calendar.
Expand All @@ -138,15 +139,15 @@ def date_offset_foll(
The date to offset from
months_offset: int, default: 12
Number of months as integer
adjust: bool, default: False
Determines if offset should adjust for business days
following: bool, default: True
Determines if days should be offset forward (following) or backward
countries: CountriesType, default: "SE"
(List of) country code(s) according to ISO 3166-1 alpha-2
custom_holidays: HolidayType, optional
Argument where missing holidays can be added as
{"2021-02-12": "Jack's birthday"} or ["2021-02-12"]
adjust: bool, default: False
Determines if offset should adjust for business days
following: bool, default: True
Determines if days should be offset forward (following) or backward
Returns
-------
Expand Down
Loading

0 comments on commit f16bcd2

Please sign in to comment.