jqfactor_analyzer源代码解读02

                                            jqfactor_analyzer单因子分析02

首先jqfactor_analyzer源代码解读01中已经得到了self._clean_factor_data(注意binning_by_group参数的使用)

                                                                   (self._clean_factor_data)

                                                          收益分析

  • # 收益能力速览
    far.plot_returns_table(demeaned=False, group_adjust=False)

找到相关函数

def plot_returns_table(self, demeaned=False, group_adjust=False):
        """打印因子收益表

        参数:
        demeaned:
        - True: 使用超额收益计算 (基准收益被认为是每日所有股票收益按照weight列中权重的加权的均值)
        - False: 不使用超额收益
        group_adjust:
        - True: 使用行业中性收益 (行业收益被认为是每日各个行业股票收益按照weight列中权重的加权的均值)
        - False: 不使用行业中性收益
        """
        mean_return_by_quantile = self.calc_mean_return_by_quantile(
            by_date=False, by_group=False,
            demeaned=demeaned, group_adjust=group_adjust,
        )[0].apply(rate_of_return, axis=0)

        mean_returns_spread, _ = self.compute_mean_returns_spread(
            upper_quant=self._factor_quantile,
            lower_quant=1,
            by_date=True,
            by_group=False,
            demeaned=demeaned,
            group_adjust=group_adjust,
        )

        pl.plot_returns_table(
            self.calc_factor_alpha_beta(demeaned=demeaned),
            mean_return_by_quantile,
            mean_returns_spread
        )

alpha,bata相关的函数

def factor_returns(factor_data, demeaned=True, group_adjust=False):
    """
    计算按因子值加权的投资组合的收益
    权重为去均值的因子除以其绝对值之和 (实现总杠杆率为1).

    参数
    ----------
    factor_data : pd.DataFrame - MultiIndex
        一个 DataFrame, index 为日期 (level 0) 和资产(level 1) 的 MultiIndex,
        values 包括因子的值, 各期因子远期收益, 因子分位数,
        因子分组(可选), 因子权重(可选)
    demeaned : bool
        因子分析是否基于一个多空组合? 如果是 True, 则计算权重时因子值需要去均值
    group_adjust : bool
        因子分析是否基于一个分组(行业)中性的组合?
        如果是 True, 则计算权重时因子值需要根据分组和日期去均值

    返回值
    -------
    returns : pd.DataFrame
        每期零风险暴露的多空组合收益
    """

    def to_weights(group, is_long_short):
        if is_long_short:
            demeaned_vals = group - group.mean()
            return demeaned_vals / demeaned_vals.abs().sum()
        else:
            return group / group.abs().sum()

    grouper = [factor_data.index.get_level_values('date')]
    if group_adjust:
        grouper.append('group')

    weights = factor_data.groupby(grouper)['factor'] \
        .apply(to_weights, demeaned)

    if not group_adjust:
        weights = weights.groupby(level='date').apply(to_weights,demeaned)

    weighted_returns = \
        factor_data[get_forward_returns_columns(factor_data.columns)] \
        .multiply(weights, axis=0)

    returns = weighted_returns.groupby(level='date').sum()

    return returns


def factor_alpha_beta(factor_data, demeaned=True, group_adjust=False):
    """
    计算因子的alpha(超额收益),
    alpha t-统计量 (alpha 显著性)和 beta(市场暴露).
    使用每期平均远期收益作为自变量(视为市场组合收益)
    因子值加权平均的远期收益作为因变量(视为因子收益), 进行回归.

    Parameters
    ----------
    factor_data : pd.DataFrame - MultiIndex
        一个 DataFrame, index 为日期 (level 0) 和资产(level 1) 的 MultiIndex,
        values 包括因子的值, 各期因子远期收益, 因子分位数,
        因子分组(可选), 因子权重(可选)
    demeaned : bool
        因子分析是否基于一个多空组合? 如果是 True, 则计算权重时因子值需要去均值
    group_adjust : bool
        因子分析是否基于一个分组(行业)中性的组合?
        如果是 True, 则计算权重时因子值需要根据分组和日期去均值
    Returns
    -------
    alpha_beta : pd.Series
        一个包含 alpha, beta, a t-统计量(alpha) 的序列
    """

    returns = factor_returns(factor_data, demeaned, group_adjust)

    universe_ret = factor_data.groupby(level='date')[
        get_forward_returns_columns(factor_data.columns)] \
        .mean().loc[returns.index]

    if isinstance(returns, pd.Series):
        returns.name = universe_ret.columns.values[0]
        returns = pd.DataFrame(returns)

    alpha_beta = pd.DataFrame()
    for period in returns.columns.values:
        x = universe_ret[period].values
        y = returns[period].values
        #加入常数项
        x = add_constant(x)
        #期数
        period_int = int(period.replace('period_', ''))

        reg_fit = OLS(y, x).fit()
        alpha, beta = reg_fit.params
        
        #年化
        alpha_beta.loc['Ann. alpha', period] = \
            (1 + alpha) ** (250.0 / period_int) - 1
        alpha_beta.loc['beta', period] = beta

    return alpha_beta

函数calc_mean_return_by_quantile(self, by_date=False, by_group=False, demeaned=False, group_adjust=False)

demeaned:
        - True: 使用超额收益计算各分位数收益,超额收益=收益-基准收益
                (基准收益被认为是每日所有股票收益按照weight列中权重的加权的均值)
        - False: 不使用超额收益

group_adjust:
        - True: 使用行业中性收益计算各分位数收益,行业中性收益=收益-行业收益
                (行业收益被认为是每日各个行业股票收益按照weight列中权重的加权的均值)
        - False: 不使用行业中性收益

                                                                               (returns)

函数factor_returns(factor_data, demeaned=True, group_adjust=False)中参数demeaned(因子分析是否基于一个多空组合? 如果是 True, 则计算权重时因子值需要去均值)。对权重去均值 (每日权重 = 每日权重 - 每日权重的均值), 使组合转换为 cash-neutral 多空组合。伪代码:

demeaned_vals = group - group.mean(),return demeaned_vals / demeaned_vals.abs().sum()

group_adjust是常见参数(因子分析是否基于一个分组(行业)中性的组合?如果是 True, 则计算权重时因子值需要根据分组和日期去均值)对权重分行业去均值 (每日权重 = 每日权重 - 每日各行业权重的均值),使组合转换为 industry-neutral 多空组合

收益(returns) = 因子N期收益 x 权重(weights)注意:这里的weights指的是根据因子值来计算的,并不是指self._clean_factor_data中的weights列

函数factor_alpha_beta(factor_data, demeaned=True, group_adjust=False)中alpha和beta线性回归后的斜率和截距

reg_fit = OLS(y, x).fit(),alpha, beta = reg_fit.params

x:因子N期收益按[日期]分组的均值        y:函数factor_returns(factor_data, demeaned=True, group_adjust=False)中的returns

疑问:#年化alpha_beta.loc['Ann. alpha', period] = (1 + alpha) ** (250.0 / period_int) - 1。这个alpha还需要年化?!

  • # 画各分位数平均收益图
    far.plot_quantile_returns_bar(by_group=False, demeaned=False, group_adjust=False)

找到相关函数

def plot_quantile_returns_bar(self, by_group=False,
                                  demeaned=False, group_adjust=False):
        """画各分位数平均收益图

        参数:
        by_group:
        - True: 各行业的各分位数平均收益图
        - False: 各分位数平均收益图
        demeaned:
        - True: 使用超额收益计算累积收益 (基准收益被认为是每日所有股票收益按照weight列中权重加权的均值)
        - False: 不使用超额收益
        group_adjust:
        - True: 使用行业中性化后的收益计算累积收益
                (行业收益被认为是每日各个行业股票收益按照weight列中权重加权的均值)
        - False: 不使用行业中性化后的收益
        """
        mean_return_by_quantile = self.calc_mean_return_by_quantile(
            by_date=False, by_group=by_group,
            demeaned=demeaned, group_adjust=group_adjust,
        )[0].apply(rate_of_return, axis=0)

        pl.plot_quantile_returns_bar(
            mean_return_by_quantile, by_group=by_group, ylim_percentiles=None
        )

def calc_mean_return_by_quantile(self, by_date=False, by_group=False,
                                     demeaned=False, group_adjust=False):
        """计算按分位数分组因子收益和标准差

        因子收益为收益按照 weight 列中权重的加权平均值

        参数:
        by_date:
        - True: 按天计算收益
        - False: 不按天计算收益
        by_group:
        - True: 按行业计算收益
        - False: 不按行业计算收益
        demeaned:
        - True: 使用超额收益计算各分位数收益,超额收益=收益-基准收益
                (基准收益被认为是每日所有股票收益按照weight列中权重的加权的均值)
        - False: 不使用超额收益
        group_adjust:
        - True: 使用行业中性收益计算各分位数收益,行业中性收益=收益-行业收益
                (行业收益被认为是每日各个行业股票收益按照weight列中权重的加权的均值)
        - False: 不使用行业中性收益
        """
        return pef.mean_return_by_quantile(self._clean_factor_data,
                                           by_date=by_date,
                                           by_group=by_group,
                                           demeaned=demeaned,
                                           group_adjust=group_adjust)


def mean_return_by_quantile(
    factor_data,
    by_date=False,
    by_group=False,
    demeaned=True,
    group_adjust=False
):
    """
    计算各分位数的因子远期收益均值和标准差

    参数
    ----------
    factor_data : pd.DataFrame - MultiIndex
        一个 DataFrame, index 为日期 (level 0) 和资产(level 1) 的 MultiIndex,
        values 包括因子的值, 各期因子远期收益, 因子分位数,
        因子分组(可选), 因子权重(可选)
    by_date : bool
        如果为 True, 则按日期计算各分位数的因子远期收益均值
    by_group : bool
        如果为 True, 则分组计算各分位数的因子远期收益均值
    demeaned : bool
        是否按日期对因子远期收益去均值
    group_adjust : bool
        是否按日期和分组对因子远期收益去均值
    Returns
    -------
    mean_ret : pd.DataFrame
        各分位数因子远期收益均值
    std_error_ret : pd.DataFrame
        各分位数因子远期收益标准差
    """

    if group_adjust:
        grouper = [factor_data.index.get_level_values('date')] + ['group']
        factor_data = demean_forward_returns(factor_data, grouper)
    elif demeaned:
        factor_data = demean_forward_returns(factor_data)
    else:
        factor_data = factor_data.copy()

    grouper = ['factor_quantile']
    if by_date:
        grouper.append(factor_data.index.get_level_values('date'))

    if by_group:
        grouper.append('group')

    mean_ret, std_error_ret = weighted_mean_return(factor_data, grouper=grouper)

    return mean_ret, std_error_ret

def demean_forward_returns(factor_data, grouper=None):
    """
    根据相关分组为因子远期收益去均值.
    分组去均值包含了投资组合分组中性化约束的假设,因此允许跨组评估因子.

    Parameters
    ----------
    factor_data : pd.DataFrame - MultiIndex
        因子远期收益
        index 为日期 (level 0) 和资产(level 1) 的 MultiIndex
        column 为远期收益的期数
    grouper : list
        如果为 None, 则只根据日期去均值
        否则则根据列表中提供的组分组去均值

    返回值
    -------
    adjusted_forward_returns : pd.DataFrame - MultiIndex
        和 factor_data 相同形状的 DataFrame, 但每个收益都被分组去均值了
    """

    factor_data = factor_data.copy()

    if not grouper:
        grouper = factor_data.index.get_level_values('date')

    cols = get_forward_returns_columns(factor_data.columns)
    factor_data[cols] = factor_data.groupby(
        grouper, as_index=False
    )[cols.append(pd.Index(['weights']))].apply(
        lambda x: x[cols].subtract(
            np.average(x[cols], axis=0, weights=x['weights'].fillna(0.0).values),
            axis=1
        )
    )

    return factor_data

def weighted_mean_return(factor_data, grouper):
    """计算(年化)加权平均/标准差"""
    forward_returns_columns = get_forward_returns_columns(factor_data.columns)

    def agg(values, weights):
        count = len(values)
        average = np.average(values, weights=weights, axis=0)
        # Fast and numerically precise
        variance = np.average(
            (values - average)**2, weights=weights, axis=0
        ) * count / max((count - 1), 1)
        return pd.Series(
            [average, np.sqrt(variance), count], index=['mean', 'std', 'count']
        )

    group_stats = factor_data.groupby(grouper)[
        forward_returns_columns.append(pd.Index(['weights']))] \
        .apply(lambda x: x[forward_returns_columns].apply(
            agg, weights=x['weights'].fillna(0.0).values
        ))

    mean_ret = group_stats.xs('mean', level=-1)

    std_error_ret = group_stats.xs('std', level=-1) \
        / np.sqrt(group_stats.xs('count', level=-1))

    return mean_ret, std_error_ret

def rate_of_return(period_ret):
    """
    转换回报率为"每期"回报率:如果收益以稳定的速度增长, 则相当于每期的回报率
    """
    period = int(period_ret.name.replace('period_', ''))
    return period_ret.add(1).pow(1. / period).sub(1)

函数调用顺序:def calc_mean_return_by_quantile(self, by_date=False, by_group=False,demeaned=False, group_adjust=False)到def mean_return_by_quantile(factor_data,by_date=False,by_group=False,demeaned=True,
group_adjust=False)到def demean_forward_returns(factor_data, grouper=None)到def weighted_mean_return(factor_data, grouper)到def rate_of_return(period_ret)

首先在mean_return_by_quantile(函数中若demeaned或者 group_adjust为True,则调用函数demean_forward_returns(根据相关分组为因子远期收益去均值。分组去均值包含了投资组合分组中性化约束的假设,因此允许跨组评估因子))重新计factor_data中的远期收益。然后按照['factor_quantile']或者['factor_quantile','group']的分组在函数weighted_mean_return中计算平均收益率和方差。最后调用函数rate_of_return(转换回报率为"每期"回报率:如果收益以稳定的速度增长, 则相当于每期的回报率)计算每天收益率。

                                  (mean_ret)                                                                                       (std_error_ret)

             

  • # 各分位数累计收益率图
    far.plot_cumulative_returns_by_quantile(period=periods, demeaned=0, group_adjust=False)

找到相关函数

def plot_cumulative_returns_by_quantile(self, period=None, demeaned=False,
                                            group_adjust=False):
        """画各分位数每日累积收益图

        参数:
        period: 调仓周期
        demeaned:
        详见 calc_mean_return_by_quantile 中 demeaned 参数
        - True: 使用超额收益计算累积收益 (基准收益被认为是每日所有股票收益按照weight列中权重加权的均值)
        - False: 不使用超额收益
        group_adjust:
        详见 calc_mean_return_by_quantile 中 group_adjust 参数
        - True: 使用行业中性化后的收益计算累积收益
                (行业收益被认为是每日各个行业股票收益按照weight列中权重加权的均值)
        - False: 不使用行业中性化后的收益
        """
        if period is None:
            period = self._periods
        if not isinstance(period, Iterable):
            period = (period,)
        period = tuple(period)
        mean_return_by_date, _ = self.calc_mean_return_by_quantile(
            by_date=True, by_group=False, demeaned=demeaned, group_adjust=group_adjust,
        )
        for p in period:
            if p in self._periods:
                pl.plot_cumulative_returns_by_quantile(
                    mean_return_by_date[convert_to_forward_returns_columns(p)],
                    period=p
                )

def calc_mean_return_by_quantile(self, by_date=False, by_group=False,
                                     demeaned=False, group_adjust=False):
        """计算按分位数分组因子收益和标准差

        因子收益为收益按照 weight 列中权重的加权平均值

        参数:
        by_date:
        - True: 按天计算收益
        - False: 不按天计算收益
        by_group:
        - True: 按行业计算收益
        - False: 不按行业计算收益
        demeaned:
        - True: 使用超额收益计算各分位数收益,超额收益=收益-基准收益
                (基准收益被认为是每日所有股票收益按照weight列中权重的加权的均值)
        - False: 不使用超额收益
        group_adjust:
        - True: 使用行业中性收益计算各分位数收益,行业中性收益=收益-行业收益
                (行业收益被认为是每日各个行业股票收益按照weight列中权重的加权的均值)
        - False: 不使用行业中性收益
        """
        return pef.mean_return_by_quantile(self._clean_factor_data,
                                           by_date=by_date,
                                           by_group=by_group,
                                           demeaned=demeaned,
                                           group_adjust=group_adjust)

def mean_return_by_quantile(
    factor_data,
    by_date=False,
    by_group=False,
    demeaned=True,
    group_adjust=False
):
    """
    计算各分位数的因子远期收益均值和标准差

    参数
    ----------
    factor_data : pd.DataFrame - MultiIndex
        一个 DataFrame, index 为日期 (level 0) 和资产(level 1) 的 MultiIndex,
        values 包括因子的值, 各期因子远期收益, 因子分位数,
        因子分组(可选), 因子权重(可选)
    by_date : bool
        如果为 True, 则按日期计算各分位数的因子远期收益均值
    by_group : bool
        如果为 True, 则分组计算各分位数的因子远期收益均值
    demeaned : bool
        是否按日期对因子远期收益去均值
    group_adjust : bool
        是否按日期和分组对因子远期收益去均值
    Returns
    -------
    mean_ret : pd.DataFrame
        各分位数因子远期收益均值
    std_error_ret : pd.DataFrame
        各分位数因子远期收益标准差
    """

    if group_adjust:
        grouper = [factor_data.index.get_level_values('date')] + ['group']
        factor_data = demean_forward_returns(factor_data, grouper)
    elif demeaned:
        factor_data = demean_forward_returns(factor_data)
    else:
        factor_data = factor_data.copy()

    grouper = ['factor_quantile']
    if by_date:
        grouper.append(factor_data.index.get_level_values('date'))

    if by_group:
        grouper.append('group')

    mean_ret, std_error_ret = weighted_mean_return(factor_data, grouper=grouper)

    return mean_ret, std_error_ret

def demean_forward_returns(factor_data, grouper=None):
    """
    根据相关分组为因子远期收益去均值.
    分组去均值包含了投资组合分组中性化约束的假设,因此允许跨组评估因子.

    Parameters
    ----------
    factor_data : pd.DataFrame - MultiIndex
        因子远期收益
        index 为日期 (level 0) 和资产(level 1) 的 MultiIndex
        column 为远期收益的期数
    grouper : list
        如果为 None, 则只根据日期去均值
        否则则根据列表中提供的组分组去均值

    返回值
    -------
    adjusted_forward_returns : pd.DataFrame - MultiIndex
        和 factor_data 相同形状的 DataFrame, 但每个收益都被分组去均值了
    """

    factor_data = factor_data.copy()

    if not grouper:
        grouper = factor_data.index.get_level_values('date')

    cols = get_forward_returns_columns(factor_data.columns)
    factor_data[cols] = factor_data.groupby(
        grouper, as_index=False
    )[cols.append(pd.Index(['weights']))].apply(
        lambda x: x[cols].subtract(
            np.average(x[cols], axis=0, weights=x['weights'].fillna(0.0).values),
            axis=1
        )
    )

    return factor_data

def weighted_mean_return(factor_data, grouper):
    """计算(年化)加权平均/标准差"""
    forward_returns_columns = get_forward_returns_columns(factor_data.columns)

    def agg(values, weights):
        count = len(values)
        average = np.average(values, weights=weights, axis=0)
        # Fast and numerically precise
        variance = np.average(
            (values - average)**2, weights=weights, axis=0
        ) * count / max((count - 1), 1)
        return pd.Series(
            [average, np.sqrt(variance), count], index=['mean', 'std', 'count']
        )

    group_stats = factor_data.groupby(grouper)[
        forward_returns_columns.append(pd.Index(['weights']))] \
        .apply(lambda x: x[forward_returns_columns].apply(
            agg, weights=x['weights'].fillna(0.0).values
        ))

    mean_ret = group_stats.xs('mean', level=-1)

    std_error_ret = group_stats.xs('std', level=-1) \
        / np.sqrt(group_stats.xs('count', level=-1))

    return mean_ret, std_error_ret

函数调用顺序:def calc_mean_return_by_quantile(self, by_date=False, by_group=False,demeaned=False, group_adjust=False)到def mean_return_by_quantile(factor_data,by_date=False,by_group=False,demeaned=True,
group_adjust=False)到def demean_forward_returns(factor_data, grouper=None)到def weighted_mean_return(factor_data, grouper)

首先calc_mean_return_by_quantile(by_date=True, by_group=False, demeaned=demeaned, group_adjust=group_adjust, )中参数by_date=True, by_group=False已经默认了,所以是按照['factor_quantile','data']的分组在函数weighted_mean_return中计算平均收益率和方差的。

                                                                                           (mean_ret)

  • # 打印信息比率(IC)相关表
    far.plot_information_table(group_adjust=False, method='rank')

查找相关的函数

def plot_information_table(self, group_adjust=False, method=None):
        """打印信息比率 (IC)相关表

        参数:
        group_adjust:
        - True:使用行业中性收益 (行业收益被认为是每日各个行业股票收益按照weight列中权重的加权的均值)
        - False:不使用行业中性收益
        method:
        - 'rank':用秩相关系数计算IC值
        - 'normal':用相关系数计算IC值
        """
        ic = self.calc_factor_information_coefficient(
            group_adjust=group_adjust,
            by_group=False,
            method=method
        )
        pl.plot_information_table(ic)


def calc_factor_information_coefficient(self, group_adjust=False, by_group=False, method=None):
        """计算每日因子信息比率 (IC值)

        参数:
        group_adjust:
        - True: 使用行业中性收益计算 IC (行业收益被认为是每日各个行业股票收益按照weight列中权重加权的均值)
        - False: 不使用行业中性收益
        by_group:
        - True: 分行业计算 IC
        - False: 不分行业计算 IC
        method:
        - 'rank': 用秩相关系数计算IC值
        - 'normal': 用普通相关系数计算IC值
        """
        if method is None:
            method = 'rank'
        if method not in ('rank', 'normal'):
            raise ValueError("`method` should be chosen from ('rank' | 'normal')")

        if method == 'rank':
            method = spearmanr
        elif method == 'normal':
            method = pearsonr
        return pef.factor_information_coefficient(self._clean_factor_data,
                                                  group_adjust=group_adjust,
                                                  by_group=by_group,
                                                  method=method)

def factor_information_coefficient(
    factor_data, group_adjust=False, by_group=False, method=stats.spearmanr
):
    """
    通过因子值与因子远期收益计算信息系数(IC).
    
    参数
    ----------
    factor_data : pd.DataFrame - MultiIndex
        一个 DataFrame, index 为日期 (level 0) 和资产(level 1) 的 MultiIndex,
        values 包括因子的值, 各期因子远期收益, 因子分位数factor_quantile,
        因子分组group(可选), 因子权重weights(可选)
    group_adjust : bool
        是否使用分组去均值后的因子远期收益计算 IC.
    by_group : bool
        是否分组计算 IC.
    Returns
    -------
    ic : pd.DataFrame
        因子信息系数(IC).
    """

    def src_ic(group):
        f = group['factor']
        _ic = group[get_forward_returns_columns(factor_data.columns)] \
            .apply(lambda x: method(x, f)[0])
        return _ic

    factor_data = factor_data.copy()

    grouper = [factor_data.index.get_level_values('date')]

    if group_adjust:
        factor_data = demean_forward_returns(factor_data, grouper + ['group'])
    if by_group:
        grouper.append('group')
        
    #with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等
    with np.errstate(divide='ignore', invalid='ignore'):
        ic = factor_data.groupby(grouper).apply(src_ic)

    return ic

函数调用顺序:plot_information_table(self, group_adjust=False, method=None)到calc_factor_information_coefficient(self, group_adjust=False, by_group=False, method=None)到factor_information_coefficient(factor_data, group_adjust=False, by_group=False, method=stats.spearmanr)。

三个函数中默认by_group=False默认不进行按行业分组。参数group_adjust(是否使用分组去均值后的因子远期收益计算 IC)如果为True,则调用函数demean_forward_returns(factor_data, grouper + ['group'])重新计算factor_data中的N期收益。在函数factor_information_coefficient(factor_data, group_adjust=False, by_group=False, method=stats.spearmanr)中通过['data']或者['data','group']进行分组计算IC。

                                                                                            (IC)

  • # 打印换手率表
    far.plot_turnover_table()

查找相关函数

def plot_turnover_table(self):
        """打印换手率表"""
        pl.plot_turnover_table(
            self.calc_autocorrelation(),
            self.quantile_turnover
        )

def calc_autocorrelation(self, rank=True):
        """根据调仓周期确定滞后期的每天计算因子自相关性

        当日因子值和滞后period天的因子值的自相关性

        参数:
        rank:
        - True: 秩相关系数
        - False: 普通相关系数
        """
        return pd.concat(
            [
                pef.factor_autocorrelation(self._clean_factor_data,
                                           period, rank=rank)
                for period in self._periods
            ],
            axis=1,
            keys=list(map(convert_to_forward_returns_columns, self._periods))
        )

def factor_autocorrelation(factor_data, period=1, rank=True):
    """
    计算指定时间跨度内平均因子排名/因子值的自相关性.
    该指标对于衡量因子的换手率非常有用.
    如果每个因子值在一个周期内随机变化,我们预计自相关为 0.

    参数
    ----------
    factor_data : pd.DataFrame - MultiIndex
        一个 DataFrame, index 为日期 (level 0) 和资产(level 1) 的 MultiIndex,
        values 包括因子的值, 各期因子远期收益, 因子分位数,
        因子分组(可选), 因子权重(可选)
    period: int, optional
        对应的因子远期收益时间跨度
    Returns
    -------
    autocorr : pd.Series
        滞后一期的因子自相关性
    """

    grouper = [factor_data.index.get_level_values('date')]

    #排序
    if rank:
        ranks = factor_data.groupby(grouper)[['factor']].rank()
    else:
        ranks = factor_data[['factor']]
    
    asset_factor_rank = ranks.reset_index().pivot(
        index='date', columns='asset', values='factor'
    )

    autocorr = asset_factor_rank.corrwith(
        asset_factor_rank.shift(period), axis=1
    )
    autocorr.name = period
    return autocorr

def quantile_turnover(self):
        """换手率分析

        返回值一个 dict, key 是 period, value 是一个 DataFrame(index 是日期, column 是分位数)
        """

        quantile_factor = self._clean_factor_data['factor_quantile']

        quantile_turnover_rate = {
            convert_to_forward_returns_columns(p):
            pd.concat([pef.quantile_turnover(quantile_factor, q, p)
                       for q in range(1, int(quantile_factor.max()) + 1)],
                      axis=1)
            for p in self._periods
        }

        return quantile_turnover_rate

def quantile_turnover(quantile_factor, quantile, period=1):
    """
    计算当期在分位数中的因子不在上一期分位数中的比例

    Parameters
    ----------
    quantile_factor : pd.Series
        包含日期, 资产, 和因子分位数的 DataFrame.
    quantile : int
        对应的分位数
    period: int, optional
        对应的因子远期收益时间跨度
    Returns
    -------
    quant_turnover : pd.Series
        每期对饮分位数因子的换手率
    """

    quant_names = quantile_factor[quantile_factor == quantile]
    quant_name_sets = quant_names.groupby(
        level=['date']
    ).apply(lambda x: set(x.index.get_level_values('asset')))
    new_names = (quant_name_sets - quant_name_sets.shift(period)).dropna()
    quant_turnover = new_names.apply(lambda x: len(x)) / quant_name_sets.apply(
        lambda x: len(x)
    )
    quant_turnover.name = quantile
    return quant_turnover

其一:函数def plot_turnover_table(self)到def calc_autocorrelation(self, rank=True)到def factor_autocorrelation(factor_data, period=1, rank=True)。上述三个函数中参数没有需要特别留意的, 函数calc_autocorrelation(根据调仓周期确定滞后期的每天计算因子自相关性,当日因子值和滞后period天的因子值的自相关性)肯定是按['date']分组进行计算的。

                                                                         (autocorr)

其二:函数plot_turnover_table(self)到def quantile_turnover(self)到def quantile_turnover(quantile_factor, quantile, period=1)参数方面没有需要特别注意的。函数def quantile_turnover(quantile_factor, quantile, period=1)按照日期分组计算当期在分位数中的因子不在上一期分位数中的比例。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值