觉得文章有收获,欢迎关注公众号鼓励一下作者呀~
在学习的过程中,也搜集了一些量化、技术的视频及书籍资源,欢迎大家关注公众号【亚里随笔】获取
也欢迎大家通过【亚里随笔】与我交流联系~

1 业绩评估指标的不稳健问题
在交易系统的测试中,我们一般需要通过一些业绩衡量指标来观测系统的相对表现,判定一个系统未来是否有盈利的潜力。但是,一些常用的业绩衡量指标如年化收益率、最大回撤、夏普比率等,并不是非常稳定,寥寥几次交易中的微小变化就能对这些不稳健指标的值产生巨大的影响。指标的不稳定性可能造成我们评估的偏差,既可能导致我们过高地评价一个理念,也可能导致我们盲目地放弃一个本来很有潜力的理念。
所谓稳健的评估指标,是指在评估的过程中数据的轻微变化并不会显著的影响一个统计指标。而不稳健的评估指标则相反,在对交易系统进行回测时,参数值的轻微变化会带来不稳健指标的大幅变化。对于不稳健的评估指标,任何对数据有影响的因素都会对测试结果产生过大的影响,这很容易导致数据过拟合。
这里以rumi策略为例,展示一下评估指标的不稳健问题。
回测设置如下:
engine.set_parameters(
vt_symbol="FGI.CZCE",
interval=Interval.HOUR,
start=datetime(2020, 1, 1),
end=datetime(2022, 1, 1),
rate=0.015 / 100, # 手续费率为万分之一,增加0.5模拟额外消耗
slippage=0, # 滑点一般为一跳
size=20,
pricetick=1.0,
capital=40000,
)
setting = {'fast_window': 2, 'slow_window': 10, 'rumi_window': 40}
常用的评估指标回测结果如下:
2023-04-08 17:06:42.521886 首个交易日: 2020-01-16
2023-04-08 17:06:42.521896 最后交易日: 2021-12-31
2023-04-08 17:06:42.521952 总收益率: 74.59%
2023-04-08 17:06:42.521959 年化收益: 37.61%
2023-04-08 17:06:42.521982 百分比最大回撤: -17.02%
2023-04-08 17:06:42.522107 Sharpe Ratio: 1.41
我们只去掉最初的一个月和最后的一个月,其他回测参数保持一致,对比评估指标的相对变化值。
对比回测设置如下:
engine.set_parameters(
vt_symbol="FGI.CZCE",
interval=Interval.HOUR,
start=datetime(2020, 1, 1) + timedelta(days=30),
end=datetime(2022, 1, 1) - timedelta(days=30),
rate=0.015 / 100, # 手续费率为万分之一,增加0.5模拟额外消耗
slippage=0, # 滑点一般为一跳
size=20,
pricetick=1.0,
capital=40000,
)
setting = {'fast_window': 2, 'slow_window': 10, 'rumi_window': 40}
常用的评估指标回测结果如下:
2023-04-08 17:09:20.564159 首个交易日: 2020-02-17
2023-04-08 17:09:20.564173 最后交易日: 2021-11-01
2023-04-08 17:09:20.564250 总收益率: 84.22%
2023-04-08 17:09:20.564260 年化收益: 48.59%
2023-04-08 17:09:20.564294 百分比最大回撤: -17.18%
2023-04-08 17:09:20.564474 Sharpe Ratio: 1.74
2023-04-08 17:09:20.564273 回归年化收益(RAR): 46.51%
普通指标的变化幅度对比:
评估指标 | (2020-01-16,2021-12-31) | (2020-02-17,2021-11-01) | 变化幅度 |
---|---|---|---|
年化收益率 | 37.61% | 48.59% | +29% |
Sharpe Ratio | 1.41 | 1.74 | +23% |
总收益率 | 74.59% | 84.22% | +13% |
百分比最大回撤 | -17.02% | -17.18% | +1% |
从上表可以看出,在我们只将回测区间去掉最初的一个月和最后的一个月的情况下,年化收益率增加了29%,Sharpe Ratio提升了23%。年化收益率和Sharpe Ratio对回测的起止日非常敏感。并且如果回撤发生在测试期的开端或结尾附近,百分比最大回撤这个指标也会对测试的起止日期高度敏感,在本次测试中回撤没有发生在开端或结尾附近,所以百分比最大回撤变化不大。
2 回归年化收益率 RAR
收益率这样的指标之所以对回测的起止日期非常敏感,是因为收益在计算的过程中,只使用了起始资金和结束资金。对年化收益率(annual_return)而言,一般的计算方法如下:
total_return = (end_balance / self.capital - 1) * 100 #总收益率
annual_return = total_return / total_days * self.annual_days #年化收益率
every_day_return = (df["balance"] / self.capital - 1) * 100 # 每天的收益率
绘制每天的收益率曲线,在曲线中every_day_return的斜率即为annual_return计算中的total_return / total_days,只是年化收益率的计算只使用了总收益率,即起点和终点。所以,改变起止日,会导致估计斜率的大大改变,从而影响年化收益率的稳定性。
改变了起止点后,计算的斜率会大大不同,但如果我们对曲线上的所有的点进行一次线性回归,就可以得到回报率的一个更好的衡量指标。在《海龟交易法则》中,将线形回归线和它所代码的回报率定义为RAR(Regressed Annual Return),即回归年化收益率。RAR由于计算的是回归线的斜率,所以对测试的起止日远不像年化收效率那样敏感。
借助numpy的polyfit工具,我们可以很方便地进行曲线的拟合,实现如下:
# RAR
every_day_return = (df["balance"] / self.capital - 1) * 100
coeff = polyfit(range(0, total_days), every_day_return, 1)
regress_annual_return = coeff[0] * self.annual_days
3 稳健风险回报比率
前面也提到了,如果最大回撤发生在测试期的前后任意一端,考虑最大回撤的相关指标就会有很大影响,如果百分比最大回撤等。并且最大回撤只是净值曲线上的一个点,并没有其他有价值的数据,一个包含更多回撤期的指标要好于这个指标。假如一个系统有32%、34%、35%、35%、36%这5次大回撤,别一个系统的5次大回撤为20%、25%、26%、29%、36,那么后者显然好于前者。
另外,回撤百分比只是一个一维指标,并不是所有30%的回撤幅度都有同样的意义。一个仅经历了两个月的回撤就转而创出新高的系统,会比持续一两年的回撤才恢复要更好。恢复时间或回撤期的长度本身也是非常重要的。
R-Cube(robust risk/reward ratio)是《海龟交易法则》中设计的一种新的风险回报指标,它考虑了起止日对收益率的影响、包含更多的回撤期及回撤期长度。R-Cube的计算方法如下:
R-Cube
=
RAR
平均最大回撤百分比
×
平均回撤天数
÷
365
\text{R-Cube} = \frac{\text{RAR}}{平均最大回撤百分比 \times 平均回撤天数 \div 365}
R-Cube=平均最大回撤百分比×平均回撤天数÷365RAR
这个分母指标有两个要素:平均最大回撤和长度调整,平均最大回撤百分比就是5次最大回撤幅度的平均值,长度调整是将这5次回撤期的平均天数除以365。R-Cube作为一个风险回报指标,它从程度和时间两个角度考虑了风险问题,它所使用的指标对测试的起止日变化并不是那么敏感,不太容易随着数据的轻微变动而发生大的变化,因此R-Cube也更稳定。
R-Cube的计算需要考虑每个回撤期,而不能简单的通过 df[“ddpercent”].nsmallest(5)来计算。
一个比较直接的R-Cube指标的计算实现如下:
# R-Cube = RAR / (平均最大衰落 x 平均衰落天数)
drop_downs = []
pre_row = None
for index, row in df["ddpercent"].items():
if pre_row is not None and pre_row == 0 and row < 0:
drop_down = {'start': index, 'max_ddpercent': row, 'end': index,
'max_ddpercent_length': 1}
elif pre_row is not None and pre_row < 0 and row == 0:
drop_down['end'] = index
if row < drop_down['max_ddpercent']:
drop_down['max_ddpercent'] = row
drop_down['max_ddpercent_length'] = (index - drop_down['start']).days
drop_downs.append(drop_down)
elif pre_row is not None and pre_row < 0 and row < 0:
drop_down['end'] = index
if row < drop_down['max_ddpercent']:
drop_down['max_ddpercent'] = row
drop_down['max_ddpercent_length'] = (index - drop_down['start']).days
pre_row = row
drop_downs.sort(key=lambda i: i['max_ddpercent'])
n_max_ddpercent = [x['max_ddpercent'] for x in drop_downs[:5]]
n_max_drawdown_durations = [x['max_ddpercent_length'] for x in drop_downs[:5]]
r_cube = regress_annual_return / (-1 * np.mean(n_max_ddpercent) * np.mean(n_max_drawdown_durations) * 12
/ self.annual_days)
4 实验对比
我们基于RAR和R-Cube进行测试,相应的变化幅度如下:
评估指标 | (2020-01-16,2021-12-31) | (2020-02-17,2021-11-01) | 变化幅度 |
---|---|---|---|
年化收益率 | 37.61% | 48.59% | +29% |
Sharpe Ratio | 1.41 | 1.74 | +23% |
总收益率 | 74.59% | 84.22% | +13% |
百分比最大回撤 | -17.02% | -17.18% | +1% |
RAR | 45.14% | 46.72% | +3.5% |
R-Cube | 2.70 | 2.76 | +2.2% |
在相同的数据变化下,可以看出稳健的评估指标RAR只增加了3.5%、R-Cube只增加了2.2%,而常用的年化收益率增加了29%、Sharpe Ratio 增加了23%。
参考资料
- 《海龟交易法则》
- VeighNa开源量化 公众号:vnpy-community