前言
本篇是量化系列的第一篇文章。《量化十万个为什么》系列旨在讨论一些自己心中的疑问,并且通过尝试解答这些问题来提升自己对于市场的认知水平。
PS:博主水平很辣鸡,请大家轻喷,多多指教!
一、为什么提这个问题?
对于一个策略来说,到底持仓多久才是比较合适的?这个恐怕是一个挺难回答的问题,那我们是否可以反向来看一看,到底超越指数的分位数到底是多少呢?
二、分析
我们选取2018年至2020年的股票数据,以沪深300作为基准,看一看持仓不同的天数,跑赢基准的概率是多少。
# 先获取股票
start_date = '20180101'
end_date = '20201231'
year_lst = assistant.GetinnerYearLst(start_date=start_date,end_date=end_date)
data_dic = assistant.ReadDayBarYear(year_lst=year_lst)
# 从 tushare 上获取 沪深300 数据
benchmark_df = pro.index_daily(ts_code='399300.SZ', start_date=start_date, end_date=end_date)
benchmark_df = benchmark_df.sort_values(by='trade_date').reset_index(drop=True)
benchmark_date_se = pd.to_datetime(benchmark_df['trade_date'].astype(str))
benchmark_date_se.name = 'datetime'
benchmark_df.index = benchmark_date_se
# 选取持仓天数为 1,2,3,5,10,20,30
test_day_num_lst = [1,2,3,5,10,20,30]
answer_dic = {}
for past_day_num in test_day_num_lst:
benchmark_price = benchmark_df['close']
benchmark_return = (benchmark_price - benchmark_price.shift(past_day_num))/benchmark_price.shift(past_day_num)
total_answer_df = pd.DataFrame(index=benchmark_date_se)
for stock_name in data_dic.keys():
stock_df = copy.copy(data_dic[stock_name])
close_price = stock_df['Close']*stock_df['Adj_Factor']
stock_return = (close_price - close_price.shift(past_day_num))/close_price.shift(past_day_num)
# 把结果合并比较
tmp_df = pd.DataFrame(columns=['result','stockreturn','bmreturn'],index=benchmark_date_se)
tmp_df['bmreturn'] = benchmark_return
tmp_df.loc[stock_return.index,'stockreturn'] = stock_return
stock_higher_index = tmp_df[tmp_df['stockreturn'] > tmp_df['bmreturn']].index
stock_lower_index = tmp_df[tmp_df['bmreturn'] > tmp_df['stockreturn']].index
tmp_df.loc[stock_higher_index,'result'] = 1
tmp_df.loc[stock_lower_index,'result'] = 0
total_answer_df[stock_name] = tmp_df['result']
total_merge_df = copy.copy(total_answer_df).T
tmp_se = total_merge_df.fillna(0).sum()/(len(total_merge_df) - total_merge_df.isnull().sum())
answer_dic.update({past_day_num:tmp_se})
我们来看一下结果:
先看看持仓一天的情况
看上去基本上是一个稳定的随机数列
其分布如下图:
均值为 0.4572 ,方差为 0.1716,所以实际上对于A股来说,随便取一只股票,持仓一天,都会有45%的概率跑赢沪深300。
持有5天的情况和1天的情况类似,分布如下图
但是,随着持仓时间的增加,概率出现了某种周期性
可以看到,30天的持仓,似乎出现了某种周期?可以看到30日持仓的周期为5-6个月。我们结合指数看看都发生了什么事
结合沪深300的走势图来看,似乎处于周期底部之后,沪深300会下跌(和沪深300走势呈负相关)?但是似乎周期的时机抓得不是特别好?我们换一个持仓20个交易日的情况来看
效果也似乎不是特别的好,我们换回持仓30个交易日的数据,求diff之后,再和指数未来一天的return求相关性。
se = answer_dic[30].diff()
bm_furt = (benchmark_price.shift(-1) - benchmark_price)/benchmark_price
pd.DataFrame({'Dif':se,'BmFurt':bm_furt}).corr()
可以看到相关性大约有-0.06,其实还是有一些关系的。也许可以做一个股指期货的因子?
最后我们来看一下不同的持仓周期跑赢指数的概率均值是多少
for k in answer_dic.keys():
print(k,answer_dic[k].mean(),answer_dic[k].std())
结果如下:
持仓周期 | 均值 | 方差 |
---|---|---|
1 日 | 0.457 | 0.172 |
2 日 | 0.451 | 0.175 |
3 日 | 0.448 | 0.177 |
5 日 | 0.442 | 0.177 |
10 日 | 0.434 | 0.173 |
20 日 | 0.424 | 0.175 |
30 日 | 0.417 | 0.17 |
总结
由上面的表格可以看出,方差总体上都差不多,实际上即使拉长了持仓周期,获得超额收益的概率也并没有降低很多,从45.7%变为41.7%,即为任何持仓周期下,跑赢沪深300的概率都差不多。