14. 绩效分析¶
14.1. Brinson 模型¶
Brinson 和 Falcher(1985年)最早对业绩归因进行研究, 由他们所创建 Brinson 模型将业绩归因为四个部分: 资产配置、个股选择、交互作用和基准收益.
14.1.1. 单期 Brinson 模型¶
当前时刻为 \(t\), 考虑时段 \([t-1, t]\) 上的业绩归因, 假设在 \(t-1\) 构建了投资组合, 且在 \([t-1, t]\) 之间没有交易.
记:
- 业绩基准组合里个股 \(j\) 的权重为 \(w^b_j\), 资产 \(i\) 的权重为 \(W^b_i=\sum\limits_{j\in i}w^b_j\);
- 实际投资组合里个股 \(j\) 的权重为 \(w^p_j\), 资产 \(i\) 的权重为 \(W^p_i=\sum\limits_{j\in i}w^p_j\);
- 个股 \(j\) 的收益率为 \(r_j\).
考虑四个投资组合:
P1: 业绩基准组合: 其中资产 \(i\) 的收益率为:
\[R^b_i=\frac{\sum\limits_{j\in i}w^b_jr_j}{W^b_i}\]
组合收益率:
\[R_{P1} = R_b = \sum\limits_iW^b_iR^b_i=\sum\limits_i\sum\limits_{j\in i}w^b_jr_j\]
P2: 主动资产配置组合: 自主选择资产配置的比例, 但是每个资产类别内部则完全按照其业绩基准配置, 即每个资产 \(i\) 的收益等于在基准中资产 \(i\) 的收益 \(R^b_i\), 而每个资产 i 的权重等于在实际组合中资产 \(i\) 的权重 \(W^p_i\), 则其组合收益率:
\[R_{P2} = \sum\limits_iW^p_iR^b_i=\sum\limits_i\frac{W^p_i}{W^b_i}\sum\limits_{j\in i}w^b_jr_j\]P3: 主动股票选择组合: 完全按照业绩基准进行资产类别的配置, 但是每个资产内部能够自主选择个股, 即组合中每个资产 \(i\) 的权重等于基准中资产 \(i\) 的权重 \(W^b_i\), 每个资产 \(i\) 的收益等于在实际组合中资产 \(i\) 的收益 \(R^p_i\), 则其组合收益率:
\[R_{P3} = \sum\limits_iW^b_iR^p_i=\sum\limits_i\frac{W^b_i}{W^p_i}\sum\limits_{j\in i}w^p_jr_j\]P4: 实际投资组合: 其中资产 \(i\) 的收益率为:
\[R^p_i=\frac{\sum\limits_{j\in i}w^p_jr_j}{W^p_i}\]
组合收益率:
\[R_{P4} = R_p = \sum\limits_iW^p_iR^p_i=\sum\limits_i\sum\limits_{j\in i}w^p_jr_j\]
Brinson 模型将超额收益分解为:
资产配置收益: 由资产配置带来的超额收益, 假设我们能够自主选择决定组合中资产配置的比例, 但是在每一个资产类别内部则完全按照该基准组合配置, 那么该组合的收益率超过基准收益率的部分称为资产配置收益(Return of Asset Allocation):
\[R_{AA} = R_{P2} - R_{P1} = \sum\limits_i(W^p_i-W^b_i)R^b_i\]个股选择收益: 由个股选择而带来的超额收益, 假设我们完全按照基准的比例进行资产类别配置, 但是在每一个资产类别内部则能够自主进行个股选择, 那么该组合的收益率超过基准收益率的部分称为个股选择收益(Return of Stock Selection):
\[R_{SS} = R_{P3} - R_{P1} = \sum\limits_iW^b_i(R^p_i-R^b_i)\]交互作用收益: 由资产配置和个股选择的交互而带来的超额收益, 投资组合的超额收益不仅来自资产配置收益和个股有选择收益, 还有一部分是由于二者的交互作用所带来的收益, 即所谓的交互作用(Interaction):
\[R_{IN} = R_{P4} - R_{P3} - R_{P2} + R_{P1} = \sum\limits_i(W^p_i-W^b_i)(R^p_i-R^b_i)\]
则总超额收益为:
\[R_{p-b} = R_{P4} - R_{P1} = R_{AA} + R_{SS} + R_{IN}\]
而后 Damien Laker 提出资产配置收益的定义可能会带来错误, 故将之修改为:
\[R'_{AA} = R_{AA} - \sum\limits_i(W^p_i-W^b_i)R_b = \sum\limits_i(W^p_i-W^b_i)(R^b_i-R_b)\]
尽管新定义的加入了基准收益, 但由于权重之和都为 1, 所以更改后的资产配置收益和原结果在总和上是相等的, 即 \(R'_{AA}=R_{AA}\). 这两者的差异在于, 原定义强调超额资产配置的收益来源于对收益更高的资产 \(i\) 的超配, 或对收益低的资产 \(j\) 的低配; 而新定义强调对表现优于基准总收益的类别 \(i\) 超配, 或劣于基准总收益的类别 \(j\) 低配, 这种更符合实际.
14.1.2. 多期 Brinson 模型¶
两个计算时点之间没有调整策略持仓, 则计算每一期的 Brinson 模型, 组合多期总收益即是单期收益的按照复利计算的结果:
\[R_p = (1+R_{p,1})(1+R_{p,2})\cdots(1+R_{p,T}) - 1\]
其中, \(R_{p,t}\) 是组合在时段 \([t-1, t]\) 上的收益率.
基准总收益为:
\[R_b = (1+R_{b,1})(1+R_{b,2})\cdots(1+R_{b,T}) - 1\]
其中, \(R_{b,t}\) 是基准在时段 \([t-1, t]\) 上的收益率.
由于复合收益率无法分解为单期收益率的和, 从而考虑对数收益率:
\[\operatorname{log}(1+R_p) - \operatorname{log}(1+R_b) = \sum\limits_{t=1}^{T}\left[\operatorname{log}(1+R_{p,t}) - \operatorname{log}(1+R_{b,t})\right]\]
对于单期有分解:
\[\operatorname{log}(1+R_{p,t}) - \operatorname{log}(1+R_{b,t}) = k_t(R_{p,t} - R_{b,t}) = k_t(R_{AA,t} + R_{SS,t} + R_{IN,t})\]
其中,
\[k_t = \frac{\operatorname{log}(1+R_{p,t}) - \operatorname{log}(1+R_{b,t})}{R_{p,t} - R_{b,t}}\]
从而多期总超额收益有如下分解:
\[\begin{split}\begin{align} R_p - R_b &= \frac{1}{k}(\operatorname{log}(1+R_p) - \operatorname{log}(1+R_b))\operatorname{log}(1+R_{p,t}) \\ &= \frac{1}{k}\sum\limits_{t=1}^{T}\left[\operatorname{log}(1+R_{p,t}) - \operatorname{log}(1+R_{b,t})\right] \\ &= \frac{1}{k}\sum\limits_{t=1}^{T}k_t(R_{p,t} - R_{b,t}) \\ &= \frac{1}{k}\sum\limits_{t=1}^{T}k_t(R_{AA,t} + R_{SS,t} + R_{IN,t}) \\ &= R_{AA} + R_{SS} + R_{IN} \end{align}\end{split}\]
其中:
\[\begin{split}\begin{align} & k = \frac{\operatorname{log}(1+R_p) - \operatorname{log}(1+R_b)}{R_p - R_b} \\ & R_{AA} = \sum\limits_{t=1}^{T}\frac{k_t}{k}R_{AA,t} \\ & R_{SS} = \sum\limits_{t=1}^{T}\frac{k_t}{k}R_{SS,t} \\ & R_{IN} = \sum\limits_{t=1}^{T}\frac{k_t}{k}R_{IN,t} \end{align}\end{split}\]
14.2. 基于特征因子模拟组合的绩效分析模型¶
基于投资组合在不同时点上的实际持仓情况,相对于特定因子组合的暴露程度;投资组合业绩相对于因子组合的暴露情况,可能是随着时间变化的;这个方法的优点是:透明度高;缺点是:数据获取的难度极高。因此,该方法比较适用于基金内部的业绩分析。
横截面回归方程:
\[\mathbf{w}=\mathbf{S}\cdot \mathbf{\beta }+\mathbf{u}\]
其中,\(\mathbf{w}=\left( {{w}_{1}},\ldots ,{{w}_{i}},\ldots ,{{w}_{N}} \right)\) 为策略在某个时点 \(t\) 的实际投资组合,如果考虑相对于某个基准的业绩分析,那么 \(\mathbf{w}\) 为策略的投资组合减去基准的投资组合;对于策略中没有持有的股票,设置其权重为0。
为因子组合构成的矩阵,每一列 \({{\mathbf{s}}_{k}}=\left( {{s}_{1,k}},\ldots ,{{s}_{i,k}},\ldots ,{{s}_{N,k}} \right)\) 代表某个特定因子的特征组合,也成为因子模拟组合(Factor Mimicking Portfolio, FMP),表示为在某个特定因子上暴露为1,在其他因子上暴露为0,并且风险最小化的组合;
\(\mathbf{\beta }=\left( {{\beta }_{1}},\ldots ,{{\beta }_{k}},\ldots ,{{\beta }_{K}} \right)\) 表示策略组合相对于因子模拟组合的暴露水平;
\(\mathbf{u}=\left( {{u}_{1}},\ldots ,{{u}_{i}},\ldots ,{{u}_{N}} \right)\) 为无法被因子解释的部分,被认为是主动投资管理能力(Alpha)。
通过横截面回归,可以得到 \(\mathbf{\beta }\) 的计算公式为:
\[\mathbf{\beta }={{\left( \mathbf{{S}'VS} \right)}^{-1}}\mathbf{{S}'Vw}\]
其中,\(\mathbf{V}={{\left( \operatorname{cov}\left( {{\mathbf{r}}_{i}},{{\mathbf{r}}_{j}} \right) \right)}_{N\times N}}\) 为通过风险模型计算的股票收益率的协方差矩阵。而因子模拟组合矩阵 \(\mathbf{S}\) 的计算公式为:
\[\mathbf{S=}{{\left( {{\left( \mathbf{{X}'}{{\mathbf{V}}^{\mathbf{-1}}}\mathbf{X} \right)}^{\mathbf{-1}}}\mathbf{{X}'}{{\mathbf{V}}^{\mathbf{-1}}} \right)}^{\prime }}\]
其中,\(\mathbf{X}=\left( {{\mathbf{x}}_{1}},\ldots ,{{\mathbf{x}}_{k}},\ldots ,{{\mathbf{x}}_{K}} \right)\) 为个股的因子暴露矩阵,每一列 \({{\mathbf{x}}_{k}}=\left( {{x}_{1,k}},\ldots ,{{x}_{i,k}},\ldots ,{{x}_{N,k}} \right)\) 代表各个股票在特定因子 \(k\) 上的暴露水平。
基于以上的模型,我们可以得到:
- 因子暴露:\(\mathbf{\beta }\)
- 风险调整的因子暴露:\(\operatorname{diag}\left( \sqrt{\mathbf{{S}'VS}} \right)\cdot \mathbf{\beta }\)
- 因子对策略组合的风险贡献:\(\frac{\sqrt{\mathbf{{S}'Vw}}\cdot \mathbf{\beta }}{\sqrt{\mathbf{{w}'Vw}}}\) ,其中,\(\sqrt{\mathbf{{S}'Vw}}\) 与 \(\mathbf{\beta }\) 之间的乘法是对应元素分别相乘。
因子对策略组合的收益贡献:\(\mathbf{r}\cdot \mathbf{\beta }\),该乘法也是对应元素相乘,其中,\(\mathbf{r}=\left( {{r}_{1}},\ldots ,{{r}_{k}},\ldots ,{{r}_{K}} \right)\) 为因子模拟组合在时段 \(\left[ t-1,t \right]\) 上的收益率。
14.3. 绩效分析脚本¶
注意
本章节的应用需要一些基本的数据, 参见 示例数据 的配置.
一个简单的绩效分析脚本如下:
# coding=utf-8
import datetime as dt
if __name__=='__main__':
import QuantStudio.api as QS
HDB = QS.FactorDB.HDF5DB(sys_args={"主目录": "C:\\HDF5Data"})
HDB.connect()
FT = HDB.getTable("ElementaryFactor")
IDs = FT.getID()
DTs = FT.getDateTime(start_dt=dt.datetime(2017, 1, 1), end_dt=dt.datetime(2017, 12, 31))
DTs = QS.Tools.DateTime.getMonthLastDateTime(DTs)
# 创建自定义因子表
CFT = QS.FactorDB.CustomFT("CFT")
Close, AdjFactor = FT.getFactor("收盘价"), FT.getFactor("复权因子")
AdjClose = QS.FactorDB.Factorize(Close * AdjFactor, factor_name="复权收盘价")
CFT.addFactors(factor_list=[AdjClose])
CFT.addFactors(factor_table=FT, factor_names=["Wind行业"], args={})
CFT.addFactors(factor_table=HDB.getTable("IndexConstituentFactor"), factor_names=["中证500成份权重", "中证800成份权重"])
CFT.setDateTime(DTs)
CFT.setID(IDs)
# 创建回测模型
Model = QS.BackTest.BackTestModel()
# 添加回测模块
iModule = QS.BackTest.PerformanceAnalysis.BrinsonModel(factor_table=CFT)
iModule["策略组合"] = "中证500成份权重"
iModule["基准组合"] = "中证800成份权重"
iModule["资产类别"] = "Wind行业"
iModule["价格因子"] = "复权收盘价"
iModule["计算时点"] = DTs
Model.Modules.append(iModule)
# 运行模型
Model.run(dts=DTs)
# 查看结果
QS.Tools.QtGUI.showOutput(Model.output())
因子库和因子表的创建设置, 模型创建以及运行, 结果展示等代码同 因子截面测试脚本 基本相似, 在 QuantStudio 中, 绩效分析模型定义在 BackTest.PerformanceAnalysis 子模块下, 上述例子中使用了 Brinson 模型, 通过 BrinsonModel 类实例化了模块对象, 然后设置了相关参数, 最后添加到 Model 对象中.
14.4. API 参考¶
-
class
BrinsonModel.BrinsonModel(factor_table, name="Brinson绩效分析模型", sys_args={}, **kwargs)¶ Brinson 绩效分析模型, 继承自
BackTestModel.BaseModule参数: - factor_table (FactorTable) – 为该模块提供数据的因子表对象
- name (str) – 模块名称
- sys_args (dict) – 对象参数
-
Args¶ 参数集:
- 策略组合: 提供策略权重信息的因子名, str, 必须为 factor_table 因子表中的因子
- 基准组合: 提供基准权重信息的因子名, str, 必须为 factor_table 因子表中的因子
- 资产类别: 提供 ID 分类信息(比如行业分类)的因子名, str, 必须为 factor_table 因子表中的因子
- 价格因子: 提供价格信息的因子名, str, 必须为 factor_table 因子表中的因子
- 计算时点: 功能计算的时点序列, 只在该序列内的时点进行测试, [datetime.datetime], 默认值 [] 表示所有时点均计算
-
class
FMPModel.FMPModel(factor_table, name="因子模拟组合绩效分析模型", sys_args={}, **kwargs)¶ 基于特征因子模拟组合的绩效分析模型, 继承自
BackTestModel.BaseModule参数: - factor_table (FactorTable) – 为该模块提供数据的因子表对象
- name (str) – 模块名称
- sys_args (dict) – 对象参数
-
Args¶ 参数集:
- 策略组合: 提供策略权重信息的因子名, str, 必须为 factor_table 因子表中的因子
- 基准组合: 提供基准权重信息的因子名, str, 必须为 factor_table 因子表中的因子
- 特征因子: 提供归因特征因子暴露的因子名, [因子], 必须为 factor_table 因子表中的因子
- 行业因子: 提供行业分类信息的因子名, str, 必须为 factor_table 因子表中的因子或者 “无” 表示没有行业因子
- 价格因子: 提供价格信息的因子名, str, 必须为 factor_table 因子表中的因子
- 风险表: 提供风险数据的风险表对象
- 计算时点: 功能计算的时点序列, 只在该序列内的时点进行测试, [datetime.datetime], 默认值 [] 表示所有时点均计算