def __init__( self, factor: Union[pd.Series, pd.DataFrame], prices: Union[pd.Series, pd.DataFrame, Callable], groupby: Union[pd.Series, pd.DataFrame, Callable], stock_start_date: Union[pd.Series, pd.DataFrame, Callable], weights: Union[float, pd.Series, pd.DataFrame, Callable] = 1.0, frequence: str = "DAY", quantiles: Union[int, Tuple[float], List[float]] = 5, bins: Union[int, Tuple[float], List[float]] = None, periods: Union[int, Tuple[int], List[int]] = (1, 5, 10), binning_by_group: bool = False, max_loss: float = 0.25, zero_aware: bool = False, ): """ 初始化输入 说明: - quantiles 与 bins 只能有一个为非空 """ self.factor = preprocess.QA_fmt_factor(factor) self.prices = prices self.groupby = groupby self.stock_start_date = stock_start_date self.weights = weights self.frequence = utils.get_frequence(frequence) self.quantiles = quantiles self.bins = bins if isinstance(periods, int): periods = (periods,) self.periods = periods self.binning_by_group = binning_by_group self.max_loss = max_loss self.zero_aware = zero_aware # 因子加工与添加因子远期收益 self.__gen_clean_factor_and_forward_returns()
end=end_date).to_qfq().data # 原始因子产生 kdj = stock_data.groupby("code").apply( QA.QAIndicator.QA_indicator_KDJ).droplevel(level=-1) k_value = kdj["KDJ_K"] d_value = kdj["KDJ_D"] j_value = kdj["KDJ_J"] # 原始因子处理 # 1. 测试 J 值 factor = d_value # 因子格式化: # - 修改因子索引 level 为先日期,后股票代码 # - 修改因子索引名称为 ['datetime', 'code'] factor = preprocess.QA_fmt_factor(factor) # 上市日期过滤:这里使用了聚宽的数据源,需要提前导入聚宽本地数据源 # QA_fetch_get_factor_start_date 做了两件事 # 1. 因子格式化 # 2. 对因子股票池附加上市日期 factor_data = preprocess.QA_fetch_get_factor_start_date(factor) factor_data = factor_data.reset_index() factor_data = factor_data.loc[(factor_data.datetime - factor_data.start_date ) > pd.Timedelta("200D")].set_index( ["datetime", "code"]) factor = factor_data['factor'] # 极值处理,默认使用 "MAD" # QA_winsorize_factor 默认使用 “MAD” 极值处理方式, 按日期分组进行极值处理 factor = preprocess.QA_winsorize_factor(factor)
def __init__( self, factor: Union[pd.Series, pd.DataFrame], prices: Union[pd.Series, pd.DataFrame, Callable], groupby: Union[pd.Series, pd.DataFrame, Callable], stock_start_date: Union[pd.Series, pd.DataFrame, Callable], weights: Union[float, pd.Series, pd.DataFrame, Callable] = 1.0, frequence: str = "DAY", quantiles: Union[int, Tuple[float], List[float]] = 5, bins: Union[int, Tuple[float], List[float]] = None, periods: Union[int, Tuple[int], List[int]] = (1, 5, 10), binning_by_group: bool = False, max_loss: float = 0.25, zero_aware: bool = False, ): """ 初始化输入 参数 --- :param factor: 即经过我们处理过的单因子数据 :param prices: 价格数据 :param groupby: 行业数据 :param stock_start_date: 上市时间 :param weights: 因子加权数据 :param frequence: 因子频率,如果是季线,相应的为 `1q`, 日线,则为 `1d` 等 :param quantiles: 分位处理,既可以是 int 值,将因子等分,也可以是 0 到 1 之间的非等分区间 :param bins: 分位处理,与 `quantiles` 只能有一个为非空 :param periods: 用于计算因子远期收益的期数 :param binning_by_group: 是否按照行业分别进行分位处理 :param max_loss: 在单因子处理时,能够忍受的最大的因子损失 (丢弃的 NaN 值比例) :param zero_aware: 是否按照因子正负值分别进行分位处理 说明: - quantiles 与 bins 只能有一个为非空 """ self.factor = preprocess.QA_fmt_factor(factor) self.prices = prices self.groupby = groupby self.stock_start_date = stock_start_date self.weights = weights self.frequence = utils.get_frequence(frequence) self.quantiles = quantiles self.bins = bins if isinstance(periods, int): periods = (periods,) self.periods = periods self.binning_by_group = binning_by_group self.max_loss = max_loss self.zero_aware = zero_aware # 因子加工与添加因子远期收益 self.__gen_clean_factor_and_forward_returns()
def get_clean_factor_and_forward_returns( factor: Union[pd.Series, pd.DataFrame], prices: Union[pd.Series, pd.DataFrame], groupby: Union[dict, pd.Series, pd.DataFrame], stock_start_date: Union[dict, pd.Series, pd.DataFrame], weights: Union[dict, pd.Series, pd.DataFrame], binning_by_group: bool = False, quantiles: Union[int, Tuple[float], List[float]] = 5, bins: Union[int, Tuple[float], List[float]] = None, periods: Union[int, Tuple[int], List[int]] = (1, 5, 15), max_loss: float = 0.25, zero_aware: bool = False, frequence: str = "1D", ) -> pd.DataFrame: """ 根据输入的因子数据,价格数据,分组数据,加权数据,分位数据等,进行因子数据合成 1. 输入的因子数据如果为: - pd.Series, 则索引应该为 ['日期' '资产'] 的 MultiIndex, 数据为因子的值 - pd.DataFrame, 则索引应该为 ['日期'], 列索引为 ['资产'] 的因子数据透视表 2. 输入的价格数据如果为: - pd.Series, 则索引应该为 ['日期', '资产'] 的 MultiIndex, 数据为价格数据 - pd.DataFrame, 则索引应该为 ['日期'], 列索引为 ['资产'] 的价格透视表 3. 输入的分组信息如果为: - dict, key 应该对应 '资产', value 对应 '行业名称' 或 '行业代码', 默认在所有日期采用同一套数据 - pd.Series, 索引为 ['日期', '资产'] 的 MultiIndex, 数据为行业信息 - pd.DataFrame, 索引为 ['日期'], 列索引为 ['资产'] 的行业信息透视表 4. 输入的权重信息如果为: - dict, key 应该对应 '资产', value 对应加权数据, 默认在所有日期采用同一套数据 - pd.Series, 索引为 ['日期', '资产'] 的 MultiIndex, 数据为加权数据 - pd.DataFrame, 索引为 ['日期'], 列索引为 ['资产'] 的加权数据透视表 参数 --- :param factor: 因子数据,仅包含因子自身值 :param prices: 价格数据,应只含有一种类型价格数据,譬如 'close' 或者 'open' :param groupby: 分组数据, 一般为行业分组 :param stock_start_date: 上市时间 :param weights: 加权数据,一般为市值加权 :param binning_by_group: 是否按照分组进行分位处理 :param quantiles: 分位数据,如果是 int 类型,将因子数据按照每个分组等间隔分位, 否则按照 quantiles 提供的分位数据进行分位, 对应 pd.qcut :param bins: 分位数据,如果是 int 类型,将因子数据按照每个分组等间隔分位, 否则按照 bins 提供的分位数据进行分位,对应 pd.cut :param periods: 远期收益对应的期数 :param max_loss: 因子计算,如果丢弃的因子数据超过该值,抛出异常 :param zero_aware: 如果因子有正负,是否按照正负区间分别进行分位处理 返回值 --- :return: 因子数据,包括因子值,因子远期收益,分位区间,分组,权重 """ # 1. 统一格式 factor = preprocess.QA_fmt_factor(factor) factor = factor.unstack(level="code") if isinstance(prices, pd.Series): prices = prices.unstack(level="code") if isinstance(periods, int): periods = (periods, ) # 2. 获取因子远期收益 forward_returns = get_forward_returns(factor, prices, periods, frequence) # 3. 格式化因子数据 factor_data = get_clean_factor( factor=factor, forward_returns=forward_returns, groupby=groupby, stock_start_date=stock_start_date, weights=weights, quantiles=quantiles, bins=bins, binning_by_group=binning_by_group, max_loss=max_loss, zero_aware=zero_aware, ) return factor_data