Commit 8ae110d4 authored by Dr.李's avatar Dr.李

added is_tradable flag for rank builder

parent 417f5234
......@@ -99,7 +99,7 @@ def er_portfolio_analysis(er: np.ndarray,
raise ValueError('linear programming optimizer in status: {0}'.format(status))
elif method == 'rank':
weights = rank_build(er, use_rank=kwargs['use_rank']).flatten() * benchmark.sum() / kwargs['use_rank']
weights = rank_build(er, use_rank=kwargs['use_rank'], masks=is_tradable).flatten() * benchmark.sum() / kwargs['use_rank']
elif method == 'ls' or method == 'long_short':
weights = long_short_build(er).flatten()
elif method == 'mv' or method == 'mean_variance':
......
......@@ -12,7 +12,12 @@ from alphamind.utilities import groupby
from alphamind.utilities import set_value
def rank_build(er: np.ndarray, use_rank: int, groups: np.ndarray=None) -> np.ndarray:
def rank_build(er: np.ndarray, use_rank: int, groups: np.ndarray=None, masks: np.ndarray=None) -> np.ndarray:
er = er.copy()
if masks is not None:
er[~masks] = -np.inf
if er.ndim == 1 or (er.shape[0] == 1 or er.shape[1] == 1):
# fast path methods for single column er
......
......@@ -18,6 +18,7 @@ class TestRankBuild(unittest.TestCase):
self.n_included = 300
self.n_groups = 30
self.n_portfolio = range(1, 10)
self.n_mask = 100
def test_rank_build(self):
for n_portfolio in self.n_portfolio:
......@@ -26,10 +27,10 @@ class TestRankBuild(unittest.TestCase):
calc_weights = rank_build(x, self.n_included)
expected_weights = np.zeros((len(x), n_portfolio))
masks = (-x).argsort(axis=0).argsort(axis=0) < self.n_included
chosen = (-x).argsort(axis=0).argsort(axis=0) < self.n_included
for j in range(x.shape[1]):
expected_weights[masks[:, j], j] = 1.
expected_weights[chosen[:, j], j] = 1.
np.testing.assert_array_almost_equal(calc_weights, expected_weights)
......@@ -45,9 +46,32 @@ class TestRankBuild(unittest.TestCase):
grouped_ordering = pd.DataFrame(-x).groupby(groups).rank()
expected_weights = np.zeros((len(x), n_portfolio))
masks = (grouped_ordering <= n_include).values
chosen = (grouped_ordering <= n_include).values
for j in range(x.shape[1]):
expected_weights[masks[:, j], j] = 1.
expected_weights[chosen[:, j], j] = 1.
np.testing.assert_array_almost_equal(calc_weights, expected_weights)
def test_rank_build_with_masks(self):
for n_portfolio in self.n_portfolio:
x = np.random.randn(self.n_samples, n_portfolio)
choices = np.random.choice(self.n_samples, self.n_mask, replace=False)
masks = np.full(self.n_samples, True, dtype=bool)
masks[choices] = False
calc_weights = rank_build(x, self.n_included, masks=masks)
expected_weights = np.zeros((len(x), n_portfolio))
filtered_index = np.arange(len(x))[masks]
filtered_x = x[masks]
big_boolen = np.full(x.shape, False, dtype=bool)
chosen = (-filtered_x).argsort(axis=0).argsort(axis=0) < self.n_included
big_boolen[filtered_index] = chosen
for j in range(x.shape[1]):
expected_weights[big_boolen[:, j], j] = 1.
np.testing.assert_array_almost_equal(calc_weights, expected_weights)
......
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