Sharpe ratio is working

This commit is contained in:
Gourav Kumar 2022-05-07 14:09:21 +05:30
parent 2a8f5b4041
commit 0d0b2121a3
3 changed files with 35 additions and 19 deletions

View File

@ -449,7 +449,7 @@ class TimeSeries(TimeSeriesCore):
prior_match: str = "closest", prior_match: str = "closest",
closest: Literal["previous", "next", "exact"] = "previous", closest: Literal["previous", "next", "exact"] = "previous",
if_not_found: Literal["fail", "nan"] = "fail", if_not_found: Literal["fail", "nan"] = "fail",
annual_compounded_returns: bool = False, annual_compounded_returns: bool = None,
date_format: str = None, date_format: str = None,
) -> float: ) -> float:
"""Calculates the volatility of the time series.add() """Calculates the volatility of the time series.add()
@ -503,6 +503,12 @@ class TimeSeries(TimeSeriesCore):
from_date = self.start_date + relativedelta(**{return_period_unit: return_period_value}) from_date = self.start_date + relativedelta(**{return_period_unit: return_period_value})
if to_date is None: if to_date is None:
to_date = self.end_date to_date = self.end_date
years = _interval_to_years(return_period_unit, return_period_value)
if annual_compounded_returns is None:
if years > 1:
annual_compounded_returns = True
else:
annual_compounded_returns = False
rolling_returns = self.calculate_rolling_returns( rolling_returns = self.calculate_rolling_returns(
from_date=from_date, from_date=from_date,
@ -524,7 +530,7 @@ class TimeSeries(TimeSeriesCore):
if return_period_unit == "months": if return_period_unit == "months":
sd *= math.sqrt(12) sd *= math.sqrt(12)
elif return_period_unit == "days": elif return_period_unit == "days":
sd *= math.sqrt(traded_days) sd *= math.sqrt(traded_days / return_period_value)
return sd return sd
@ -544,19 +550,32 @@ class TimeSeries(TimeSeriesCore):
--------- ---------
TimeSeries.calculate_rolling_returns() TimeSeries.calculate_rolling_returns()
""" """
kwargs["return_period_unit"] = kwargs.get("return_period_unit", self.frequency.freq_type) kwargs["return_period_unit"] = kwargs.get("return_period_unit", self.frequency.freq_type)
kwargs["return_period_value"] = kwargs.get("return_period_value", 1) 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: years = _interval_to_years(kwargs["return_period_unit"], kwargs["return_period_value"])
start_date = self.start_date + relativedelta( if kwargs.get("annual_compounded_returns", True):
if years >= 1:
kwargs["annual_compounded_returns"] = True
annualise_returns = False
else:
kwargs["annual_compounded_returns"] = False
annualise_returns = True
elif not kwargs["annual_compounded_returns"]:
annualise_returns = False
if kwargs.get("from_date") is None:
kwargs["from_date"] = self.start_date + relativedelta(
**{kwargs["return_period_unit"]: kwargs["return_period_value"]} **{kwargs["return_period_unit"]: kwargs["return_period_value"]}
) )
kwargs["from_date"] = start_date kwargs["to_date"] = kwargs.get("to_date", self.end_date)
rr = self.calculate_rolling_returns(**kwargs) rr = self.calculate_rolling_returns(**kwargs)
return statistics.mean(rr.values) mean_rr = statistics.mean(rr.values)
if annualise_returns:
mean_rr = (1 + mean_rr) ** (1 / years) - 1
return mean_rr
def max_drawdown(self) -> MaxDrawdown: def max_drawdown(self) -> MaxDrawdown:
"""Calculates the maximum fall the stock has taken between any two points. """Calculates the maximum fall the stock has taken between any two points.

View File

@ -21,10 +21,10 @@ def sharpe_ratio(
closest: Literal["previous", "next"] = "previous", closest: Literal["previous", "next"] = "previous",
date_format: str = None, date_format: str = None,
): ):
pass
if risk_free_data is None and risk_free_rate is None: 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") 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 = { common_params = {
"from_date": from_date, "from_date": from_date,
@ -37,18 +37,13 @@ def sharpe_ratio(
"closest": closest, "closest": closest,
"date_format": date_format, "date_format": date_format,
} }
returns_ts = time_series_data.calculate_rolling_returns(**common_params, annual_compounded_returns=True) average_rr = time_series_data.average_rolling_return(**common_params, annual_compounded_returns=True)
if risk_free_data is not None: excess_returns = average_rr - risk_free_rate
risk_free_data = returns_ts.sync(risk_free_data)
else:
risk_free_data = risk_free_rate
excess_returns = returns_ts - risk_free_data
sd = time_series_data.volatility( sd = time_series_data.volatility(
**common_params, **common_params,
annualize_volatility=True, annualize_volatility=True,
) )
sharpe_ratio = excess_returns.mean() / sd sharpe_ratio_value = excess_returns / sd
return sharpe_ratio return sharpe_ratio_value

View File

@ -206,6 +206,8 @@ class TestTimeSeriesCreation:
class TestTimeSeriesBasics: class TestTimeSeriesBasics:
FincalOptions.get_closest = "exact"
def test_fill(self): def test_fill(self):
ts_data = create_test_data(frequency=AllFrequencies.D, num=50, skip_weekends=True) ts_data = create_test_data(frequency=AllFrequencies.D, num=50, skip_weekends=True)
ts = TimeSeries(ts_data, frequency="D") ts = TimeSeries(ts_data, frequency="D")