2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

引言

杜魯門說,“你不能預測未來的唯一問題,就在於你不瞭解歷史

”。歐奈爾在《笑傲股市》一書中,通過總結1880-2008年表現最為強勁的100多隻股票價格形態圖來洞察牛股的選股和把握時機,並結合基本面分析提出了CANSLIM選股法則。美國股市有200多年曆史,經歷了各種跌宕起伏,如同一位飽經風霜的老人,有無盡的人生經驗值得分享。而A股才將近30年,像一個潮氣蓬勃的少年,跌跌撞撞,卻又對未來滿懷期待。那麼A股近30年以來,市場整體收益率情況如何?有哪些公司股票經得起時間考驗,取得了持續的高收益率,又有哪些公司股票從終點回到起點,甚至跌到懷疑人生?

本文基於A股2005-2020.2期間所有個股的交易數據,使用Python考察市場收益率統計分佈,以及累計漲(跌)幅居前的股票及其特徵,為大家挖掘中長期牛股提供一定的技術參考和分析路徑。“授人以魚不如授人以漁”,所以下面著重從Python量化的角度為大家展示數據的處理和分析過程,而結果的解讀仁者見仁,不做深入展開,文中提及的股票也不構成任何投資建議。

獲取數據

考慮到2005年股權分置改革以前,A股市場制度較不健全,上市公司數量相對較少,因此考察的是2005-2020.2年期間的樣本數據,不含已退市個股。數據使用tushare pro下載並保存到當地sqlite3數據庫中。csv格式數據(截至2020.2.24)已分享在百度網盤上,在公眾號後臺回覆“

A股數據”或“20200225”可獲取下載鏈接。如需獲取本地數據庫下載和調用數據的所有完整源碼,可通過加入知識星球。關於數據庫管理與操作參見推文【手把手教你】Python面向對象編程入門及股票數據管理應用實例。


<code>import pandas as pd
#以下是自己寫的腳本文件,包括數據獲取和畫圖
from base import ts_pro,sql_engine
pro=ts_pro()
from update_sql import update_sql,get_trade_date,info_sql
from RPS import get_data,RPS
from plot_stock import stock_plot

#更新數據庫
update_sql(table_name='daily_data')
#數據庫已更新至20200225日數據/<code>

使用本地腳本文件從數據庫中調取2004年2020年2月24日所有A股的前復權價格數據。下表展示的是最近5個交易日3307只個股的價格數據。

<code>all_df=get_data(date='20040101')
all_df.index=pd.to_datetime(all_df.index)
all_df.tail()/<code>
2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

(點擊查看大圖)

2020年以來漲跌統計分析

由於新冠肺炎疫情的黑天鵝事件,2月3日春節後第一天開盤上證綜指暴跌接近8個點,出現千股跌停的慘況,但是這隻黑天鵝並未嚇退自2019年年底以來的科技股和特斯拉行情。科技股的半導體、元器件和芯片概念個股漲幅驚人,新股斯達半導連續16個一字板,收益率達到318%。特斯拉概念的奧特佳和模塑科技股價均實現了翻番。不少踏空的人感嘆,這波行情來得太特麼出乎意料了,難道新冠肺炎對經濟沒有影響嗎?其實事實有時候不是很重要的,人們對事實的反應才是最重要的。在股市上,基本面和消息本身不是最重要的,最重要的是人們對它的理解和反應。股價不是對基本面的反映,而是對想象力的反映股市對新東西的炒作有自己的邏輯,這個邏輯是先把股價炒上天,再用時間來還債。這就是很多人看不懂股市而天天喊風險、喊泡沫的原因。

<code>def plot_2020_stock(r=False):
from pyecharts import Bar
#注意這裡用的pyecharts為0.5.11舊版本
df_2020=all_df['2020']
df_2020_ret=df_2020.apply(lambda x:(((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)

df=df_2020_ret.sort_values(ascending=r)[:10]
attr=df.index
v=df.values.round(2)
title='漲' if r==False else '跌'
bar=Bar(f'2020年以來最大{title}幅',
width=900,height=400,title_pos='center')
bar.add('',attr,v,is_splitline_show=False,
is_label_show=True,xaxis_label_textsize=9,
is_datazoom_show=False)
return bar
plot_2020_stock()/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」


<code>plot_2020_stock(r=True)/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

2005-2020年曆年收益率統計分析

接下來分析A股2005年以來歷年的個股收益率情況。首先對2006年-2020年曆年收益率進行描述性統計分析。

<code>#從數據庫從調用數據
def describe_ret():
engine=sql_engine()
dec_df=pd.DataFrame()
for y in range(2006,2021):
d1=str(y)+'0000'
d2=str(y+1)+'0000'
sql=f"select * from daily_data where trade_date>{d1} and trade_date sql_df=pd.read_sql(sql,engine)
data=sql_df.sort_values(['ts_code','trade_date'])
data['adjclose']=data.groupby('ts_code').apply(lambda x:x.close*x.adj_factor/x.adj_factor.iloc[-1]).values
df=data.set_index(['trade_date','ts_code'])['adjclose']
#數據重排,列名為代碼
df_close=df.unstack()
df_ret=df_close.apply(lambda x:(((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)
dec_df[str(y)]=df_ret.describe().round(3)
return dec_df

describe_ret()/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

(點擊查看大圖)


2006年市場只有1353只個股,到了2020年增加到3783只。從收益率的均值來看,只有2008、2011和2018三年為負,其餘均為正,看來這十五年裡個股平均是漲多跌少啊。先別急,可能大多是被平均了呢,何況炒股一直是少數人賺錢的遊戲。從標準差和各分位數不難看,個股之間每年的分化都特別大,尤其在2007和2015年典型的牛市期間,標準差超過100%。除了收益率均值為負的那三年,其餘年份的標準差均超過20%,漲幅最大的高達幾倍至十幾二十倍,最差的虧損70%多。2019年,萬集科技搭上了ETC這波快車,業績大幅增長,2019年股價翻了四倍多。另外,值得一提的是,2015年的新股次新股明星暴風集團一年實現21倍的收益率,後來卻因為業績困局一路被腰斬,從116.46(前復權)跌至今天的3.25,慘不忍睹。看來出來混總是要還的,正所謂佛魔相伴,如果沒有基本面支撐,透支行情背後就是還債行情。

歷年漲幅最大個股

<code>def find_annual_stock(df):
#將時間索引轉化為年
new_df=df.to_period('Y')

#根據年進行聚類求每一年的累計收益率
dd=new_df.groupby(new_df.index).apply(lambda x: (((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1])
#獲取每一年收益率最大的個股及其收益率
final_df=pd.DataFrame()
final_df['股票名稱']=dd.T.idxmax()
final_df['累計收益率']=dd.T.max()-1
#股票代碼
code_list=pro.stock_basic(list_status='L').ts_code.values
name_list=pro.stock_basic(list_status='L').name.values
stock_dict=dict(zip(name_list,code_list))
#將代碼隱射為股票名稱
final_df['code']=[stock_dict[name] for name in list(final_df['股票名稱'])]
return final_df

#畫圖,更直觀化
def plot_annual_stock(df):
from pyecharts import Bar
#2020年已經分析過了
attr=df.股票名稱[1:-1]
attr=[str(i)+'\\n'+str(j) for (i,j) in zip(attr.values,attr.index)]
v=df.累計收益率[1:-1].round(2)
bar=Bar('歷年漲幅最大個股\\n2005年-2020年',
width=900,height=400,title_pos='center')
bar.add('',attr,v,is_splitline_show=False,
is_label_show=True,xaxis_label_textsize=9,
is_datazoom_show=False)
return bar

final_df=find_annual_stock(all_df)
plot_annual_stock(final_df)/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」


stock_plot('暴風集團',250*5).kline_plot(ktype=0)

2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」


<code>stock_plot('萬集科技').kline_plot(ktype=0)/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

2005-2020年區間累計漲幅

前面是以某一年為分析期間,如果把時間拉長,有哪些公司股票能夠長期持續領跑呢?又有哪些公司是跌到媽都不認得的?

(1)以2005年為起點,考察往後1至15年各股的累計收益率情況。2005-XX年(XX=2005, 2006,...,2020)期間累計行情排名前五以及倒數前五的由下圖所示。一眼望去,漲幅居前的是我們常說的大白馬股,其中生物醫藥和白酒板塊的個股十分搶眼,尤其是恆瑞醫藥,股價十五年實現了141倍增長,難怪高瓴資本的張磊特別偏好生物醫藥股。跌幅居前的個股就不說了,中國石油一出場即是顛覆,此後便坐上了滑翔機。

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

ret_2005_xx()


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

(點擊查看大圖)


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

(點擊查看大圖)

stock_plot('恆瑞醫藥',n=15*250).kline_plot(ktype=0)


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」


(2)以2020.2.25日為終點,考察往前1至15年各股的累計收益率情況。XX-2020年(XX=2005, 2006,...,2020)期間累計行情排名前五以及倒數前五的由下圖所示。結果與(1)相比有些差異,

近三年來漲幅居前的主要是科技和新興主題概念股(如網紅經濟星期六),當然這些短期暴漲股很可能走的是先透支後還債的行情。不出意外,時間一拉長,漲幅居前的仍然是生物醫藥股,其中泰康生物是股群中最靚的仔,連續七八年位列漲幅前五。看來長期牛股是經得起時間考驗並不斷創新高的,歐奈爾在總結美股牛股的時候提出,“當股價漲至接近年度最高點時買入股票,千萬不要在股價跌得很低從而看似很便宜的情況下買入。應該買那些價格更高而不是價格更低的股票。

<code>def cal_cum_ret(year):
year=str(year)
data=all_df[year:]
total_ret=data.apply(lambda x: (((x/x.shift(1)-1).fillna(0)+1.0).cumprod()).iloc[-1]-1)
first_=(total_ret.sort_values(ascending=False)[:10]).round(2)
last_=(total_ret.sort_values(ascending=False)[-10:]).round(2)
return first_,last_

def ret_rank():
up,down=pd.DataFrame(),pd.DataFrame()
for year in range(2005,2021):
u,d=cal_cum_ret(year)
up[str(year)]=list(zip(u.index,u.values))
down[str(year)]=list(zip(d.index,d.values))
return up,down

up_ret,down_ret=ret_rank()

up_ret/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

(點擊查看大圖)


<code>down_ret/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

(點擊查看大圖)

2005年至2019收益率評價指標

下面結合績效評價指標,考察2005至2019期間個股的累計總收益率、年化收益率、最大回撤和夏普比率情況。

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

查看年化收益率排名前十五的個股情況,恆瑞醫藥2005-2019年累計收益率為139.99%,年化收益39%,最大回撤39.22%,夏普比率為3.97,作為“買入持有策略”當之無愧的王者,當然排在第二的貴州茅臺似乎知名度更高。其他上榜的個股年化超過25%,夏普比率大於2.5,但最大回撤均接近或超過60%,金證股份更高達90%。

<code>perf_df=performance(all_df)
perf0=perf_df.sort_values('年化收益率%',ascending=False)
perf0[:15].T/<code>


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」


最後,看下所有A股2005-2019年期間收益率和業績評價指標的描述性統計。A股十五年總收益率均值為200%,年化均值4.65%,最大回撤75.94%,夏普比率0.84,似乎不太理想。但是回到“炒股是少數人賺錢的遊戲”上又似乎很合理,因為個股之間的分化非常大,強者恆強!

perf_df.describe().round(2)


2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」

結語

本文使用Python對A股2005-2020歷史數據進行了統計分析,試圖從個股收益率的維度為大家揭示市場的某種微觀結構及其演變。本文並未對中長期牛股及其漲跌背景深入展開分析,對此感興趣的讀者可以結合宏觀背景、公司基本面進一步總結國內牛股的特徵,分析某些行業某些個股之所以能持續走強的深層次原因。儘管過去不能代表未來,但歷史總是驚人的相似。

多層次多維度去總結和分析股市的歷史走勢,有助於我們更好的把握當下和未來。實際上任何技術、方法、工具都必須依託在對股市本質認識的基礎上。經歷、教育背景、資金大小、交易週期等不同,對股市的理解必然不一樣,但關鍵是要形成與自己操作風格相匹配的股市交易系統。比如你做長線投資,必須從長線的角度去理解股市長期波動的主導因素是什麼。

當前疫情的陰霾還未退散,經濟難言觸底反彈,很多人感到迷茫與彷徨,但我堅信我們生活在一個擁有無窮機會的時期,是一個新理念、新產業和新領域層出不窮的時代。但是,你只有系統地學習和不斷總結,才能學會如何認清並充分利用這些新機遇


關於Python金融量化

專注於分享Python在金融量化領域的應用。加入知識星球,可以免費獲取量化投資視頻資料、量化金融相關PDF資料、公眾號文章Python完整源碼、量化投資前沿分析框架,與博主直接交流、結識圈內朋友等。

2005-2020年A股數據挖掘:誰是最大的牛股?「附Python分析源碼」


分享到:


相關文章: