jqfactor_analyzer
jqfactor_analyzer copied to clipboard
calc_top_down_cumulative_returns 错误
def calc_top_down_cumulative_returns(self, period=None,
demeaned=False, group_adjust=False):
if period is None:
period = self._periods[0]
period_col = convert_to_forward_returns_columns(period)
mean_returns, _ = self.calc_mean_return_by_quantile(
by_date=True, by_group=False,
demeaned=demeaned, group_adjust=group_adjust,
)
mean_returns = mean_returns.apply(rate_of_return, axis=0)
# period>1时,这里重复计算了。rate_of_return取了一次(1/N)次幂
# 然后performance.cumulative_returns里又取了一次(1/N)次幂
# 计算因子加权、分位数累计收益时,没有这个问题。只有top-down的多算了一次
# 见图,纵坐标差太多
upper_quant = mean_returns[period_col].xs(self._factor_quantile,
level='factor_quantile')
lower_quant = mean_returns[period_col].xs(1,
level='factor_quantile')
return pef.cumulative_returns(upper_quant - lower_quant, period=period)
def rate_of_return(period_ret):
period = int(period_ret.name.replace('period_', ''))
return period_ret.add(1).pow(1. / period).sub(1)
def cumulative_returns(returns, period):
returns = returns.fillna(0)
if period == 1:
return returns.add(1).cumprod()
#
# 构建 N 个交错的投资组合
#
def split_portfolio(ret, period):
return pd.DataFrame(np.diag(ret))
sub_portfolios = returns.groupby(
np.arange(len(returns.index)) // period, axis=0
).apply(split_portfolio, period)
sub_portfolios.index = returns.index
#
# 将 N 期收益转换为 1 期收益, 方便计算累积收益
#
def rate_of_returns(ret, period):
return ((np.nansum(ret) + 1)**(1. / period)) - 1
sub_portfolios = rolling_apply(
sub_portfolios,
window=period,
func=rate_of_returns,
min_periods=1,
args=(period,)
)
sub_portfolios = sub_portfolios.add(1).cumprod()
#
# 求 N 个投资组合累积收益均值
#
return sub_portfolios.mean(axis=1)