光大证券技术择时系列报告之一是RSRS,之二是RSRS推广到行业轮动,之三是放量恰是入市时:成交量择时初探。
这篇研报主要讲的是用交易量来构造一个择时策略。
里面提到,“价涨量先行”,成交量较大时指数大概率上涨。
构造成交量的时间序列排名指标方式如下:
- 数据上除了当日的成交量以外,我们还需取前 N 个交易日的每日成 交量数据,共 N 1 个成交量的值。
- 将该 N 1 个成交量数据按从小到大进行排序,计算当日成交量在这 N 1 个数值中的排名 n,最小即为 1,最大即为 N 1。
- 通过运算 2 * (n-N-1) / N 将当日成交量排名标准化为[-1, 1]内的数 值。
上面是研报提到的构造方式,但是标准化的公式有问题,2 (n-N-1) / N 映射到的区间是[-2,0],应该改为(n-平均数)/平均数,即 2( n-(N-1)/2) /N才对。
择时方法是用上面的构造方式算出来[-1,1]的数去和阈值做判断,其含义其实就是当成交量时序排名处于最大的一段范围内就买入,否则卖出。
核心代码:
bars = get_bars(g.security,g.N 1,unit='1d',
fields=['date', 'open','high','low','close','volume'],
include_now=False, end_dt=None, fq_ref_date=None)
print bars
last_day_volume = bars[-1]['volume']
lt_last_day_volume_count = 0
for i in range(0,len(bars)-1):
if bars[i]['volume'] < last_day_volume:
lt_last_day_volume_count = 1
last_day_volume_rank = lt_last_day_volume_count 1
std_score = 2.0*(last_day_volume_rank -1 - g.N/2.0)/g.N
if std_score > g.S:
g.tc = 7
order_target_value(g.security, context.portfolio.total_value)
elif std_score < g.S:
order_target_value(g.security, 0)
然后里面提到参数(N=35,S=0.8)的择时效果更佳,我们将其 作为沪深 300 成交量时序排名择时策略的参数。中证 500 的参数由样本内表现确定为(N=30, S=0.5)。
我根据研报的策略写的代码应该没什么错,尝试复现了一下,达不到研报中说的收益。不知道是研报注水了,还是我忽略了什么东西,或者是里面隐藏了什么条件。
我的测试结果:
沪深300,N=35 S=0.8
2007-03-05 到 2014-01-01
策略收益 30.87% 策略年化收益 4.13% 基准收益 -7.12% Alpha 0.007 Beta 0.113 Sharpe 0.012 胜率 0.562 盈亏比 1.608 最大回撤 13.43%
中证500, N=30 S=0.5
2007-03-05 到 2014-01-01
策略收益 142.98% 策略年化收益 14.29% 基准收益 52.94% Alpha 0.097 Beta 0.237 Sharpe 0.614 胜率 0.504 盈亏比 1.677 最大回撤 18.19%
在中证500上面还好一些,年化14% 最大回撤18%,但也没达到研报上写的中证500年化25.5% 最大回撤17%
沪深300上面就更差了,年化才4% 回撤13%,研报上面写的年化15.2% 回撤11%
我这算复现失败了吗?大佬们帮忙看看是哪里不对,还是说研报真的注水了。但按理说不会啊,这篇研报作者是RSRS的作者。