01 引言
中国证监会于 2014 年和 2016 年分别批准了沪港通和深港通,建立了大陆和香港股市的互联互通机制,市场通常把沪股通和深股通的合计流入资金称为北向资金。换句话说,北上资金就是指从香港流入大陆股市的资金,而内地流入香港股市的资金则被称为南下资金。市场广 泛认为北向资金是“聪明钱”,会对市场的短期走势有一定的指示作用,因此本文对该指标进行统计分析,并借鉴华泰金工研量化资产配置7月月报《北向资金走向预示市场短期或震荡》关于北上资金的择时思路,构建基于北向资金的股市择时策略,并进行历史回测。结果表明,北向资金对于判断沪深 300指数涨跌具有较好的预示作用。
02 数据获取
本文所使用的指数数据和北上资金数据均来自tushare.pro。如果由于积分受限,可在公众号后台回复“北上资金”获取相应csv格式数据。
<code>import
pandasas
pdimport
numpyas
npimport
matplotlib.pyplotas
plt %matplotlib inlinefrom
pylabimport
mpl mpl.rcParams['font.sans-serif'
]=['SimHei'
] mpl.rcParams['axes.unicode_minus'
]=False
/<code>
由于tushare对北上资金数据的单次提取有限制(300条/次),需要通过获取两个时间周期内的交易日历,分次提取数据。
<code>import
tushareas
ts token='输入你的token'
pro=ts.pro_api(token) /<code>
<code>def
get_cal_date
(start,
end
): cal_date=pro.trade_cal(exchange=''
, start_date=start, end_date=end
) cal_date=cal_date[cal_date.is_open==1
] dates=cal_date.cal_date.valuesreturn
dates/<code>
定义北向资金数据获取函数。
<code> def get_north_money(start
,end
): dates=get_cal_date(start
,end
) df=pro.moneyflow_hsgt(start_date=start
, end_date=end
)for
iin
range
(0
,len
(dates)-300
,300
): d0=pro.moneyflow_hsgt(start_date=dates[i], end_date=dates[i+300
]) df=pd.concat([d0,df]) df=df.drop_duplicates() df.index=pd.to_datetime(df.trade_date) df=df.sort_index()return
df/<code>
定义指数数据获取函数。
<code>def
get_index_data
(code,start,
end
): index_df = pro.index_daily(ts_code=code, start_date=start,end_date=end
) index_df.index=pd.to_datetime(index_df.trade_date) index_df=index_df.sort_index()return
index_df/<code>
获取常用的几个指数2014-2020期间收盘价数据。
<code> indexs={'上证综指'
:'000001.SH'
,'深证成指'
:'399001.SZ'
,'沪深300'
:'000300.SH'
,'创业板指'
:'399006.SZ'
,'上证50'
:'000016.SH'
,'中证500'
:'000905.SH'
,'中小板指'
:'399005.SZ'
,'上证180'
:'000010.SH'
} start='20141117'
end
='20200812'
/<code>
<code>index_data=pd.DataFrame() for name,code in indexs.items(): index_data[name]=get_index_data(code,start
,end
)['close'
] /<code>
03 探索性分析
理论上而言,股市的上涨离不开资金的推动,而市场的活跃又会反过来吸引更多资金加入博弈。近年来,北上资金受到市场的关注越来越大,被看作是短期市场风向标,与市场指数存在一定的正向关系。当然理论在现实中不一定成立,所以在利用北上资金构建择时策略前,有必要先对指数和北上资金的关系进行探索性分析。
<code>#累计收益 (index_data/index_data.iloc[0
]).plot
(figsize=(14
,6
))plt
.title
('A股指数累积收益率\n 2014-2020'
,size=15
)plt
.show
() /<code>
陆股通覆盖大部分宽基指数成分股,即北向资金可投资的股票池覆盖了上证 50、沪深 300、中证 500 的绝大多数指数成分股,下面对各大指数的收益率和北上资金进行相关性分析。
<code> all_ret=index_data/index_data.shift(1)-1 north_data=get_north_money(start
,end
) all_data=all_ret.join(north_data['north_money'
],how='inner'
) all_data.rename(columns
={'north_money'
:'北向资金'
},inplace=True
) all_data.dropna(inplace=True
)/<code>
<code>all_data
.corr
()/<code>
上图显示,2014年至2020年8月整个交易期间内,北上资金与各大指数收益率均存在一定的正相关,但相关系数较低,分布在0.23-0.29之间。由于北上资金相对整个A股市场来说,体量还是比较小的,因此该指标的指示作用可能体现在短期内。下面使用120日的滚动窗口考察下北上资金与指数的相关性。
<code>all_data
.rolling
(120).corr
().tail
(9) /<code>
数据显示,北上资金与各大指数的滚动窗口120日相关系数均大于0.5,其中沪深300与北上资金相关系数最高(0.7),可见中短期内,北上资金的大小对指数收益率具有一定的指示作用。下面以沪深300指数为例,对二者的散点图进行回归线拟合。图形再次支持了北上资金与沪深300指数的正相关性。
<code>import
seaborn
as
sns
plt
.figure
(figsize=(10
,6
))sns
.regplot
(x=list(all_data["北向资金"
][-120
:]),y=list(all_data["沪深300"
][-120
:]))plt
.title
('沪深300与北向资金拟合回归线'
,size=15
)plt
.xlabel
('北向资金'
,size=12
)plt
.ylabel
('沪深300收益率'
,size=12
)plt
.show
()/<code>
再来观察一下沪深300日收益率与北上资金的波动情况,二者具有一定的同步性。
<code>#沪深300
指数收益率与北向资金 final_data=all_data[['沪深300','北向资金']]
.dropna() final_data.plot(secondary_y='北向资金'
,figsize=(12
,6
)) plt.title('沪深300日收益率 VS 北向资金'
,size=15
) plt.show()/<code>
<code>def
cal_rol_cor
(data,period=
30
): cors=data.rolling(period).corr() cors=cors.dropna().iloc[1
::2
,0
] cors=cors.reset_index() cors=cors.set_index('trade_date'
)return
cors['沪深300'
]/<code>
最后从纵向角度考察沪深300收益率与北上资金的相关性。数据显示,2014年至2020年8月期间,二者相关系数均值为0.33,最大值为0.7。图形显示,二者的相关性近年来逐渐走高。
<code>cor=cal_rol_cor(final_data,period=120) cor.describe() /<code>
<code>count
:1236
mean
:0.335
std
:0.219
min
:-0
.215
25%:0.219
50%:0.379
75%:0.525
max
:0.706
/<code>
<code>cor
.plot
(figsize=(14
,6
),label='移动120日相关系数'
)plt
.title
('沪深300与北向资金移动120日相关系数'
,size=15
)plt
.axhline
(cor.mean(), c='r'
,label='相关系数均值=0.33'
)plt
.legend
(loc=2
)plt
.show
()/<code>
04策略实例
从上面的探索性分析发现,北上资金与各大指数中短期内存在一定的正相关性,下面参考华泰金工研报的思路,基于北向资金变动数据构建布林带择时策略,并对择时模型进行回测分析。
策略思路如下:
(1) 当该日北向资金流入规模 > 过去 252 个交易日的北向资金均值 + 1.5 倍标准差, 则全仓买入沪深 300;
(2) 当该日北向资金流入规模 < 过去 252 个交易日的北向资金均值 - 1.5 倍标准差, 则清仓卖出沪深 300;
(3) 以第二天开盘价买入(研报是以收盘价来计量)。
定义策略函数:
<code>def
North_Strategy
(data,window,stdev_n,cost)
:'''输入参数: data:包含北向资金和指数价格数据 window:移动窗口 stdev_n:几倍标准差 cost:手续费 '''
df=data.copy().dropna() df['mid'
] = df['北向资金'
].rolling(window).mean() stdev = df['北向资金'
].rolling(window).std() df['upper'
] = df['mid'
] + stdev_n * stdev df['lower'
] = df['mid'
] - stdev_n * stdev df['ret'
]=df.close/df.close.shift(1
)-1
df.dropna(inplace=True
) df.loc[df['北向资金'
]>df.upper,'signal'
] =1
df.loc[df['北向资金'
]'signal'] =0
df['position'
]=df['signal'
].shift(1
) df['position'
].fillna(method='ffill'
,inplace=True
) df['position'
].fillna(0
,inplace=True
) df.loc[df.index[0
],'capital_ret'
] =0
df.loc[df['position'
] > df['position'
].shift(1
),'capital_ret'
] = \ (df.close/ df.open-1
) * (1
- cost) df.loc[df['position'
] 'position'].shift(1
),'capital_ret'
] = \ (df.open / df.close.shift(1
)-1
) * (1
-cost) df.loc[df['position'
] == df['position'
].shift(1
),'capital_ret'
] = \ df['ret'
] * df['position'
] df['策略净值'
]=(df.capital_ret+1.0
).cumprod() df['指数净值'
]=(df.ret+1.0
).cumprod()return
df/<code>
受篇幅所限,策略评价指标、可视化函数和主函数代码省略,完整代码见知识星球“Python金融量化”上分享(扫描下方二维码即可加入)。
<code>def
performance
(df)
:pass
/<code>
<code>def
plot_performance
(df,name)
:pass
/<code>
<code>def
main
(code=
'000300.SH'
,start='20141117'
,end='20200812'
,window=252
,stdev_n=1.5
,cost=0.00
):pass
/<code>
首先以沪深300指数进行回测,滚动窗口默认250日,手续费默认为0。回测结果显示,基于北上资金的择时策略表现较好,年化收益率17.8%,高于基准的5.3%,最大回撤17%低于基准32%,夏普比率为2.2。
<code>main
(code='000300.SH'
)/<code>
<code>回测标的:沪深300指数 回测期间:20151208—20200812 策略年胜率为:80.0
% 策略月胜率为:64.58
% 策略周胜率为:60.98
% 总收益率: 策略:106.36
%,沪深300:26.03
% 年化收益率:策略:17.81
%, 沪深300:5.37
% 最大回撤: 策略:17.28
%, 沪深300:32.46
% 策略Alpha
: 0.15
,Beta
:0.46
,夏普比率:2.2
/<code>
考虑到北上资金2016年后才开始备受关注,而且前文的探索性分析也显示相关性是2016年后逐年攀高,因此将回测起始时间改为2016年,交易手续费设置为1%(有点高)。结果显示,这一期间(实际上是2017年至今)的择时策略表现更佳,年化收益率达到24%。
<code>main
(code='000300.SH'
,start='20161117'
,cost=0.01
) /<code>
<code>回测标的:沪深300指数 回测期间:20171205—20200812 策略年胜率为:50.0
% 策略月胜率为:65.52
% 策略周胜率为:61.86
% 总收益率: 策略:72.01
%,沪深300:15.65
% 年化收益率:策略:23.93
%, 沪深300:5.92
% 最大回撤: 策略:17.29
%, 沪深300:32.46
% 策略Alpha
: 0.21
,Beta
:0.45
,夏普比率:2.1
/<code>
最后以创业板为标的进行历史回测,结果显示,策略效益整体优于基准,与沪深300指数相比,除了年化收益率外,其最大回撤和夏普比率相对差些。
<code>main
(code='399006.SZ'
) /<code>
<code>回测标的:创业板指指数 回测期间:20151208—20200812 策略年胜率为:80.0
% 策略月胜率为:54.17
% 策略周胜率为:54.88
% 总收益率: 策略:133.88
%,沪深300:-3
.75
% 年化收益率:策略:21.19
%, 沪深300:-0
.86
% 最大回撤: 策略:37.17
%, 沪深300:57.57
% 策略Alpha
: 0.22
,Beta
:0.5
,夏普比率:1.92
/<code>
05 结语
本文对各大指数与北上资金的相关性进行了探索性分析,并借鉴华泰金工研报关于利用北上资金来构建择时策略的思路,对沪深300和创业板指数进行了历史回测。回测结果表明,北上资金的流动规模具有一定的实战指示意义,短期内可用于对对大盘的走向进行研判,同时可用于对指数进行择时,指导股指期货交易。本文最后的历史回测与研报原文并未完全吻合,但策略表现上大同小异,可能与回测环境的配置有关,感兴趣的读者可试试采用回测框架(如backtrader)或量化平台进行更严谨的回测。本文的分析仅供学习参考,不构成任何投资建议!
参考资料:
华泰证券·《北向资金走向预示市场短期或震荡》2020.08
关于Python金融量化
专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取量化投资视频资料、量化金融相关PDF资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。