当前位置:   article > 正文

2005-2020年A股数据挖掘:谁是最大的牛股?【附Python分析源码】

历年股票预测的结果

引言

杜鲁门说,“你不能预测未来的唯一问题,就在于你不了解历史”。欧奈尔在《笑傲股市》一书中,通过总结1880-2008年表现最为强劲的100多只股票价格形态图来洞察牛股的选股和把握时机,并结合基本面分析提出了CANSLIM选股法则。美国股市有200多年历史,经历了各种跌宕起伏,如同一位饱经风霜的老人,有无尽的人生经验值得分享。而A股才将近30年,像一个潮气蓬勃的少年,跌跌撞撞,却又对未来满怀期待。那么A股近30年以来,市场整体收益率情况如何?有哪些公司股票经得起时间考验,取得了持续的高收益率,又有哪些公司股票从终点回到起点,甚至跌到怀疑人生?

本文基于A股2005-2020.2期间所有个股的交易数据,使用Python考察市场收益率统计分布,以及累计涨(跌)幅居前的股票及其特征,为大家挖掘中长期牛股提供一定的技术参考和分析路径。“授人以鱼不如授人以渔”,所以下面着重从Python量化的角度为大家展示数据的处理和分析过程,而结果的解读仁者见仁,不做深入展开,文中提及的股票也不构成任何投资建议。

01

获取数据


考虑到2005年股权分置改革以前,A股市场制度较不健全,上市公司数量相对较少,因此考察的是2005-2020.2年期间的样本数据,不含已退市个股。数据使用tushare pro下载并保存到当地sqlite3数据库中。csv格式数据(截至2020.2.24)已分享在百度网盘上,在公众号后台回复“A股数据”或“20200225”可获取下载链接。如需获取本地数据库下载和调用数据的所有完整源码,可通过加入知识星球。关于数据库管理与操作参见推文【手把手教你】Python面向对象编程入门及股票数据管理应用实例

  1. import pandas as pd
  2. #以下是自己写的脚本文件,包括数据获取和画图
  3. from base import ts_pro,sql_engine
  4. pro=ts_pro()
  5. from update_sql import update_sql,get_trade_date,info_sql
  6. from RPS import get_data,RPS
  7. from plot_stock import stock_plot
  1. #更新数据库
  2. update_sql(table_name='daily_data')
  3. #数据库已更新至20200225日数据

使用本地脚本文件从数据库中调取2004年2020年2月24日所有A股的前复权价格数据。下表展示的是最近5个交易日3307只个股的价格数据。

  1. all_df=get_data(date='20040101')
  2. all_df.index=pd.to_datetime(all_df.index)
  3. all_df.tail()

(点击查看大图)

02

2020年以来涨跌统计分析


由于新冠肺炎疫情的黑天鹅事件,2月3日春节后第一天开盘上证综指暴跌接近8个点,出现千股跌停的惨况,但是这只黑天鹅并未吓退自2019年年底以来的科技股和特斯拉行情。科技股的半导体、元器件和芯片概念个股涨幅惊人,新股斯达半导连续16个一字板,收益率达到318%。特斯拉概念的奥特佳和模塑科技股价均实现了翻番。不少踏空的人感叹,这波行情来得太特么出乎意料了,难道新冠肺炎对经济没有影响吗?其实事实有时候不是很重要的,人们对事实的反应才是最重要的。在股市上,基本面和消息本身不是最重要的,最重要的是人们对它的理解和反应。股价不是对基本面的反映,而是对想象力的反映股市对新东西的炒作有自己的逻辑,这个逻辑是先把股价炒上天,再用时间来还债。这就是很多人看不懂股市而天天喊风险、喊泡沫的原因。

  1. def plot_2020_stock(r=False):
  2.     from pyecharts import Bar
  3.     #注意这里用的pyecharts为0.5.11旧版本
  4.     df_2020=all_df['2020']
  5.     df_2020_ret=df_2020.apply(lambda x:(((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)
  6.     df=df_2020_ret.sort_values(ascending=r)[:10]
  7.     attr=df.index
  8.     v=df.values.round(2)
  9.     title='涨' if r==False else '跌'
  10.     bar=Bar(f'2020年以来最大{title}幅',
  11.              width=900,height=400,title_pos='center')
  12.     bar.add('',attr,v,is_splitline_show=False,
  13.         is_label_show=True,xaxis_label_textsize=9,
  14.         is_datazoom_show=False)
  15.     return bar
  16. plot_2020_stock()

plot_2020_stock(r=True)

03

2005-2020年历年收益率统计分析


接下来分析A股2005年以来历年的个股收益率情况。首先对2006年-2020年历年收益率进行描述性统计分析。

  1. #从数据库从调用数据
  2. def describe_ret():
  3.     engine=sql_engine()
  4.     dec_df=pd.DataFrame()
  5.     for y in range(2006,2021):
  6.         d1=str(y)+'0000'
  7.         d2=str(y+1)+'0000'
  8.         sql=f"select * from daily_data where trade_date>{d1} and trade_date<{d2}"
  9.         sql_df=pd.read_sql(sql,engine)
  10.         data=sql_df.sort_values(['ts_code','trade_date'])
  11.         data['adjclose']=data.groupby('ts_code').apply(lambda x:x.close*x.adj_factor/x.adj_factor.iloc[-1]).values
  12.         df=data.set_index(['trade_date','ts_code'])['adjclose']
  13.         #数据重排,列名为代码
  14.         df_close=df.unstack()
  15.         df_ret=df_close.apply(lambda x:(((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)
  16.         dec_df[str(y)]=df_ret.describe().round(3)
  17.     return dec_df 
describe_ret()

(点击查看大图)

2006年市场只有1353只个股,到了2020年增加到3783只。从收益率的均值来看,只有2008、2011和2018三年为负,其余均为正,看来这十五年里个股平均是涨多跌少啊。先别急,可能大多是被平均了呢,何况炒股一直是少数人赚钱的游戏。从标准差和各分位数不难看,个股之间每年的分化都特别大,尤其在2007和2015年典型的牛市期间,标准差超过100%。除了收益率均值为负的那三年,其余年份的标准差均超过20%,涨幅最大的高达几倍至十几二十倍,最差的亏损70%多。2019年,万集科技搭上了ETC这波快车,业绩大幅增长,2019年股价翻了四倍多。另外,值得一提的是,2015年的新股次新股明星暴风集团一年实现21倍的收益率,后来却因为业绩困局一路被腰斩,从116.46(前复权)跌至今天的3.25,惨不忍睹。看来出来混总是要还的,正所谓佛魔相伴,如果没有基本面支撑,透支行情背后就是还债行情

历年涨幅最大个股

  1. def find_annual_stock(df):
  2.     #将时间索引转化为年
  3.     new_df=df.to_period('Y')
  4.     #根据年进行聚类求每一年的累计收益率
  5.     dd=new_df.groupby(new_df.index).apply(lambda x: (((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1])
  6.     #获取每一年收益率最大的个股及其收益率
  7.     final_df=pd.DataFrame()
  8.     final_df['股票名称']=dd.T.idxmax()
  9.     final_df['累计收益率']=dd.T.max()-1
  10.     #股票代码
  11.     code_list=pro.stock_basic(list_status='L').ts_code.values
  12.     name_list=pro.stock_basic(list_status='L').name.values
  13.     stock_dict=dict(zip(name_list,code_list))
  14.     #将代码隐射为股票名称
  15.     final_df['code']=[stock_dict[name] for name in list(final_df['股票名称'])]
  16.     return final_df
  1. #画图,更直观化
  2. def plot_annual_stock(df):
  3.     from pyecharts import Bar
  4.     #2020年已经分析过了
  5.     attr=df.股票名称[1:-1]
  6.     attr=[str(i)+'\n'+str(j) for (i,j) in  zip(attr.values,attr.index)]
  7.     v=df.累计收益率[1:-1].round(2)
  8.     bar=Bar('历年涨幅最大个股\n2005年-2020年',
  9.              width=900,height=400,title_pos='center')
  10.     bar.add('',attr,v,is_splitline_show=False,
  11.         is_label_show=True,xaxis_label_textsize=9,
  12.         is_datazoom_show=False)
  13.     return bar
  1. final_df=find_annual_stock(all_df)
  2. plot_annual_stock(final_df)

stock_plot('暴风集团',250*5).kline_plot(ktype=0) 

stock_plot('万集科技').kline_plot(ktype=0)


04

2005-2020年区间累计涨幅


前面是以某一年为分析期间,如果把时间拉长,有哪些公司股票能够长期持续领跑呢?又有哪些公司是跌到妈都不认得的?

(1)以2005年为起点,考察往后1至15年各股的累计收益率情况。2005-XX年(XX=2005, 2006,...,2020)期间累计行情排名前五以及倒数前五的由下图所示。一眼望去,涨幅居前的是我们常说的大白马股,其中生物医药和白酒板块的个股十分抢眼,尤其是恒瑞医药,股价十五年实现了141倍增长,难怪高瓴资本的张磊特别偏好生物医药股。跌幅居前的个股就不说了,中国石油一出场即是颠覆,此后便坐上了滑翔机。

  1. def ret_2005_xx():
  2.     ret_df=pd.DataFrame()
  3.     for y in range(2005,2021):
  4.         year=str(y)
  5.         data=all_df[:year]
  6.         total_ret=data.apply(lambda x: (((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)
  7.         tret=total_ret.sort_values(ascending=False).round(2)
  8.         ret_df[year]=list(zip(tret.index,tret.values))
  9.     return ret_df

ret_2005_xx()

(点击查看大图)

( 点击查看大图 )


stock_plot('恒瑞医药',n=15*250).kline_plot(ktype=0)

(2)以2020.2.25日为终点,考察往前1至15年各股的累计收益率情况。XX-2020年(XX=2005, 2006,...,2020)期间累计行情排名前五以及倒数前五的由下图所示。结果与(1)相比有些差异,近三年来涨幅居前的主要是科技和新兴主题概念股(如网红经济星期六),当然这些短期暴涨股很可能走的是先透支后还债的行情。不出意外,时间一拉长,涨幅居前的仍然是生物医药股,其中泰康生物是股群中最靓的仔,连续七八年位列涨幅前五。看来长期牛股是经得起时间考验并不断创新高的,欧奈尔在总结美股牛股的时候提出,“当股价涨至接近年度最高点时买入股票,千万不要在股价跌得很低从而看似很便宜的情况下买入。应该买那些价格更高而不是价格更低的股票。

  1. def cal_cum_ret(year):
  2.     year=str(year)
  3.     data=all_df[year:]
  4.     total_ret=data.apply(lambda x: (((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)
  5.     first_=(total_ret.sort_values(ascending=False)[:10]).round(2)
  6.     last_=(total_ret.sort_values(ascending=False)[-10:]).round(2)
  7.     return first_,last_
  8. def ret_rank():
  9.     up,down=pd.DataFrame(),pd.DataFrame()
  10.     for year in range(2005,2021):
  11.         u,d=cal_cum_ret(year)
  12.         up[str(year)]=list(zip(u.index,u.values))
  13.         down[str(year)]=list(zip(d.index,d.values))
  14.     return up,down
up_ret,down_ret=ret_rank()
up_ret

(点击查看大图)

down_ret

(点击查看大图)

05

2005年至2019收益率评价指标

下面结合绩效评价指标,考察2005至2019期间个股的累计总收益率、年化收益率、最大回撤和夏普比率情况。

  1. def performance(all_df):
  2.     cum_ret=all_df[:'2019'].apply(lambda x: ((x/x.shift(1)-1).fillna(0)+1.0).cumprod())
  3.     total_ret=(cum_ret.iloc[-1]-1).sort_values(ascending=False)
  4.     annual_ret=total_ret.apply(lambda x:pow(1+x,1/15)-1)
  5.     dd=(cum_ret.cummax()-cum_ret)/cum_ret.cummax()
  6.     d=dd.max()
  7.     exReturn=all_df.apply(lambda x: (x/x.shift(1)-1).fillna(0)-0.03/250)
  8.     sharper_atio=np.sqrt(len(exReturn))*exReturn.mean()/exReturn.std()
  9.     perf_df=pd.DataFrame()
  10.     perf_df['总收益率']=round(total_ret,3)
  11.     perf_df['年化收益率%']=round(annual_ret*100,2)
  12.     perf_df['最大回撤%']=round(d*100,2)
  13.     perf_df['夏普比率']=round(sharper_atio,2)
  14.     return perf_df

查看年化收益率排名前十五的个股情况,恒瑞医药2005-2019年累计收益率为139.99%,年化收益39%,最大回撤39.22%,夏普比率为3.97,作为“买入持有策略”当之无愧的王者,当然排在第二的贵州茅台似乎知名度更高。其他上榜的个股年化超过25%,夏普比率大于2.5,但最大回撤均接近或超过60%,金证股份更高达90%。

  1. perf_df=performance(all_df)
  2. perf0=perf_df.sort_values('年化收益率%',ascending=False)
  3. perf0[:15].T

最后,看下所有A股2005-2019年期间收益率和业绩评价指标的描述性统计。A股十五年总收益率均值为200%,年化均值4.65%,最大回撤75.94%,夏普比率0.84,似乎不太理想。但是回到“炒股是少数人赚钱的游戏”上又似乎很合理,因为个股之间的分化非常大,强者恒强!


perf_df.describe().round(2)

结语

本文使用Python对A股2005-2020历史数据进行了统计分析,试图从个股收益率的维度为大家揭示市场的某种微观结构及其演变。本文并未对中长期牛股及其涨跌背景深入展开分析,对此感兴趣的读者可以结合宏观背景、公司基本面进一步总结国内牛股的特征,分析某些行业某些个股之所以能持续走强的深层次原因。尽管过去不能代表未来,但历史总是惊人的相似。多层次多维度去总结和分析股市的历史走势,有助于我们更好的把握当下和未来。实际上任何技术、方法、工具都必须依托在对股市本质认识的基础上。经历、教育背景、资金大小、交易周期等不同,对股市的理解必然不一样,但关键是要形成与自己操作风格相匹配的股市交易系统。比如你做长线投资,必须从长线的角度去理解股市长期波动的主导因素是什么。

当前疫情的阴霾还未退散,经济难言触底反弹,很多人感到迷茫与彷徨,但我坚信我们生活在一个拥有无穷机会的时期,是一个新理念、新产业和新领域层出不穷的时代。但是,你只有系统地学习和不断总结,才能学会如何认清并充分利用这些新机遇

关于Python金融量化

专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取量化投资视频资料、量化金融相关PDF资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/584750
推荐阅读
相关标签
  

闽ICP备14008679号