炒股问题_股票知识问答_股票黑马推荐_问股网_在线诊股 设为首页 - 加入收藏 - 网站地图

选股策略测试工具(注册制选股策略)

1. 概述


本文以海通证券《选股因子系列研究(十二)——“量”与“价”的结合》的研究方法为模板,试图分析量价相关关系作为因子的效果:

  • 将股票在短期内的量价走势分类为量价背离与量价同向,并通过量价相关性来衡量量价走势的背离与同向程度
  • 按照量价因子选股的月度多空收益在1%以上,得到了很显著的alpha
  • 纯多头组合在六年回测中年化收益达到22.4%,信息比率达到2.22
  • 量价因子等权叠加了反转因子后,六年回测年化收益达到26.0%,信息比率达到2.55

2. 量价因子构建


股票交易中,最显然的指标无非价格成交量,大多经典的技术指标其实都是围绕着价格和成交量来构建,本文中尝试将这两者结合起来构建量价因子。中短周期上,量价走势分类为量价背离与量价同向,并通过量价相关性来衡量量价走势的背离与同向的程度。因此,量价相关性,也就是本文中的量价因子,可以简单定义为:

  • 一段时间窗口内,股票收盘价与股票日换手率之间的秩相关系数

本文中的量价相关系数计算,采取的时间窗口为15个交易日

下面给出本文中用来计算量价因子的程序代码

import matplotlib.pyplot as plt from matplotlib import rc from matplotlib import dates rc('mathtext', default='regular') import seaborn as sns sns.set_style('white') import datetime import numpy as np import pandas as pd import time import scipy.stats as st from CAL.PyCAL import * # CAL.PyCAL中包含font

def getVolPriceCorrAll(universe, begin, end, window, file_name): # 计算各股票历史区间window天窗口移动的量价相关系数 # 拿取上海证券交易所日历 cal_dates = DataAPI.TradeCalGet(exchangeCD=u"XSHG", beginDate=begin, endDate=end).sort('calendarDate') cal_dates = cal_dates[cal_dates['isOpen']==1] all_dates = cal_dates['calendarDate'].values.tolist() # 工作日列表 print str(window) + ' days Price-Volume-Corr will be calculated for ' + str(len(universe)) + ' stocks:' count = 0 secs_time = 0 start_time = time.time() ret_data = pd.DataFrame() # 保存计算出来的收益率数据 ret_data.to_csv(file_name) N = 10 for i in range(len(universe)/N+1): sub_univ = universe[i*N:(i+1)*N] if len(sub_univ) == 0: continue data = DataAPI.MktEqudAdjGet(secID=sub_univ, beginDate=begin, endDate=end, field='secID,tradeDate,turnoverRate,preClosePrice,closePrice') # 拿取数据 for stk in sub_univ: # 对每一只股票分别计算历史window天前望收益率 tmp_ret_data = data[data.secID==stk].sort('tradeDate') corr_data = range(len(tmp_ret_data)) for i in range(window-1, len(tmp_ret_data)): x = tmp_ret_data['turnoverRate'].values[i-window+1:i+1] y = tmp_ret_data['closePrice'].values[i-window+1:i+1] corr_data[i] = st.spearmanr(x, y)[0] # 计算前向收益率 tmp_ret_data['corr'] = corr_data tmp_ret_data = tmp_ret_data[['tradeDate','corr']] tmp_ret_data.columns = ['tradeDate', stk] ret_data = pd.read_csv(file_name) if ret_data.empty: ret_data = tmp_ret_data else: ret_data = ret_data[ret_data.columns[1:]] ret_data = ret_data.merge(tmp_ret_data, on='tradeDate', how='outer') ret_data = ret_data.sort('tradeDate') ret_data.to_csv(file_name) # 打印进度部分 count += 1 if count > 0 and count % 2 == 0: finish_time = time.time() print count*N, print ' ' + str(np.round((finish_time-start_time) - secs_time, 0)) + ' seconds elapsed.' secs_time = (finish_time-start_time) return ret_data def getBackwardReturnsAll(universe, begin, end, window, file_name): # 计算各股票历史区间回报率,过去window天的收益率 print str(window) + ' days backward returns will be calculated for ' + str(len(universe)) + ' stocks:' count = 0 secs_time = 0 start_time = time.time() N = 50 ret_data = pd.DataFrame() for stk in universe: data = DataAPI.MktEqudAdjGet(secID=stk, beginDate=begin, endDate=end, field='secID,tradeDate,closePrice') # 拿取数据 tmp_ret_data = data.sort('tradeDate') # 计算历史窗口收益率 tmp_ret_data['forwardReturns'] = tmp_ret_data['closePrice'] / tmp_ret_data['closePrice'].shift(window) - 1.0 tmp_ret_data = tmp_ret_data[['tradeDate','forwardReturns']] tmp_ret_data.columns = ['tradeDate', stk] if ret_data.empty: ret_data = tmp_ret_data else: ret_data = ret_data.merge(tmp_ret_data, on='tradeDate', how='outer') # 打印进度部分 count += 1 if count > 0 and count % N == 0: finish_time = time.time() print count, print ' ' + str(np.round((finish_time-start_time) - secs_time, 0)) + ' seconds elapsed.' secs_time = (finish_time-start_time) ret_data.to_csv(file_name) return ret_data def getForwardReturnsAll(universe, begin, end, window, file_name): # 计算各股票历史区间前瞻回报率,未来window天的收益率 print str(window) + ' days forward returns will be calculated for ' + str(len(universe)) + ' stocks:' count = 0 secs_time = 0 start_time = time.time() N = 50 ret_data = pd.DataFrame() for stk in universe: data = DataAPI.MktEqudAdjGet(secID=stk, beginDate=begin, endDate=end, field='secID,tradeDate,closePrice') # 拿取数据 tmp_ret_data = data.sort('tradeDate') # 计算历史窗口前瞻收益率 tmp_ret_data['forwardReturns'] = tmp_ret_data['closePrice'].shift(-window) / tmp_ret_data['closePrice'] - 1.0 tmp_ret_data = tmp_ret_data[['tradeDate','forwardReturns']] tmp_ret_data.columns = ['tradeDate', stk] if ret_data.empty: ret_data = tmp_ret_data else: ret_data = ret_data.merge(tmp_ret_data, on='tradeDate', how='outer') # 打印进度部分 count += 1 if count > 0 and count % N == 0: finish_time = time.time() print count, print ' ' + str(np.round((finish_time-start_time) - secs_time, 0)) + ' seconds elapsed.' secs_time = (finish_time-start_time) ret_data.to_csv(file_name) return ret_data def getMarketValueAll(universe, begin, end, file_name): # 获取股票历史每日市值 print 'MarketValue will be calculated for ' + str(len(universe)) + ' stocks:' count = 0 secs_time = 0 start_time = time.time() N = 50 ret_data = pd.DataFrame() for stk in universe: data = DataAPI.MktEqudAdjGet(secID=stk, beginDate=begin, endDate=end, field='secID,tradeDate,marketValue') # 拿取数据 tmp_ret_data = data.sort('tradeDate') # 市值部分 tmp_ret_data = tmp_ret_data[['tradeDate','marketValue']] tmp_ret_data.columns = ['tradeDate', stk] if ret_data.empty: ret_data = tmp_ret_data else: ret_data = ret_data.merge(tmp_ret_data, on='tradeDate', how='outer') # 打印进度部分 count += 1 if count > 0 and count % N == 0: finish_time = time.time() print count, print ' ' + str(np.round((finish_time-start_time) - secs_time, 0)) + ' seconds elapsed.' secs_time = (finish_time-start_time) ret_data.to_csv(file_name) return ret_data def getWindowMeanTurnoverRateAll(universe, begin, end, window, file_name): # 获取股票历史滚动窗口平均换手率 print 'WindowMeanTurnoverRate will be calculated for ' + str(len(universe)) + ' stocks:' count = 0 secs_time = 0 start_time = time.time() N = 100 ret_data = pd.DataFrame() for stk in universe: data = DataAPI.MktEqudAdjGet(secID=stk, beginDate=begin, endDate=end, field='secID,tradeDate,turnoverRate') # 拿取数据 tmp_ret_data = data.sort('tradeDate') # 市值部分 tmp_ret_data['windowMeanTurnoverRate'] = pd.rolling_mean(tmp_ret_data['turnoverRate'], window=window) tmp_ret_data = tmp_ret_data[['tradeDate','windowMeanTurnoverRate']] tmp_ret_data.columns = ['tradeDate', stk] if ret_data.empty: ret_data = tmp_ret_data else: ret_data = ret_data.merge(tmp_ret_data, on='tradeDate', how='outer') # 打印进度部分 count += 1 if count > 0 and count % N == 0: finish_time = time.time() print count, print ' ' + str(np.round((finish_time-start_time) - secs_time, 0)) + ' seconds elapsed.' secs_time = (finish_time-start_time) ret_data.to_csv(file_name) return ret_data

上面分别定义了计算本文关心的几个变量的函数,其中包括:

  • 价量相关系数,getVolPriceCorrAll
  • 历史收益率,getBackwardReturnsAll
  • 未来收益率,getForwardReturnsAll
  • 市值,getMarketValueAll
  • 历史窗口日均换手率,getWindowMeanTurnoverRateAll

下面利用这五个函数分别计算我们需要的各种变量(我们只用了全A股中的50只作为示例,感兴趣的读者只需要将下面cell中第5行中的universe修改即可计算更大股票池的数据),并将这些变量保存在文件中以供调用。

begin_date = '20060101' # 开始日期 end_date = '20160802' # 结束日期 universe = set_universe('A') # 股票池 universe = universe[0:50] # 计算速度缓慢,仅以部分股票池作为sample # ----------- 计算量价相关系数部分 ---------------- window_corr = 15 print '=======================' start_time = time.time() forward_returns_data = getVolPriceCorrAll(universe=universe, begin=begin_date, end=end_date, window=window_corr, file_name='VolPriceCorr_W15_FullA_sample.csv') finish_time = time.time() print '' print str(finish_time-start_time) + ' seconds elapsed in total.' # ----------- 计算股票历史窗口(一个月)收益率部分 ---------------- window_return = 20 print '=======================' start_time = time.time() forward_returns_data = getBackwardReturnsAll(universe=universe, begin=begin_date, end=end_date, window=window_return, file_name='BackwardReturns_W20_FullA_Sample.csv') finish_time = time.time() print '' print str(finish_time-start_time) + ' seconds elapsed in total.' # ----------- 计算股票历史窗口(三个月)收益率部分 ---------------- window_return = 60 print '=======================' start_time = time.time() forward_returns_data = getBackwardReturnsAll(universe=universe, begin=begin_date, end=end_date, window=window_return, file_name='BackwardReturns_W60_FullA_Sample.csv') finish_time = time.time() print '' print str(finish_time-start_time) + ' seconds elapsed in total.' # ----------- 计算股票前瞻收益率部分 ---------------- window_return = 20 print '=======================' start_time = time.time() forward_returns_data = getForwardReturnsAll(universe=universe, begin=begin_date, end=end_date, window=window_return, file_name='ForwardReturns_W20_FullA_Sample.csv') finish_time = time.time() print '' print str(finish_time-start_time) + ' seconds elapsed in total.' # ----------- 计算股票历史市值部分 ---------------- print '=======================' start_time = time.time() forward_returns_data = getMarketValueAll(universe=universe, begin=begin_date, end=end_date, file_name='MarketValues_FullA_Sample.csv') finish_time = time.time() print '' print str(finish_time-start_time) + ' seconds elapsed in total.' # ----------- 计算历史月度日均换手率部分 ---------------- window = 20 print '=======================' start_time = time.time() forward_returns_data = getWindowMeanTurnoverRateAll(universe=universe, begin=begin_date, end=end_date, window=window, file_name='TurnoverRateWindowMean_W20_FullA_Sample.csv') finish_time = time.time() print '' print str(finish_time-start_time) + ' seconds elapsed in total.'

3. 量价因子截面特征


3.1 首先加载计算好的数据文件:

# 提取数据 corr_data = pd.read_csv('VolPriceCorr_W15_FullA.csv') # 15天窗口量价相关系数 forward_20d_return_data = pd.read_csv('ForwardReturns_W20_FullA.csv') # 未来20天收益率 backward_20d_return_data = pd.read_csv('BackwardReturns_W20_FullA.csv') # 过去20天收益率 backward_60d_return_data = pd.read_csv('BackwardReturns_W60_FullA.csv') # 过去60天收益率 mkt_value_data = pd.read_csv('MarketValues_FullA.csv') # 市值数据 turnover_rate_data = pd.read_csv('TurnoverRateWindowMean_W20_FullA.csv') # 过去20天日均换手率数据 corr_data['tradeDate'] = map(Date.toDateTime, map(DateTime.parseISO, corr_data['tradeDate'])) forward_20d_return_data['tradeDate'] = map(Date.toDateTime, map(DateTime.parseISO, forward_20d_return_data['tradeDate'])) backward_20d_return_data['tradeDate'] = map(Date.toDateTime, map(DateTime.parseISO, backward_20d_return_data['tradeDate'])) backward_60d_return_data['tradeDate'] = map(Date.toDateTime, map(DateTime.parseISO, backward_60d_return_data['tradeDate'])) mkt_value_data['tradeDate'] = map(Date.toDateTime, map(DateTime.parseISO, mkt_value_data['tradeDate'])) turnover_rate_data['tradeDate'] = map(Date.toDateTime, map(DateTime.parseISO, turnover_rate_data['tradeDate'])) corr_data = corr_data[corr_data.columns[1:]].set_index('tradeDate') forward_20d_return_data = forward_20d_return_data[forward_20d_return_data.columns[1:]].set_index('tradeDate') backward_20d_return_data = backward_20d_return_data[backward_20d_return_data.columns[1:]].set_index('tradeDate') backward_60d_return_data = backward_60d_return_data[backward_60d_return_data.columns[1:]].set_index('tradeDate') mkt_value_data = mkt_value_data[mkt_value_data.columns[1:]].set_index('tradeDate') turnover_rate_data = turnover_rate_data[turnover_rate_data.columns[1:]].set_index('tradeDate')

下表中,展示了我们计算好的corr_data数据文件的一部分,主要为了说明我们接下来使用的数据dataframe的结构:

  • 每一行为日期,每个交易日均有计算数据,从2006年到2016年8月
  • 每一列为股票,股票池为全A股

corr_data.tail()

得到相关系数表:

3.2 量价相关因子截面特征

接下来,我们简单检查一下我们计算得到的量价相关因子的截面特征

# 量价相关性历史表现 n_quantile = 10 # 和海通研报一样,统计十分位数 cols_mean = ['meanQ'+str(i+1) for i in range(n_quantile)] cols = cols_mean corr_means = pd.DataFrame(index=corr_data.index, columns=cols) # 计算相关系数分组平均值 for dt in corr_means.index: qt_mean_results = [] # 相关系数去掉nan和绝对值大于1的 tmp_corr = corr_data.ix[dt].dropna() tmp_corr = tmp_corr[(tmp_corr<=1.0) & (tmp_corr>=-1.0)] pct_quantiles = 1.0/n_quantile for i in range(n_quantile): down = tmp_corr.quantile(pct_quantiles*i) up = tmp_corr.quantile(pct_quantiles*(i+1)) mean_tmp = tmp_corr[(tmp_corr<=up) & (tmp_corr>=down)].mean() qt_mean_results.append(mean_tmp) corr_means.ix[dt] = qt_mean_results # corr_means是对历史每一天,求量价相关系数在各个十分位里面的平均值 corr_means.tail()

 

 

下图给出了2006年至2016年间,在不同时点,将市场上所有股票按量价相关性分10组后,第1组、第5组以及第10组股票量价相关性的均值情况,即我们所说的量价相关性截面特征

  • 观察下图可知,量价相关性的截面特征较为稳定

# 量价相关性历史表现作图 fig = plt.figure(figsize=(16, 6)) ax1 = fig.add_subplot(111) lns1 = ax1.plot(corr_means.index, corr_means.meanQ1, label='Q1') lns2 = ax1.plot(corr_means.index, corr_means.meanQ5, label='Q5') lns3 = ax1.plot(corr_means.index, corr_means.meanQ10, label='Q10') lns = lns1+lns2+lns3 labs = [l.get_label() for l in lns] ax1.legend(lns, labs, bbox_to_anchor=[0.5, 0.1], loc='', ncol=3, mode="", borderaxespad=0., fontsize=12) ax1.set_ylabel(u'量价相关系数', fontproperties=font, fontsize=16) ax1.set_xlabel(u'日期', fontproperties=font, fontsize=16) ax1.set_title(u"量价相关性历史表现", fontproperties=font, fontsize=16) ax1.grid()

3.3 量价因子的预测能力初探

接下来,我们计算了每一天的量价因子之后20日收益的秩相关系数

# ‘过去十五天量价相关系数’和‘之后20天收益’的秩相关系数计算 ic_data = pd.DataFrame(index=corr_data.index, columns=['IC','pValue']) # 计算相关系数 for dt in ic_data.index: tmp_corr = corr_data.ix[dt] tmp_ret = forward_20d_return_data.ix[dt] cor = pd.DataFrame(tmp_corr) ret = pd.DataFrame(tmp_ret) cor.columns = ['corr'] ret.columns = ['ret'] cor['ret'] = ret['ret'] cor = cor[~np.isnan(cor['corr'])][~np.isnan(cor['ret'])] if len(cor) < 5: continue # ic,p_value = st.pearsonr(q['Q'],q['ret']) # 计算相关系数 IC # ic,p_value = st.pearsonr(q['Q'].rank(),q['ret'].rank()) # 计算秩相关系数 RankIC ic, p_value = st.spearmanr(cor['corr'],cor['ret']) # 计算秩相关系数 RankIC ic_data['IC'][dt] = ic ic_data['pValue'][dt] = p_value # print len(ic_data['IC']), len(ic_data[ic_data.IC>0]), len(ic_data[ic_data.IC<0]) print 'mean of IC: ', ic_data['IC'].mean() print 'median of IC: ', ic_data['IC'].median() print 'the number of IC(all, plus, minus): ', (len(ic_data), len(ic_data[ic_data.IC>0]), len(ic_data[ic_data.IC<0]))

mean of IC:

-0.04 median of IC: -0.0477574767849 the number of IC(all, plus, minus): (2572, 778, 1760)

从上面计算结果和下图可知,量价因子和未来20日收益的秩相关系数在大部分时间为负,量价因子对于未来20天的收益有预测性

# ‘过去十五天量价相关系数’和‘之后20天收益’的秩相关系数作图 fig = plt.figure(figsize=(16, 6)) ax1 = fig.add_subplot(111) lns1 = ax1.plot(ic_data.index, ic_data.IC, label='IC') lns = lns1 labs = [l.get_label() for l in lns] ax1.legend(lns, labs, bbox_to_anchor=[0.5, 0.1], loc='', ncol=3, mode="", borderaxespad=0., fontsize=12) ax1.set_ylabel(u'相关系数', fontproperties=font, fontsize=16) ax1.set_xlabel(u'日期', fontproperties=font, fontsize=16) ax1.set_title(u"量价因子和未来20日收益之间的秩相关系数", fontproperties=font, fontsize=16) ax1.grid()

4. 量价因子历史回测概述

本节使用2006年以来的数据对于量价相关性因子历史表现进行回测,进一步简单设计量价因子选股的几个风险因子暴露情况。


4.1 量价因子选股的分组超额收益

n_quantile = 10 # 和海通研报一样,统计十分位数 cols_mean = [i+1 for i in range(n_quantile)] cols = cols_mean excess_returns_means = pd.DataFrame(index=corr_data.index, columns=cols) # 计算相关系数分组的超额收益平均值 for dt in excess_returns_means.index: qt_mean_results = [] # 相关系数去掉nan和绝对值大于1的 tmp_corr = corr_data.ix[dt].dropna() tmp_corr = tmp_corr[(tmp_corr<=1.0) & (tmp_corr>=-1.0)] tmp_return = forward_20d_return_data.ix[dt].dropna() tmp_return_mean = tmp_return.mean() pct_quantiles = 1.0/n_quantile for i in range(n_quantile): down = tmp_corr.quantile(pct_quantiles*i) up = tmp_corr.quantile(pct_quantiles*(i+1)) i_quantile_index = tmp_corr[(tmp_corr<=up) & (tmp_corr>=down)].index mean_tmp = tmp_return[i_quantile_index].mean() - tmp_return_mean qt_mean_results.append(mean_tmp) excess_returns_means.ix[dt] = qt_mean_results excess_returns_means.dropna(inplace=True) excess_returns_means.tail()

 

  • 上表计算结果,给出了2006年开始,每天进行量价因子十分位选股后,每个分组内股票在未来一个月相对于市场平均收益的超额收益均值
  • 注意:十分位分组中,量价因子由小到大排序,即第一组为量价因子最小的组
  • 下图展示,量价因子十分位选股后,在未来一个月各个分组的超额收益,可以发现:因子多空收益明显,且因子空头收益更强

fig = plt.figure(figsize=(12, 6)) ax1 = fig.add_subplot(111) excess_returns_means_dist = excess_returns_means.mean() # lns1 = ax1.plot(excess_returns_means_dist.index, excess_returns_means_dist.values, '--o', label='IC') excess_dist_plus = excess_returns_means_dist[excess_returns_means_dist>0] excess_dist_minus = excess_returns_means_dist[excess_returns_means_dist<0] lns2 = ax1.bar(excess_dist_plus.index, excess_dist_plus.values, align='center', color='r', width=0.35) lns3 = ax1.bar(excess_dist_minus.index, excess_dist_minus.values, align='center', color='g', width=0.35) ax1.set_xlim(left=0.5, right=len(excess_returns_means_dist)+0.5) ax1.set_ylim(-0.01, 0.004) ax1.set_ylabel(u'超额收益', fontproperties=font, fontsize=16) ax1.set_xlabel(u'十分位分组', fontproperties=font, fontsize=16) ax1.set_xticks(excess_returns_means_dist.index) ax1.set_xticklabels([int(x) for x in ax1.get_xticks()], fontproperties=font, fontsize=14) ax1.set_yticklabels([str(x*100)+'0%' for x in ax1.get_yticks()], fontproperties=font, fontsize=14) ax1.set_title(u"量价相关性选股因子超额收益", fontproperties=font, fontsize=16) ax1.grid()

4.2 量价因子选股的市值分布特征

检查量价因子的小市值暴露情况。因为很多策略因为小市值暴露在A股市场表现优异。

n_quantile = 10 # 和海通研报一样,统计十分位数 cols_mean = [i+1 for i in range(n_quantile)] cols = cols_mean mkt_value_means = pd.DataFrame(index=corr_data.index, columns=cols) # 计算相关系数分组的超额收益平均值 for dt in mkt_value_means.index: qt_mean_results = [] # 相关系数去掉nan和绝对值大于1的 tmp_corr = corr_data.ix[dt].dropna() tmp_corr = tmp_corr[(tmp_corr<=1.0) & (tmp_corr>=-1.0)] tmp_mkt_value = mkt_value_data.ix[dt].dropna() tmp_mkt_value = tmp_mkt_value.rank()/len(tmp_mkt_value) pct_quantiles = 1.0/n_quantile for i in range(n_quantile): down = tmp_corr.quantile(pct_quantiles*i) up = tmp_corr.quantile(pct_quantiles*(i+1)) i_quantile_index = tmp_corr[(tmp_corr<=up) & (tmp_corr>=down)].index mean_tmp = tmp_mkt_value[i_quantile_index].mean() qt_mean_results.append(mean_tmp) mkt_value_means.ix[dt] = qt_mean_results mkt_value_means.dropna(inplace=True) mkt_value_means.tail()

  • 上表计算结果,给出了2006年开始,每天进行量价因子十分位选股后,每个分组内股票的市值百分位均值
  • 下图展示,量价因子十分位选股后,各个分组的市值百分位历史均值:量价因子有略微的大市值暴露,与市值因子负相关

fig = plt.figure(figsize=(12, 6)) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() mkt_value_means_dist = mkt_value_means.mean() lns1 = ax1.bar(mkt_value_means_dist.index, mkt_value_means_dist.values, align='center', width=0.35) lns2 = ax2.plot(excess_returns_means_dist.index, excess_returns_means_dist.values, 'o-r') ax1.legend(lns1, ['market value(left axis)'], loc=2, fontsize=12) ax2.legend(lns2, ['excess return(right axis)'], fontsize=12) ax1.set_ylim(0.4, 0.6) ax2.set_ylim(-0.01, 0.004) ax1.set_xlim(left=0.5, right=len(mkt_value_means_dist)+0.5) ax1.set_ylabel(u'市值百分位数', fontproperties=font, fontsize=16) ax2.set_ylabel(u'超额收益', fontproperties=font, fontsize=16) ax1.set_xlabel(u'十分位分组', fontproperties=font, fontsize=16) ax1.set_xticks(mkt_value_means_dist.index) ax1.set_xticklabels([int(x) for x in ax1.get_xticks()], fontproperties=font, fontsize=14) ax1.set_yticklabels([str(x*100)+'%' for x in ax1.get_yticks()], fontproperties=font, fontsize=14) ax2.set_yticklabels([str(x*100)+'0%' for x in ax2.get_yticks()], fontproperties=font, fontsize=14) ax1.set_title(u"量价相关性选股因子市值分布特征", fontproperties=font, fontsize=16) ax1.grid()

 

4.3 量价因子选股的换手率分布特征

n_quantile = 10 # 和海通研报一样,统计十分位数 cols_mean = [i+1 for i in range(n_quantile)] cols = cols_mean turnover_rate_means = pd.DataFrame(index=corr_data.index, columns=cols) # 计算相关系数分组的超额收益平均值 for dt in turnover_rate_means.index: qt_mean_results = [] # 相关系数去掉nan和绝对值大于1的 tmp_corr = corr_data.ix[dt].dropna() tmp_corr = tmp_corr[(tmp_corr<=1.0) & (tmp_corr>=-1.0)] tmp_turnover_rate = turnover_rate_data.ix[dt].dropna() pct_quantiles = 1.0/n_quantile for i in range(n_quantile): down = tmp_corr.quantile(pct_quantiles*i) up = tmp_corr.quantile(pct_quantiles*(i+1)) i_quantile_index = tmp_corr[(tmp_corr<=up) & (tmp_corr>=down)].index mean_tmp = tmp_turnover_rate[i_quantile_index].mean() qt_mean_results.append(mean_tmp) turnover_rate_means.ix[dt] = qt_mean_results turnover_rate_means.dropna(inplace=True) turnover_rate_means.tail()

  • 上表计算结果,给出了2006年开始,每天进行量价因子十分位选股后,每个分组内股票的前一个月日均换手率的均值
  • 下图展示,量价因子十分位选股后,各个分组的1个月日均换手率均值:量价因子对于低换手率有一定风险暴露,换手率随组别上升而逐渐升高

fig = plt.figure(figsize=(12, 6)) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() turnover_rate_means_dist = turnover_rate_means.mean() lns1 = ax1.bar(turnover_rate_means_dist.index, turnover_rate_means_dist.values, align='center', width=0.35) lns2 = ax2.plot(excess_returns_means_dist.index, excess_returns_means_dist.values, 'o-r') ax1.legend(lns1, ['turnover rate(left axis)'], loc=2, fontsize=12) ax2.legend(lns2, ['excess return(right axis)'], fontsize=12) ax1.set_ylim(0, 0.05) ax2.set_ylim(-0.01, 0.004) ax1.set_xlim(left=0.5, right=len(turnover_rate_means_dist)+0.5) ax1.set_ylabel(u'换手率', fontproperties=font, fontsize=16) ax2.set_ylabel(u'超额收益', fontproperties=font, fontsize=16) ax1.set_xlabel(u'十分位分组', fontproperties=font, fontsize=16) ax1.set_xticks(turnover_rate_means_dist.index) ax1.set_xticklabels([int(x) for x in ax1.get_xticks()], fontproperties=font, fontsize=14) ax1.set_yticklabels([str(x*100)+'%' for x in ax1.get_yticks()], fontproperties=font, fontsize=14) ax2.set_yticklabels([str(x*100)+'0%' for x in ax2.get_yticks()], fontproperties=font, fontsize=14) ax1.set_title(u"量价相关性选股因子换手率分布特征", fontproperties=font, fontsize=16) ax1.grid()

 

4.4 量价因子选股的一个月反转分布特征

n_quantile = 10 # 和海通研报一样,统计十分位数 cols_mean = [i+1 for i in range(n_quantile)] cols = cols_mean hist_returns_means = pd.DataFrame(index=corr_data.index, columns=cols) # 计算相关系数分组的超额收益平均值 for dt in hist_returns_means.index: qt_mean_results = [] # 相关系数去掉nan和绝对值大于1的 tmp_corr = corr_data.ix[dt].dropna() tmp_corr = tmp_corr[(tmp_corr<=1.0) & (tmp_corr>=-1.0)] tmp_return = backward_20d_return_data.ix[dt].dropna() tmp_return_mean = tmp_return.mean() pct_quantiles = 1.0/n_quantile for i in range(n_quantile): down = tmp_corr.quantile(pct_quantiles*i) up = tmp_corr.quantile(pct_quantiles*(i+1)) i_quantile_index = tmp_corr[(tmp_corr<=up) & (tmp_corr>=down)].index mean_tmp = tmp_return[i_quantile_index].mean() - tmp_return_mean qt_mean_results.append(mean_tmp) hist_returns_means.ix[dt] = qt_mean_results hist_returns_means.dropna(inplace=True) hist_returns_means.tail()

  • 上表计算结果,给出了2006年开始,每天进行量价因子十分位选股后,每个分组内股票的前一个月超额涨幅(超出市场平均值)的均值
  • 下图展示,量价因子十分位选股后,各个分组的前一个月超额涨幅均值:量价因子对于一个月反转因子有一定风险暴露(多头组合即第一组中的股票前一个月平均跑输市场)

fig = plt.figure(figsize=(12, 6)) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() hist_returns_means_dist = hist_returns_means.mean() lns1 = ax1.bar(hist_returns_means_dist.index, hist_returns_means_dist.values, align='center', width=0.35) lns2 = ax2.plot(excess_returns_means_dist.index, excess_returns_means_dist.values, 'o-r') ax1.legend(lns1, ['20 day return(left axis)'], loc=2, fontsize=12) ax2.legend(lns2, ['excess return(right axis)'], fontsize=12) ax1.set_ylim(-0.03, 0.07) ax2.set_ylim(-0.01, 0.004) ax1.set_xlim(left=0.5, right=len(hist_returns_means_dist)+0.5) ax1.set_ylabel(u'历史一个月收益率', fontproperties=font, fontsize=16) ax2.set_ylabel(u'超额收益', fontproperties=font, fontsize=16) ax1.set_xlabel(u'十分位分组', fontproperties=font, fontsize=16) ax1.set_xticks(hist_returns_means_dist.index) ax1.set_xticklabels([int(x) for x in ax1.get_xticks()], fontproperties=font, fontsize=14) ax1.set_yticklabels([str(x*100)+'%' for x in ax1.get_yticks()], fontproperties=font, fontsize=14) ax2.set_yticklabels([str(x*100)+'0%' for x in ax2.get_yticks()], fontproperties=font, fontsize=14) ax1.set_title(u"量价相关性选股因子一个月历史收益率(一个月反转因子)分布特征", fontproperties=font, fontsize=16) ax1.grid()

4.5 量价因子选股的三个月反转分布特征

 

n_quantile = 10 # 和海通研报一样,统计十分位数 cols_mean = [i+1 for i in range(n_quantile)] cols = cols_mean hist_returns_means = pd.DataFrame(index=corr_data.index, columns=cols) # 计算相关系数分组的超额收益平均值 for dt in hist_returns_means.index: qt_mean_results = [] # 相关系数去掉nan和绝对值大于1的 tmp_corr = corr_data.ix[dt].dropna() tmp_corr = tmp_corr[(tmp_corr<=1.0) & (tmp_corr>=-1.0)] tmp_return = backward_60d_return_data.ix[dt].dropna() tmp_return_mean = tmp_return.mean() pct_quantiles = 1.0/n_quantile for i in range(n_quantile): down = tmp_corr.quantile(pct_quantiles*i) up = tmp_corr.quantile(pct_quantiles*(i+1)) i_quantile_index = tmp_corr[(tmp_corr<=up) & (tmp_corr>=down)].index mean_tmp = tmp_return[i_quantile_index].mean() - tmp_return_mean qt_mean_results.append(mean_tmp) hist_returns_means.ix[dt] = qt_mean_results hist_returns_means.dropna(inplace=True) hist_returns_means.tail()

  • 上表计算结果,给出了2006年开始,每天进行量价因子十分位选股后,每个分组内股票的前三个月超额涨幅(超出市场平均值)的均值
  • 下图展示,量价因子十分位选股后,各个分组的前三个月超额涨幅均值:股票分组在三个月涨幅上的分布并未呈现出明显的单调性,仅呈现出“两头高,中间低”的特点

fig = plt.figure(figsize=(12, 6)) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() hist_returns_means_dist = hist_returns_means.mean() lns1 = ax1.bar(hist_returns_means_dist.index, hist_returns_means_dist.values, align='center', width=0.35) lns2 = ax2.plot(excess_returns_means_dist.index, excess_returns_means_dist.values, 'o-r') ax1.legend(lns1, ['60 day return(left axis)'], loc=2, fontsize=12) ax2.legend(lns2, ['excess return(right axis)'], fontsize=12) ax1.set_ylim(-0.02, 0.04) ax2.set_ylim(-0.01, 0.004) ax1.set_xlim(left=0.5, right=len(hist_returns_means_dist)+0.5) ax1.set_ylabel(u'历史三个月收益率', fontproperties=font, fontsize=16) ax2.set_ylabel(u'超额收益', fontproperties=font, fontsize=16) ax1.set_xlabel(u'十分位分组', fontproperties=font, fontsize=16) ax1.set_xticks(hist_returns_means_dist.index) ax1.set_xticklabels([int(x) for x in ax1.get_xticks()], fontproperties=font, fontsize=14) ax1.set_yticklabels([str(x*100)+'%' for x in ax1.get_yticks()], fontproperties=font, fontsize=14) ax2.set_yticklabels([str(x*100)+'0%' for x in ax2.get_yticks()], fontproperties=font, fontsize=14) ax1.set_title(u"量价相关性选股因子三个月历史收益率(三个月反转因子)分布特征", fontproperties=font, fontsize=16) ax1.grid()

 

5. 量价因子历史回测净值表现


接下来,考察上述量价因子的选股能力的回测效果。历史回测的基本设置如下:

  • 回测时段为2010年1月1日至2016年8月1日
  • 股票池为A股全部股票
  • 组合每15个交易日调仓,交易费率设为双边万分之二
  • 调仓时,涨停、停牌不买入,跌停、停牌不卖出;
  • 每月底调仓时,选择股票池中量价因子最小的20%的股票;

5.1 量价因子最小20%股票

start = '2010-01-01' # 回测起始时间 end = '2016-08-01' # 回测结束时间 benchmark = 'ZZ500' # 策略参考标准 universe = set_universe('A') # 证券池,支持股票和基金 capital_base = 10000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 refresh_rate = 15 # 调仓频率,表示执行handle_data的时间间隔 corr_data = pd.read_csv('VolPriceCorr_W15_FullA.csv') # 读取量价因子数据 corr_data = corr_data[corr_data.columns[1:]].set_index('tradeDate') corr_dates = corr_data.index.values quantile_five = 1 # 选取股票的量价因子五分位数,1表示选取股票池中因子最小的10%的股票 commission = Commission(0.0002,0.0002) # 交易费率设为双边万分之二 def initialize(account): # 初始化虚拟账户状态 pass def handle_data(account): # 每个交易日的买入卖出指令 pre_date = account.previous_date.strftime("%Y-%m-%d") if pre_date not in corr_dates: # 只在计算过量价因子的交易日调仓 return # 拿取调仓日前一个交易日的量价因子,并按照相应十分位选择股票 pre_corr = corr_data.ix[pre_date] pre_corr = pre_corr.dropna() pre_corr = pre_corr[(pre_corr<=1.0) & (pre_corr>=-1.0)] pre_corr_min = pre_corr.quantile((quantile_five-1)*0.2) pre_corr_max = pre_corr.quantile(quantile_five*0.2) my_univ = pre_corr[pre_corr>=pre_corr_min][pre_corr<pre_corr_max].index.values # 调仓逻辑 univ = [x for x in my_univ if x in account.universe] # 不在股票池中的,清仓 for stk in account.valid_secpos: if stk not in univ: order_to(stk, 0) # 在目标股票池中的,等权买入 for stk in univ: order_pct_to(stk, 1.1/len(univ))

 

bt_all = {} # 用来保存三个策略运行结果:量价因子,20日反转因子,量价因子与20日反转因子等权重叠加 bt_all['corr'] = bt # 保存量价因子回测结果

5.2 一个月反转因子最小(近一个月涨幅最低的)20%股票

start = '2010-01-01' # 回测起始时间 end = '2016-08-01' # 回测结束时间 benchmark = 'ZZ500' # 策略参考标准 universe = set_universe('A') # 证券池,支持股票和基金 capital_base = 10000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 refresh_rate = 15 # 调仓频率,表示执行handle_data的时间间隔 revs_data = pd.read_csv('BackwardReturns_W20_FullA.csv') # 读取反转因子数据 revs_data = revs_data[revs_data.columns[1:]].set_index('tradeDate') revs_dates = revs_data.index.values quantile_five = 1 # 选取股票的20日反转因子的五分位数,1表示选取股票池中因子最小的20%的股票 commission = Commission(0.0002,0.0002) # 交易费率设为双边万分之二 def initialize(account): # 初始化虚拟账户状态 pass def handle_data(account): # 每个交易日的买入卖出指令 pre_date = account.previous_date.strftime("%Y-%m-%d") if pre_date not in revs_dates: # 只在计算过反转因子的交易日调仓 return # 拿取调仓日前一个交易日的反转因子,并按照相应十分位选择股票 pre_revs = revs_data.ix[pre_date] pre_revs = pre_revs.dropna() pre_revs_min = pre_revs.quantile((quantile_five-1)*0.2) pre_revs_max = pre_revs.quantile(quantile_five*0.2) my_univ = pre_revs[pre_revs>=pre_revs_min][pre_revs<pre_revs_max].index.values # 调仓逻辑 univ = [x for x in my_univ if x in account.universe] # 不在股票池中的,清仓 for stk in account.valid_secpos: if stk not in univ: order_to(stk, 0) # 在目标股票池中的,等权买入 for stk in univ: order_pct_to(stk, 1.1/len(univ))

 

bt_all['revs'] = bt # 保存一个月反转因子回测结果

5.3 量价因子叠加反转因子选股

  • 量价因子和反转因子分别标准化,之后相加生成叠加因子,选叠加因子最小的20%股票

start = '2010-01-01' # 回测起始时间 end = '2016-08-01' # 回测结束时间 benchmark = 'ZZ500' # 策略参考标准 universe = set_universe('A') # 证券池,支持股票和基金 capital_base = 10000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 refresh_rate = 15 # 调仓频率,表示执行handle_data的时间间隔 corr_data = pd.read_csv('VolPriceCorr_W15_FullA.csv') # 读取量价因子数据 corr_data = corr_data[corr_data.columns[1:]].set_index('tradeDate') corr_dates = corr_data.index.values revs_data = pd.read_csv('BackwardReturns_W20_FullA.csv') # 读取反转因子数据 revs_data = revs_data[revs_data.columns[1:]].set_index('tradeDate') quantile_five = 1 # 选取股票的因子五分位数,1表示选取股票池中因子最小的20%的股票 commission = Commission(0.0002,0.0002) # 交易费率设为双边万分之二 def initialize(account): # 初始化虚拟账户状态 pass def handle_data(account): # 每个交易日的买入卖出指令 pre_date = account.previous_date.strftime("%Y-%m-%d") if pre_date not in corr_dates: # 只在计算过量价因子的交易日调仓 return # 拿取调仓日前一个交易日的量价因子和反转因子,并按照相应分位选择股票 pre_corr = corr_data.ix[pre_date] pre_corr = pre_corr[(pre_corr<=1.0) & (pre_corr>=-1.0)] pre_revs = revs_data.ix[pre_date] # 量价因子和反转因子只做简单的等权叠加 pre_data = pd.Series(standardize(pre_corr.to_dict())) + pd.Series(standardize(pre_revs.to_dict())) # 因子标准化使用了uqer的函数standardize pre_data = pre_data.dropna() pre_data_min = pre_data.quantile((quantile_five-1)*0.2) pre_data_max = pre_data.quantile(quantile_five*0.2) my_univ = pre_data[pre_data>=pre_data_min][pre_data<pre_data_max].index.values # 调仓逻辑 univ = [x for x in my_univ if x in account.universe] # 不在股票池中的,清仓 for stk in account.valid_secpos: if stk not in univ: order_to(stk, 0) # 在目标股票池中的,等权买入 for stk in univ: order_pct_to(stk, 1.1/len(univ))

 

bt_all['corr + revs'] = bt

5.4 上述三个组合对比

此处对比,量价因子、反转因子、量价因子叠加反转因子这三个组合的回测结果

results = {} for x in bt_all.keys(): results[x] = {} results[x]['bt'] = bt_all[x]

fig = plt.figure(figsize=(10,8)) fig.set_tight_layout(True) ax1 = fig.add_subplot(211) ax2 = fig.add_subplot(212) ax1.grid() ax2.grid() for qt in ['corr','revs','corr + revs']: bt = results[qt]['bt'] data = bt[[u'tradeDate',u'portfolio_value',u'benchmark_return']] data['portfolio_return'] = data.portfolio_value/data.portfolio_value.shift(1) - 1.0 # 总头寸每日回报率 data['portfolio_return'].ix[0] = data['portfolio_value'].ix[0]/ 10000000.0 - 1.0 data['excess_return'] = data.portfolio_return - data.benchmark_return # 总头寸每日超额回报率 data['excess'] = data.excess_return + 1.0 data['excess'] = data.excess.cumprod() # 总头寸对冲指数后的净值序列 data['portfolio'] = data.portfolio_return + 1.0 data['portfolio'] = data.portfolio.cumprod() # 总头寸不对冲时的净值序列 data['benchmark'] = data.benchmark_return + 1.0 data['benchmark'] = data.benchmark.cumprod() # benchmark的净值序列 results[qt]['hedged_max_drawdown'] = max([1 - v/max(1, max(data['excess'][:i+1])) for i,v in enumerate(data['excess'])]) # 对冲后净值最大回撤 results[qt]['hedged_volatility'] = np.std(data['excess_return'])*np.sqrt(252) results[qt]['hedged_annualized_return'] = (data['excess'].values[-1])**(252.0/len(data['excess'])) - 1.0 # data[['portfolio','benchmark','excess']].plot(figsize=(12,8)) # ax.plot(data[['portfolio','benchmark','excess']], label=str(qt)) ax1.plot(data['tradeDate'], data[['portfolio']], label=str(qt)) ax2.plot(data['tradeDate'], data[['excess']], label=str(qt)) ax1.legend(loc=0, fontsize=12) ax2.legend(loc=0, fontsize=12) ax1.set_ylabel(u"净值", fontproperties=font, fontsize=16) ax2.set_ylabel(u"对冲净值", fontproperties=font, fontsize=16) ax1.set_title(u"量价因子和反转因子选股能力对比 - 净值走势", fontproperties=font, fontsize=16) ax2.set_title(u"量价因子和反转因子选股能力对比 - 对冲中证500指数后净值走势", fontproperties=font, fontsize=16)

 

上图中可以发现:

  • 蓝色曲线为量价因子,绿色为反转因子,红色为量价因子叠加反转因子
  • 量价因子的漫长的熊市中走势稳健,并一直打败反转因子
  • 反转因子在15年之后表现出色
  • 量价因子叠加反转因子,能起到意想不到的叠加效果

5.5 量价因子选股 —— 不同五分位数组合回测走势比较

 

# 可编辑部分与 strategy 模式一样,其余部分按本例代码编写即可 # -----------回测参数部分开始,可编辑------------ start = '2010-01-01' # 回测起始时间 end = '2016-08-01' # 回测结束时间 benchmark = 'ZZ500' # 策略参考标准 universe = set_universe('A') # 证券池,支持股票和基金 capital_base = 10000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 refresh_rate = 15 # 调仓频率,表示执行handle_data的时间间隔 corr_data = pd.read_csv('VolPriceCorr_W15_FullA.csv') # 读取量价因子数据 corr_data = corr_data[corr_data.columns[1:]].set_index('tradeDate') corr_dates = corr_data.index.values # ---------------回测参数部分结束---------------- # 把回测参数封装到 SimulationParameters 中,供 quick_backtest 使用 sim_params = quartz.SimulationParameters(start, end, benchmark, universe, capital_base) # 获取回测行情数据 idxmap, data = quartz.get_daily_data(sim_params) # 运行结果 results_corr = {} # 调整参数(选取股票的量价因子五分位数),进行快速回测 for quantile_five in range(1, 6): # ---------------策略逻辑部分---------------- commission = Commission(0.0002,0.0002) # 交易费率设为双边万分之二 def initialize(account): # 初始化虚拟账户状态 pass def handle_data(account): # 每个交易日的买入卖出指令 pre_date = account.previous_date.strftime("%Y-%m-%d") if pre_date not in corr_dates: # 只在计算过量价因子的交易日调仓 return # 拿取调仓日前一个交易日的量价因子,并按照相应十分位选择股票 pre_corr = corr_data.ix[pre_date] pre_corr = pre_corr.dropna() pre_corr = pre_corr[(pre_corr<=1.0) & (pre_corr>=-1.0)] pre_corr_min = pre_corr.quantile((quantile_five-1)*0.2) pre_corr_max = pre_corr.quantile(quantile_five*0.2) my_univ = pre_corr[pre_corr>=pre_corr_min][pre_corr<pre_corr_max].index.values # 调仓逻辑 univ = [x for x in my_univ if x in account.universe] # 不在股票池中的,清仓 for stk in account.valid_secpos: if stk not in univ: order_to(stk, 0) # 在目标股票池中的,等权买入 for stk in univ: order_pct_to(stk, 1.1/len(univ)) # ---------------策略逻辑部分结束---------------- # 把回测逻辑封装到 TradingStrategy 中,供 quick_backtest 使用 strategy = quartz.TradingStrategy(initialize, handle_data) # 回测部分 bt, acct = quartz.quick_backtest(sim_params, strategy, idxmap, data, refresh_rate=refresh_rate, commission=commission) # 对于回测的结果,可以通过 perf_parse 函数计算风险指标 perf = quartz.perf_parse(bt, acct) # 保存运行结果 tmp = {} tmp['bt'] = bt tmp['annualized_return'] = perf['annualized_return'] tmp['volatility'] = perf['volatility'] tmp['max_drawdown'] = perf['max_drawdown'] tmp['alpha'] = perf['alpha'] tmp['beta'] = perf['beta'] tmp['sharpe'] = perf['sharpe'] tmp['information_ratio'] = perf['information_ratio'] results_corr[quantile_five] = tmp print str(quantile_five), print 'done'

1

2

3

4

5 done

fig = plt.figure(figsize=(10,8)) fig.set_tight_layout(True) ax1 = fig.add_subplot(211) ax2 = fig.add_subplot(212) ax1.grid() ax2.grid() for qt in results_corr: bt = results_corr[qt]['bt'] data = bt[[u'tradeDate',u'portfolio_value',u'benchmark_return']] data['portfolio_return'] = data.portfolio_value/data.portfolio_value.shift(1) - 1.0 # 总头寸每日回报率 data['portfolio_return'].ix[0] = data['portfolio_value'].ix[0]/ 10000000.0 - 1.0 data['excess_return'] = data.portfolio_return - data.benchmark_return # 总头寸每日超额回报率 data['excess'] = data.excess_return + 1.0 data['excess'] = data.excess.cumprod() # 总头寸对冲指数后的净值序列 data['portfolio'] = data.portfolio_return + 1.0 data['portfolio'] = data.portfolio.cumprod() # 总头寸不对冲时的净值序列 data['benchmark'] = data.benchmark_return + 1.0 data['benchmark'] = data.benchmark.cumprod() # benchmark的净值序列 results_corr[qt]['hedged_max_drawdown'] = max([1 - v/max(1, max(data['excess'][:i+1])) for i,v in enumerate(data['excess'])]) # 对冲后净值最大回撤 results_corr[qt]['hedged_volatility'] = np.std(data['excess_return'])*np.sqrt(252) results_corr[qt]['hedged_annualized_return'] = (data['excess'].values[-1])**(252.0/len(data['excess'])) - 1.0 # data[['portfolio','benchmark','excess']].plot(figsize=(12,8)) # ax.plot(data[['portfolio','benchmark','excess']], label=str(qt)) ax1.plot(data['tradeDate'], data[['portfolio']], label=str(qt)) ax2.plot(data['tradeDate'], data[['excess']], label=str(qt)) ax1.legend(loc=0, fontsize=12) ax2.legend(loc=0, fontsize=12) ax1.set_ylabel(u"净值", fontproperties=font, fontsize=16) ax2.set_ylabel(u"对冲净值", fontproperties=font, fontsize=16) ax1.set_title(u"量价因子 - 不同五分位数分组选股净值走势", fontproperties=font, fontsize=16) ax2.set_title(u"量价因子 - 不同五分位数分组选股对冲中证500指数后净值走势", fontproperties=font, fontsize=16)

上面的图片显示“量价因子-不同五分位数分组选股”的净值走势,其中下面一张图片展示出各组头寸对冲完中证500指数后的净值走势,可以看到:

  • 不同的五分位数组对应的净值走势顺序区分度很高!

下面的表格展示出不同分位数组合的各项风险指标,每次调仓均买入量价因子最小的20%股票的策略,即最小分位数的组合(组合1)各项指标表现都非常出色:

# results 转换为 DataFrame import pandas results_pd = pandas.DataFrame(results_corr).T.sort_index() results_pd = results_pd[[u'alpha', u'beta', u'information_ratio', u'sharpe', u'annualized_return', u'max_drawdown', u'volatility', u'hedged_annualized_return', u'hedged_max_drawdown', u'hedged_volatility']] for col in results_pd.columns: results_pd[col] = [np.round(x, 3) for x in results_pd[col]] cols = [(u'风险指标', u'Alpha'), (u'风险指标', u'Beta'), (u'风险指标', u'信息比率'), (u'风险指标', u'夏普比率'), (u'纯股票多头时', u'年化收益'), (u'纯股票多头时', u'最大回撤'), (u'纯股票多头时', u'收益波动率'), (u'对冲后', u'年化收益'), (u'对冲后', u'最大回撤'), (u'对冲后', u'收益波动率')] results_pd.columns = pd.MultiIndex.from_tuples(cols) results_pd.index.name = u'五分位组别' results_pd

5.6 量价因子叠加反转因子选股 —— 不同五分位数组合回测走势比较

  • 量价因子和反转因子分别标准化,之后直接等权相加生成叠加因子

# 可编辑部分与 strategy 模式一样,其余部分按本例代码编写即可 # -----------回测参数部分开始,可编辑------------ start = '2010-01-01' # 回测起始时间 end = '2016-08-01' # 回测结束时间 benchmark = 'ZZ500' # 策略参考标准 universe = set_universe('A') # 证券池,支持股票和基金 capital_base = 10000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 refresh_rate = 15 # 调仓频率,表示执行handle_data的时间间隔 corr_data = pd.read_csv('VolPriceCorr_W15_FullA.csv') # 读取量价因子数据 corr_data = corr_data[corr_data.columns[1:]].set_index('tradeDate') corr_dates = corr_data.index.values revs_data = pd.read_csv('BackwardReturns_W20_FullA.csv') # 读取反转因子数据 revs_data = revs_data[revs_data.columns[1:]].set_index('tradeDate') # ---------------回测参数部分结束---------------- # 把回测参数封装到 SimulationParameters 中,供 quick_backtest 使用 sim_params = quartz.SimulationParameters(start, end, benchmark, universe, capital_base) # 获取回测行情数据 idxmap, data = quartz.get_daily_data(sim_params) # 运行结果 results_corrPlusRevs = {} # 调整参数(选取股票的因子五分位数),进行快速回测 for quantile_five in range(1, 6): # ---------------策略逻辑部分---------------- commission = Commission(0.0002,0.0002) # 交易费率设为双边万分之二 def initialize(account): # 初始化虚拟账户状态 pass def handle_data(account): # 每个交易日的买入卖出指令 pre_date = account.previous_date.strftime("%Y-%m-%d") if pre_date not in corr_dates: # 只在计算过量价因子的交易日调仓 return # 拿取调仓日前一个交易日的量价因子和反转因子,并按照相应分位选择股票 pre_corr = corr_data.ix[pre_date] pre_corr = pre_corr[(pre_corr<=1.0) & (pre_corr>=-1.0)] pre_revs = revs_data.ix[pre_date] # 量价因子和反转因子只做简单的等权叠加 pre_data = pd.Series(standardize(pre_corr.to_dict())) + pd.Series(standardize(pre_revs.to_dict())) pre_data = pre_data.dropna() pre_data_min = pre_data.quantile((quantile_five-1)*0.2) pre_data_max = pre_data.quantile(quantile_five*0.2) my_univ = pre_data[pre_data>=pre_data_min][pre_data<pre_data_max].index.values # 调仓逻辑 univ = [x for x in my_univ if x in account.universe] # 不在股票池中的,清仓 for stk in account.valid_secpos: if stk not in univ: order_to(stk, 0) # 在目标股票池中的,等权买入 for stk in univ: order_pct_to(stk, 1.1/len(univ)) # ---------------策略逻辑部分结束---------------- # 把回测逻辑封装到 TradingStrategy 中,供 quick_backtest 使用 strategy = quartz.TradingStrategy(initialize, handle_data) # 回测部分 bt, acct = quartz.quick_backtest(sim_params, strategy, idxmap, data, refresh_rate=refresh_rate, commission=commission) # 对于回测的结果,可以通过 perf_parse 函数计算风险指标 perf = quartz.perf_parse(bt, acct) # 保存运行结果 tmp = {} tmp['bt'] = bt tmp['annualized_return'] = perf['annualized_return'] tmp['volatility'] = perf['volatility'] tmp['max_drawdown'] = perf['max_drawdown'] tmp['alpha'] = perf['alpha'] tmp['beta'] = perf['beta'] tmp['sharpe'] = perf['sharpe'] tmp['information_ratio'] = perf['information_ratio'] results_corrPlusRevs[quantile_five] = tmp print str(quantile_five), print 'done'

1

2

3

4

5 done

fig = plt.figure(figsize=(10,8)) fig.set_tight_layout(True) ax1 = fig.add_subplot(211) ax2 = fig.add_subplot(212) ax1.grid() ax2.grid() for qt in results_corrPlusRevs: bt = results_corrPlusRevs[qt]['bt'] data = bt[[u'tradeDate',u'portfolio_value',u'benchmark_return']] data['portfolio_return'] = data.portfolio_value/data.portfolio_value.shift(1) - 1.0 # 总头寸每日回报率 data['portfolio_return'].ix[0] = data['portfolio_value'].ix[0]/ 10000000.0 - 1.0 data['excess_return'] = data.portfolio_return - data.benchmark_return # 总头寸每日超额回报率 data['excess'] = data.excess_return + 1.0 data['excess'] = data.excess.cumprod() # 总头寸对冲指数后的净值序列 data['portfolio'] = data.portfolio_return + 1.0 data['portfolio'] = data.portfolio.cumprod() # 总头寸不对冲时的净值序列 data['benchmark'] = data.benchmark_return + 1.0 data['benchmark'] = data.benchmark.cumprod() # benchmark的净值序列 results_corrPlusRevs[qt]['hedged_max_drawdown'] = max([1 - v/max(1, max(data['excess'][:i+1])) for i,v in enumerate(data['excess'])]) # 对冲后净值最大回撤 results_corrPlusRevs[qt]['hedged_volatility'] = np.std(data['excess_return'])*np.sqrt(252) results_corrPlusRevs[qt]['hedged_annualized_return'] = (data['excess'].values[-1])**(252.0/len(data['excess'])) - 1.0 # data[['portfolio','benchmark','excess']].plot(figsize=(12,8)) # ax.plot(data[['portfolio','benchmark','excess']], label=str(qt)) ax1.plot(data['tradeDate'], data[['portfolio']], label=str(qt)) ax2.plot(data['tradeDate'], data[['excess']], label=str(qt)) ax1.legend(loc=0, fontsize=12) ax2.legend(loc=0, fontsize=12) ax1.set_ylabel(u"净值", fontproperties=font, fontsize=16) ax2.set_ylabel(u"对冲净值", fontproperties=font, fontsize=16) ax1.set_title(u"量价因子与反转因子等权叠加选股 - 不同五分位数分组选股净值走势", fontproperties=font, fontsize=16) ax2.set_title(u"量价因子与反转因子等权叠加选股 - 不同五分位数分组选股对冲中证500指数后净值走势", fontproperties=font, fontsize=16)

 

上面的图片显示“量价因子叠加反转因子-不同五分位数分组选股”的净值走势,其中下面一张图片展示出各组头寸对冲完中证500指数后的净值走势,可以看到:

  • 不同的五分位数组对应的净值走势顺序区分度很高!

下面的表格展示出不同分位数组合的各项风险指标,每次调仓均买入量价因子反转因子叠加后最小的20%股票的策略,即最小分位数的组合(组合1)各项指标表现都非常出色:

# results 转换为 DataFrame import pandas results_pd = pandas.DataFrame(results_corrPlusRevs).T.sort_index() results_pd = results_pd[[u'alpha', u'beta', u'information_ratio', u'sharpe', u'annualized_return', u'max_drawdown', u'volatility', u'hedged_annualized_return', u'hedged_max_drawdown', u'hedged_volatility']] for col in results_pd.columns: results_pd[col] = [np.round(x, 3) for x in results_pd[col]] cols = [(u'风险指标', u'Alpha'), (u'风险指标', u'Beta'), (u'风险指标', u'信息比率'), (u'风险指标', u'夏普比率'), (u'纯股票多头时', u'年化收益'), (u'纯股票多头时', u'最大回撤'), (u'纯股票多头时', u'收益波动率'), (u'对冲后', u'年化收益'), (u'对冲后', u'最大回撤'), (u'对冲后', u'收益波动率')] results_pd.columns = pd.MultiIndex.from_tuples(cols) results_pd.index.name = u'五分位组别' results_pd

5.7 更长回测时间 —— 06年开始回测

  • 量价因子和反转因子分别标准化,之后直接等权相加生成叠加因子
  • 此处选择叠加因子最小的20%股票作为持仓组合

start = '2006-01-01' # 回测起始时间 end = '2016-08-01' # 回测结束时间 benchmark = 'ZZ500' # 策略参考标准 universe = set_universe('A') # 证券池,支持股票和基金 capital_base = 2000000 # 起始资金 freq = 'd' # 策略类型,'d'表示日间策略使用日线回测 refresh_rate = 15 # 调仓频率,表示执行handle_data的时间间隔 corr_data = pd.read_csv('VolPriceCorr_W15_FullA.csv') # 读取量价因子数据 corr_data = corr_data[corr_data.columns[1:]].set_index('tradeDate') corr_dates = corr_data.index.values revs_data = pd.read_csv('BackwardReturns_W20_FullA.csv') # 读取反转因子数据 revs_data = revs_data[revs_data.columns[1:]].set_index('tradeDate') quantile_five = 1 # 选取股票的因子五分位数,1表示选取股票池中因子最小的20%的股票 commission = Commission(0.0002,0.0002) # 交易费率设为双边万分之二 def initialize(account): # 初始化虚拟账户状态 pass def handle_data(account): # 每个交易日的买入卖出指令 pre_date = account.previous_date.strftime("%Y-%m-%d") if pre_date not in corr_dates: # 只在计算过量价因子的交易日调仓 return # 拿取调仓日前一个交易日的量价因子和反转因子,并按照相应分位选择股票 pre_corr = corr_data.ix[pre_date] pre_corr = pre_corr[(pre_corr<=1.0) & (pre_corr>=-1.0)] pre_revs = revs_data.ix[pre_date] # 量价因子和反转因子只做简单的等权叠加 pre_data = pd.Series(standardize(pre_corr.to_dict())) + pd.Series(standardize(pre_revs.to_dict())) pre_data = pre_data.dropna() pre_data_min = pre_data.quantile((quantile_five-1)*0.2) pre_data_max = pre_data.quantile(quantile_five*0.2) my_univ = pre_data[pre_data>=pre_data_min][pre_data<pre_data_max].index.values # 调仓逻辑 univ = [x for x in my_univ if x in account.universe] # 不在股票池中的,清仓 for stk in account.valid_secpos: if stk not in univ: order_to(stk, 0) # 在目标股票池中的,等权买入 for stk in univ: order_pct_to(stk, 1.1/len(univ))

fig = plt.figure(figsize=(12,5)) fig.set_tight_layout(True) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() ax1.grid() bt_quantile = bt data = bt_quantile[[u'tradeDate',u'portfolio_value',u'benchmark_return']] data['portfolio_return'] = data.portfolio_value/data.portfolio_value.shift(1) - 1.0 data['portfolio_return'].ix[0] = data['portfolio_value'].ix[0]/ 2000000.0 - 1.0 data['excess_return'] = data.portfolio_return - data.benchmark_return data['excess'] = data.excess_return + 1.0 data['excess'] = data.excess.cumprod() data['portfolio'] = data.portfolio_return + 1.0 data['portfolio'] = data.portfolio.cumprod() data['benchmark'] = data.benchmark_return + 1.0 data['benchmark'] = data.benchmark.cumprod() # ax.plot(data[['portfolio','benchmark','excess']], label=str(qt)) ax1.plot(data['tradeDate'], data[['portfolio']], label='portfolio(left)') ax1.plot(data['tradeDate'], data[['benchmark']], label='benchmark(left)') ax2.plot(data['tradeDate'], data[['excess']], label='hedged(right)', color='r') ax1.legend(loc=2) ax2.legend(loc=0) ax2.set_ylim(bottom=0.5, top=5) ax1.set_ylabel(u"净值", fontproperties=font, fontsize=16) ax2.set_ylabel(u"对冲指数净值", fontproperties=font, fontsize=16) ax2.set_ylabel(u"对冲指数净值", fontproperties=font, fontsize=16) ax1.set_title(u"量价因子反转因子叠加选股的前20%股票回测走势", fontproperties=font, fontsize=16)

  • 上图可以看到从06年起的回测结果,展示出量价因子反转因子叠加后的稳定的alpha输出

我们根据量价因子叠加反转因子选取股票组合,表现最好的组合其06年以来年化收益达到41.4%,alpha达到22.6%,beta仅为0.88,展示出稳定盈利的能力。

(本文由公众号越声投顾(yslcw927))整理,仅供参考,不构成操作建议。如自行操作,注意仓位控制和风险自负。)

今天给大家分享一个选股策略,教您如何轻轻松选出长线大牛股。今天帮大家选一次,按照该策略选出票,之后需要大家自己操作哦!

选股策略如下:

1、主营同比增长率≥50%;

2、主营三年复合增长率≥50%;

3、股东人数环比变化≤0%;

4、基金重仓股。

解释:选股策略为何什么要这样的设计呢?一般来说,基金重仓股是指基金持股比例占上市公司流通股比例的20%。这说该股有着比较强的稳定性,无论在熊市还是牛市,不易出现大涨大跌;回撤率保持较好,稳步上升。

对于主营同比增长和主营环比增长,说明该股为成长性较好的优秀股票,再加上股东人数环比是在减少的,也说明该股目前筹码相对开始集中,人均持股数相对开始增加。因而更有利于股价的上涨与稳定。

操作:如下所示,打开官网,登录进入后,找到选股平台,并分别填上图中标记的红色部分,然后执行选股即可,然后这里要提示大家,我们在选择基金重仓股时,直接基金持流通股比例大于或等于20%即可!

在如下图所示,根据该选股策略,截止2016年11月8号,沪深二千多只股票,共选出三只股票,分别为恒华科技、信维通信和中国动力,可以说这三只个股有望成为长线优质大牛股。

当然选股的时候也可以关注以下以下的指标

盈利能力:盈利能力是股东回报的根本来源。我们认为在经济增速下行期间,行业内 盈利能力领先且产品毛利率较为稳定的企业拥有更加良好的抵抗风险的能力,我们采 用行业内 ROE 排行(ROE 行业分位)来衡量行业内一家公司的盈利能力所处的地位, 并采取当季毛利率环比波动来去除那些成本快速上升或产品/服务价格快速下降的行 业与公司。

成长性:高成长性推动超额回报,但同时业绩增速高的公司往往估值更高,并在未延续成长性时面临戴维斯双杀的危险。我们认为公司的成长性需要更多地结合基本面的 研究来判断行业空间和公司质地,因此我们首先将成长性的标准设定为当季扣非净利 润增长 20%及以上,且增速相较上季度未大幅下滑。

估值:我们选取 1)市盈率小于 25 倍及 2)PB 小于历史分位 60%作为标准。

资产质地:我们排除了负债过高与商誉比过高的企业,并将在个股研究中进一步关注 公司的股权质押率及控制权的稳定的问题。

每个散户从入市到稳定盈利都一段很长的路要走,这期间有很多艰辛和挫折,或许只有炒过股票的人才知道,有时你会一直亏损却不知所措,有时你会觉得明明按照技术严格操作走势却恰恰相反,有时买入却开始大跌,有时卖出却开始大涨,这一切的一切只有进入股市的人才能体会。小编是一个炒股十年的老股民,经历过大涨,经历过大跌,用血汗总结出炒股铁律十条,看下那几条禁忌是你正在犯得,那几天经验你正在遵守。

一、切忌逆势买进

你看到这一条的反应可能会是:“切,还用你说?”我相信,这甚至是每个股民都知道的铁律。但是你是否这样做了呢?有多少次你一次次买进一次次亏损,最后你才发现你一直在下跌段买进,比如2018年的大盘就是如此。怎样避免逆势买进?最简单的方法就是60日均线下方不操作,60日均线向下不操作,甚至60日均线打平不操作。

二、无盈利不加仓

这条可能会有很多股友反对,因为一大部分股友是在亏损后在下方支撑位买入以降低成本,结果最终全仓被套,这样你可能连回本的机会都没有了。无盈利不加仓,准确来说是指试仓部分没有出现盈利,也就是承认买入计划失败,则应该按照止损点止损或者出现盈利后再按照交易计划加仓。

三、无计划不交易

这一条很好理解,但是却很难做到,因为可能每个股友都会有冲动进场的经历,本来坚持每天写交易计划的人就不多。你可以前天晚上制定第二天交易计划,也可以利用中午休市的时候制定或改变下午的交易计划,就是不能在交易变化中改变自己的交易计划,至少至少应该交易前在纸上写下应该怎么做,止损位置在哪里之后再进场。

四、只抓属于自己交易系统的盈利

有的股友股票池有很多只,今天你买的股票下跌或者涨幅很小,结果买有买的股票却连续涨停,那么你会怎么做呢?你可能会一头热就冲进涨停股票,而下午迎接你的是天地板的跌停。其实完全没有必要,每个人的交易系统就是自己的避风港,一旦离开港口你无法保证自己的安全。

五、每次只持仓两只股票

我们最常听到的一句话就是把鸡蛋放进多个篮子里面,其实这是一个矛盾点,如果真的把鸡蛋放进多个篮子,那么你有多少精力可以兼顾每个篮子呢?对于资金量相对较小的散户而言,持仓两只股票为宜,一是避免了因为只买一直股票导致的随机性损失,二是两只股票资金相对不算分散,一旦一只涨幅较大,整体也会有不错的收益。

六、上午卖出,下午买进

这一点不能一概而论,原则上上午是交易比较激情的时间,一天的高点容易在这个时间段产生,而且上午卖出一旦买错下午还可以有补仓进场的机会。下午买进目的在于减少风险,减少持股时间,以便在第二天上午根绝盘面做出有利操作。

七、切忌全进全出,仓位管理很重要

有多少股友炒股喜欢全仓全进全出,相信这样做的不在少数。我个人不是激进派,也不喜欢激进操作,全进固然盈利的话涨幅惊人,但是作为散户炒股保本为第一要务,所以在建仓时尽量采用试仓-加仓的手法分批建仓。

八、多时间维度操作

大多数的股票只看日线交易,其实这样是不对的,换种说法单维度操作有点像全进全出。单一维度操作容易造成操作滞后,或者止损时损失巨大。例如可以采用日线、60分钟、15分钟的三维时间维度操作,三个维度买卖点设定好对应一定的仓位,可以避免一次性出现较大的损失。

九、切勿追涨杀跌

这条是家喻户晓但在实际操盘时却会犯的错误。切勿追涨是指在股票上涨时,应该耐心等待回调买入;切勿杀跌是指,下跌支撑后应该等待回调不破卖出。

十、赢不赢利不重要,正不正确才重要

这条一出,相信很多人会骂我装B,其实还真不是这样的,相当于扑鱼时忽略掉抓到几条鱼,而将经历放在渔的技术上。将重点放在过程而不是结果,一旦我们将经历放在交易的正确与否而不是到底今天赢了多少钱来的更有意义。

如果您喜欢以上文章,想了解更多股市投资经验及技巧,关注公众号越声投顾(yslcw927),干货很多!

全面注册制直接利好券商、创投和白马蓝筹股。所以,下周我们一定要远离高位题材赛道,围绕上述理念做文章。

本人以五矿为例,说一下下周的选股逻辑。因为,它是集券商、创投、央企改革等概念为一体的白马股,是全面注册制的最大受益者。

1.从券商下手,最好是头部券商

(1)优势:五矿是绩优价低多题材的稀缺股,它拥有一家B类券商公司、排名前三的信托公司和排名前十的期货公司,要是分拆上市,就是三家上市公司。

(2)劣势:五矿没有头部券商,主业有点分散。

2.退而求其次,出击创投概念

(1)优势:五矿的创投业务做得风生水起,不说投资银行、金融租赁、基金等,光其国际金融资产租赁业务就有10来个亿的收入,要是投资的哪个企业能上市,立马身价倍增。

(2)劣势:在创投上排名不怎么靠前,非龙头老大。

3.寻找白马蓝筹,远离阿猫阿狗

(1)从多元金融板块来说,它是基本面最好的公司,这一点可在公开信息中查到。估计每股收益可达0.613元,市盈率只有10.7倍,市净率不到0.6倍,妥妥的白马。

(2)劣势:优先股的发行虽利好它的财务,却也限制了股价。另外,五矿的庄似乎不够硬,若能换庄,必有大为。

4.从央企重组、重新估值上潜伏

(1)优势:很少有人知道,五矿还是央企改革的先锋,在五矿集团中举足轻重。早在去年上锋提出价值重估时,曾有一波20厘米的表现。

(2)劣势:似乎没有介入金融科技,固守在传统金控平台。

总之,五矿在四个央企金融平台上,它的质地是最优的,其他已有表现,五矿也不能落后。

以上是我个人的选股思路,并非操作建议。股友若有更好的选股思路,我们一起交流。

2月17日,备受资本市场关注的全面注册制正式实施。这场足足准备了10年的改革,在经过2019年科创板试点注册制,2020年创业板注册制“增量+存量”改革,2021年北交所成立并同步试点注册制后,正式向全市场铺开。A股亦告别了执行31年的审批、核准制,迈入全面注册制时代。而围绕全面注册制下,加速扩容的选股难度、迥然不同的打新价值、分化加大的交投策略,它们会更加验证“炒股不如买基金”吗?

注册制改革的本质是把选择权交给市场

区别于过去核准制时代下,一家企业若想上市,必须达到上市标准,还得经过证监会资料审核、价值判断等重重流程;注册制下,企业达到上市标准后,只需要把资料提交给证券交易所,并且申请注册,主管机关形式审查中若无异议,申请即自动生效,可以向社会公开进行招股。至于发行人的营业性质、财力素质、发展前景、发行数量与价格实质等条件,不再作为发行审核要求,监管也不作出价值判断。真正将企业价值判断的选择权交给市场,且责任分散到各个市场主体。

对于投资者而言机会更多,但专业性也同步升级

对于个人投资者而言,注册制的推行有助于增加投资选择和机会,但同时优胜劣汰更为严酷的市场环境下,也更加考验投资者的耐心和成熟度。首先,上市公司数量增多、个股分化加剧、波动幅度加大,这对投资者的定价能力、风险管理以及时间精力都提出了更高要求。其次,“打新”躺赢成为历史,“炒差炒新”也难再常胜,投资者需要注意转换思维。数据显示,2019-2022年区间若直接投资A股,那么有56%的选股概率收益将低于25%,但有74%的选基概率收益率可达到“25%”以上。而全面注册制的落地,这将加剧个股投资收益的分化程度,对于个人投资者而言需要更加注重公司长期基本面的研究,提升投资专业性,同时借道公募基金参与股票投资,将专业的事情交给专业的人,也或是不错的选择。

拥抱新时代,公募基金“专业价值”有望进一步突显

而公募基金的专业价值,有望在全面注册制进一步凸显。相比于个人投资者,公募基金作为专业的投资机构,在全产业链的深度跟踪、上市公司的长期调研、和投资价值的专业把握上,积累了深厚的投研“内功”。Wind数据显示,2022年基金公司对A股上市公司调研次数高达12.85万次,刷新了历年调研之最,也超越了所有主流机构。在全面注册制这个更考验投研能力的时代,公募基金有望凭借团队化、专业化、系统化的作战方式,更快速地在扩容股票池中遴选优质标的,将研究成果高效转化为投资业绩,承担更多的居民资产配置功能。

投资有风险,基金投资需谨慎。

在投资前请投资者认真阅读《基金合同》《招募说明书》等法律文件。基金净值可能低于初始面值,有可能出现亏损。基金管理人承诺以诚实守信、勤勉尽责的原则管理和运用基金资产,但不保证一定盈利,也不保证最低收益。过往业绩及其净值高低并不预示未来业绩表现。其他基金的业绩不构成对本基金业绩表现的保证。以上信息仅供参考,如需购买相关基金产品,请您关注投资者适当性管理相关规定、提前做好风险测评,并根据您自身的风险承受能力购买与之相匹配的风险等级的基金产品。

[选股策略测试工具(注册制选股策略)]

引用地址:https://www.gupiaohao.com/202304/29936.html

tags: