最近大宗商品开始史无前例疯狂上涨模式,成为期货圈热门话题,不管是媒体还是国家监管层均有极大关注。对于交易者来说,在全球大宗商品持续通胀的情况下,择时做多就显得更有意义。本篇文章就以国内商品期货黑色系为标的,开发一个多头择时策略。
为何最近大宗商品疯狂上涨,尤其是黑色系频繁上演涨停潮?综合各方观点来看,主要有以下几方面原因: 1、美元指数持续下跌 2020年新冠肺炎疫情暴发以来,美元指数持续下跌,而大宗商品是以美元计价的,持续的弱美元走势,间接推动了商品价格的上涨。
2、货币供应量 2020年疫情之后,全球主要经济体央行集体放水,尤其是美欧日三国M2同比增速超过20%,在各国央行宽松政策不变的情况下,市场通胀预期仍然强烈。
3、全球经济复苏 随着各国疫苗接种顺利,经济回暖,大宗商品需求反弹,全球制造业采购经理指数(PMI)持续扩张,制造业的复苏对工业品价格形成支撑。
2021年与我们日常生活息息相关的上游物资,不知不觉均出现明显上涨。正如巴菲特所言这一切都拜美联储宽松的货币和财政政策所赐,由于疫情期间美国出台的一系列天量刺激措施,全球的经济复苏已经裹挟着通胀奔涌而来。 图片来源:新浪财经、东方财富
如图所示,上图是美元指数从2018年5月至今的数据,下图是大宗商品指数从2018年8月至今的数据,从图中可以看出,美元指数和大宗商品指数始终呈相反的走势。
大宗商品上涨是全球性问题,并不只是只有国内大宗商品价格上涨。而美元作为大宗商品标价用货币,两者关系大致上类似价格和需求量的关系,即大宗商品价格的变化通常与美元相反,通常美元指数下跌,大宗商品上涨。
费雪方程式可以解释货币供应量、物价水平、国民收入之间的数量关系,公式如下:
MV=PQ
其中:
由于疫情的出现,导致产品滞销,进而导致企业贷款需求减少,那么货币周转速率(V)就会降低,费雪方程式(MV=PQ)就会失去平衡(左边变小),如果不加以控制就会出现通货紧缩的风险,为了减缓费雪方程式左边的MV下降速度,全球主要央行采取的方法是开启印钞机,增大货币总量(M)应对。
而如今,疫情过后经济复苏,货币周转率(V)已经接近正常,但超发的货币(M)一时半会收不回来,导致费雪方程式(MV=PQ)又失去平衡(左边变大)。
那么既然费雪方程式(MV=PQ)是等式,相应的方程式右边也会变大,不是商品价格(P)变大,就是商品数量(Q)变大,或者同时变大。但是我们知道商品数量变大是需要一个过程的,是需要一定时间的,那么市场会启动自我修复,在商品数量(M)不可能立刻变大的情况下,只能是商品价格(P)变大。
综上尽管市场种种短期波动具有不确定性,但2021年可能是大宗商品牛市真正开始的一年。好了,话不多说,接下来我们就以国内商品期货黑色系为标的,开发一个多头择时策略。
商品期货黑色系多头择时策略是通过有针对性的对标历史数据、市场规律、交易模式等方面的分析,采用固定的、数量化的交易模式,来发掘其中的交易机会并实现盈利。该策略以优宽(youquant.com)量化的MY语言来实现交易策略的具体实施。具体策略逻辑为:
第1步:计算前4根K线最高价与开盘价的差的均值
HO1 := REF(H, 1) - REF(O, 1);
HO2 := REF(H, 2) - REF(O, 2);
HO3 := REF(H, 3) - REF(O, 3);
HO4 := REF(H, 4) - REF(O, 4);
HTO := (HO1 + HO2 + HO3 + HO4) / 4;
第2步:计算HO1、HO2、HO3、HO4均值
LINE := O - HTO * N;
第3步:计算多头开仓信号
D1 := REF(C, 1) < REF(C, 2);
D2 := REF(C, 2) < REF(C, 3);
D3 := REF(C, 3) < REF(C, 4);
D := D1 && D2 && D3 && C > LINE;
第4步:计算多头平仓信号
K1 := REF(C, 1) > REF(C, 2);
K2 := REF(C, 2) > REF(C, 3);
K3 := REF(C, 3) > REF(C, 4);
K := K1 && K2 && K3 && C <= LINE;
T1 := BARSLAST(BARSLAST(K) < BARSLAST(D));
DT := IFELSE(T1 <= REF(T1, 1), 0, (C - VALUEWHEN(T1 = 1, C)));
第5步:下单交易
D, BK;
T1 < 5 && T1 > 3 && DT < 7, SP;
回测配置
回测绩效
资金曲线
(*backtest start: 2015-02-22 00:00:00 end: 2021-05-07 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] args: [["ContractType","rb000",126961]] *) HO1 := REF(H, 1) - REF(O, 1); HO2 := REF(H, 2) - REF(O, 2); HO3 := REF(H, 3) - REF(O, 3); HO4 := REF(H, 4) - REF(O, 4); HTO := (HO1 + HO2 + HO3 + HO4) / 4; LINE := O - HTO * N; D1 := REF(C, 1) < REF(C, 2); D2 := REF(C, 2) < REF(C, 3); D3 := REF(C, 3) < REF(C, 4); D := D1 && D2 && D3 && C > LINE; K1 := REF(C, 1) > REF(C, 2); K2 := REF(C, 2) > REF(C, 3); K3 := REF(C, 3) > REF(C, 4); K := K1 && K2 && K3 && C <= LINE; T1 := BARSLAST(BARSLAST(K) < BARSLAST(D)); DT := IFELSE(T1 <= REF(T1, 1), 0, (C - VALUEWHEN(T1 = 1, C))); D, BK; T1 < 5 && T1 > 3 && DT < 7, SP;template: strategy.tpl:40:21: executing "strategy.tpl" at <.api.GetStrategyListByName>: wrong number of args for GetStrategyListByName: want 7 got 6