股票学习网

股票行情网,股票入门,和讯股票,股票查询 - - 股票学习网!

选股策略测试工具(第二天必涨选股法)

2023-06-09 13:40分类:炒股经验 阅读:

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,展示出稳定盈利的能力。

1、GRU概述

  GRU是LSTM网络的一种效果很好的变体,它较LSTM网络的结构更加简单,而且效果也很好,因此也是当前非常流形的一种网络。GRU既然是LSTM的变体,因此也是可以解决RNN网络中的长依赖问题。

  在LSTM中引入了三个门函数:输入门、遗忘门和输出门来控制输入值、记忆值和输出值。而在GRU模型中只有两个门:分别是更新门和重置门。具体结构如下图所示:

图中的zt和rt分别表示更新门和重置门。更新门用于控制前一时刻的状态信息被带入到当前状态中的程度,更新门的值越大说明前一时刻的状态信息带入越多。重置门控制前一状态有多少信息被写入到当前的候选集ht上,重置门越小,前一状态的信息被写入的越少。

按照资料中的步骤,搭建深度学习模型,选择GRU算法,构建包括特征和标签提取、特征预处理、样本内训练、交叉验证和样本外测试等步骤。最终在每个月底可以产生对全部个股下期上涨概率的预测值,然后根据正确率、AUC 等指标以及策略回测结果对模型进行评价。我们的模型设置为月频换仓,为了让模型及时学习到市场特征的变化并兼顾计算效率,我们采用了滚动回测方法,即从 2019年1月1开始,每月底重新构建一次模型,在下一月进行测试。我们还根据模型的预测结果构建了沪深300成份内选股和中证500成份内选股策略,通过年化收益率、夏普比率、最大回撤等指标综合评价策略效果。

截至2022年4月1,中证500指数增强收益150%,同期指数50%,超额100%,夏普比率1.24,最大回撤24%。

同期LSTM收益160%,同期指数50%,超额110%,夏普比率1.28,最大回撤28%。

截至2022年4月1,沪深300指数增强收益100%,同期指数40%,超额60%,夏普比率1,最大回撤32%。

同期LSTM收益120%,同期指数40%,超额80%,夏普比率1.15,最大回撤26%。

总结:GRU的最终收益,夏普比率均略低于LSTM,但计算时间和收敛速度比LSTM快。

在股市实战中,很多朋友都很崇尚所谓的“超短线”战法,以达到快进快出、获得收益的目的!这个想法或者这种需求本身没有问题,毕竟在股市博弈之中,大家都想要赢得胜利,获得可观的收益。在这里,就与大家分享一种超短线战法,基本操作流程是:T-1日选股、T日买进、T+1日卖出

第一步 T-1日选股

这里提到的“T-1日选股”的意思是,在决定买入当天的前一个交易日,要先进行选股操作,确定拟买入的股票标的。标的的选取范围要限定在当日的涨停股之中,记住一定要是涨停股,这样选股范围就会大幅缩小,而且涨停股一般也较为强势,后期继续上涨的概率较大。

这样,T日计划买入的股票标的可以定在1-3只,多了会就存在选择困难。

第二步 T日买入

根据T-1日确定的选股标的以及标的股在T日的集合竞价情况,最终决定买入1只股票,买入的时机把握要果断。当然,标的股都不好的情况下,也可以选择放弃。

第三步 T+1日卖出

受限于A股的交易规则,T日买进的股票,当天是无法卖出的,因此在T+1日的时候,无论涨跌,不管是赚了多少,还是亏了多少,也不管T+2日是否还会继续涨,一定要择机选择卖出要坚决完成卖出操作,不能犹豫,不能恋战,否则会形成不好的习惯!

第四步 操作总结

总结主要包括:1.一轮操作的盈亏情况;2.盈亏对应标的股票的特征情况;3.买入卖出时机的把握情况。

注意事项

注意事项主要包括:1.无关涨跌盈亏,坚决按照流程完成操作计划;2.可以将仓位分成2批,交替进行,第一批仓位在T日执行买进操作后,当日收盘后即可进行第二批仓位T-1日的选股操作;3.对于连续上涨的强势涨停股,可以持续保持跟踪操作。

本战法来源于股友的A股实践操作总结,观察其实践操作2周后,在此分享,仅供参考!

做交易的四层境界

我们做交易,也一样是这四层境界:

第一层境界是“用心”。

此时因为刚入门,会有很多妄想跟杂念,而这些妄念会使我们分心,所以更须要练习专心──希望藉着“心思专注”的训练,能够把思绪的杂质跟残渣都过滤掉,剩下精纯的思想。

第二层境界是“无心”。

此时因为妄念减少,所以思想变的轻盈飘逸、灵活有神,也就是一种很自然的状态。自然就是不刻意、不扭捏。从很纯淨的动机出发,努力做事,而不存坏的心机。

第三层境界是“精进”。

此时既然已经达到无心的高度境界,当然就要更用功──此时不用功,更待何时?

第四层境界是“常用”。

此时一切正常发展、自然运作,不受感情的羁绊,一切自然,该休息就休息、该猛烈就猛烈,一切随机缘、任运乘势,积极成长,花最少的力气、却得到最好的效果。交易十大秘诀,你知道几个?

不要逆势而为。赚到真正大钱的方法就是确定主要的趋势,然后顺势而为。如果市场的趋势不利于你,那么你就该离场了。当你处在熊市,而主趋势在下跌时,你应当等待反弹,并且做空,而不是试图选择其底部。在大熊市里,你可能在其下跌过程中好几次错过底部,输的精光。同样的道理也适用于大牛市,要总是跟随潮涨潮落——永远不要逆之而动。

“月线看势、周线选股、日线分时”。在市场中有很多投资者在观察和分析大盘跟个股时经常都是盯着日K线图来看的,但是对于周、月线就看的很少且研究不多。

然而,如果能够熟练使用周线看盘和选股,那就会让头脑更加清醒冷静,同时也可以减少操作中的失误。

怎么利用周线选股?

每个人选股的方式不一样,有的人喜欢选短线股,有的人喜欢选长线股,不管你是选择短线股还是长线股,不能套用,因为选股思路是不一样的,那怎么选择股票,相信大家或多或少都知道些选股技巧,但真正选到好股盈利的人却很少,所以下面就来给大家介绍下怎么用周线选股。

周线,就是说一周的股票k线图,以周一开盘到周五收盘,以一周内最低价为最低价,以一周内最高价为最高价,一般都是由5天日K线组成的。

一、周线选股法则:

1、如果一只股票长期在低位沉寂,但某周收一根带巨量的周阳线,且在未来3到5天内持续上涨不跌;

2、随后股价回落后,长时间内都是小阴小阳横盘,期间缩跌量涨带量,且不管怎么调整理,股价都不怕首周大量大阳的底部;

3、在某只股周均线粘合在一起,再次放量离开横盘平台时,我们可以初步介入;股价前高时,表示主升行情将展开,我们可以及时加重仓位。

二、周线选股的要点:

1、选股:选10周均线趋势向上的个股。坚决回避10周均线趋势向下的个股;

2、介入点1:强势股5,10,20,30周线正排列向上时(弱势股:负排列向下)并周线排列开口不大时,介入点:股价回档5周均线附近;

3、介入点2:10周均线趋势向上,股价回到10周均线附近;

4、介入点3:横盘股,选择10,20,30周线粘合的个股;

三、利用周K线选股应注意的6个地方:

1、必须发生在跌势中,且有相当的跌势才算是打底的理想区,跌幅不深只是下跌阶段中的休息区,暂时止跌并不能为打底。

2、打底的K线一定要有下影线,因为下影线表示探底后获得支撑,为反弹的必要条件。

3、跌势中必须出现明显量缩才会酝酿打底,且打底完成必须配合成交量放大才会推升。

4、打底的K线可以月线、周线、日线为准,打底区域越长,其涨势也越大。

5、如果能选择月K线、周K线、日K线、60分钟K线的底部“共振”区间,则该底部的可靠性极高。

6、周K线两阳夹一阴“多方炮”更有向上攻击能力。

四、周线选股具体操作技巧:

1、选股:选10周均线趋势向上的个股。坚决回避10周均线趋势向下的个股;

2、介入点:(1)强势股5,10,20,30周线正排列向上时(弱势股:负排列向下)并周线排列开口不大时;(2)介入点:股价回到5周均线附近;

3、介入点2:10周均线趋势向上,股价回到十周均线附近。

4、介入点3:横盘股,选择10,20,30周线粘合的个股。

5、介入点4:10周均线趋势向上,如果股价跌破10周均线,可在20,30周均线之上考虑介入,但如果跌破30周均线,跑。

五、周线选股介入点:

1、股价回到5周均线附近;

2、10周均线趋势向上,股价回档到10周均线附近。

3、横盘股,选择10,20,30周线粘合的个股

4、10周均线趋势向上,如果股价跌,我们可以在20或者30周均线上考虑介入,但如果跌破了30周均线,那就赶紧跑。

周线操作技巧,不计日内得失

日线是股价每天波动的反映,但是如果我们过分沉迷于每日的股价涨跌,会“只见树木,不见森林”,因此要从更长的周期把握股价的走势,还得应用周线图来观察。一般来说,在周线图上,我们可通过观察周线与日线的共振、二次金叉、阻力位、背离等几个现象寻找买卖点。

1、周线与日线共振

周线反映的是股价的中期趋势,而日线反映的是股价的日常波动,若周线指标与日线指标同时发出买入信号,信号的可靠性便会大增,如周线KDJ与日线KDJ共振,常是一个较佳的买点。日线KDJ是一个敏感指标,变化快,随机性强,经常发生虚假的买、卖信号,使投资者无所适从。运用周线KDJ与日线KDJ共同金叉(从而出现“共振”),就可以过滤掉虚假的买入信号,找到高质量的买入信号。

不过,在实际操作时往往会碰到这样的问题:由于日线KDJ的变化速度比周线KDJ快,当周线KDJ金叉时,日线KDJ已提前金叉几天,股价也上升了一段,买入成本已抬高,为此,激进型的投资者可在周线K、J两线勾头、将要形成金叉时提前买入,以求降低成本。

2、周线二次金叉

当股价(周线图)经历了一段下跌后反弹起来突破30周线位时,我们称为“周线一次金叉”,不过,此时往往只是庄家在建仓而已,我们不应参与,而应保持观望;当股价(周线图)再次突破30周线时,我们称为“周线二次金叉”,这意味着庄家洗盘结束,即将进入拉升期,后市将有较大的升幅。此时可密切注意该股的动向,一旦其日线系统发出买入信号,即可大胆跟进。

3、周线的阻力

周线的支撑与阻力,较日线图上的可靠度更高。从今年以来的行情我们可以发现一个规律,以周线角度来看,不少超跌品种第一波反弹往往到达了60周均线附近就有了不小的变化。以周K线形态分析,如果上冲周K线以一根长长的上影线触及60周均线,这样的走势说明60周线压力较大,后市价格多半还要回调;如果以一根实体周线上穿甚至触及60周均线,那么后市继续上涨、彻底突破60周均线的可能性很大。

实际上60周均线就是日线图形中的年线,但单看年线很难分清突破的意愿,走势往往由于单日波动的连续性而不好分割,而周线考察的时间较长,一旦突破之后稳定性较好,我们有足够的时间来确定投资策略。

4、周线的背离

日线的背离并不能确认股价是否见顶或见底,但若周线图上的重要指标出现底背离和顶背离,则几乎是中级以上底(顶)的可靠信号,大家不妨回顾过去重要底部和顶部时的周线指标,对寻找未来的底部应有良好的借鉴作用。

周线突破平台或者K线突破60周均线买入战法的操作要领

1、周线要突破长期的震荡平台。如果是一二月的不符合我们这里讲的战法。

2、K线在60周线之上,同时5、10、20周线在60周线上方。

3、MACD突破0轴,出现红柱

当周线突破了平台或K线突破了60周线,我们再利用日线结合来确定买卖点。

周线突破平台或者生命线(60均线买入法)注意的技术要点:

1、周线突破长期(时间周期可以定为3-12个月份左右或更长一些)的震荡或盘整的高点方可买入。

2、macd指标背离,且突破0柱!绿柱走完,红柱出现最好,这时候是介入的好时机。

3、k线上穿生命线,且5.10和20均在生命线上方,买入就对了。

下面列举一些经周线突破出现买点以及突破后的强势上涨走势图:

周线抓黑马

一、周线黑马三大要素

1、均线运行要素。7周均线上穿14周均线时,坚决买进;反之,7周均线下穿14周均线时,毫不留恋地卖出,一般,我们通常的运用5周10周,在研判一个股票的时候,需要调整调整一下看看,避免主力是在洗盘还是在出货.

2、成交量要素。一周成交量超过前周4至5倍时,可以放心买入.

3、在5周中,无论是周阴线还是周阳线,到达这个时间限度,不论赢多赢少最好是卖出了结.因为周线黑马往往以上升时间来衡量,如果不掌握这个规律,就有可能由盈变亏。在均线交叉、成交量放大4倍以上和5周时间这三大要素中,前两大要素是买入的最佳机遇,是抓住黑马、迅速骑上的条件,后一条是巩固获利成果的重要条件。

二、周移动平均线的运用方法

1、周移动平均线的时间参数的设置为5周、13周、34周。

2、当股价在5周均线之上收阳,而5周均线也同步上扬,其后收阳可能大。

当股价在5周均线之上收阴,但没破5周均线,且5周线继续上升,股价为短线调整,下周继续上升可能大。

3、当股价在5周均线之下收阴,且5周线处下行状态,其后下行可能大。

当股价在5周均线之下收阳,而5周线仍处下跌状态,为短线反弹,其后下跌可能大。

4、当股价持续上升后收周阴线,且破5周线,而且下周均线掉头下行并且高于股价,则股价要作中线调整,应离场。

5、当股价持续下跌后收周阳线,且收市价高于5周线,而且下周均线掉头上行并且低于股价,则有中级上升行情,应中线持股。

6、短期周均线与中长期周均线形成黄金交*,且中长期均线横走或开始上升,股价有中长期的升势,短期周均线与中长期周均线形成死亡交*,且中长期均线横走或开始下跌,股价有中长期的调整

7、当股价处中期盘整,均线无大的意义,应多注重周线本身的分析和成交量的变化。

三、周线跳空缺口

突破的缺口越大,力度越大

在历史上,凡是出现周线跳空缺口的,主力都要有足够的勇气和资金,一些底气不足的主力是不敢留下缺口的。绝大多数涨得好的股票在周线上都能看到缺口。

缺口保持三天不补,它的运行就像磁悬浮一样悬浮起来。三天不补缺口必上涨!

回调至缺口买入,等来的是涨停板!

股价在短期内(15天内),在某一30%的价格区间内,间断或连续拉出两个涨停,该股至少相对第二涨停板的收盘价会有短线10%套利空间,是短线高手逢低买入短线的重点技巧。

向上跳空缺口5天内未完全回补,受趋势快线获得支撑后大阳突破!股价以开盘向上跳空5个点以上的缺口,一周内不回补可放心买入。

四、周线牛股形态

实战中周线牛股形态有下列六大特征:

1、周线均线形态成密集缠绕形且成多头排列,均线间的乖离极小;

2、五周攻击线金叉十周操盘线;

3、 60周决策线金叉120周趋势线;

4、 30周生命线下降不行,走平或略微上翘最佳;

5、 MACD指标刚开始金叉,红柱出现;

6、周线K线第一次放量;

实战范例:

000049,德赛电池,周线图,不用多说了,和上述周线六大特征核对一下,两波行情每波股价都翻了好几倍,主力都是猴精的,日线级别往往会遮蔽我们的双眼,但周线级别一般不存在技术诱空。

注意:一旦个股符合周线六大特征,我们就要介入,介入的时点就是符合日线图六大特征的那根K线,日线六大特征是和周线六大特征一样的,只不过级别降低罢了。

五、周线二次金叉

当股价(周线图)经历了一段下跌后反弹起来突破30周线位时,我们称为“周线一次金叉”,不过,此时往往只是庄家在建仓而已,我们不应参与,而应保持观望;当股价(周线图)再次突破30周线时,我们称为“周线二次金叉”,这意味着庄家洗盘结束,即将进入拉升期,后市将有较大的升幅。此时可密切注意该股的动向,一旦其日线系统发出买入信号,即可大胆跟进。

六、经典周线波段技术

七、周线多周期共振金叉买入法

原理:5周线金叉10周线,说明股价有中线继续上涨动能,成交量金叉,说明在股价上涨是资金主动性买入所致;周线MACD金叉,说明中线继续向好;周线KDJ金叉,说明中线上涨行情出现黄金买入点。在股票图形上,一旦出现均线、成交量、MACD、KDJ共振金叉,就是短中线买入点。

请大家先将看图软件略做修改:将画面调成四图组合状态;再将技术指标调整为MACD和KDJ组合。然后再将KDJ指标的参数指标中的(9.3.3)调整为(9.9.9),然后再将股票K线图切换到周线状态。

画面组合——选择四图组合。

特征:

1、五周线上穿10周线;

2、成交量指标金叉;

3、MACD指标金叉;

4、KDJ指标金叉。

结论:一旦股票周K线图出现四种指标共振金叉,即为中线黄金买入点。

注意:在使用这种方法时,建议采用复权方式,复权后效果最接近股价运行实际。

以上为个人多年炒股总结,大家一定要收藏,反复学习,自己获益!我是南巷,一个经历过三轮牛熊,擅长逻辑选股,技术择时的人,只做认知范围内的交易,每一次的方向都得到了盘面的印证!

如果你觉得有帮助可以点赞收藏。感谢你的阅读,关注我学习更多炒股知识。

https://www.xusbuy.com

上一篇:5分钟超短线期货技巧(期货技巧大全)

下一篇:股票(600635股票交易)

相关推荐

返回顶部