利用Calmar指标捕捉期间强势股

de1a96a2262613ced135b4c8931b81cc.gif

引言

卡玛比率(Calmar Ratio) 与夏普比率类似,本来是用来衡量基金业绩表现的指标,描述的是收益和最大回撤之间的关系。计算方式比较简单,为年化收益率与历史最大回撤之间的比率。Calmar比率数值越大,基金的业绩表现越好;反之,基金的业绩表现越差。和夏普比率不同的是,卡玛比率是用最大回撤衡量风险,用年化收益率衡量收益。相比标准差,最大回撤能更准确地衡量基金的风险,尤其控制回撤的能力,因此这个指标又被称为夏普比率的“进阶版”。下面基于沪深京A股数据,使用区间(如20、60、120、200日)收益率和区间最大回撤的比值来衡量Calmar比率,根据结果进行排序,筛选区间强势股。以下选股标的仅供学习参考,不构成任何投资建议,交易有风险,投资需谨慎。

a5eb260ccab472f62430ef1ab422785d.gif

数据获取

下面使用公众号开发的qstock包获取A股市场全部个股的收盘价作为分析样本,qstock基于多线程优点是获取数据非常快,缺点是某些线程可能卡死导致某些个股获取数据失败。大家也可以使用akshare接口替代。

import qstock as qs
import pandas as pd
#获取沪深全市场A股代码
codes=qs.get_code()
#获取沪深全市场A股2020年以来后复权价格数据
#剔除观察值不足250交易日个股
#当网络不太稳定时,可能获取不到全部数据或报错
prices=qs.get_price(code_list=codes,start='20210101',fqt=2)[-250:].dropna(axis=1)

运行结果:
    84%|███████████████████████ | 4283/5116 [01:17<00:15, 55.30it/s]

prices.tail()

4f01912a3a2db870230576f04992c2b0.jpeg

由于网络或其他原因,使用多线程只获取了4283只个股收盘价数据(占比84%),剔除观测值少于250的样本只剩3626只个股。如果想获取全部A股数据,可以使用akshare接口,但时间比较长,约30分钟左右,具体看get_price2函数。

#如果无法获取全部A股数据,可以使用akshare接口,但时间比较长,约30分钟左右
from tqdm import tqdm
import akshare as ak

def get_price2(code_list, start='20210101', end='20230207', freq='d', fqt=1):
    '''code_list输入股票list列表
    如code_list=['中国平安','贵州茅台','工业富联']
    '''
    def run(code):
        try:
            temp = ak.stock_zh_a_hist(symbol="300114", period="daily", start_date=start, end_date=end, adjust="hfq")
            temp[str(code)]=temp['收盘']
            data_list.append(temp[str(code)])
            pbar.update()
        except:
            pass
    data_list = []
    for code in tqdm(code_list):
        try:
            run(code)
        except:
            continue
    # 转换为dataframe
    df = pd.concat(data_list, axis=1)
    return df
#使用akshare接口获取全部收盘价数据
#prices2=get_price2(codes)

7a4a6105e25b6ae7fa878edf8e4c0e1d.gif

Calmar比率计算与探索性分析

先以250个交易日为区间考察一下截面价格动量(期间累计收益率)与风险(期间最大回撤)的统计分布特点和相关关系。

#计算kama比率:即期间收益率除以最大回撤
def calmar(s):
    ret=(s/s.iloc[0]-1).iloc[-1]
    drawdown=(1-s/s.cummax()).max()
    kama=ret/drawdown
    return kama
data=prices[-250:].dropna(axis=1)
rets=data.apply(lambda s:(s/s[0]-1)[-1])
drawdowns=data.apply(lambda s:(1-s/s.cummax()).max())
calmars=data.apply(lambda s:calmar(s))
calmar_df=pd.concat([rets.to_frame('rets'),drawdowns.to_frame('drawdowns'),calmars.to_frame('calmars')],axis=1)
#注意,这里东方财富数据端口存在一些问题,招商南油后复权价格存在负数,剔除出样本
calmar_df=calmar_df[-(calmar_df['drawdowns']>=1)]
calmar_df.describe()

94d4e27bf4366944b58f6a847fd8fdd3.jpeg

过去250个交易日,3625个样本里,收益率中位数为-6%,75%分位数为8.8%,最大值253%,最小值为-58.9%,呈现“二八法则”现象,赚钱的个股占少数。最大回撤最大为67.9%,意味着你买入某只股票一直持有250个交易日,最大可能亏损67.9%,最小亏损是3.08%。下面一起来看下哪些个股近一年的最大回撤在10%以内。基本上都是些银行股、还有高速公路等大盘股,这些个股最大回撤低,期间收益率自然也高不起来,毕竟要获得高的收益就得承受一定的高风险。正如佛说,“要想享受鱼肉的鲜美,就得接受鱼刺的纠缠。”

calmar_df[calmar_df['drawdowns']<0.10]

d42f0dc68d9b8b555053dbfe416029ba.jpeg

箱线图显示,Calmars比率有较多离群值,主要是因为当最大回撤很小时,计算得到的比值会比较大。

qs.box(calmar_df)

c6b5304dd630a66e3d2beadb68ff9991.jpeg

以区间累计收益率为y轴,最大回撤为x轴,可以看出二者并非简单的线性关系,收益率越高,一般最大回撤也越高,但最大回撤越高的时候,可能收益率越低。由此可见,要想获得高收益需要承担一定的高风险,但是承担高风险不必然带来高收益。所以遇到亏损死扛并非是一个好的投资决策。

qs.scatter(x='drawdowns',y='rets',data=calmar_df)

a7ecd9f89b6a66c1898668786623f8cb.jpeg

以区间累计收益率为y轴,Calmars为x轴,二者呈现出正向关系(这是因为计算Calmars比率时收益率为分子)。因此使用Calmar比率可以一定程度上筛选出某期间的强势股,当然该指标也有局限性,尤其是当期间最大回撤很小时,得到的比率比较大,但不代表该股价格上很强势。

qs.scatter(x='calmars',y='rets',data=calmar_df)

bd3873bbe556f9b7fb2b3388e75c40aa.jpeg

1de756d8ab6db22e36d4513d6f516188.gif

个股Calmars指标排名

下面以20、60、120、200日区间为例,计算A股的Calmars比率并排序筛选收益率高回撤小的强势个股,这里相当于假设基金买入持有某只个股,然后对该基金的业绩进行评价。

#计算多个期间序列的kama比率并排序
def stock_calmar(data,w_list=[20,60,120,200]):
    df=data.copy()
    result=pd.DataFrame()
    for w in w_list:
        temp=df[-w:].dropna(axis=1).apply(lambda s:calmar(s))
        result[str(w)+'日']=temp.sort_values(ascending=False)[:50].index
    return result
result=stock_calmar(prices)
result

e84b71e3ee8f95ba5f37df9d52c02fd5.jpeg

榜上名单大都是近期涨势较好的强势股,根据动量交易策略(强者恒强),再结合个股基本面,可以构建投资组合。

6fd0c7f7cae3f51fad88538a6390342e.gif

结果可视化

下面使用qstock的可视化模块对部分结果进行可视化展示。

qs.kline(qs.get_data('世运电路')[-20:])

237334fcdd2d654128e7e0964e4f097e.jpeg

qs.kline(qs.get_data('奥联电子')[-60:])

bb9006b1cc25a524db15421064795818.jpeg

qs.kline(qs.get_data('惠城环保')[-120:])

f53fb0a1804ab693a63cc1c411d0b625.jpeg

qs.kline(qs.get_data('招商南油')[-200:])

9bbe9745ed1d8b2df33e9e042e483645.jpeg

# 强势股云图
w_data=qs.ret_top_list(result)
qs.chart_wordcloud(w_data,title=None)

4a20aa601b3e0cf69792c8571366f308.jpeg

f101e994612ae1856d807400d7537206.png

关于Python金融量化

76505f29a599f3a050470368f1e40ce9.png

专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取qstock源代码、30多g的量化投资视频资料、量化金融相关PDF资料、公众号文章Python完整源码、与博主直接交流、答疑解惑等。添加个人微信sky2blue2可获取八五折优惠。

7b162dcda364b9a03e2aeb42aec38caf.jpeg

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值