Commit 24995683 authored by Dr.李's avatar Dr.李

added benchmark to quantile analysis

parent 8da2de3f
...@@ -59,9 +59,6 @@ def factor_analysis(factors: pd.DataFrame, ...@@ -59,9 +59,6 @@ def factor_analysis(factors: pd.DataFrame,
do_neutralize=True, do_neutralize=True,
**kwargs) -> Tuple[pd.DataFrame, Optional[pd.DataFrame]]: **kwargs) -> Tuple[pd.DataFrame, Optional[pd.DataFrame]]:
if risk_exp is not None:
risk_exp = risk_exp[:, risk_exp.sum(axis=0) != 0]
data_pack = FDataPack(raw_factors=factors.values, data_pack = FDataPack(raw_factors=factors.values,
groups=industry, groups=industry,
benchmark=benchmark, benchmark=benchmark,
......
...@@ -40,7 +40,14 @@ def quantile_analysis(factors: pd.DataFrame, ...@@ -40,7 +40,14 @@ def quantile_analysis(factors: pd.DataFrame,
risk_exp=risk_exp) risk_exp=risk_exp)
er = data_pack.factor_processing(pre_process, post_process, do_neutralize) @ factor_weights er = data_pack.factor_processing(pre_process, post_process, do_neutralize) @ factor_weights
return q_anl_impl(er, n_bins, dx_return) raw_return = q_anl_impl(er, n_bins, dx_return)
if benchmark is not None:
b_ret = np.dot(benchmark, dx_return)
b_total = benchmark.sum()
return raw_return * b_total - b_ret
else:
return raw_return
def q_anl_impl(er: np.ndarray, def q_anl_impl(er: np.ndarray,
......
...@@ -63,6 +63,10 @@ class FDataPack(object): ...@@ -63,6 +63,10 @@ class FDataPack(object):
self.benchmark = benchmark.flatten() self.benchmark = benchmark.flatten()
else: else:
self.benchmark = None self.benchmark = None
if risk_exp is not None:
risk_exp = risk_exp[:, risk_exp.sum(axis=0) != 0]
self.risk_exp = risk_exp self.risk_exp = risk_exp
self.constraints = constraints self.constraints = constraints
self.risk_names = risk_names self.risk_names = risk_names
......
...@@ -24,6 +24,8 @@ class TestQuantileAnalysis(unittest.TestCase): ...@@ -24,6 +24,8 @@ class TestQuantileAnalysis(unittest.TestCase):
self.x = np.random.randn(n, 5) self.x = np.random.randn(n, 5)
self.x_w = np.random.randn(n_f) self.x_w = np.random.randn(n_f)
self.r = np.random.randn(n) self.r = np.random.randn(n)
self.b_w = np.random.randint(0, 10, n)
self.b_w = self.b_w / float(self.b_w.sum())
self.risk_exp = np.random.randn(n, 3) self.risk_exp = np.random.randn(n, 3)
self.n_bins = 10 self.n_bins = 10
...@@ -72,6 +74,27 @@ class TestQuantileAnalysis(unittest.TestCase): ...@@ -72,6 +74,27 @@ class TestQuantileAnalysis(unittest.TestCase):
expected = q_anl_impl(er, self.n_bins, self.r) expected = q_anl_impl(er, self.n_bins, self.r)
np.testing.assert_array_almost_equal(calculated, expected) np.testing.assert_array_almost_equal(calculated, expected)
def test_quantile_analysis_with_benchmark(self):
f_df = pd.DataFrame(self.x)
calculated = quantile_analysis(f_df,
self.x_w,
self.r,
n_bins=self.n_bins,
do_neutralize=True,
benchmark=self.b_w,
risk_exp=self.risk_exp,
pre_process=[winsorize_normal, standardize],
post_process=[standardize])
er = self.x_w @ factor_processing(self.x,
[winsorize_normal, standardize],
self.risk_exp,
[standardize],
True).T
raw_er = q_anl_impl(er, self.n_bins, self.r)
expected = raw_er * self.b_w.sum() - np.dot(self.b_w, self.r)
np.testing.assert_array_almost_equal(calculated, expected)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment