Commit 7c867f41 authored by Dr.李's avatar Dr.李

update alpha mind utilities and examples

parent c6d7f90c
......@@ -90,7 +90,7 @@ def er_portfolio_analysis(er: np.ndarray,
cons_exp = constraints.risk_exp
return lbound, ubound, cons_exp, risk_lbound, risk_ubound
if benchmark is not None and method == 'risk_neutral':
if method == 'risk_neutral':
lbound, ubound, cons_exp, risk_lbound, risk_ubound = create_constraints(benchmark, **kwargs)
turn_over_target = kwargs.get('turn_over_target')
......
......@@ -94,7 +94,7 @@ def factor_analysis(f_name):
if __name__ == '__main__':
from dask.distributed import Client
client = Client('10.63.6.176:8786')
client = Client('10.63.6.13:8786')
engine = SqlEngine()
df = engine.fetch_factor_coverage()
......
......@@ -105,21 +105,28 @@ class LinearConstraints(object):
def __init__(self,
bounds: Dict[str, BoxBoundary],
cons_mat: pd.DataFrame,
backbone: np.ndarray):
backbone: np.ndarray=None):
pyFinAssert(len(bounds) == cons_mat.shape[1], "Number of bounds should be same as number of col of cons_mat")
pyFinAssert(cons_mat.shape[0] == len(backbone),
"length of back bond should be same as number of rows of cons_mat")
self.names = list(bounds.keys())
self.bounds = bounds
self.cons_mat = cons_mat
self.backbone = backbone
pyFinAssert(cons_mat.shape[0] == len(backbone) if backbone is not None else True,
"length of back bond should be same as number of rows of cons_mat")
def risk_targets(self) -> Tuple[np.ndarray, np.ndarray]:
lower_bounds = []
upper_bounds = []
if self.backbone is None:
backbone = np.zeros(len(self.cons_mat))
else:
backbone = self.backbone
for name in self.names:
center = self.backbone @ self.cons_mat[name].values
center = backbone @ self.cons_mat[name].values
l, u = self.bounds[name].bounds(center)
lower_bounds.append(l)
upper_bounds.append(u)
......
......@@ -32,7 +32,7 @@ class TestRank(unittest.TestCase):
data_rank = rank(self.x, groups=self.groups)
df = pd.DataFrame(self.x, index=self.groups)
expected_rank = df.groupby(level=0).apply(lambda x: x.values.argsort().argsort())
expected_rank = df.groupby(level=0).apply(lambda x: x.values.argsort(axis=0).argsort(axis=0))
print(expected_rank)
......@@ -229,7 +229,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 8.86 s\n"
"Wall time: 21.8 s\n"
]
}
],
......@@ -246,9 +246,17 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 1h 1min 15s\n"
]
}
],
"source": [
"%%time\n",
"\n",
......@@ -276,7 +284,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
......@@ -289,7 +297,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
......@@ -302,7 +310,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
......
This diff is collapsed.
# -*- coding: utf-8 -*-
"""
Created on 2018-3-5
@author: cheng.li
"""
import numpy as np
import pandas as pd
import statsmodels.api as sm
from alphamind.api import (
SqlEngine, LinearConstraints, er_portfolio_analysis, alpha_logger
)
def cross_section_analysis(ref_date,
factor_name,
universe,
horizon,
constraint_risk,
linear_bounds,
lbound,
ubound,
engine):
codes = engine.fetch_codes(ref_date, universe)
risk_exposure = engine.fetch_risk_model(ref_date, codes)[1][['code'] + constraint_risk]
factor_data = engine.fetch_factor(ref_date, factor_name, codes)
industry_matrix = engine.fetch_industry_matrix(ref_date, codes, 'sw_adj', 1)
total_data = pd.merge(factor_data, risk_exposure, on='code')
total_data = pd.merge(total_data, industry_matrix, on='code').dropna()
total_risk_exp = total_data[constraint_risk]
constraints = LinearConstraints(linear_bounds, total_risk_exp)
er = total_data[factor_name].values
industry = total_data.industry_name.values
target_pos, _ = er_portfolio_analysis(er,
industry,
None,
constraints,
False,
None,
method='risk_neutral',
lbound=lbound*np.ones(len(er)),
ubound=ubound*np.ones(len(er)))
codes = total_data.code.tolist()
target_pos['code'] = codes
dx_returns = engine.fetch_dx_return(ref_date, codes, horizon=horizon, offset=1)
target_pos = pd.merge(target_pos, dx_returns, on=['code'])
activate_weight = target_pos.weight.values
excess_return = np.exp(target_pos.dx.values) - 1.
port_ret = np.log(activate_weight @ excess_return + 1.)
ic = np.corrcoef(excess_return, activate_weight)[0, 1]
x = sm.add_constant(activate_weight)
results = sm.OLS(excess_return, x).fit()
t_stats = results.tvalues[1]
alpha_logger.info(f"{ref_date} is finished with {len(target_pos)} stocks for {factor_name}")
return port_ret, ic, t_stats
if __name__ == '__main__':
from alphamind.api import (
Universe, map_freq, risk_styles, industry_styles, macro_styles, BoundaryType, create_box_bounds
)
"""
Back test parameter settings
"""
start_date = '2010-01-01'
end_date = '2018-02-28'
category = 'sw_adj'
level = 1
freq = '20b'
universe = Universe('custom', ['zz800'])
data_source = 'postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha'
engine = SqlEngine(data_source)
horizon = map_freq(freq)
"""
Factor Model
"""
factor_name = 'SIZE'
"""
Constraints
"""
risk_names = list(set(risk_styles).difference({factor_name}))
industry_names = list(set(industry_styles).difference({factor_name}))
constraint_risk = risk_names + industry_names + macro_styles
b_type = []
l_val = []
u_val = []
for name in constraint_risk:
if name in set(risk_styles):
b_type.append(BoundaryType.ABSOLUTE)
l_val.append(0.0)
u_val.append(0.0)
else:
b_type.append(BoundaryType.RELATIVE)
l_val.append(1.0)
u_val.append(1.0)
linear_bounds = create_box_bounds(constraint_risk, b_type, l_val, u_val)
ref_date = '2018-02-08'
df = pd.DataFrame(columns=['ret', 'ic', 't.'])
print(cross_section_analysis(ref_date,
factor_name,
universe,
horizon,
constraint_risk,
linear_bounds,
lbound=-0.01,
ubound=0.01,
engine=engine))
\ No newline at end of file
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