def ssd(returns): """ Calculate semi standard deviation of returns """ ret = np.copy(returns) mean_ret = nanmean(ret) ret[ret > nanmean(ret)] = mean_ret std = 0 for curr_ret in ret: std += (curr_ret - mean_ret) * (curr_ret - mean_ret) std /= (ret.shape[0] - 1) return np.sqrt(std)
def information_ratio(returns, factor_returns): """ Determines the Information ratio of a strategy. Parameters ---------- returns : pd.Series or np.ndarray Daily returns of the strategy, noncumulative. - See full explanation in :func:`~empyrical.stats.cum_returns`. factor_returns: float / series Benchmark return to compare returns against. Returns ------- float The information ratio. Note ----- See https://en.wikipedia.org/wiki/information_ratio for more details. """ if len(returns) < 2: return np.nan active_return = _adjust_returns(returns, factor_returns) tracking_error = nanstd(active_return, ddof=1) if np.isnan(tracking_error): return 0.0 if tracking_error == 0: return np.nan return nanmean(active_return) / tracking_error
def alpha_aligned(returns, factor_returns, risk_free=0.0, period=DAILY, annualization=None, _beta=None): """Calculates annualized alpha. If they are pd.Series, expects returns and factor_returns have already been aligned on their labels. If np.ndarray, these arguments should have the same shape. Parameters ---------- returns : pd.Series or np.ndarray Daily returns of the strategy, noncumulative. - See full explanation in :func:`~empyrical.stats.cum_returns`. factor_returns : pd.Series or np.ndarray Daily noncumulative returns of the factor to which beta is computed. Usually a benchmark such as the market. - This is in the same style as returns. risk_free : int, float, optional Constant risk-free return throughout the period. For example, the interest rate on a three month us treasury bill. period : str, optional Defines the periodicity of the 'returns' data for purposes of annualizing. Value ignored if `annualization` parameter is specified. Defaults are: 'monthly':12 'weekly': 52 'daily': 252 annualization : int, optional Used to suppress default values available in `period` to convert returns into annual returns. Value should be the annual frequency of `returns`. - See full explanation in :func:`~empyrical.stats.annual_return`. _beta : float, optional The beta for the given inputs, if already known. Will be calculated internally if not provided. Returns ------- float Alpha. """ if len(returns) < 2: return np.nan ann_factor = annualization_factor(period, annualization) if _beta is None: _beta = beta_aligned(returns, factor_returns, risk_free) adj_returns = _adjust_returns(returns, risk_free) adj_factor_returns = _adjust_returns(factor_returns, risk_free) alpha_series = adj_returns - (_beta * adj_factor_returns) return nanmean(alpha_series) * ann_factor
def sortino_ratio(returns, required_return=0, period=DAILY, annualization=None, _downside_risk=None): """ Determines the Sortino ratio of a strategy. Parameters ---------- returns : pd.Series or pd.DataFrame Daily returns of the strategy, noncumulative. - See full explanation in :func:`~empyrical.stats.cum_returns`. required_return: float / series minimum acceptable return period : str, optional Defines the periodicity of the 'returns' data for purposes of annualizing. Value ignored if `annualization` parameter is specified. Defaults are: 'monthly':12 'weekly': 52 'daily': 252 annualization : int, optional Used to suppress default values available in `period` to convert returns into annual returns. Value should be the annual frequency of `returns`. _downside_risk : float, optional The downside risk of the given inputs, if known. Will be calculated if not provided. Returns ------- depends on input type series ==> float DataFrame ==> pd.Series Annualized Sortino ratio. """ if len(returns) < 2: return np.nan ann_factor = annualization_factor(period, annualization) if len(returns) < 2: return np.nan adj_returns = _adjust_returns(returns, required_return) mu = nanmean(adj_returns, axis=0) dsr = (_downside_risk if _downside_risk is not None else downside_risk( returns, required_return)) sortino = mu / dsr if len(returns.shape) == 2: sortino = pd.Series(sortino, index=returns.columns) return sortino * ann_factor
def downside_risk(returns, required_return=0, period=DAILY, annualization=None): """ Determines the downside deviation below a threshold Parameters ---------- returns : pd.Series or np.ndarray or pd.DataFrame Daily returns of the strategy, noncumulative. - See full explanation in :func:`~empyrical.stats.cum_returns`. required_return: float / series minimum acceptable return period : str, optional Defines the periodicity of the 'returns' data for purposes of annualizing. Value ignored if `annualization` parameter is specified. Defaults are: 'monthly':12 'weekly': 52 'daily': 252 annualization : int, optional Used to suppress default values available in `period` to convert returns into annual returns. Value should be the annual frequency of `returns`. Returns ------- float, pd.Series depends on input type series ==> float DataFrame ==> pd.Series Annualized downside deviation """ if len(returns) < 1: return np.nan ann_factor = annualization_factor(period, annualization) downside_diff = _adjust_returns(returns, required_return).copy() mask = downside_diff > 0 downside_diff[mask] = 0.0 squares = np.square(downside_diff) mean_squares = nanmean(squares, axis=0) dside_risk = np.sqrt(mean_squares) * np.sqrt(ann_factor) if len(returns.shape) == 2 and isinstance(returns, pd.DataFrame): dside_risk = pd.Series(dside_risk, index=returns.columns) return dside_risk
def sortino_ratio(returns, required_return=0, period=DAILY, annualization=None, _downside_risk=None): """ Determines the Sortino ratio of a strategy. Parameters ---------- returns : pd.Series or np.ndarray or pd.DataFrame Daily returns of the strategy, noncumulative. - See full explanation in :func:`~empyrical.stats.cum_returns`. required_return: float / series minimum acceptable return period : str, optional Defines the periodicity of the 'returns' data for purposes of annualizing. Value ignored if `annualization` parameter is specified. Defaults are: 'monthly':12 'weekly': 52 'daily': 252 annualization : int, optional Used to suppress default values available in `period` to convert returns into annual returns. Value should be the annual frequency of `returns`. _downside_risk : float, optional The downside risk of the given inputs, if known. Will be calculated if not provided. Returns ------- float, pd.Series depends on input type series ==> float DataFrame ==> pd.Series Annualized Sortino ratio. """ if len(returns) < 2: return np.nan ann_factor = annualization_factor(period, annualization) adj_returns = _adjust_returns(returns, required_return) mu = nanmean(adj_returns, axis=0) dsr = (_downside_risk if _downside_risk is not None else downside_risk(returns, required_return)) sortino = mu / dsr return sortino * ann_factor