diff --git a/README.MD b/README.MD index 6ff8994..005c2d5 100644 --- a/README.MD +++ b/README.MD @@ -70,5 +70,6 @@ Out[4]: 'excess_annual_volatility': 0.14574262245479186, 'excess_max_drawdown': 0.050301584825935344, 'var': 0.025161857442751474, - 'win_rate': 0.3} + 'win_rate': 0.3, + 'correlation': 0.7136492542281812} ``` diff --git a/rqrisk/risk.py b/rqrisk/risk.py index 8a6ef5b..2d2f7c9 100644 --- a/rqrisk/risk.py +++ b/rqrisk/risk.py @@ -207,5 +207,10 @@ def win_rate(self): def excess_win_rate(self): return len(self._portfolio[self._portfolio > self._benchmark]) / self.period_count + @indicator_property(min_period_count=2) + def correlation(self): + # 相关系数算法参考 https://numpy.org/doc/stable/reference/generated/numpy.corrcoef.html?highlight=corr#numpy.corrcoef + return np.corrcoef(self._portfolio, self._benchmark)[0][1] + def all(self): return {k: getattr(self, k) for k, v in self.__class__.__dict__.items() if isinstance(v, IndicatorProperty)} diff --git a/setup.cfg b/setup.cfg index 9b66261..6527fdc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,7 +5,7 @@ [metadata] name = rqrisk -version = 1.0.3 +version = 1.0.4 [versioneer] VCS = git diff --git a/test.py b/test.py index a5be4bd..5d0cd57 100644 --- a/test.py +++ b/test.py @@ -73,6 +73,11 @@ index=pd.date_range('2000-1-30', periods=9, freq='W') ) +volatile_monthly_benchmark = pd.Series( + np.array([1, 2, -5, 3, 10, -3, -1, 4, 1]) / 100, + index=pd.date_range('2000-1-30', periods=9, freq='M') +) + def _r(returns, benchmark_returns, risk_free_rate, period=DAILY): if benchmark_returns is None: @@ -262,3 +267,19 @@ def _assert(returns, benchmark, desired_win_rate): _assert(positive_returns, zero_benchmark, 1) _assert(negative_returns, zero_benchmark, 0) + +def test_correlation(): + """ 测试相关系数 """ + def _assert(returns, benchmark, period): + r = _r(returns, benchmark, 0, period) + assert_almost_equal(r.correlation, returns.corr(benchmark)) + + _assert(one_return, one_benchmark, DAILY) # np.nan + _assert(positive_returns, simple_benchmark, DAILY) # np.nan + _assert(positive_returns, volatile_benchmark, DAILY) # 0.05773502691896258 + _assert(negative_returns, simple_benchmark, DAILY) # np.nan + _assert(negative_returns, volatile_benchmark, DAILY) # -0.32984900530449723 + _assert(weekly_returns, simple_weekly_benchamrk, WEEKLY) # np.nan + _assert(weekly_returns, volatile_weekly_benchmark, WEEKLY) # -0.3411258215912419 + _assert(monthly_returns, simple_monthly_benchamrk, MONTHLY) # np.nan + _assert(monthly_returns, volatile_monthly_benchmark, MONTHLY) # -0.3411258215912419