Implemented sortino ratio
This commit is contained in:
parent
f46ebaa8a9
commit
6c8800bef2
@ -455,3 +455,115 @@ def correlation(
|
||||
|
||||
cor = statistics.correlation(asset_rr.values, market_rr.values)
|
||||
return cor
|
||||
|
||||
|
||||
@date_parser(3, 4)
|
||||
def sortino_ratio(
|
||||
time_series_data: TimeSeries,
|
||||
risk_free_data: TimeSeries = None,
|
||||
risk_free_rate: float = None,
|
||||
from_date: str | datetime.datetime = None,
|
||||
to_date: str | datetime.datetime = None,
|
||||
frequency: Literal["D", "W", "M", "Q", "H", "Y"] = None,
|
||||
return_period_unit: Literal["years", "months", "days"] = "years",
|
||||
return_period_value: int = 1,
|
||||
as_on_match: str = "closest",
|
||||
prior_match: str = "closest",
|
||||
closest: Literal["previous", "next"] = "previous",
|
||||
date_format: str = None,
|
||||
) -> float:
|
||||
"""Calculate the Sharpe ratio of any time series
|
||||
|
||||
Sharpe ratio is a measure of returns per unit of risk,
|
||||
where risk is measured by the standard deviation of the returns.
|
||||
|
||||
The formula for Sharpe ratio is:
|
||||
(average asset return - risk free rate)/volatility of asset returns
|
||||
|
||||
Parameters
|
||||
----------
|
||||
time_series_data:
|
||||
The time series for which Sharpe ratio needs to be calculated
|
||||
|
||||
risk_free_data:
|
||||
Risk free rates as time series data.
|
||||
This should be the time series of risk free returns,
|
||||
and not the underlying asset value.
|
||||
|
||||
risk_free_rate:
|
||||
Risk free rate to be used.
|
||||
Either risk_free_data or risk_free_rate needs to be provided.
|
||||
If both are provided, the time series data will be used.
|
||||
|
||||
from_date:
|
||||
Start date from which returns should be calculated.
|
||||
Defaults to the first date of the series.
|
||||
|
||||
to_date:
|
||||
End date till which returns should be calculated.
|
||||
Defaults to the last date of the series.
|
||||
|
||||
frequency:
|
||||
The frequency at which returns should be calculated.
|
||||
|
||||
return_period_unit: 'years', 'months', 'days'
|
||||
The type of time period to use for return calculation.
|
||||
|
||||
return_period_value: int
|
||||
The value of the specified interval type over which returns needs to be calculated.
|
||||
|
||||
as_on_match: str, optional
|
||||
The mode of matching the as_on_date. Refer closest.
|
||||
|
||||
prior_match: str, optional
|
||||
The mode of matching the prior_date. Refer closest.
|
||||
|
||||
closest: str, optional
|
||||
The mode of matching the closest date.
|
||||
Valid values are 'exact', 'previous', 'next' and next.
|
||||
|
||||
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
|
||||
-------
|
||||
Value of Sharpe ratio as a float.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If risk free data or risk free rate is not provided.
|
||||
"""
|
||||
|
||||
interval_days = int(_interval_to_years(return_period_unit, return_period_value) * 365 + 1)
|
||||
|
||||
if from_date is None:
|
||||
from_date = time_series_data.start_date + datetime.timedelta(days=interval_days)
|
||||
if to_date is None:
|
||||
to_date = time_series_data.end_date
|
||||
|
||||
if risk_free_data is None and risk_free_rate is None:
|
||||
raise ValueError("At least one of risk_free_data or risk_free rate is required")
|
||||
elif risk_free_data is not None:
|
||||
risk_free_rate = risk_free_data.mean()
|
||||
|
||||
common_params = {
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"frequency": frequency,
|
||||
"return_period_unit": return_period_unit,
|
||||
"return_period_value": return_period_value,
|
||||
"as_on_match": as_on_match,
|
||||
"prior_match": prior_match,
|
||||
"closest": closest,
|
||||
"date_format": date_format,
|
||||
}
|
||||
average_rr_ts = time_series_data.calculate_rolling_returns(**common_params, annual_compounded_returns=True)
|
||||
average_rr = statistics.mean(average_rr_ts.values)
|
||||
|
||||
excess_returns = average_rr - risk_free_rate
|
||||
sd = statistics.stdev([i for i in average_rr_ts.values if i < 0])
|
||||
|
||||
sortino_ratio_value = excess_returns / sd
|
||||
return sortino_ratio_value
|
||||
|
Loading…
Reference in New Issue
Block a user