對於以定投指數的方式理財的朋友,最需要關注的指標便是各個指數的估值,在指數低估時買入,高估時賣出,那如何製作一張估值圖來跟蹤指數的估值情況呢?本文就從0到1介紹如何用Matplotlib畫一張漂亮的指數估值圖。
作者 | 易執
準備數據
首先,準備我們需要的數據,一般來說,經歷了一輪牛熊週期的歷史估值更具比較意義,所以,這裡以上證指數2013年到目前為止的行情數據為例進行演示,同時,採用滾動市盈率為估值指標。數據來源為tushare。
<code>import
pandasas
pdimport
numpyas
npimport
matplotlib.pyplotas
pltimport
tushareas
tsfrom
datetimeimport
* %matplotlib inline plt.rcParams['font.sans-serif'
] ='FangSong'
pro = ts.pro_api() index_df = pro.index_dailybasic(ts_code ="000001.SH"
,start_date ="20130101"
, end_date ="20200311"
,fields="trade_date,pe_ttm"
) index_df.sort_values(by
="trade_date"
,inplace=True) x = pd.to_datetime(index_df["trade_date"
]).values y = index_df["pe_ttm"
].values/<code>
根據得到的數據,可以繪製出上證指數市盈率的走勢圖:
<code>fig,ax = plt.subplots(figsize=(12,8)) ax.plot(x,y)/<code>
接下來便需要根據一定的規則,將估值劃分為高估區、正常區以及低估區。
估值區間劃分
參照比較常見的劃分方法,本文將大於80%分位數的區域視為高估區間,低於20%分位數的區域視為低估區間,位於兩者之間的,則為正常區間。下面的代碼算出了這幾個關鍵數據點
<code>max
= np.max(y)pe_80
= np.percentile(y,80
)pe_20
= np.percentile(y,20
)min
= np.min(y)now
= y[-1
] /<code>
繪圖
根據分割的數據點,就可以進行繪圖了,這裡主要用到fill_between函數繪製各區域的顏色分割,將高估區域用紅色塊填充,正常區間用黃色塊填充,低估值區域用綠色塊填充。同時為了顯示效果,將圖的上下限分別設置為最大值+1和最小值-1。
<code>fig,ax = plt.subplots(figsize=(12
,8
)) ax.plot(x,y,linewidth=3
) ax.fill_between(x,min
-1
,pe_20,facecolor ="#00ff80"
,alpha=0.2
) ax.fill_between(x,pe_20,pe_80,facecolor ="#ffff4d"
,alpha=0.2
) ax.fill_between(x,pe_80,max
+1
,facecolor ="#ff69b4"
,alpha=0.2
)/<code>
整個圖形的大致輪廓已經出來了,為了更好的顯示效果,接下來還需要對圖形進行微調。比如:
- 去掉座標軸的刻度並將相應字體放大-->ax.tick_params()
- 去掉圖形與座標軸之間的空白-->ax.margins()
- 在圖中標出當日市盈率-->ax.text()
- 將圖形的方框去掉-->plt.box()
- 為圖標添加標題-->plt.title
所以,在之前代碼的基礎上,加入下面的調整代碼,就可以得到最終的成品圖
<code>fig,ax = plt.subplots(figsize=(12
,8
)) ax.plot(x,y,linewidth=3
) ax.fill_between(x,min
-1
,pe_20,facecolor ="#00ff80"
,alpha=0.2
) ax.fill_between(x,pe_20,pe_80,facecolor ="#ffff4d"
,alpha=0.2
) ax.fill_between(x,pe_80,max
+1
,facecolor ="#ff69b4"
,alpha=0.2
) ax.tick_params(axis='both'
, which='both'
,length=0
) ax.tick_params(axis='both'
, which='major'
, labelsize=16
) ax.margins(0.01
,0
) ax.text(0.75
,0.9
,"市盈率 = {}"
.format
(now),transform=ax.transAxes,fontdict={'size'
:18
}) plt.xticks(rotation=45
) plt.box(False) plt.title("上證指數估值圖"
,fontdict={'size'
:24
})/<code>
函數封裝
進一步地,為了將上面的代碼複用,可以將所有繪圖的代碼封裝成函數,之後只需要輸入相應的指數代碼(可以值寬基指數、行業板塊指數)和時間範圍,即可快速生成一張估值圖。
<code>def pe_plot(ts_code = "",name="",period=5): now = datetime.now() end_date = str(now.date()).replace("-"
,""
) start_date =str
(now.year-period
)+end_date[4
:] index_df = pro.index_dailybasic(ts_code = ts_code,start_date = start_date, end_date = end_date,fields
="trade_date,pe_ttm"
) index_df.sort_values(by
="trade_date"
,inplace=True
) x = pd.to_datetime(index_df["trade_date"
]).values y = index_df["pe_ttm"
].valuesmax
= np.max(y) pe_80 = np.percentile(y,80
) pe_20 = np.percentile(y,20
)min
= np.min(y)now
= y[-1
] fig,ax = plt.subplots(figsize=(12
,8
)) ax.plot(x,y,linewidth=3
) ax.fill_between(x,min
-1
,pe_20,facecolor ="#00ff80"
,alpha=0.2
) ax.fill_between(x,pe_20,pe_80,facecolor ="#ffff4d"
,alpha=0.2
) ax.fill_between(x,pe_80,max
+1
,facecolor ="#ff69b4"
,alpha=0.2
) ax.tick_params(axis='both'
, which='both'
,length
=0
) ax.tick_params(axis='both'
, which='major'
, labelsize=16
) ax.margins(0.01
,0
) ax.text(0.75
,0.9
,"市盈率 = {}"
.format(now
), transform=ax.transAxes,fontdict={'size'
:18
}) plt.xticks(rotation=45
) plt.box(False
) plt.title("{}估值圖"
.format(name
),fontdict={'size'
:24
}) plt.show()/<code>
比如,生成一張創業板指數近5年的估值圖
<code>pe_plot
(ts_code="399006.SZ"
,name="創業板指"
,period=5
)/<code>
【五一感恩回饋大放送】
CDA數據科學研究院也隆重推出五一小長假幸運狂歡周活動,回饋廣大的莘莘學子,回饋一直不斷學習、不斷進取的每一個行路人!
【活動時間】
4月30--5月6日
【豐厚獎品】
一等獎:iphone11
二等獎:5折萬元優惠
三等獎:CDA系列圖書
51幸運獎:天貓精靈
數量有限,先到先得,抽完為止!!
掃描下方海報二維碼參與抽獎吧↓↓↓