Skip to content

Commit

Permalink
New version 1.7.3 (#176)
Browse files Browse the repository at this point in the history
- Consolidated all_properties() method and its string validations.
- Simplified pandas.pct_change() after new pandas type stubs and fill_method no longer required by mypy.
- Simplified dependencies after bug in statsmodels resolved in version 0.14.3.
- Miscellaneous dependency and lockfile updates
  • Loading branch information
karrmagadgeteer2 authored Sep 17, 2024
1 parent 9e2768a commit beb98d8
Show file tree
Hide file tree
Showing 14 changed files with 489 additions and 502 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ default_language_version:

repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.6.2
rev: v0.6.5
hooks:
- id: ruff
args: [ --fix, --exit-non-zero-on-fix ]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.1
rev: v1.11.2
hooks:
- id: mypy
additional_dependencies:
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Version [1.7.3] - 2024-09-17

- Consolidated all_properties() method and its string validations.
- Simplified pandas.pct_change() after new pandas type stubs and fill_method no longer required by mypy.
- Simplified dependencies after bug in statsmodels resolved in version 0.14.3.
- Miscellaneous dependency and lockfile updates

## Version [1.7.2] - 2024-08-24

- Replaced the dot operator from numpy and pandas with the Python @ operator.
Expand Down
80 changes: 34 additions & 46 deletions openseries/_common_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@
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, Index, MultiIndex, Series, date_range
from pandas import (
DataFrame,
DatetimeIndex,
Index,
MultiIndex,
Series,
date_range,
to_datetime,
)
from pandas.tseries.offsets import CustomBusinessDay
from plotly.graph_objs import Figure # type: ignore[import-untyped,unused-ignore]
from plotly.io import to_html # type: ignore[import-untyped,unused-ignore]
Expand Down Expand Up @@ -351,9 +359,7 @@ def worst_month(self: Self) -> float | Series[float]:
"""
wmdf = self.tsdf.copy()
wmdf.index = DatetimeIndex(wmdf.index)
result = (
wmdf.resample("BME").last().pct_change(fill_method=cast(str, None)).min()
)
result = wmdf.resample("BME").last().pct_change().min()

if self.tsdf.shape[1] == 1:
return float(result.iloc[0])
Expand Down Expand Up @@ -521,8 +527,8 @@ def align_index_to_local_cdays(
An OpenFrame object
"""
startyear = DatetimeIndex(self.tsdf.index)[0].year
endyear = DatetimeIndex(self.tsdf.index)[-1].year
startyear = to_datetime(self.tsdf.index[0]).year
endyear = to_datetime(self.tsdf.index[-1]).year
calendar = holiday_calendar(
startyear=startyear,
endyear=endyear,
Expand Down Expand Up @@ -1021,9 +1027,7 @@ def arithmetic_ret_func(
time_factor = how_many / fraction

result = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.mean()
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change().mean()
* time_factor
)

Expand Down Expand Up @@ -1081,9 +1085,7 @@ def vol_func(
time_factor = how_many / fraction

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

if self.tsdf.shape[1] == 1:
return float(cast(SupportsFloat, result.iloc[0]))
Expand Down Expand Up @@ -1279,22 +1281,20 @@ def _var_implied_vol_and_target_func(
if drift_adjust:
imp_vol = (-sqrt(time_factor) / norm.ppf(level)) * (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.quantile(1 - level, interpolation=interpolation)
- self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.sum()
/ len(
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(
fill_method=cast(str, None),
),
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(),
)
)
else:
imp_vol = (
-sqrt(time_factor)
* self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.quantile(1 - level, interpolation=interpolation)
/ norm.ppf(level)
)
Expand Down Expand Up @@ -1357,14 +1357,14 @@ def cvar_down_func(
cvar_df = self.tsdf.loc[cast(int, earlier) : cast(int, later)].copy(deep=True)
result = [
cvar_df.loc[:, x] # type: ignore[call-overload,index]
.pct_change(fill_method=cast(str, None))
.pct_change()
.sort_values()
.iloc[
: int(
ceil(
(1 - level)
* cvar_df.loc[:, x] # type: ignore[index]
.pct_change(fill_method=cast(str, None))
.pct_change()
.count(),
),
)
Expand Down Expand Up @@ -1424,7 +1424,7 @@ def downside_deviation_func(
)
how_many = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.count(numeric_only=True)
)
if periods_in_a_year_fixed:
Expand All @@ -1439,7 +1439,7 @@ def downside_deviation_func(

dddf = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.sub(min_accepted_return / time_factor)
)

Expand Down Expand Up @@ -1542,7 +1542,7 @@ def skew_func(
)
result: NDArray[float64] = skew(
a=self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.to_numpy(),
bias=True,
nan_policy="omit",
Expand Down Expand Up @@ -1589,9 +1589,7 @@ def kurtosis_func(
to_dt=to_date,
)
result: NDArray[float64] = kurtosis(
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(
fill_method=cast(str, None),
),
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(),
fisher=True,
bias=True,
nan_policy="omit",
Expand Down Expand Up @@ -1687,19 +1685,13 @@ def positive_share_func(
)
pos = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))[1:][
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(
fill_method=cast(str, None),
)[1:]
.pct_change()[1:][
self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change()[1:]
> zero
]
.count()
)
tot = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))[1:]
.count()
)
tot = self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change().count()
share = pos / tot
if self.tsdf.shape[1] == 1:
return float(share.iloc[0])
Expand Down Expand Up @@ -1875,9 +1867,7 @@ def omega_ratio_func(
from_dt=from_date,
to_dt=to_date,
)
retdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(
fill_method=cast(str, None),
)
retdf = self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change()
pos = retdf[retdf > min_accepted_return].sub(min_accepted_return).sum()
neg = retdf[retdf < min_accepted_return].sub(min_accepted_return).sum()
ratio = pos / -neg
Expand Down Expand Up @@ -1965,7 +1955,7 @@ def value_ret_calendar_period(
period = "-".join([str(year), str(month).zfill(2)])
vrdf = self.tsdf.copy()
vrdf.index = DatetimeIndex(vrdf.index)
resultdf = DataFrame(vrdf.pct_change(fill_method=None)) # type: ignore[arg-type]
resultdf = DataFrame(vrdf.pct_change())
result = resultdf.loc[period] + 1
cal_period = result.cumprod(axis="index").iloc[-1] - 1
if self.tsdf.shape[1] == 1:
Expand Down Expand Up @@ -2017,7 +2007,7 @@ def var_down_func(
)
result = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.quantile(1 - level, interpolation=interpolation)
)

Expand Down Expand Up @@ -2065,7 +2055,7 @@ def worst_func(
)
result = (
self.tsdf.loc[cast(int, earlier) : cast(int, later)]
.pct_change(fill_method=cast(str, None))
.pct_change()
.rolling(observations, min_periods=observations)
.sum()
.min()
Expand Down Expand Up @@ -2111,9 +2101,7 @@ def z_score_func(
from_dt=from_date,
to_dt=to_date,
)
zscframe = self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change(
fill_method=cast(str, None),
)
zscframe = self.tsdf.loc[cast(int, earlier) : cast(int, later)].pct_change()
result = (zscframe.iloc[-1] - zscframe.mean()) / zscframe.std()

if self.tsdf.shape[1] == 1:
Expand Down Expand Up @@ -2182,7 +2170,7 @@ def rolling_return(
ret_label = cast(tuple[str], self.tsdf.iloc[:, column].name)[0]
retseries = (
self.tsdf.iloc[:, column]
.pct_change(fill_method=cast(str, None))
.pct_change()
.rolling(observations, min_periods=observations)
.sum()
)
Expand Down Expand Up @@ -2259,7 +2247,7 @@ def rolling_vol(
else:
time_factor = self.periods_in_a_year
vol_label = cast(tuple[str, ValueType], self.tsdf.iloc[:, column].name)[0]
dframe = self.tsdf.iloc[:, column].pct_change(fill_method=cast(str, None))
dframe = self.tsdf.iloc[:, column].pct_change()
volseries = dframe.rolling(
observations,
min_periods=observations,
Expand Down
7 changes: 3 additions & 4 deletions openseries/datefixer.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def generate_calendar_date_range(
)
calendar = holiday_calendar(
startyear=start.year,
endyear=tmp_range[-1].year,
endyear=date_fix(tmp_range[-1]).year,
countries=countries,
)
return [
Expand All @@ -351,7 +351,7 @@ def generate_calendar_date_range(
if end and not start:
tmp_range = date_range(end=end, periods=trading_days * 365 // 252, freq="D")
calendar = holiday_calendar(
startyear=tmp_range[0].year,
startyear=date_fix(tmp_range[0]).year,
endyear=end.year,
countries=countries,
)
Expand All @@ -371,7 +371,6 @@ def generate_calendar_date_range(
raise ValueError(msg)


# noinspection PyUnusedLocal
def _do_resample_to_business_period_ends(
data: DataFrame,
freq: LiteralBizDayFreq,
Expand Down Expand Up @@ -421,4 +420,4 @@ def _do_resample_to_business_period_ends(
]
+ [copydata.index[-1]],
)
return dates.drop_duplicates()
return DatetimeIndex(dates.drop_duplicates())
Loading

0 comments on commit beb98d8

Please sign in to comment.