Changes for number of days and skip weekends
This commit is contained in:
parent
c481e2b786
commit
f00305771b
@ -7,8 +7,13 @@ from typing import Iterable, List, Literal, Mapping, Union
|
|||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
from .core import AllFrequencies, TimeSeriesCore, date_parser
|
from .core import AllFrequencies, Series, TimeSeriesCore, date_parser
|
||||||
from .utils import _find_closest_date, _interval_to_years, _preprocess_match_options
|
from .utils import (
|
||||||
|
FincalOptions,
|
||||||
|
_find_closest_date,
|
||||||
|
_interval_to_years,
|
||||||
|
_preprocess_match_options,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@date_parser(0, 1)
|
@date_parser(0, 1)
|
||||||
@ -17,6 +22,7 @@ def create_date_series(
|
|||||||
end_date: Union[str, datetime.datetime],
|
end_date: Union[str, datetime.datetime],
|
||||||
frequency: Literal["D", "W", "M", "Q", "H", "Y"],
|
frequency: Literal["D", "W", "M", "Q", "H", "Y"],
|
||||||
eomonth: bool = False,
|
eomonth: bool = False,
|
||||||
|
skip_weekends: bool = False,
|
||||||
) -> List[datetime.datetime]:
|
) -> List[datetime.datetime]:
|
||||||
"""Create a date series with a specified frequency
|
"""Create a date series with a specified frequency
|
||||||
|
|
||||||
@ -53,8 +59,6 @@ def create_date_series(
|
|||||||
if eomonth and frequency.days < AllFrequencies.M.days:
|
if eomonth and frequency.days < AllFrequencies.M.days:
|
||||||
raise ValueError(f"eomonth cannot be set to True if frequency is higher than {AllFrequencies.M.name}")
|
raise ValueError(f"eomonth cannot be set to True if frequency is higher than {AllFrequencies.M.name}")
|
||||||
|
|
||||||
# start_date = _parse_date(start_date)
|
|
||||||
# end_date = _parse_date(end_date)
|
|
||||||
datediff = (end_date - start_date).days / frequency.days + 1
|
datediff = (end_date - start_date).days / frequency.days + 1
|
||||||
dates = []
|
dates = []
|
||||||
|
|
||||||
@ -67,9 +71,12 @@ def create_date_series(
|
|||||||
date = date.replace(day=1).replace(month=next_month) - relativedelta(days=1)
|
date = date.replace(day=1).replace(month=next_month) - relativedelta(days=1)
|
||||||
|
|
||||||
if date <= end_date:
|
if date <= end_date:
|
||||||
|
if frequency.days > 1 or not skip_weekends:
|
||||||
|
dates.append(date)
|
||||||
|
elif date.weekday() < 5:
|
||||||
dates.append(date)
|
dates.append(date)
|
||||||
|
|
||||||
return dates
|
return Series(dates, data_type="date")
|
||||||
|
|
||||||
|
|
||||||
class TimeSeries(TimeSeriesCore):
|
class TimeSeries(TimeSeriesCore):
|
||||||
@ -387,8 +394,8 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
@date_parser(1, 2)
|
@date_parser(1, 2)
|
||||||
def volatility(
|
def volatility(
|
||||||
self,
|
self,
|
||||||
from_date: Union[datetime.date, str],
|
from_date: Union[datetime.date, str] = None,
|
||||||
to_date: Union[datetime.date, str],
|
to_date: Union[datetime.date, str] = None,
|
||||||
frequency: Literal["D", "W", "M", "Q", "H", "Y"] = None,
|
frequency: Literal["D", "W", "M", "Q", "H", "Y"] = None,
|
||||||
as_on_match: str = "closest",
|
as_on_match: str = "closest",
|
||||||
prior_match: str = "closest",
|
prior_match: str = "closest",
|
||||||
@ -399,6 +406,7 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
interval_value: int = 1,
|
interval_value: int = 1,
|
||||||
date_format: str = None,
|
date_format: str = None,
|
||||||
annualize_volatility: bool = True,
|
annualize_volatility: bool = True,
|
||||||
|
traded_days: int = None,
|
||||||
):
|
):
|
||||||
"""Calculates the volatility of the time series.add()
|
"""Calculates the volatility of the time series.add()
|
||||||
|
|
||||||
@ -414,6 +422,11 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ValueError(f"Invalid argument for frequency {frequency}")
|
raise ValueError(f"Invalid argument for frequency {frequency}")
|
||||||
|
|
||||||
|
if from_date is None:
|
||||||
|
from_date = self.start_date + relativedelta(**{interval_type: interval_value})
|
||||||
|
if to_date is None:
|
||||||
|
to_date = self.end_date
|
||||||
|
|
||||||
if annual_compounded_returns is None:
|
if annual_compounded_returns is None:
|
||||||
annual_compounded_returns = False if frequency.days <= 366 else True
|
annual_compounded_returns = False if frequency.days <= 366 else True
|
||||||
|
|
||||||
@ -431,10 +444,13 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
)
|
)
|
||||||
sd = statistics.stdev(rolling_returns.values)
|
sd = statistics.stdev(rolling_returns.values)
|
||||||
if annualize_volatility:
|
if annualize_volatility:
|
||||||
|
if traded_days is None:
|
||||||
|
traded_days = FincalOptions.traded_days
|
||||||
|
|
||||||
if interval_type == "months":
|
if interval_type == "months":
|
||||||
sd *= math.sqrt(12)
|
sd *= math.sqrt(12)
|
||||||
elif interval_type == "days":
|
elif interval_type == "days":
|
||||||
sd *= math.sqrt(252)
|
sd *= math.sqrt(traded_days)
|
||||||
|
|
||||||
return sd
|
return sd
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ from .exceptions import DateNotFoundError, DateOutOfRangeError
|
|||||||
class FincalOptions:
|
class FincalOptions:
|
||||||
date_format: str = "%Y-%m-%d"
|
date_format: str = "%Y-%m-%d"
|
||||||
closest: str = "before" # after
|
closest: str = "before" # after
|
||||||
|
traded_days: int = 365
|
||||||
|
|
||||||
|
|
||||||
def _parse_date(date: str, date_format: str = None):
|
def _parse_date(date: str, date_format: str = None):
|
||||||
|
Loading…
Reference in New Issue
Block a user