option to return nan in case of failure in return_calc
return calc returns tuple
This commit is contained in:
parent
9e4049a973
commit
870d0bd96b
@ -122,9 +122,11 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
def calculate_returns(
|
def calculate_returns(
|
||||||
self,
|
self,
|
||||||
as_on: Union[str, datetime.datetime],
|
as_on: Union[str, datetime.datetime],
|
||||||
|
return_actual_date: bool = True,
|
||||||
as_on_match: str = "closest",
|
as_on_match: str = "closest",
|
||||||
prior_match: str = "closest",
|
prior_match: str = "closest",
|
||||||
closest: str = "previous",
|
closest: str = "previous",
|
||||||
|
if_not_found: Literal['fail', 'nan'] = 'fail',
|
||||||
compounding: bool = True,
|
compounding: bool = True,
|
||||||
interval_type: Literal['years', 'months', 'days'] = 'years',
|
interval_type: Literal['years', 'months', 'days'] = 'years',
|
||||||
interval_value: int = 1,
|
interval_value: int = 1,
|
||||||
@ -137,6 +139,10 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
as_on : datetime.datetime
|
as_on : datetime.datetime
|
||||||
The date as on which the return is to be calculated.
|
The date as on which the return is to be calculated.
|
||||||
|
|
||||||
|
return_actual_date : bool, default True
|
||||||
|
If true, the output will contain the actual date based on which the return was calculated.
|
||||||
|
Set to False to return the date passed in the as_on argument.
|
||||||
|
|
||||||
as_on_match : str, optional
|
as_on_match : str, optional
|
||||||
The mode of matching the as_on_date. Refer closest.
|
The mode of matching the as_on_date. Refer closest.
|
||||||
|
|
||||||
@ -147,15 +153,28 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
The mode of matching the closest date.
|
The mode of matching the closest date.
|
||||||
Valid values are 'exact', 'previous', 'next' and next.
|
Valid values are 'exact', 'previous', 'next' and next.
|
||||||
|
|
||||||
|
if_not_found : 'fail' | 'nan'
|
||||||
|
What to do when required date is not found:
|
||||||
|
* fail: Raise a ValueError
|
||||||
|
* nan: Return nan as the value
|
||||||
|
|
||||||
compounding : bool, optional
|
compounding : bool, optional
|
||||||
Whether the return should be compounded annually.
|
Whether the return should be compounded annually.
|
||||||
|
|
||||||
years : int, optional
|
interval_type : 'years', 'months', 'days'
|
||||||
number of years for which the returns should be calculated
|
The type of time period to use for return calculation.
|
||||||
|
|
||||||
|
interval_value : int
|
||||||
|
The value of the specified interval type over which returns needs to be calculated.
|
||||||
|
|
||||||
|
date_format: str
|
||||||
|
The date format to use for this operation.
|
||||||
|
Should be passed as a datetime library compatible string.
|
||||||
|
Sets the date format only for this operation. To set it globally, use FincalOptions.date_format
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
The float value of the returns.
|
A tuple containing the date and float value of the returns.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
@ -170,13 +189,19 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
|
|
||||||
as_on = _parse_date(as_on, date_format)
|
as_on = _parse_date(as_on, date_format)
|
||||||
as_on_delta, prior_delta = _preprocess_match_options(as_on_match, prior_match, closest)
|
as_on_delta, prior_delta = _preprocess_match_options(as_on_match, prior_match, closest)
|
||||||
|
original_as_on = as_on
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
current = self.data.get(as_on, None)
|
current = self.data.get(as_on, None)
|
||||||
if current is not None:
|
if current is not None:
|
||||||
break
|
break
|
||||||
elif not as_on_delta:
|
elif not as_on_delta:
|
||||||
raise ValueError("As on date not found")
|
if if_not_found == 'fail':
|
||||||
|
raise ValueError(f"As on date {original_as_on} not found")
|
||||||
|
elif if_not_found == 'nan':
|
||||||
|
return as_on, float("NaN")
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Invalid argument for if_not_found: {if_not_found}")
|
||||||
as_on += as_on_delta
|
as_on += as_on_delta
|
||||||
|
|
||||||
prev_date = as_on - relativedelta(**{interval_type: interval_value})
|
prev_date = as_on - relativedelta(**{interval_type: interval_value})
|
||||||
@ -185,14 +210,19 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
if previous is not None:
|
if previous is not None:
|
||||||
break
|
break
|
||||||
elif not prior_delta:
|
elif not prior_delta:
|
||||||
raise ValueError("Previous date not found")
|
if if_not_found == 'fail':
|
||||||
|
raise ValueError(f"Previous date {previous} not found")
|
||||||
|
elif if_not_found == 'nan':
|
||||||
|
return (as_on if return_actual_date else original_as_on), float("NaN")
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Invalid argument for if_not_found: {if_not_found}")
|
||||||
prev_date += prior_delta
|
prev_date += prior_delta
|
||||||
|
|
||||||
returns = current / previous
|
returns = current / previous
|
||||||
if compounding:
|
if compounding:
|
||||||
years = _interval_to_years(interval_type, interval_value)
|
years = _interval_to_years(interval_type, interval_value)
|
||||||
returns = returns ** (1 / years)
|
returns = returns ** (1 / years)
|
||||||
return returns - 1
|
return (as_on if return_actual_date else original_as_on), returns - 1
|
||||||
|
|
||||||
def calculate_rolling_returns(
|
def calculate_rolling_returns(
|
||||||
self,
|
self,
|
||||||
@ -202,6 +232,7 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
as_on_match: str = "closest",
|
as_on_match: str = "closest",
|
||||||
prior_match: str = "closest",
|
prior_match: str = "closest",
|
||||||
closest: str = "previous",
|
closest: str = "previous",
|
||||||
|
if_not_found: Literal['fail', 'nan'] = 'fail',
|
||||||
compounding: bool = True,
|
compounding: bool = True,
|
||||||
interval_type: Literal['years', 'months', 'days'] = 'years',
|
interval_type: Literal['years', 'months', 'days'] = 'years',
|
||||||
interval_value: int = 1,
|
interval_value: int = 1,
|
||||||
@ -234,8 +265,9 @@ class TimeSeries(TimeSeriesCore):
|
|||||||
as_on_match=as_on_match,
|
as_on_match=as_on_match,
|
||||||
prior_match=prior_match,
|
prior_match=prior_match,
|
||||||
closest=closest,
|
closest=closest,
|
||||||
|
if_not_found=if_not_found
|
||||||
)
|
)
|
||||||
rolling_returns.append((i, returns))
|
rolling_returns.append(returns)
|
||||||
rolling_returns.sort()
|
rolling_returns.sort()
|
||||||
return self.__class__(rolling_returns, self.frequency.symbol)
|
return self.__class__(rolling_returns, self.frequency.symbol)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user