跑赢指数的分位数是多少?

前言

本篇是量化系列的第一篇文章。《量化十万个为什么》系列旨在讨论一些自己心中的疑问,并且通过尝试解答这些问题来提升自己对于市场的认知水平。
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的概率都差不多。

上一篇:HZHControls控件库学习笔记 第一部分 (动态多输入窗体)


下一篇:面试必备知识点:悲观锁和乐观锁的那些事儿