|
|
@ -407,7 +407,7 @@ class TimeSeries(TimeSeriesCore): |
|
|
|
if_not_found: Literal["fail", "nan"] = "fail", |
|
|
|
annual_compounded_returns: bool = None, |
|
|
|
date_format: str = None, |
|
|
|
): |
|
|
|
) -> float: |
|
|
|
"""Calculates the volatility of the time series.add() |
|
|
|
|
|
|
|
The volatility is calculated as the standard deviaion of periodic returns. |
|
|
@ -431,6 +431,20 @@ class TimeSeries(TimeSeriesCore): |
|
|
|
Number of traded days per year to be considered for annualizing volatility. |
|
|
|
Only used when annualizing volatility for a time series with daily frequency. |
|
|
|
If not provided, will use the value in FincalOptions.traded_days. |
|
|
|
|
|
|
|
Remaining options are passed on to rolling_return function. |
|
|
|
|
|
|
|
Returns: |
|
|
|
------- |
|
|
|
Returns the volatility number as float |
|
|
|
|
|
|
|
Raises: |
|
|
|
------- |
|
|
|
ValueError: If frequency string is outside valid values |
|
|
|
|
|
|
|
Also see: |
|
|
|
-------- |
|
|
|
TimeSeries.calculate_rolling_returns() |
|
|
|
""" |
|
|
|
|
|
|
|
if frequency is None: |
|
|
@ -473,6 +487,54 @@ class TimeSeries(TimeSeriesCore): |
|
|
|
|
|
|
|
return sd |
|
|
|
|
|
|
|
def average_rolling_return(self, **kwargs) -> float: |
|
|
|
"""Calculates the average rolling return for a given period |
|
|
|
|
|
|
|
Parameters |
|
|
|
---------- |
|
|
|
kwargs: parameters to be passed to the calculate_rolling_returns() function |
|
|
|
|
|
|
|
Returns |
|
|
|
------- |
|
|
|
float |
|
|
|
returns the average rolling return for a given period |
|
|
|
|
|
|
|
Also see: |
|
|
|
--------- |
|
|
|
TimeSeries.calculate_rolling_returns() |
|
|
|
""" |
|
|
|
|
|
|
|
kwargs["return_period_unit"] = kwargs.get("return_period_unit", self.frequency.freq_type) |
|
|
|
kwargs["return_period_value"] = kwargs.get("return_period_value", 1) |
|
|
|
kwargs["to_date"] = kwargs.get("to_date", self.end_date) |
|
|
|
|
|
|
|
if kwargs.get("from_date", None) is None: |
|
|
|
start_date = self.start_date + relativedelta( |
|
|
|
**{kwargs["return_period_unit"]: kwargs["return_period_value"]} |
|
|
|
) |
|
|
|
kwargs["from_date"] = start_date |
|
|
|
|
|
|
|
rr = self.calculate_rolling_returns(**kwargs) |
|
|
|
return statistics.mean(rr.values) |
|
|
|
|
|
|
|
def max_drawdown(self): |
|
|
|
max_val_dict = {} |
|
|
|
|
|
|
|
prev_val = 0 |
|
|
|
prev_date = list(self.data)[0] |
|
|
|
|
|
|
|
for dt, val in self.data.items(): |
|
|
|
if val > prev_val: |
|
|
|
max_val_dict[dt] = (dt, val, 0) |
|
|
|
prev_date, prev_val = dt, val |
|
|
|
else: |
|
|
|
max_val_dict[dt] = (prev_date, prev_val, val / prev_val - 1) |
|
|
|
|
|
|
|
max_drawdown = min(max_val_dict.items(), key=lambda x: x[1][2]) |
|
|
|
max_drawdown = dict(start_date=max_drawdown[1][0], end_date=max_drawdown[0], drawdown=max_drawdown[1][2]) |
|
|
|
|
|
|
|
return max_drawdown |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
date_series = [ |
|
|
|