diff --git a/pyfolio/tests/test_timeseries.py b/pyfolio/tests/test_timeseries.py index c2691ae8..1528a0a0 100644 --- a/pyfolio/tests/test_timeseries.py +++ b/pyfolio/tests/test_timeseries.py @@ -338,6 +338,18 @@ def test_sortino(self, returns, expected): timeseries.sortino_ratio(returns), expected, DECIMAL_PLACES) + def test_tail_ratio(self): + returns = np.random.randn(10000) + self.assertAlmostEqual( + timeseries.tail_ratio(returns), + 1., 1) + + def test_common_sense_ratio(self): + returns = pd.Series(np.random.randn(1000) + .1) + self.assertAlmostEqual( + timeseries.common_sense_ratio(returns), + 0.024031933021535612, DECIMAL_PLACES) + class TestMultifactor(TestCase): simple_rets = pd.Series( diff --git a/pyfolio/timeseries.py b/pyfolio/timeseries.py index c63e40ba..aafcdfef 100644 --- a/pyfolio/timeseries.py +++ b/pyfolio/timeseries.py @@ -497,6 +497,52 @@ def stability_of_timeseries(returns): return rhat +def tail_ratio(returns): + """Determines the ratio between the right (95%) and left tail (5%). + + For example, a ratio of 0.25 means that losses are four times + as bad as profits. + + Parameters + ---------- + returns : pd.Series + Daily returns of the strategy, noncumulative. + - See full explanation in tears.create_full_tear_sheet. + + Returns + ------- + float + tail ratio + + """ + + return np.abs(np.percentile(returns, 95)) / \ + np.abs(np.percentile(returns, 5)) + + +def common_sense_ratio(returns): + """Common sense ratio is the multiplication of the tail ratio and the + Gain-to-Pain-Ratio -- sum(profits) / sum(losses). + + See http://bit.ly/1ORzGBk for more information on motivation of + this metric. + + + Parameters + ---------- + returns : pd.Series + Daily returns of the strategy, noncumulative. + - See full explanation in tears.create_full_tear_sheet. + + Returns + ------- + float + common sense ratio + + """ + return tail_ratio(returns) * (1 + annual_return(returns)) + + SIMPLE_STAT_FUNCS = [ annual_return, annual_volatility, @@ -508,6 +554,8 @@ def stability_of_timeseries(returns): sortino_ratio, stats.skew, stats.kurtosis, + tail_ratio, + common_sense_ratio, ] FACTOR_STAT_FUNCS = [