184 lines
7.2 KiB
Python
184 lines
7.2 KiB
Python
# -*- encoding:utf-8 -*-
|
|
"""
|
|
组合参数辅助模块
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
import copy
|
|
from itertools import product
|
|
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
import pandas as pd
|
|
from .ABuGridSearch import ParameterGrid
|
|
from scipy import stats
|
|
# noinspection PyUnresolvedReferences
|
|
from ..CoreBu.ABuFixes import range, xrange
|
|
|
|
__author__ = '阿布'
|
|
__weixin__ = 'abu_quant'
|
|
|
|
# TODO 使用enum代替K常量
|
|
# 代表买因子参数组合
|
|
K_GEN_FACTOR_PARAMS_BUY = 0
|
|
# 代表卖因子参数组合
|
|
K_GEN_FACTOR_PARAMS_SELL = 1
|
|
|
|
|
|
def gen_factor_grid(type_param, factors, need_empty_sell=False):
|
|
"""
|
|
:param type_param: grid目标,为K_GEN_FACTOR_PARAMS_BUY或K_GEN_FACTOR_PARAMS_SELL需要重构
|
|
:param factors: 可迭代序列,元素为因子dict 如:
|
|
{'class': [AbuFactorBuyBreak], 'xd': [42]}, {'class': [AbuFactorBuyBreak],'xd': [60]}
|
|
:param need_empty_sell: 只针对卖出因子组合添加一个完全不使用任何卖出因子的组合
|
|
:return: 返回因子dict的组合参数序列
|
|
"""
|
|
|
|
# 通过ParameterGrid将factor包装,即通过ParameterGrid将dict对象product(*values),详阅读ParameterGrid
|
|
grid_params = [ParameterGrid(factor) for factor in factors]
|
|
# 进行product调用ParameterGrid__iter__进行product(*values)
|
|
factor_params = product(*grid_params)
|
|
factor_params = [list(pd_cls) for pd_cls in factor_params]
|
|
|
|
if len(factors) > 1:
|
|
# 把单独一个factor的加进去
|
|
for grid_single in grid_params:
|
|
for single in grid_single:
|
|
factor_params.append([single])
|
|
if need_empty_sell and type_param == K_GEN_FACTOR_PARAMS_SELL:
|
|
# 只有sell的factor要加个空的,买的因子要是全空就没办法玩了
|
|
factor_params.append([]) # 最后加一个完全不使用因子的
|
|
|
|
return factor_params
|
|
|
|
|
|
def score_pd_plot(grid_score_pd, y_key, x_key=None):
|
|
"""对最优结果score可视化,暂时未迁移完整,需迁移其余最优模块后可用"""
|
|
if x_key is not None:
|
|
xt = pd.crosstab(grid_score_pd[x_key], grid_score_pd[y_key])
|
|
xt_pct = xt.div(xt.sum(1).astype(float), axis=0)
|
|
xt_pct.plot(kind='bar',
|
|
stacked=True,
|
|
title=str(x_key) + ' -> ' + str(y_key))
|
|
plt.xlabel(str(x_key))
|
|
plt.ylabel(str(y_key))
|
|
else:
|
|
for col in grid_score_pd.columns:
|
|
if col.startswith('Y_'):
|
|
continue
|
|
xt = pd.crosstab(grid_score_pd[col], grid_score_pd[y_key])
|
|
xt_pct = xt.div(xt.sum(1).astype(float), axis=0)
|
|
xt_pct.plot(kind='bar',
|
|
stacked=True,
|
|
title=str(col) + ' -> ' + str(y_key))
|
|
plt.xlabel(str(col))
|
|
plt.ylabel(str(y_key))
|
|
plt.show()
|
|
|
|
|
|
# noinspection PyTypeChecker
|
|
def make_grid_score_pd(grid_scores, score_index=0):
|
|
"""对最优结果score分析处理,暂时未迁移完整,需迁移其余最优模块后可用"""
|
|
unique_sell_factor = {slFac['class'] for grid in grid_scores for slFac in grid[2]}
|
|
unique_buy_factor = {byFac['class'] for grid in grid_scores for byFac in grid[3]}
|
|
|
|
grid_pd = pd.DataFrame([alpha_params[1] for alpha_params in grid_scores])
|
|
factor_pd = pd.DataFrame([factor_params[2] for factor_params in grid_scores])
|
|
factor_buy_pd = pd.DataFrame([factor_params[3] for factor_params in grid_scores])
|
|
|
|
org_columns = factor_pd.shape[1]
|
|
for columns_ind in xrange(0, org_columns):
|
|
factor_pd[str(columns_ind) + 'class'] = factor_pd[columns_ind].apply(lambda x:
|
|
None if x is None else x['class'])
|
|
|
|
org_buy_columns = factor_buy_pd.shape[1]
|
|
for columns_ind in xrange(0, org_buy_columns):
|
|
factor_buy_pd[str(columns_ind) + 'class'] = factor_buy_pd[columns_ind].apply(lambda x:
|
|
None if x is None else x['class'])
|
|
|
|
def rm_noise_key(fun_dict):
|
|
copy_dict = copy.deepcopy(fun_dict)
|
|
if 'draw' in copy_dict:
|
|
del copy_dict['draw']
|
|
if 'show' in copy_dict:
|
|
del copy_dict['show']
|
|
if 'class' in copy_dict:
|
|
del copy_dict['class']
|
|
return copy_dict
|
|
|
|
def make_factor_pd(x_pd, sel_fac):
|
|
def make_factor_pd_inner(p_x_pd):
|
|
if p_x_pd is None:
|
|
return 0
|
|
if p_x_pd == sel_fac:
|
|
return 1
|
|
return 0
|
|
|
|
y_ret = x_pd.apply(make_factor_pd_inner)
|
|
if np.count_nonzero(y_ret) > 0:
|
|
return 1
|
|
return 0
|
|
|
|
def make_factor_param_pd(x_pd, unique_facts):
|
|
def make_factor_param_pd_inner(p_x_pd):
|
|
if p_x_pd is None:
|
|
return
|
|
class_key = p_x_pd['class'].__name__
|
|
x_pd_copy = rm_noise_key(p_x_pd)
|
|
for item in x_pd_copy.items():
|
|
unique_item = class_key + ':' + str(item[0]) + ':' + str(item[1])
|
|
unique_facts.append(unique_item)
|
|
|
|
x_pd.apply(make_factor_param_pd_inner)
|
|
|
|
for selFac in unique_sell_factor:
|
|
grid_pd[selFac.__name__] = factor_pd.iloc[:, org_columns:].apply(
|
|
make_factor_pd, args=(selFac,), axis=1)
|
|
for buyFac in unique_buy_factor:
|
|
grid_pd[buyFac.__name__] = factor_buy_pd.iloc[:, org_buy_columns:].apply(
|
|
make_factor_pd, args=(buyFac,), axis=1)
|
|
|
|
unique_factor_params = []
|
|
unique_factor_buy_params = []
|
|
factor_pd.iloc[:, 0:org_columns].apply(make_factor_param_pd, args=(unique_factor_params,), axis=1)
|
|
factor_buy_pd.iloc[:, 0:org_buy_columns].apply(make_factor_param_pd, args=(unique_factor_buy_params,), axis=1)
|
|
|
|
unique_factor_params = set(unique_factor_params)
|
|
unique_factor_buy_params = set(unique_factor_buy_params)
|
|
|
|
def dummies_params(x_pd, p_sel_fac_param):
|
|
def dummies_params_inner(p_x_pd):
|
|
if p_x_pd is None:
|
|
return 0
|
|
class_key = p_x_pd['class'].__name__
|
|
x_pd_copy = rm_noise_key(p_x_pd)
|
|
for item in x_pd_copy.items():
|
|
unique_item = class_key + ':' + str(item[0]) + ':' + str(item[1])
|
|
if p_sel_fac_param == unique_item:
|
|
return 1
|
|
return 0
|
|
|
|
y_ret = x_pd.apply(dummies_params_inner)
|
|
if np.count_nonzero(y_ret) > 0:
|
|
return 1
|
|
return 0
|
|
|
|
for sel_fac_param in unique_factor_params:
|
|
grid_pd[sel_fac_param] = factor_pd.iloc[:, 0:org_columns].apply(
|
|
dummies_params, args=(sel_fac_param,), axis=1)
|
|
for buy_fac_param in unique_factor_buy_params:
|
|
grid_pd[buy_fac_param] = factor_pd.iloc[:, 0:org_columns].apply(
|
|
dummies_params, args=(buy_fac_param,), axis=1)
|
|
|
|
grid_pd['Y_REG'] = [score[0][score_index] if isinstance(score[0], list) else score[0]
|
|
for score in grid_scores]
|
|
|
|
grid_pd['Y_LOG_MEDIAN'] = np.where(
|
|
grid_pd['Y_REG'] > grid_pd['Y_REG'].median(), 1, 0)
|
|
grid_pd['Y_LOG_618'] = np.where(
|
|
grid_pd['Y_REG'] > stats.scoreatpercentile(grid_pd['Y_REG'], 61.8), 1, 0)
|
|
|
|
return grid_pd
|