基于百度指数的股票收益率多因子模型研究

  • 导语
  • 数据获取
    • 基于qdata获取百度指数
    • 基于efiance获取股票数据
    • 数据集合并
    • 运行数据获取
  • 数据处理
  • 可视化分析
    • 各百度指数间相关性分析
    • 话题热度时间及股票收益率总览
    • 话题热度分布
    • 相关话题热度与股票股价及收益率的关系图
  • 多因子模型的搭建
    • CAPM
    • 多因子策略

导语

个人投资者购买股票的决策过程大致如下所示


考虑这样一个用户场景:在一个平平无奇的交易日上午,个人投资者习惯性地①打开了某理财APP(同花顺、东方财富、雪球股票等)查看自选股票的涨跌及股价、行业板块涨跌及个股龙虎榜等,看得差不多就去资讯板块查看头条快讯、文章推荐等,看到感兴趣的就会②点击进去浏览,在浏览上面这些信息之后看上某一支股票就会③在搜索栏寻找这只股票,并点击查看相关的具体信息(相关的动态资讯、盘口、研究报告等),然后可能还会在许多资讯类APP(微博、百度、今日头条等)⑦搜索关于该个股的相关话题、相关行业的讯息,最后可能④做出了购买决策。

这时,整个决策过程的路径便是①②③(⑦)④

考虑另一个用户场景:个人投资者在忙碌了一天后回到家中刷起了快手抖音(资讯娱乐类APP),APP上⑤推送了财经类博主的个股或公司解读视频,⑥他很感兴趣所以不知不觉地把视频看完了,翻阅了些视频评论之后在该APP或其他资讯类APP中⑦搜索关于该个股的话题、相关行业的讯息,又或者会③打开理财类APP搜索该个股或相关板块的具体信息,并想着明天开盘就买入。

这时,整个决策过程的路径便是⑤⑥(③)(⑦)④

可以看出来,⑦在资讯类APP上搜索这个行为始终不是用户购买个股这个行为的必经之路,但是由于⑦是一个主动搜索的行为,往往能代表着用户对这类话题或者相关个股的强烈兴趣。而在如今的自媒体时代,种草经济、内容输出的现象盛行,个人投资者都会想要在自己做出购买决策判断前去看看别人的看法和观点,所以⑦这个位置对于个人投资者来说还是很重要的。何况⑦处于用户决策漏斗通往购买决策的最后一道关口,理论上讲转化率会较高,所以如果能够量化⑦的一个搜索量,也算约等于知道有多少用户处于④的购买决策中。

而根据流动性溢价原理,当越来越多人关注到或者想得到某一支个股的时候,即个股的流动性增加甚至膨胀的时候,股价便会一定程度地超过它应有的价值,导致错误定价,即溢价。这时,该个股的短期便会产生超额收益率。当然,个股的长期收益率还是会趋近于他的真实价值,毕竟“市场短期是投票器,长期是称重器“。

所幸有一种方式可以量化⑦搜索量,这就是通过百度指数表示⑦的量化指标,然后探究相关话题搜索量与个股的短期收益率之间的关系来验证以上的论述并期望将相关话题的搜索量可以加入量化投资多因子模型中去,增加量化投资的收益。

#导入第三方包
from qdata.baidu_index import get_search_index
from qdata.baidu_index.common import split_keywords
from datetime import datetime, timedelta
import time
import pandas as pd
from datetime import datetime, timedelta
import efinance as ef

数据获取

基于qdata获取百度指数

def baidu_index(keywords_list,cookies,start_date,day_diff):#获取百度指数的第三方包原地址:https://github.com/longxiaofei/spider-BaiduIndexdf_index=pd.DataFrame()keywords_list = keywords_listcookies = cookiesstart_date= start_dateday_diff=day_diff#统一日期格式的输入以便后续获取相同时间段的股票数据start_date_tuple=datetime.strptime(start_date,'%Y-%m-%d')end_date_tuple=start_date_tuple+timedelta(days=day_diff)end_date=end_date_tuple.strftime('%Y-%m-%d')i=0 #控制只保留一列日期数据date_list=[]for keywords in split_keywords(keywords_list):for single_keyword in keywords:print(single_keyword)time.sleep(15)index_list=[]try:for index in get_search_index(keywords_list=[single_keyword],start_date=start_date,end_date=end_date,cookies=cookies):index_list.append(index['index'])date_list.append(index['date'])i+=1if i ==1:df_index['date']=date_listdf_index[index['keyword'][0]]=index_listexcept Exception as e:passdf_index=df_index.head(int(len(df_index)/3)) #亲测qdata获取的百度指数在300条以内的时候是会重复提取3次的,且大于300条时数据会混乱return df_index

基于efiance获取股票数据

def stock_data(stock_code,start_date,day_diff):#获取股票数据第三方包原地址:https://github.com/Micro-sheep/efinancestock_code = stock_codestart_date= start_dateday_diff=day_diffstart_date_tuple=datetime.strptime(start_date,'%Y-%m-%d')end_date_tuple=start_date_tuple+timedelta(days=day_diff)start_day= start_date_tuple.strftime('%Y%m%d')end_day= end_date_tuple.strftime('%Y%m%d')df_stock = ef.stock.get_quote_history(stock_code, beg=start_day, end=end_day)df_stock=df_stock[['日期','收盘']]df_stock.columns=['date','close']df_sh = ef.stock.get_quote_history('上证指数', beg=start_day, end=end_day)df_sh=df_sh[['日期','收盘']]df_sh.columns=['date','sh']df_stock=pd.merge(df_stock,df_sh)return df_stock

数据集合并

def initial_data(df_stock,df_index):#合并百度指数和股票指数的数据集df_backup=pd.merge(df_stock,df_index,on='date',how='right')df_backup.fillna(method='ffill',inplace=True)df_backup['date']=pd.to_datetime(df_backup['date'],format='%Y-%m-%d')for i in range(3,len(df_backup.columns)):df_backup.iloc[:,i]=df_backup.iloc[:,i].astype('int')return df_backup

运行数据获取

keywords_list=[['中兴通讯'],['zte'],['5G'],['边缘计算'],['物联网'],['新能源汽车'],['自动驾驶'],['车联网'],['ICT'],['数字经济'],['通讯行业'],['智慧城市'],['人工智能'],['网络安全']]
cookies = """BIDUPSID=187E54B46AD95D7D0C6CA7C17A441A00; PSTM=1652806892; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID=8769DC8382346675420D39751AB8C7F4:FG=1; Hm_lvt_d101ea4d2a5c67dab98251f0b5de24dc=1654905894; delPer=0; PSINO=6; ZFY=MwsVhdDRPk111Nng:AhOi4P1nZQRrR1Mc6azfnAjjqKo:C; BAIDUID_BFESS=8769DC8382346675420D39751AB8C7F4:FG=1; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; BA_HECTOR=210k2ha4252ha00h8g1hahv6d15; H_PS_PSSID=36426_36559_36624_36592_36455_31253_36511_36452_36420_36166_36520_26350_36469_36314; BCLID=7189016615800227754; BDSFRCVID=iNPOJexroG0leprDmD978gjVjopWxY5TDYrELPfiaimDVu-VJeC6EG0Pts1-dEu-EHtdogKK3gOTH4AF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tR30WJbHMTrDHJTg5DTjhPrMLN3dWMT-MTryKKJs54JKshOnBn7b-q4vXp5jLbvkJGnRh4oNBUJtjJjYhfO45DuZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPUjfc9LUkqW2cdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLtCvEDRbN2KTD-tFO5eT22-usMeQR2hcHMPoosIJ1bJ3KQ5K8b4vf5lRRB5rj--nwJxbUotoHXh3tMt_thtOp-CrpWDTm_q5TtUJMqIDzbMohqfLn5MOyKMniJCj9-pPKWhQrh459XP68bTkA5bjZKxtq3mkjbPbDfn028DKuDjREh40822Ta54cbb4o2WbCQfnkV8pcN2b5oQT8jbq3H0T57JGQf3x7gB-o2SPnXjqOUWJDkXb3ha4o0amnpL66CWJ5TMl5jDh3MKToDb-otexQ7bIny0hvcJR6cShPCyUjrDRLbXU6BK5vPbNcZ0l8K3l02V-bIe-t2XjQhDHR02t3-MPoa3RTeb6rjDnCry-5UXUI82h5y05OQ56RHKIQh556bHf7eXn523nk4jJORXRj4BNRhBRjValb4fj6Ky4oTjxL1Db3Jb5_L5gTtsl5dbnboepvojtcc3MvByPjdJJQOBKQB0KnGbUQkeq8CQft20b0EeMtjW6LEtR30WJbHMTrDHJTg5DTjhPrMMtTTWMT-MTryKKJs54JKsb6eejtWbPIZMxnjLbvkJGnRh4oNBUJtjJjYhfO45DuZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPUDUJ9LUkJ0mcdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLK-oj-D8Ge5u53e; BCLID_BFESS=7189016615800227754; BDSFRCVID_BFESS=iNPOJexroG0leprDmD978gjVjopWxY5TDYrELPfiaimDVu-VJeC6EG0Pts1-dEu-EHtdogKK3gOTH4AF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tR30WJbHMTrDHJTg5DTjhPrMLN3dWMT-MTryKKJs54JKshOnBn7b-q4vXp5jLbvkJGnRh4oNBUJtjJjYhfO45DuZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPUjfc9LUkqW2cdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLtCvEDRbN2KTD-tFO5eT22-usMeQR2hcHMPoosIJ1bJ3KQ5K8b4vf5lRRB5rj--nwJxbUotoHXh3tMt_thtOp-CrpWDTm_q5TtUJMqIDzbMohqfLn5MOyKMniJCj9-pPKWhQrh459XP68bTkA5bjZKxtq3mkjbPbDfn028DKuDjREh40822Ta54cbb4o2WbCQfnkV8pcN2b5oQT8jbq3H0T57JGQf3x7gB-o2SPnXjqOUWJDkXb3ha4o0amnpL66CWJ5TMl5jDh3MKToDb-otexQ7bIny0hvcJR6cShPCyUjrDRLbXU6BK5vPbNcZ0l8K3l02V-bIe-t2XjQhDHR02t3-MPoa3RTeb6rjDnCry-5UXUI82h5y05OQ56RHKIQh556bHf7eXn523nk4jJORXRj4BNRhBRjValb4fj6Ky4oTjxL1Db3Jb5_L5gTtsl5dbnboepvojtcc3MvByPjdJJQOBKQB0KnGbUQkeq8CQft20b0EeMtjW6LEtR30WJbHMTrDHJTg5DTjhPrMMtTTWMT-MTryKKJs54JKsb6eejtWbPIZMxnjLbvkJGnRh4oNBUJtjJjYhfO45DuZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPUDUJ9LUkJ0mcdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLK-oj-D8Ge5u53e; BDUSS=3Q0fndZYmhwTUx1clRIakN3MGFQZ1dvdVFoTVRYYXZodjd5aGNTY3QxWXdqdEJpSVFBQUFBJCQAAAAAAAAAAAEAAACFwjdLanVubmp1bm5iaGFwcHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADABqWIwAalia; SIGNIN_UC=70a2711cf1d3d9b1a82d2f87d633bd8a04052555077nxoxWNVqgLJ6Xa0qo%2F6rmA4PAvmTQkcjbUJg35LkCEWutkQ74GGWD038uzCXIfqCas7eHeIAN%2Bv%2BPVN55Wx8xvWfWFiBOEYRPMOwl2abJVMRF4lMo2oHx8ECV4qxoJ93XMBJGtQgEdvUET6q5H0buMrQaULeAQp%2Bi2oLaW2E8gr3boMVotEfJngpS98GYj8ICGLjCD0NYN%2FVOrtGOeaTXpNqMdMUX1AODWyflIby6TyoMXhFGZ82ofRnZgpXpl05YLqOoCgJXa4yYhzwzknhZGMhtWbqPQPNlUdAbZQwpm4%3D96416976362718933879039618364210; __cas__rn__=405255507; __cas__st__212=f7adc00a94a71e45793164597a0f3e17f64a496e22409f08bb0a3d40204c45fa694168b8a1de0d302a1a387f; __cas__id__212=40859543; CPID_212=40859543; CPTK_212=30581114; Hm_up_d101ea4d2a5c67dab98251f0b5de24dc=%7B%22uid_%22%3A%7B%22value%22%3A%221261945477%22%2C%22scope%22%3A1%7D%7D; bdindexid=kpp4j4d1kq6vuhqu55f1n3dkl5; Hm_lpvt_d101ea4d2a5c67dab98251f0b5de24dc=1655243068; ab_sr=1.0.1_ZThlZmY5MWJjZDcyMDk0ZGY4NTY5OTM5ZGNkMjkzOWY3MDZkYzE0NTY0MWIwYWRjZDFhMjAwMzM5ZTA3MzlhOTA5MjAxMjc5M2ZmMDIzNTUyOTNmZWY1MzRjMjIxMzJlMWM5ZGYzN2YxMmMxNmRhNTQ1MTEwMDEwNTc2YzA2ZGEyYTBjN2JkYjcwZjg1MmFhMGRjMDU4NjYxMDMwMTQ3NQ==; BDUSS_BFESS=3Q0fndZYmhwTUx1clRIakN3MGFQZ1dvdVFoTVRYYXZodjd5aGNTY3QxWXdqdEJpSVFBQUFBJCQAAAAAAAAAAAEAAACFwjdLanVubmp1bm5iaGFwcHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADABqWIwAalia; RT="z=1&dm=baidu.com&si=j93mjd353ci&ss=l4eowfjs&sl=f&tt=10hw&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=34nb&ul=3ppr"""
start_date= '2020-01-02'
day_diff=300 #获取百度指数的总天数。注意:亲测qdata获取的百度指数在300条以内的时候是会重复提取3次的,且大于300条时数据较乱,所以尽量控制day_diff<=300
stock='中兴通讯'
Rf_year=0.04 #无风险年化利率
diff_num=3 #几日收益率
threshold=1.2df_index=baidu_index(keywords_list,cookies,start_date,day_diff)
df_stock=stock_data(stock,start_date,day_diff)
df_backup=initial_data(df_stock,df_index)
df_backup

数据处理

百度指数的官方定义是:以网民在百度的搜索量为数据基础,以关键词为统计对象,科学分析并计算出各个关键词在百度网页搜索中搜索频次的加权。

所以每个关键词之间都可能有数量级的差异,这会一定程度上夸大数量级大的关键词的作用且忽略数量级小的关键词。在实际场景中,某一关键词的百度指数的变化或者说异常高的点比它的绝对值更具有参考价值,因为互联网用户对关键词搜索关注程度的突发性爆发会更能代表某一股票的流动性爆发从而造成市场的错误定价。所以要先以百度指数为基础新设立一个新的指标–话题指数change_index来量化当天的一个关键词的百度指数偏离了多少该关键词平均的百度指数。

1.先用pairplot函数查看百度指数的数值分布。

sns.pairplot(df_backup)


2.如图上所示,百度指数的数值分布近似于正态分布,这时异常值检测最基础的方法就是标记出与平均值偏差k倍sigma(标准差)的数值,但由于这种异常值检测是相对于一整个时间段而言的,检测出来的异常值始终是大于某一特定数值,这时互联网用户对关键词的爆发就相对于一个较长的时间段而言了。而一种更进阶的做法是,设定一个时长为5天的时间窗口,标记出与前5天平均值偏差k倍sigma的数值作为异常值,就能不仅能标记出绝对峰值,也能标记出百度指数的绝对峰值了。

#探究移动sigma与整体sigma方法标记异常值(被关注的话题)的效果对比
topic=df_comb.columns[4]
sigma=(df_comb[topic]-df_comb[topic].mean())/df_comb[topic].std()df_rolling_method=df_comb[df_comb['change_'+topic]>=threshold]
df_total_method=df_comb[sigma>=threshold]fig, (ax1,ax2)=plt.subplots(2,sharex=True)
ax1.plot(df_comb['date'],df_comb[topic],linestyle='--',color='tab:purple')
ax1.plot(df_rolling_method['date'],df_rolling_method[topic],'ro',markersize=2)
ax1.set_ylabel('rolling method')ax2.plot(df_comb['date'],df_comb[topic],linestyle='--',color='tab:purple')
ax2.plot(df_total_method['date'],df_total_method[topic],'ro',markersize=2)
ax2.set_ylabel('total method')#优化日期格式
locator = mdates.AutoDateLocator(minticks=10, maxticks=15)
formatter = mdates.ConciseDateFormatter(locator)
ax1.xaxis.set_major_locator(locator)
ax1.xaxis.set_major_formatter(formatter)
ax1.xaxis.set_minor_locator(mdates.MonthLocator())fig.savefig('image/相对峰值与绝对峰值.jpg',dpi=500)


3.将话题指数change_index(k)<threshold值的重新赋值为0,表示该关键词百度指数无明显爆发,change_index(k)>threshold值保持不变表示该关键词百度指数爆发了且当日增长了k倍的5日标准差。

4.分别计算上证指数和选定股票的短期收益率

def stock_topic(df):for col in range(3,len(df.columns)):single_col = df.iloc[:,col]moving_avg = single_col.rolling(window=5).mean(center=True) #计算各话题指数的5日移动平均值moving_std = single_col.rolling(window=5).std(center=True) ##计算各话题指数的5日移动标准差值col_name='initial_change_'+df.columns[col]df[col_name]=(single_col-moving_avg)/moving_std col2_name='change_'+df.columns[col]df[col2_name]=df.apply(lambda x:x[col_name] if x[col_name]>=threshold else 0 ,axis=1) #将超过平均值的threshold倍标准差的数值保留,并将没超过的设为0df.fillna(0,inplace=True)df_comb=df.reset_index(drop=True)Rf=(1+Rf_year)**(1/365)-1 #计算无风险日利率df_comb['sh_ret']=(df_comb['sh']/(df_comb['sh']-df_comb['sh'].diff(diff_num))-1-Rf)*100 #计算上证指数的diff_num日收益率百分比数df_comb['close_ret']=(df_comb['close']/(df_comb['close']-df_comb['close'].diff(diff_num))-1-Rf)*100 #计算要研究的股票的diff_num日收益率百分比数df_comb.dropna(inplace=True)df_comb.reset_index(drop=True,inplace=True)return df_comb
pd.options.display.encoding = 'GBK'df=df_backup.copy()
df_comb=stock_topic(df)
df_comb

可视化分析

各百度指数间相关性分析

df=df_backup.copy()
df_corr = df.corr(method='pearson')
cmap = sns.diverging_palette(220, 10, as_cmap=True)
fig, ax = plt.subplots(figsize=(10,10))pd.options.display.encoding = 'GBK'sns.heatmap(df_corr, cmap=cmap, vmax=1.0, center=0, fmt='.2f',square=True, linewidths=.5, annot=True, cbar_kws={"shrink": .75})ax.set_title('各特征的皮尔逊系数')
plt.savefig('image/各特征的皮尔逊系数.jpg',dpi=300)
plt.show()


皮尔逊系数-Pearson代表着两两特征的相关系数,趋近于-1表示线性负相关,趋近于0表示线性不相关,趋近于1表示线性正相关。如图上所示,大部分特征相关性较低,表示后面训练出来的多因子模型不太会受到多重共线性的影响。

话题热度时间及股票收益率总览

import matplotlib.pyplot as plt
import seaborn as snsx_columns_list=[]
x_columns_list.append('date')
for i in range(3,len(df_backup.columns)):x_columns_list.append('change_'+df_backup.columns[i])df_map=df_comb[x_columns_list]
df_map.set_index('date',inplace=True)
df_map.Tstock='sh'
df_hot=df_comb[df_comb['change_'+topic]>=threshold]cmap = sns.diverging_palette(220, 10, as_cmap=True)
fig, (ax1,ax2) = plt.subplots(2,figsize=(10,10))sns.heatmap(df_map.T, cmap=cmap, vmax=1.0, center=0, fmt='.2f',ax=ax1,cbar=False,square=False, linewidths=.5, annot=False, cbar_kws={"shrink": .75},xticklabels=False,yticklabels=True)
ax1.set_ylabel('话题热度时间表')ax2.plot(df_comb['date'],df_comb['close_ret'],label=stock+'_stock')
ax2.set_ylabel('股票收益率')plt.savefig('image/话题热度时间及股票收益率总览.jpg',dpi=300)
plt.show()

话题热度分布

df_index_change=df_comb[x_columns_list]
df_index_change=df_index_change.iloc[:,1:]empty_num_list=[]
specific_num_list=[]
for col in df_index_change.columns:empty_num_list.append(sum(df_index_change[col]==0))specific_num_list.append(sum(df_index_change[col]!=0))N = len(empty_num_list)
ind = np.arange(N)    # the x locations for the groups
width = 0.35       # the width of the bars: can also be len(x) sequencefig, ax = plt.subplots()p1 = ax.bar(ind, empty_num_list, width, label='话题未被关注的天数')
p2 = ax.bar(ind, specific_num_list, width,bottom=empty_num_list,label='话题被关注的天数')ax.axhline(0, color='grey', linewidth=0.8)ax.set_title('话题热度分布')
ax.set_xticks(ind, labels=df_index_change.columns)
ax.legend()ax.bar_label(p1, label_type='center')
ax.bar_label(p2, label_type='center')
plt.setp(ax.get_xticklabels(), rotation=90, horizontalalignment='right')
plt.legend(loc='lower left')plt.savefig('image/话题热度分布.jpg',dpi=300)
plt.show()


在样本量为300天的数据集中,各话题百度指数爆发的天数大约为总样本的10%-20%, 存在真实样本数不足的隐患,后续可以增加样本量的提取以解决此问题。

相关话题热度与股票股价及收益率的关系图

for i in range(3,len(df_backup.columns)):topic=df_backup.columns[i]df_hot=df_comb[df_comb['change_'+topic]>threshold]fig, (ax1,ax2,ax3)=plt.subplots(3,sharex=True)ax1.plot(df_comb['date'],df_comb[topic],linestyle='--',color='tab:purple',label=topic)ax1.plot(df_hot['date'],df_hot[topic],'ro',markersize=2)ax1.set_ylabel(topic+'_index')ax2.plot(df_comb['date'],df_comb['close'],label=stock+'_stock_price')ax2.plot(df_hot['date'],df_hot['close'],'ro',markersize=2)ax2.set_ylabel(stock+'_stock_price')ax3.plot(df_comb['date'],df_comb['close_ret'],linestyle='--',label=stock+'_stock_ret')ax3.plot(df_hot['date'],df_hot['close_ret'],'ro',markersize=2)ax3.set_ylabel(stock+'_stock_ret')locator = mdates.AutoDateLocator(minticks=10, maxticks=15)formatter = mdates.ConciseDateFormatter(locator)ax1.xaxis.set_major_locator(locator)ax1.xaxis.set_major_formatter(formatter)ax1.xaxis.set_minor_locator(mdates.MonthLocator())ax1.set(title='相关话题热度与股票股价及收益率的关系图')fig.legend(prop={'size':8})fig.savefig('image/'+topic+'_'+stock+'.jpg', dpi=500)

部分生成的图如下所示



可见,单一的相关话题热度峰值与股票收益率之间没有明显的关系。

多因子模型的搭建

说到多因子模型就很难能绕开CAPM(资产定价模型)来搭建,这是因为个股往往会一定程度的跟随大盘的走势波动。

CAPM

美国学者夏普、林特尔、特里诺和莫辛等人于1964年在资产组合理论的基础上发展出来了一个资本资产定价模型(简称CAPM模型)。这个模型根据股票本身的风险和市场风险的相关性估算出单个股票的期望收益率。

在公开市场中,越高的收益率往往伴随着越高的风险,这时因为高收益率低风险的资产进入公开市场后势必很快由于大家争相购买而抬高到应有的价格区间中,从而变成低收益低风险的资产,反之亦然。所以现在市场可自由交易的资产中,资产的预期收益率和波动等同于资产的风险。

而资产的收益率和波动很大程度上被系统性风险所影响,其中系统性风险即市场风险-- 通常由大盘指数的波动率来衡量(波动即风险)。这种关系通常被写成

ri=单个股票的风险(预期收益率)
rf=无风险收益率
rM=大盘期望的收益率
βi即为市场因子

import statsmodels.api as sm
def capm():X=df_comb['sh_ret']y=df_comb['close_ret']x=sm.add_constant(X)md_capm=sm.OLS(y,x)  result=md_capm.fit()  return resultcapm().summary()


如上图所示,以市场因子作为唯一影响因子预测股票的收益率的结果为Adj.R-squared=0.384,sh_ret=1.38。该结果表示大盘收益率每上涨1%,中兴通讯的收益率会上涨1.38%,且中兴通讯的波动的38.4%可以用大盘的波动解释,即如果中兴通讯上涨了10%,这10%中有3.84%是由于大盘收益率的上涨。

多因子策略

CAPM首先就假设了市场风险是唯一风险因子。但在现实中,仅仅由市场风险是不足以解释资产回报的,因此,人们对CAPM做了改进,认为资产的收益率中的一部分是资产内秉特性,记为αi,那么有

其中,αi可以是成长类因子、估值类因子、现金流类因子、经营效率类因子、财务质量类因子等,而在本文中αi是话题指数因子。

def multi_factor():x_columns_list=[]for i in range(3,len(df_backup.columns)):x_columns_list.append('change_'+df_backup.columns[i])x_columns_list.append('sh_ret')X=df_comb[x_columns_list]y=df_comb['close_ret']x=sm.add_constant(X)md_capm=sm.OLS(y,x)  result=md_capm.fit()  return result
multi_factor().summary()


如上图所示,整体效果而言Adj.R-squared=0.384。该结果表示中兴通讯的波动的39%可以用大盘+相关关键词的百度指数的波动解释,总体增加了0.5%的可解释性。

result=multi_factor(Rf_year)x_columns_list=[]
for i in range(3,len(df_backup.columns)):x_columns_list.append('change_'+df_backup.columns[i])
x_columns_list.append('sh_ret')X=df_comb[x_columns_list]
y=df_comb['close_ret']
x=sm.add_constant(X)df_comb['close_ret_pred']=result.predict(x)fig, ax1=plt.subplots()
ax1.plot(df_comb['date'],df_comb['close_ret'],linestyle='--',color='tab:purple',label='实际收益率')ax2 = ax1.twinx()
ax2.plot(df_comb['date'],df_comb['close_ret_pred'],label='预测收益率')locator = mdates.AutoDateLocator(minticks=10, maxticks=15)
formatter = mdates.ConciseDateFormatter(locator)
ax1.xaxis.set_major_locator(locator)
ax1.xaxis.set_major_formatter(formatter)
ax1.xaxis.set_minor_locator(mdates.MonthLocator())
ax1.set(title='股票收益率拟合')fig.legend(loc='upper right')
plt.savefig('image/股票收益率拟合.jpg',dpi=300)
fig.show()

fig = plt.figure(figsize=(15,8))
fig = sm.graphics.plot_regress_exog(result,"sh_ret", fig =fig)
plt.savefig('image/拟合结果分析.jpg',dpi=300)

# 回归系数表汇总提取
coef_df = pd.DataFrame({"params": result.params,   # 回归系数"std err": result.bse,     # 回归系数标准差"t": round(result.tvalues,3),       # 回归系数T值"p-values": round(result.pvalues,3) # 回归系数P值})coef_df[['coef_0.025','coef_0.975']] = result.conf_int() # 回归系数置信区间 默认5%,括号中可填具体数字 比如0.05, 0.1
coef_df.sort_values('p-values',inplace=True)import numpy as np
df_draw=coef_df.T
df_box=df_draw.loc[['params','coef_0.025','coef_0.975'],:]
fig, (ax1,ax2)=plt.subplots(2)
ax1.violinplot(df_box,showmeans=False,showmedians=True)ax1.xaxis.set_ticklabels([])
ax1.set_ylabel('coef')
ax1.set_title('线性模型拟合结果')bar=ax2.bar(coef_df.index,coef_df['p-values'],width=0.5)
ax2.bar_label(bar,padding=3,size=7)
ax2.set_ylabel('p-value')
ax2.set_xlabel('feature')
plt.setp(ax2.get_xticklabels(), rotation=90, horizontalalignment='right')plt.savefig('image/线性模型拟合结果特征分析.jpg',dpi=300)
plt.show()


如图上所示,上证指数、车联网、物联网的p-value分别为0、0.074、0.092,这表示当置信度=0.11时,我们有充分理由相信上证指数的短期收益率、“车联网”的百度指数、“物联网”的百度指数可以一定程度地估算出‘中兴通讯’的收益率约等于1.3568上证指数的短期收益率+0.9044
“车联网”的百度指数+0.9411*“物联网”的百度指数。即当互联网用户对车联网或物联网的关注度爆发的那一天,‘中兴通讯’的股价预计获得约为1%的超额收益α。

所以,我们可以将置信度高的相关关键词的百度指数作为选择特定股票的因子作为多因子模型的部分加入到交易策略模型中去。

基于百度指数的股票收益率多因子模型研究相关推荐

  1. 基于百度搜索指数生成的可视化地图

    下载地址:https://download.csdn.net/download/Mrrunsen/69566348 基于百度搜索指数生成的可视化地图说明文档 程序说明 该程序是基于百度搜索指数生成的可 ...

  2. 2021 百度指数采集工具与研究

    百度指数是以百度海量网民行为数据为基础的数据分享平台.在这里,你可以研究关键词搜索趋势.洞察网民兴趣和需求.监测舆情动向.定位受众特征.对趋势研究有一定的指导意义. 历来百度指数的采集是爬虫界的梦魇. ...

  3. 2020 论文研究数据之 - 百度指数采集工具

    百度指数是以百度海量网民行为数据为基础的数据分享平台. 在这里,你可以研究关键词搜索趋势.洞察网民需求变化.监测媒体舆情趋势.定位数字消费者特征:还可以从行业的角度,分析市场特点. 在此本文提供采集百 ...

  4. matlab指数跟踪优化模型,基于聚类选股的上证50指数跟踪遗传算法优化模型研究...

    [摘要]中国的证券市场经过二十多年的发展,已经从一棵幼苗发展成了一棵枝繁叶茂的参天大树,市场指数体系的建立也已基本完善,建成了上证综合指数.深证综合指数.沪深300指数.上证180指数.上证50指数. ...

  5. 百度指数、360指数爬虫python版:基于selenium+chrome和图像识别技术

    如果需要帮忙爬取数据,请加QQ:2422035338 一.前言: 1.本博客主要介绍百度指数爬取,360指数获取类似: 2.想要获取数据必须先登录百度指数,频繁登陆会导致要求输入验证码和手机验证码: ...

  6. 百度指数可视化_可视化指数

    百度指数可视化 Abstract:– Analysis of the visual representations of exponentials.– Proposals to solve curre ...

  7. 鉴赏百度指数,打造自己的爆款数据产品

    开局一张图 如何才能设计出爆款数据产品?这个问题就好比"怎样才能画出世界名画一样",没有定法.但经常欣赏优秀的作品,尤其是在专业人士的指引下鉴赏名作,一定是各个阶段画家的必经之路. ...

  8. 爬虫天坑系列-百度指数爬虫

    原文地址:http://blog.shenjianshou.cn/?p=170 giithub:https://github.com/TTyb/Baiduindex 最近有很多朋友跟我说," ...

  9. R语言量化技术分析的百度指数关注度交易策略可视化

    全文链接:http://tecdat.cn/?p=31556 传统的经济理论认为股票市场是有效的,价格波动是对市场信息的反应,投资者能够及时处理所有实时信息并做出最优决策(点击文末"阅读原文 ...

  10. 基于百度时空大数据的城市计算(讲座精华笔记)

    基于百度时空大数据的城市计算(讲座精华笔记) THU数据派 2017-05-27 23:24 [导读]本文整理自2017年5月24日,百度自动驾驶事业部创始团队成员.高级技术顾问秦伟俊博士在清华大数据 ...

最新文章

  1. Ubuntu下git使用教程
  2. php excel 读取日期问题
  3. 如何使用SAP Cloud for Customer的Key User Tool将Mashup添加到UI上
  4. python选取特定行_pandas.DataFrame选取/排除特定行的方法
  5. [基础]全局组、域本地组、通用组的区别与联系
  6. php输出内容到页面,php实时输出内容
  7. 组态软件基础知识概述
  8. php jwt payload,php实现jwt
  9. HTML5写的简单登录页面
  10. python如何解压zip文件_Python压缩解压zip文件
  11. STM32F103标准库函数驱动max30102心率血氧模块
  12. 践行快乐音乐教育 郎朗The ONE全球公益钢琴盛典传递音乐力量!
  13. 数学建模上课(一)推导万有引力定律
  14. 完全java实现一款开源的报表工具简表(JOR)
  15. 我不是蓝牙大神,但还是斗胆对蓝牙学习路线给点建议!
  16. 小马哥---高仿苹果6 plus 主板型号Q33 6582芯片刷机拆机主板图与开机界面图 镜面后壳
  17. 国产AI绘画海克斯科技——爱作画AIGC开放平台
  18. Android项目开发:简易计步器
  19. 统计学练习题——组合,排列组合
  20. 无法启动此程序,因为计算机中丢失vcruntime140.dll”的解决方法

热门文章

  1. L. Simone and graph coloring
  2. Windows远程应用发布
  3. java实现屏幕亮度调节
  4. 怎么制作表情DIY,动态GIF表情包如何制作?
  5. 使用容联云通讯实现短信验证登入
  6. 做sxy官网的一点经验
  7. Ghibli works
  8. scrapy---拉勾网Ajax爬虫
  9. 计算机教师个人品德事迹材料,教师个人品德事迹材料
  10. 两人分组问题:显示In function 'int main()'求大佬解惑