Py学习  »  Python

中金固收 | 风格轮动:规律、策略与Python实现

中金点睛 • 2 年前 • 415 次点击  

当固收+的投资者们提到“选结构”,风格的倾向几乎是首要的问题。从去年以来,市场至少经历过大盘成长转向小盘(2021年1月末)、小盘转向大盘价值(2021年10月)两次体感较为明显的风格转向。虽然个股、转债层面还有诸多值得讨论的细节,但风格上站错位置,几乎很难拿回好的回报。而在近期,投资者更加集中关注的,是成长是否有抄底价值。在此,我们基于历史情况和数据分析,给出一些可行的思路。


一、A股特征:趋势与边界并存



两个月窗口,正负20%是关键边际值


我们对近10年的风格相对跑赢幅度进行统计,以上证50和中证1000分别代表大\小盘,国证成长和国证价值代表成长\价值。相对稳定的结论是,两个月窗口下,市场整体的轮动偏移幅度基本在正负20%以内(不考虑2015年那一次过大的波动)。这意味着在统计意义上,正负20%是风格偏移的边际值,若触及则后续大概率会出现均值回归。若进一步细看,正负10%已经具备较大约束力。同时我们发现成长价值的分化较大小盘而言更弱,即使不考虑2014-2015年。但值得注意的是,在来到边界值之前,市场倾向于延续原来的方向。


图表1:股市风格轮动情况(40天涨跌幅差值,单位%)

资料来源:万得资讯,中金公司研究部,注:蓝线代表大票跑赢小票幅度,橙线代表价值跑赢成长幅度



轮动从两象限变为四象限


以2020年为节点,我们进一步观测到在此以前,风格相对跑赢幅度的散点具备较明显的正斜率,这意味着市场整体呈现着“小盘≈成长”、“大盘≈价值”的格局,即轮动是一个两象限互动。而随着2020年以来创业板企业体量明显增长,大盘成长股和小盘价值股的结构性机遇,上图的散点的分散度加剧,市场风格轮动的可能性增多。成为典型的四象限运动,也就是大盘不再与价值挂钩,小盘也不一定就意味着成长——而就实际样本来看,“小盘价值”多为一些小周期股,而这些标的可能股票的覆盖度不高,但却常常作为转债的发行人。


图表2:分年度股市风格轮动情况(2012-2019)

资料来源:万得资讯,中金公司研究部


图表2(续):分年度股市风格轮动情况(2020-2022YTD)

资料来源:万得资讯,中金公司研究部,注:2022年数据截至2022年3月24日



长期趋势偏好成长


而如果我们拉长窗口,能看到成长更容易在长时间窗口占据优势。也即,上述“40交易日20%”的约束关系聚焦于中短期,与更长期限视角下,风格的优劣势具备趋势性不矛盾。但在大小盘中,这样的趋势性则更不明显。


下图则试图说明这个问题:横轴为观测窗口,纵轴为99%的概率下,成长\价值或大盘\小盘的极限跑赢幅度。可以看到,就成长与价值而言,存在时间窗口越大,可能累计的分化越大的情况。而对于大小盘而言,极限分化度不稳定地随窗口扩大而扩大(而图上小盘在100日左右的占优主要来自行情整体强势后,小盘弹性更大,并非严格的风格问题)。


图表3:板块轮动偏离阈值情况(大小盘)

资料来源:万得资讯,中金公司研究部


图表3(续):板块轮动偏离阈值情况(价值成长)

资料来源:万得资讯,中金公司研究部


二、转债与风格轮动的适配度



考虑边界和趋势的转债轮动策略


固收+投资者的一个显著特征是可以用转债补足一些“深挖个股”触及不到的风格。而我们经过测算,风格轮动型策略也与转债的策略相适配。延续上述观察,市场的风格是一个趋势与约束并存的变量,我们很容易得到如下的一个策略:当换仓时,风格偏离未接近阈值时,我们遵循市场风格偏移的势能;若突破阈值,则做反向处理。


具体实现方式上,我们需要下面的辅助函数,以得到当前风格偏移的状态,程序如下。这里相当于生成一个1.a中的图表。实现上没有其他需要注意之处,但为避免后续编号混乱,在设定风格与对应代码的字典时选择了OrderedDict。


图表4:观测板块轮动的基础程序


def getDictPairs():
    return OrderedDict({"BigSmall": ["000016.SH", "000852.SH"],
            "ValueGrowth": ["399371.SZ", "399370.SZ"]})

def divergence(dictPairs, start, end, lstDay=None):
    if lstDay is None:
        lstDay = [40]
    
    lstCodes = []
    for v in dictPairs.values():
        lstCodes += v

    _, dfPct = w.wsd(",".join(lstCodes), "Close", dayOffset(start, -max(lstDay) - 1),
                     end, usedf=True)

    dfRet = pd.DataFrame(index=dfPct.index)

    for n in lstDay:
        for k, v in dictPairs.items():
            dfPctRolling = dfPct.rolling(n).apply(lambda x: 100  * (x[-1] / x[0] - 1))
            dfRet[k + ":{_n} days".format(_n=n)] = dfPctRolling[v[0]] - dfPctRolling[v[1]]
            
    dfRet.index = map(lambda x: x.strftime("%Y/%m/%d"), pd.to_datetime(dfRet.index))
    
    return dfRet.dropna(how="any")

资料来源:万得资讯,中金公司研究部



在选择风格时,我们首先判定其偏移度距离阈值是否较远,然后判定是否超出阈值,按照下图逻辑:


图表5:板块轮动策略逻辑示意

资料来源:万得资讯,中金公司研究部


由于已经设定好偏移数据,这里可以直接进入择券程序,择券框架请见《是时候,选出优秀的策略了》[1]。具体实现较为简单,没有值得特别注意之处。


图表6:具体择券程序


def rotation(obj, codes, date, tempCodes, dfAssetBook):
    # 获取市场风格分化情况.
    if not hasattr(obj, 'divergence'):
        obj.divergence = divergence(dictPairs, start, end)

    # 获取转债标的风格数据,得到dictStyle为字典,共有size和style两个字段,各保存一个表格以注明大小盘、成长价值风格
    if not hasattr(obj, 'dictStyle'):
        obj.dictStyle = getStyle(obj)

    sizeScore, styleScore = obj.divergence.loc[date, ["BigSmall:40 days" ,"ValueGrowth:40 days"]]

    # 获取阈值的相关数据,这里我们采取动态把控,而非定量的阈值
    drSize, drStyle = 1 if sizeScore > 0 else -1,1 if styleScore > 0 else -1
    idx = obj.divergence.index.get_loc(date)
    # theta代表该风格过去1年在40交易日内累计偏移度的95%分位数,epsilon则是这一偏移度绝对值的0.5倍标准差
    # 下面判断当前状态与阈值距离时,则以 score - theta的绝对值是否大于epsilon为准
    thetaSize, thetaStyle = obj.divergence.iloc[idx - 250:idx].abs().quantile(0.95)
    epsilonSize, epsilonStyle = obj.divergence.iloc[idx - 250:idx].abs().std() / 2.
    
    # 经过计算后,下面stylePick的choice将显示为所选风格的字符
    stylePicks = {'size': {'score': sizeScore, 'direction': drSize, 'theta': thetaSize, 'epsilon': epsilonSize,
                           'choice': 0, 'category': ['large', 'small']},
                  'style': {'score': styleScore, 'direction': drStyle, 'theta': thetaStyle, 'epsilon': epsilonStyle,
                            'choice': 0, 'category': ['value', 'growth']}}

    for k, v in stylePicks.items():
        # 判定:当前状态距离阈值是否较远
        if abs(v['score'] - v['theta'] * v['direction']) >= v['epsilon']:
            
            v["choice"] = v["direction"] if abs(v["score"]) < v["theta"] else -v["direction"]

        else:
            v['choice'] = -v['direction']
            
        v['choice'] = v['category'][0] if v['choice'] == 1 else v['category'][1]
    # 这里选择对应风格的品种,取交集
    srs = obj.dictStyle['size'].loc[date, tempCodes] == stylePicks['size']['choice']
    srs *= obj.dictStyle['style'].loc[date, tempCodes] == stylePicks['style']['choice']

    return srs[srs].index

资料来源:万得资讯,中金公司研究部



上述策略的效果我们测算如下:


图表7:策略具体情况

资料来源:万得资讯,中金公司研究部,回测数据自2017年12月29日至2022年4月6日


图表8:策略净值情况

资料来源:万得资讯,中金公司研究部,回测数据自2017年12月29日至2022年4月6日


同时这一策略的“生产率”也相对比较稳定,没有出现某一风格长时间占据主导地位的情况:直观角度来看大票仍然占比不低,因此我们认为加权策略的稳定性具备一定保证。


图表9:策略实际选择板块情况

资料来源:万得资讯,中金公司研究部


三:固收+择股的风格轮动


《再看固收+的绝对收益》[2]中,我们谈到固收+择股普遍具有分散、低估值、近似复制宽基的特性。我们希望借助风格轮动这个话题,再进一步推拟固收+择股还有什么可能性。根据我们测算,按照上述方式直接则股,亦可在250日的滚动窗口下,以接近76%的胜率战胜万得全A。而与债券结合后,在例如简单的股二债八分配下,亦可得到明显的增强效果。投资者可以考虑将股票、转债策略与债券结合,得到更加适合自己的风险回报分布(以下债券市场以债券指数为替代)。


图表10:固收+策略具体情况

资料来源:万得资讯,中金公司研究部,回测数据自2016年12月29日至2022年4月6日


图表11:固收+策略净值情况

资料来源:万得资讯,中金公司研究部,回测数据自2016年12月29日至2022年4月6日

文章来源

本文摘自:2022年4月8日已经发布的《固收+与风格轮动:规律、策略与Python实现

杨 冰 SAC执业证书编号:S0080515120002;SFC CE Ref: BOM868

房 铎 SAC执业证书编号:S0080519110001

罗 凡 SAC执业证书编号:S0080120070107

陈健恒 SAC执业证书编号:S0080511030011;SFC CE Ref: BBM220


法律声明

向上滑动参见完整法律声明及二维码

特别提示

本公众号不是中国国际金融股份有限公司(下称“中金公司”)研究报告的发布平台。本公众号只是转发中金公司已发布研究报告的部分观点,订阅者若使用本公众号所载资料,有可能会因缺乏对完整报告的了解或缺乏相关的解读而对资料中的关键假设、评级、目标价等内容产生理解上的歧义。订阅者如使用本资料,须寻求专业投资顾问的指导及解读。

本公众号所载信息、意见不构成所述证券或金融工具买卖的出价或征价,评级、目标价、估值、盈利预测等分析判断亦不构成对具体证券或金融工具在具体价位、具体时点、具体市场表现的投资建议。该等信息、意见在任何时候均不构成对任何人的具有针对性的、指导具体投资的操作意见,订阅者应当对本公众号中的信息和意见进行评估,根据自身情况自主做出投资决策并自行承担投资风险。

中金公司对本公众号所载资料的准确性、可靠性、时效性及完整性不作任何明示或暗示的保证。对依据或者使用本公众号所载资料所造成的任何后果,中金公司及/或其关联人员均不承担任何形式的责任。

本公众号仅面向中金公司中国内地客户,任何不符合前述条件的订阅者,敬请订阅前自行评估接收订阅内容的适当性。订阅本公众号不构成任何合同或承诺的基础,中金公司不因任何单纯订阅本公众号的行为而将订阅人视为中金公司的客户。

一般声明

本公众号仅是转发中金公司已发布报告的部分观点,所载盈利预测、目标价格、评级、估值等观点的给予是基于一系列的假设和前提条件,订阅者只有在了解相关报告中的全部信息基础上,才可能对相关观点形成比较全面的认识。如欲了解完整观点,应参见中金研究网站(http://research.cicc.com)所载完整报告。

本资料较之中金公司正式发布的报告存在延时转发的情况,并有可能因报告发布日之后的情势或其他因素的变更而不再准确或失效。本资料所载意见、评估及预测仅为报告出具日的观点和判断。该等意见、评估及预测无需通知即可随时更改。证券或金融工具的价格或价值走势可能受各种因素影响,过往的表现不应作为日后表现的预示和担保。在不同时期,中金公司可能会发出与本资料所载意见、评估及预测不一致的研究报告。中金公司的销售人员、交易人员以及其他专业人士可能会依据不同假设和标准、采用不同的分析方法而口头或书面发表与本资料意见不一致的市场评论和/或交易观点。

在法律许可的情况下,中金公司可能与本资料中提及公司正在建立或争取建立业务关系或服务关系。因此,订阅者应当考虑到中金公司及/或其相关人员可能存在影响本资料观点客观性的潜在利益冲突。与本资料相关的披露信息请访http://research.cicc.com/disclosure_cn,亦可参见近期已发布的关于相关公司的具体研究报告。

本订阅号是由中金公司研究部建立并维护的官方订阅号。本订阅号中所有资料的版权均为中金公司所有,未经书面许可任何机构和个人不得以任何形式转发、转载、翻版、复制、刊登、发表、修改、仿制或引用本订阅号中的内容。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/131628
 
415 次点击