Commit 92ca2ac2 authored by Dr.李's avatar Dr.李

added portfolio builder based on percent

parent 8c77b8e4
# -*- coding: utf-8 -*-
"""
Created on 2017-5-4
@author: cheng.li
"""
import numpy as np
from numpy import zeros
from numpy import zeros_like
from alphamind.cyimpl import groupby
from alphamind.utilities import set_value
def percent_build(er: np.ndarray, percent: float, groups: np.ndarray=None) -> np.ndarray:
if er.ndim == 1 or (er.shape[0] == 1 or er.shape[1] == 1):
""" fast path methods for single column er"""
neg_er = -er.flatten()
length = len(neg_er)
weights = zeros((length, 1))
if groups is not None:
group_ids = groupby(groups)
for current_index in group_ids:
current_ordering = neg_er[current_index].argsort()
current_ordering.shape = -1, 1
use_rank = int(percent * len(current_index))
set_value(weights, current_index[current_ordering[:use_rank]], 1.)
else:
ordering = neg_er.argsort()
use_rank = int(percent * len(neg_er))
weights[ordering[:use_rank]] = 1.
return weights.reshape(er.shape)
else:
neg_er = -er
weights = zeros_like(er)
if groups is not None:
group_ids = groupby(groups)
for current_index in group_ids:
current_ordering = neg_er[current_index].argsort(axis=0)
use_rank = int(percent * len(current_index))
set_value(weights, current_index[current_ordering[:use_rank]], 1)
else:
ordering = neg_er.argsort(axis=0)
use_rank = int(percent * len(neg_er))
set_value(weights, ordering[:use_rank], 1.)
return weights
......@@ -6,19 +6,10 @@ Created on 2017-4-26
"""
import numpy as np
import numba as nb
from numpy import zeros
from numpy import zeros_like
from alphamind.cyimpl import groupby
@nb.njit(nogil=True, cache=True)
def set_value(mat, used_level, to_fill):
length, width = used_level.shape
for i in range(length):
for j in range(width):
k = used_level[i, j]
mat[k, j] = to_fill
from alphamind.utilities import set_value
def rank_build(er: np.ndarray, use_rank: int, groups: np.ndarray=None) -> np.ndarray:
......
# -*- coding: utf-8 -*-
"""
Created on 2017-5-4
@author: cheng.li
"""
import unittest
import numpy as np
import pandas as pd
from alphamind.portfolio.percentbuilder import percent_build
class TestPercentBuild(unittest.TestCase):
def test_percent_build(self):
n_samples = 3000
p_included = 0.1
n_portfolios = range(1, 10)
n_include = int(n_samples * p_included)
for n_portfolio in n_portfolios:
x = np.random.randn(n_samples, n_portfolio)
calc_weights = percent_build(x, p_included)
expected_weights = np.zeros((len(x), n_portfolio))
masks = (-x).argsort(axis=0).argsort(axis=0) < n_include
for j in range(x.shape[1]):
expected_weights[masks[:, j], j] = 1.
np.testing.assert_array_almost_equal(calc_weights, expected_weights)
def test_percent_build_with_group(self):
n_samples = 3000
p_included = 0.1
n_groups = 30
n_portfolios = range(1, 10)
for n_portfolio in n_portfolios:
x = np.random.randn(n_samples, n_portfolio)
groups = np.random.randint(n_groups, size=n_samples)
calc_weights = percent_build(x, p_included, groups)
grouped_ordering = pd.DataFrame(-x).groupby(groups).rank()
grouped_count = pd.DataFrame(-x).groupby(groups).transform(lambda x: x.count())
expected_weights = np.zeros((len(x), n_portfolio))
n_include = (grouped_count * p_included).astype(int)
masks = (grouped_ordering <= n_include).values
for j in range(x.shape[1]):
expected_weights[masks[:, j], j] = 1.
np.testing.assert_array_almost_equal(calc_weights, expected_weights)
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
......@@ -52,6 +52,15 @@ class TestRunner(object):
sys.exit(0)
@nb.njit(nogil=True, cache=True)
def set_value(mat, used_level, to_fill):
length, width = used_level.shape
for i in range(length):
for j in range(width):
k = used_level[i, j]
mat[k, j] = to_fill
@nb.njit(nogil=True, cache=True)
def group_mapping(groups: np.ndarray) -> np.ndarray:
length = groups.shape[0]
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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