网络相传亚洲有四大邪术,日本化妆,韩国整容,泰国变X,Z国PS。
这些都是让人在颜值上看起来很美,类似地,在量化交易领域,也有四大邪术能让净值曲线看起来很美,今儿个来说量化四大邪术当中的第一个,也可能是大伙儿听到的最多的一个,它就是"未来函数",后面三个下期接着唠~
未来函数之前
未来函数之后
带未来函数的那条净值曲线美不美?要是有骗子用这种净值曲线去卖策略割韭菜,可能有不少不懂行的萌新上当受骗吧~
"未来函数",顾名思义,就是在量化研究和策略回测当中,使用了当前时间点还没有发生的数据,引入了未来的信息去决定当前的交易信号。
这就相当于至尊宝举起月光宝盒,大喊"般若波罗蜜",时光倒流,带着已知,穿越回去,挽救爱情,而金融的实盘行情当中,没有这种神奇外挂,也无法给你未来的信息。所以啊,有未来函数的策略,回测看起来像《安乐传》当中的迪丽热巴,实盘起来就成了《黑悟空》里面的金池长老。
刚才说的都是抽象的概念,接下来我举一个实打实的例子,并且这个带未来函数的策略,还可以"巧妙"地通过量化平台的防未来检验。
这是之前群友发的一个圣杯策略,据说是非常牛逼,拿策略源码一回测,哦豁,这TM真的是小母牛坐火箭,牛逼上天了啊!!!
回测从2014年开始,近10年的累计收益率是8359157.97%,年化收益率是198.49%,夏普为6.297,好嘛,10年8万多倍,每年翻2番,什么西蒙斯、巴菲特、索罗斯,仨人捆一块儿都不是对手,在这个“圣杯”面前都是渣渣。
这么逆天的收益曲线,以我多年踩坑的直觉,肯定是有猫腻啊,二话不说,先在原来策略基础上打开防未来函数功能,在回测设置部分加入以下代码。
# 打开防未来函数功能
set_option("avoid_future_data", True)
设置avoid_future_data为True,表示开启防未来函数功能,也就是在回测当中,使用包含时间参数的官方API去获取数据时,如果获取了当前日期之后的数据,程序则会抛出异常,无法正常回测。
重新回测后,绩效还是纹丝不动,还是10年83591倍,每年翻2番,真正的猫腻还是要耐下心来细细读代码才能发现的。
通读下来,这个"圣杯"就是一个单因子策略,大致分3步走:
(1)每5个交易日交易一次,以创业板指成分股为基础股票池,剔除停牌无法交易的股票,形成当次的可交易股票池。
(2)在可交易股票池中,以Zura Kakushadze大神《101 Formulaic Alphas》论文中的第101号因子当前值作为选股因子,数值从大到小排序,选出其中数值最大的前10支股票。
(3)对于这10支股票,等权买入,不在此列的持仓则卖出,在此列的持仓则需要重新恢复到等权。
这个策略中的"第101号因子当前值"就是带有未来函数的了,但是很“巧妙”地绕开了avoid_future_data的检查机制,下面细说。
avoid_future_data一般用来防止当天使用当天之后的数据,但是如果当天使用当天的数据呢,就不会抛出未来函数异常(至少这个策略没有),就可以正常回测。虽然是当天调用当天数据,但却是开盘时就获得了这一天的涨跌幅信息,具体情况往下看。
def get_stock_factor_values(date):
no = '101'
cmd = 'alpha_'+no+'(date, g.all_stocks)'
df = eval(cmd)
df = df.sort_values(ascending=False)
return df
today = str(context.current_dt)[0:10]
df = get_stock_factor_values(today)
获取因子数据时,使用的是当天的日期,而这个alpha_101因子的计算式子是:(收盘价 - 开盘价) / ((最高价 - 最低价) + 0.001)。
“收盘价 - 开盘价”是日线Bar中实体的长度,“最高价 - 最低价”是整个日线Bar的长度,“0.001”是防止分母为0,简单来说,这个因子就是衡量实体占整个Bar的比例,数值越大,占比越高。
那什么时候数值最大呢?如果分母里面没有那个0.001,那光头光脚的阳线数值最大,只要不是一字板,那么这个因子的数值都是1.0。但现在是有了0.001,那就是涨幅越大的光头光脚阳线的因子数值越大,举个极端的例子。
假设close - open = high - low = 0.001,则alpha_101 = 0.5;
假设close - open = high - low = 1.0,则alpha_101 = 0.999。
看到了没,这个策略相当于在开盘时就选中了今天涨幅最大的股票进行买入,变相地会卖出今天涨幅“不如意”的股票,并且策略当中是使用order_target和order_target_value函数进行交易,默认是按照开盘价成交的,这妥妥明确地吃到一整天肥美的涨幅。
那咱就把获取因子的数据调整到上一个交易日,重新回测一遍,你瞧,原形毕露了吧,10年累计收益-78.13%,年化收益-13.87%,连基准指数都没有跑过,怎一个惨字了得!
date = str(context.previous_date)[0:10]
df = get_stock_factor_values(date)
看到了吧,即使这个量化策略持仓周期是5天,只有1天的未来信息,但也可以带来巨大的虚假繁荣,一旦未来函数被揪出来,圣杯的光芒就会迅速地黯然褪去,如果不想中"未来函数"的邪,可以看一下之前的避坑贴《答应我,在量化策略回测里,避开未来函数这4个坑》。
最后想说的是,即使现在量化平台越来越完善,有很多功能防止用户出错,但只要是人设计的系统,总会有不完美的地方,就怕别有用心的人会利用这些漏洞和缺陷,钻未来函数的空子,构建出漂亮的“庞氏曲线”割韭菜。
人生在世,可要长点儿心呐,别中了这种邪,上了这种当~
原文首发链接:《量化四大邪术之一:般若波罗蜜》