【历史文档】高阶技巧-情绪指标的构建和使用
由qxiao创建,最终由small_q 被浏览 535 用户
更新
本文内容对应旧版平台与旧版资源,其内容不再适合最新版平台,请查看新版平台的使用说明
新版量化开发IDE(AIStudio):
https://bigquant.com/wiki/doc/aistudio-aiide-NzAjgKapzW
新版模版策略:
https://bigquant.com/wiki/doc/demos-ecdRvuM1TU
新版数据平台:
https://bigquant.com/data/home
https://bigquant.com/wiki/doc/dai-PLSbc1SbZX
新版表达式算子:
https://bigquant.com/wiki/doc/dai-sql-Rceb2JQBdS
新版因子平台:
https://bigquant.com/wiki/doc/bigalpha-EOVmVtJMS5
导语
很多朋友在股票行情软件上能看到很多情绪的指标,例如每日涨停/跌停数,每日上涨股票数,昨日涨停溢价,昨日连板溢价,行业板块百日新高等。此篇文章了介绍如何在宽邦平台上构建这些情绪指标以及如何使用的思路。
指标构建
每日涨停/跌停数
定义
统计每日的股票涨停数和跌停数
构建
在输入特征列表中加入price_limit_status_0抽取股票的涨跌停因子,然后按照日期分组计算每日的涨停/跌停数,同时获取中证500指数数据作为对照,用T.plot方法画出每日涨停/跌停数和指数走势图。
#获取指数数据
df_index_000905 = DataSource('bar1d_index_CN_STOCK_A').read(instruments=['000905.HIX'], start_date='2018-01-01')
df_index_000905['returns'] = (df_index_000905.close / df_index_000905.close.shift(1) -1) + 1
df_index_000905['中证500'] = df_index_000905['returns'].cumprod()
df_index_000905['中证500'] = df_index_000905['中证500'] .fillna(1)
#涨停和跌停数
def cal_limit(x):
x['涨停数'] = len(x[x.price_limit_status_0==3])
x['跌停数'] = len(x[x.price_limit_status_0==1])
x['上涨数'] = len(x[x.return_0>1])
return x
df_limit = df_total.groupby('date').apply(cal_limit)
df_limit = df_limit.drop_duplicates(subset=['date'],keep='last').sort_values('date').reset_index()
df_limit = pd.merge(left=df_limit,right=df_index_000905[['date','中证500']],left_on='date',right_on='date')
#与指数合并
options = {'chart': {'type': 'spline', 'height': 600},}
T.plot(df_limit[['date','涨停数','跌停数','中证500']].set_index('date'),title='每日涨停跌停数',panes=[['涨停数', '跌停数', '60%'], ['中证500', '40%']],options=options)
每日上涨股票数
定义
统计每日上涨股票的数量
构建
在输入特征列表中加入return_0,抽取股票的当日收益因子,此因子大于1表示股票当日上涨,然后按照日期分组计算每日的上涨股票数,同时获取指数数据,用T.plot方法画出每日上涨股票和指数走势图。
代码跟每日涨停/跌停数的构建类似,最终效果图如下:
可以看到跟行情软件的涨跌家数指标在相同时间段内走势相同:
昨日涨停溢价
定义
T-1日涨停股票在T日的算术平均涨跌幅
构建
利用price_limit_status_0==3过滤出当日涨停的股票,return_0往后偏移一天即可求出次日的收益率,具体代码如下:
#根据收益率计算指数净值
df_yj = df_total.copy().reset_index(drop=True)
df_yj = df_yj[df_yj.price_limit_status_0==3]
#获取交易日为了填充空值
df_trade = DataSource("trading_days").read(start_date="2018-01-01")
df_trade = df_trade[df_trade.country_code=='CN']
df_trade.sort_values('date')
def cal_return(x):
return x.next_return.mean()
df_yj = df_yj.groupby('date').apply(cal_return)
df_yj = pd.DataFrame(df_yj).rename(columns={0:'return'})
df_yj = pd.merge(left=df_trade,right=df_yj,left_on='date',right_index=True,how='left')
df_yj = df_yj.set_index('date')
df_yj['return'] = df_yj['return'].fillna(1)
df_yj['return'] = df_yj['return'].shift(1)
df_yj['return'] = df_yj['return'].fillna(1)
df_yj['净值'] = df_yj['return'].cumprod()
最终效果图如下,大家会发现这是一根”宇宙射线”,已经涨停的股票一般是很难买进的,所以大家不要想着每天去买涨停的票然后收益率会像下图一下。那是不是说这个指标就没有什么意义,后面我们会介绍如何使用此指标来做仓位控制的思路。
跟行情软件的昨日涨停指数走势类似(前复权)
昨日连板溢价
定义
T-1日连板股票在T日的算术平均涨跌幅,跟涨停溢价指标不同的是,统计的股票T-2日也是涨停的。
构建
利用price_limit_status_0==3过滤出当日涨停的股票,往前偏移一天同时过滤出前一天也涨停的股票,return_0往后偏移一天即可求出次日的收益率,具体代码如下:
#昨日连扳指数
df_lb = df_total.copy().reset_index(drop=True)
df_lb = df_lb[(df_lb.price_limit_status_0==3)&(df_lb.pre_limit_status_0==3)]
def cal_return(x):
return x.next_return.mean()
df_lb = df_lb.groupby('date').apply(cal_return)
df_lb = pd.DataFrame(df_lb).rename(columns={0:'return'})
df_lb['return'] = df_lb['return'].shift(1)
df_lb['return'] = df_lb['return'].fillna(1)
df_lb['净值'] = df_lb['return'].cumprod()
T.plot(df_lb['净值'])
效果图如下:
跟行情软件的昨日连板指数走势一致:
行业板块百日新高数
定义
统计每个板块创过去100个交易日新高的股票数。
构建
代码列表中输入如下代码,抽取100个交易日的最高价格因子,然后判断当日收盘价是否超过过去100日的最高价。
maxhigh100=ts_max(high_0, 100)
flag=where(close_0>shift(maxhigh100,1),1,0)
以申万一级行业作为统计标的,计算每个行业的百日新高股票数
#计算每个行业的百日新高股票数
df_industry = DataSource("industry_CN_STOCK_A").read(start_date="2018-01-01")
df_basic_industry = DataSource("basic_info_IndustrySw").read()
df_basic_industry = df_basic_industry[df_basic_industry.version==2021]
#股票数据
df_stock = m4.data.read()
df_result = pd.merge(left=df_stock,right=df_industry[['instrument','date','industry_sw_level1']],on=['instrument','date'],how='left')
df_result = df_result.dropna(subset=['industry_sw_level1'])
df_result['industry_sw_level1'] = df_result['industry_sw_level1'].astype(int).astype(str)
df_result = pd.merge(left=df_result,right=df_basic_industry[['code','name']],left_on='industry_sw_level1',right_on='code',how='left')
#按照时间分类计算行业的数据
def cal_industry(x):
return x.groupby('name').apply(lambda x:len(x[x.flag==1]))
df_result = df_result.groupby('date').apply(cal_industry)
获取行业的百日新高股票数,然后画出某个行业的走势图:
#转换成宽表格式
df_tmp = pd.DataFrame(df_result)
df_tmp = df_tmp.reset_index()
df_tmp = df_tmp.pivot(index='date',columns='name',values=0)
df_tmp = df_tmp.fillna(method='bfill')
#画出某个行业的百日新高数走势图
T.plot(df_tmp[['医药生物']],title='百日涨停数')
可以画出某段时间的行业百日新高数,可以做个对比,看出哪些行业已经退潮,或者是当前的热门行业
#画图最近几日各板块百日新高数占比趋势
df_day_pct_tmp = df_tmp.copy()
df_day_pct_tmp['合计'] = df_tmp.sum(axis=1)
df_day_pct_tmp.index = df_day_pct_tmp.index.strftime('%Y-%m-%d')
#画出最近5日的情况
for date in df_day_pct_tmp.index[-1:]:
df_day_pct = df_day_pct_tmp[df_day_pct_tmp.index==date]
total = df_day_pct.iloc[0]['合计']
df_day_pct = df_day_pct.T
#求出每个行业百日新高数占比
df_day_pct['pct'] = df_day_pct.iloc[0:-1,0]/total
df_day_pct=df_day_pct.iloc[0:-2]['pct']
#只取有涨停的板块
df_day_pct = df_day_pct[df_day_pct>0]
df_day_pct = df_day_pct.sort_values(ascending=False)
options={'title': {'text': "百日新高行业占比"+date},'chart': {'type': 'column'}}
T.plot(df_day_pct,options=options)
指标的使用
上面介绍了一些情绪指标的构建,那么如何使用这些指标来提高我们策略的效率呢?不同的人不同的策略使用方法可能都不相同,这里构建昨日涨停溢价的RSI指标为例,抛砖引玉。
相对强弱指数RSI是根据一定时期内上涨和下跌幅度之和的比率制作出的一种技术曲线。能够反映出市场在一定时期内的景气程度。
在构建昨日涨停溢价指标的代码基础上,利用talib包传入每日涨停溢价的均值,可以直接计算出RSI指标的值,我们再画出中证500的走势图,一起观察下。
N = 5
df_yj["rsi"] = ta.RSI(df_yj['return'].values, timeperiod=N)
#合并指数数据
df_yj = pd.merge(left=df_yj,right=df_index_000905[['date','中证500']],left_on='date',right_on='date')
df_yj = df_yj.set_index('date')
options = {'chart': {'type': 'spline', 'height': 600},}
T.plot(df_yj[['rsi','中证500']],panes=[['rsi', '60%'], ['中证500','40%']],options=options,title='涨停溢价RSI')
大家可以看到当RSI低于某个值的时候,市场处于超卖区,中证500的走势恰好也是一个低谷。当然,这只是一个概率,而且用中证500来观察这种短期情绪指标不是最好的选择(大家有更好的方法可以评论区回复),这里只是作为示例,大家可以结合自己的策略来进行回测,在超卖区进行建仓或者加仓,在超买区进行平仓或者建仓。涨停溢价属于短期情绪指标,所以如果大家有一些短线追涨策略,相关性可能会更高。
\
完整代码
https://bigquant.com/experimentshare/c92c776fb50b4338b367a4d32845e443
\