教你用Python自制一張好看的指數(shù)估值圖

對(duì)于以定投指數(shù)的方式理財(cái)?shù)呐笥?,最需要關(guān)注的指標(biāo)便是各個(gè)指數(shù)的估值,在指數(shù)低估時(shí)買入,高估時(shí)賣出,那如何制作一張估值圖來(lái)跟蹤指數(shù)的估值情況呢?本文就從0到1介紹如何用Matplotlib畫一張漂亮的指數(shù)估值圖。
準(zhǔn)備數(shù)據(jù)
首先,準(zhǔn)備我們需要的數(shù)據(jù),一般來(lái)說(shuō),經(jīng)歷了一輪牛熊周期的歷史估值更具比較意義,所以,這里以上證指數(shù)2013年到目前為止的行情數(shù)據(jù)為例進(jìn)行演示,同時(shí),采用滾動(dòng)市盈率為估值指標(biāo)。數(shù)據(jù)來(lái)源為tushare。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import tushare as ts
from datetime import *
%matplotlib inline
#設(shè)置顯示中文
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
根據(jù)得到的數(shù)據(jù),可以繪制出上證指數(shù)市盈率的走勢(shì)圖:
fig,ax = plt.subplots(figsize=(12,8))
ax.plot(x,y)

接下來(lái)便需要根據(jù)一定的規(guī)則,將估值劃分為高估區(qū)、正常區(qū)以及低估區(qū)。
估值區(qū)間劃分
參照比較常見的劃分方法,本文將大于80%分位數(shù)的區(qū)域視為高估區(qū)間,低于20%分位數(shù)的區(qū)域視為低估區(qū)間,位于兩者之間的,則為正常區(qū)間。下面的代碼算出了這幾個(gè)關(guān)鍵數(shù)據(jù)點(diǎn)
max = np.max(y)
pe_80 = np.percentile(y,80)
pe_20 = np.percentile(y,20)
min = np.min(y)
now = y[-1] #為了后續(xù)標(biāo)出當(dāng)日估值
繪圖
根據(jù)分割的數(shù)據(jù)點(diǎn),就可以進(jìn)行繪圖了,這里主要用到fill_between函數(shù)繪制各區(qū)域的顏色分割,將高估區(qū)域用紅色塊填充,正常區(qū)間用黃色塊填充,低估值區(qū)域用綠色塊填充。同時(shí)為了顯示效果,將圖的上下限分別設(shè)置為最大值+1和最小值-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)

整個(gè)圖形的大致輪廓已經(jīng)出來(lái)了,為了更好的顯示效果,接下來(lái)還需要對(duì)圖形進(jìn)行微調(diào)。比如:
去掉坐標(biāo)軸的刻度并將相應(yīng)字體放大--> ax.tick_params()去掉圖形與坐標(biāo)軸之間的空白--> ax.margins()在圖中標(biāo)出當(dāng)日市盈率--> ax.text()將圖形的方框去掉--> plt.box()為圖標(biāo)添加標(biāo)題--> plt.title
所以,在之前代碼的基礎(chǔ)上,加入下面的調(diào)整代碼,就可以得到最終的成品圖
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("上證指數(shù)估值圖",fontdict={'size':24})

函數(shù)封裝
進(jìn)一步地,為了將上面的代碼復(fù)用,可以將所有繪圖的代碼封裝成函數(shù),之后只需要輸入相應(yīng)的指數(shù)代碼(可以值寬基指數(shù)、行業(yè)板塊指數(shù))和時(shí)間范圍,即可快速生成一張估值圖。
def pe_plot(ts_code = "",name="",period=5):
#準(zhǔn)備數(shù)據(jù)
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"].values
#劃定分割范圍
max = 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()
比如,生成一張創(chuàng)業(yè)板指數(shù)近5年的估值圖
pe_plot(ts_code="399006.SZ",name="創(chuàng)業(yè)板指",period=5)
-END-
掃碼添加早小起,進(jìn)入Python技術(shù)交流群
