**导语:**商品期货交易上线啦!听闻这个消息的小编当然坐不住了,决定立刻商品期货走一波!本文选择实现的是经典的海龟交易法,之前[量化课堂](https://www.joinquant.com/post/1401?f=study&m=algorithm)已经有海龟交易法在股票当中的应用了,这一次让我们来看看海龟策略在商品期货中的应用吧!
##海龟交易是什么
作为经典的交易策略,相信很多人都已经很清楚什么是海龟交易法了,如果你已经清楚明白的知道了什么是**唐奇安通道**、**真实波幅**、**N值(ATR)**和**Unit**,也能够熟练地掌握他们的算法,那你大可直接跳过这一部分,进入策略实现的部分。
如果你想快速认识什么是海龟交易策略,或是想重新回顾一下,那就让我们开始吧!
###唐奇安通道
先让我们上一张图!

图中这个完全将K线包裹在内的通道线就是**唐奇安通道**,它的上线与下线分别取的是20日最高价与最低价,因此当当前价格突破上线或者下线的时候,都能作为很好的突破信号。
就像上图图中所示,当价格突破上线的时候,往往意味着一轮向上行情的开启,我们在这个时候进行多仓买入操作。
类似的,当价格突破下线的时候,往往意味着一轮向下行情的开启,我们在这个时候进行卖空操作。

这就是海龟交易法的基础,当然,作为一个成熟的交易法则,我们还需要一些指标来判断加仓点、止损点与每次买入卖出的数量。而用来判断的依据,我们叫做真实波幅与N值。
###真实波幅
话不多说先上公式!
$$True Range=Max(High-Low, \left| pre\ close-High\right|, \left|pre\ close-Low\right|)$$
其中:High是指当日最高价,Low为当日最低价,pre_close是指前一日收盘价。
公式看上去很复杂,其实它要表达的就是**昨日收盘以后股票的最大波幅**,让我们来看看K线图里真实波幅具体指哪一部分。

从图片中我们可以很容易的看出,真实波幅就是昨天收盘后股票的最大振幅,也就是图片中最长的那一根箭头所表示的位置。
###N值(ATR)
N值是海龟交易法当中非常重要的一个概念,它还有一个名字,那就是ATR(Average True Range),也就是**平均真实波幅**的意思,话不多说,老规矩上公式先!
$$N(ATR)=\frac{1}{days}\times\sum\limits_{i=1}^{days}True Range_i$$
或者用滑动平均的方法:
$$N(ATR)_t=\frac{(days-1)\times N(ATR)_{t-1}+TrueRange_t}{days}$$
其中:days是取平均的天数,比如我们要取真实波幅20日的平均,days就取20;TrueRange是真实波幅。
从公式可以看出,**N(ATR)值其实就是标的days日内的平均真实波幅,当这个值大的时候,就说明这段时间股票每一天的波动率都很大,当这个值小的时候,就说明这段时间每一天的波动率都很小。**
因此在海龟交易法中,**每当标的价格上涨(下跌)0.5个N(ATR)时,我们就加仓1个Unit的多头(空头)仓位;当标的价格上涨(下跌)2个N(ATR)时,我们就对空头(多头)仓位进行平仓止损。**
让我们举一个例子来看看N值究竟怎么算~为了方便起见,我们就令days=5,由于TrueRange计算时用的是前一日的收盘价,因此我们自己计算时**收盘价要取前一日的数据而不是当天的**:
* 收盘价: 35190., 35490., 36060., 35840., 35710.
* 最高价: 35700., 36080., 36210., 36060., 35990.
* 最低价: 35280., 35640., 35610., 35630., 35640.
用以上三行价格中的最大值减去最小值便能得到真实波幅数据:
* TrueRange: 510., 590., 600., 430., 350.
计算这五个数的平均值有$(510+590+600+430+350)\div5=548$
因此5日N(ATR)便为548
###Unit
知道了买点、卖点、止损点与加仓点,我们就需要知道每一次建仓与加仓都需要购买多少数量,老规矩,看公式!
$$Unit=\frac{1\%\times Account}{N(ATR)\times coef}$$
其中:Account表示账户中的总资金,coef为该商品期货一手的数量,如铜为5吨一手,则对铜的商品期货来说,coef就等于5。下面是一些常见商品期货的coef表格:
```pythong
'A':10, 'AG':15, 'AL':5, 'AU':1000,
'B':10, 'BB':500, 'BU':10, 'C':10,
'CF':5, 'CS':10, 'CU':5, 'ER':10,
'FB':500, 'FG':20, 'FU':50, 'GN':10,
'HC':10, 'I':100, 'IC':200, 'IF':300,
'IH':300, 'J':100, 'JD':5, 'JM':60,
'JR':20, 'L':5, 'LR':10, 'M':10,
'MA':10, 'ME':10, 'NI':1, 'OI':10,
'P':10, 'PB':5, 'PM':50, 'PP':5,
'RB':10, 'RI':20, 'RM':10, 'RO':10,
'RS':10, 'RU':10, 'SF':5, 'SM':5,
'SN':1, 'SR':10, 'T':10000, 'TA':5,
'TC':100, 'TF':10000, 'V':5, 'WH':20,
'WR':10, 'WS':50, 'WT':10, 'Y':10,
'ZC':100, 'ZN':5
```
我们接着用之前那个例子来看看Unit的计算。之前的数据小编取的是期货铜的价格,则coef应该为5,假设我们的账户当中有1,000,000的现金。
$$Unit=\frac{1\%\times 1,000,000}{548\times5}=3.65\approx4$$
可以得到每一次购买、加仓,我们都需要购买4手的期货铜。
##策略实现
到这里,相信你已经知道什么是海龟交易法了,让我们来总结一下这个策略究竟是怎样的吧!
* 计算期货标的的N(ATR)与Unit;
* 判断价格是否突破了唐奇安通道,若是向上突破则多头仓位开仓,空头仓位平仓;向下突破则空头仓位开仓,多头仓位平仓;
* 若期货价格高于(低于)上次买入价格0.5个ATR,则加仓一个Unit的多头(空头)仓位;
* 若期货价格低于(高于)上次买入价格2个ATR,则平仓多头(空头)仓位止损。
###划重点——商品期货代码一定要注意
商品期货策略开始一定要记得设置账户属性为期货账户,不然是没有办法交易的哦~具体的代码参考如下:
```python
set_subportfolios([SubPortfolioConfig(cash=context.portfolio.starting_cash, type='index_futures')])
# 也不要忘了同时要更改手续费,还要设置保证金比例哦
# 期货类每笔交易时的手续费是:买入时万分之0.23,卖出时万分之0.23,平今仓为万分之23
set_order_cost(OrderCost(open_commission=0.000023, close_commission=0.000023,close_today_commission=0.0023), type='index_futures')
# 设定保证金比例
set_option('futures_margin_rate', 0.15)
```
###回测
构建好策略以后,小编便用沪铜期货“CU”作为标的来试验了一下大名鼎鼎的海龟交易法:

结果还不错哦~大家可以克隆代码以后自己改标的尝试一下,还可以根据自己以往海龟交易的经验优化一下买点卖点与止损函数。
以上就是海龟交易法在商品期货的尝试,大家快把代码克隆起来,商品期货走一波!
对铜是有效,但对菜粕就一塌糊涂,劝新手不要拿去就用。
2017-10-28
学习了感觉很有收获,就是有时候操作的不是主力合约,这个说明里面没有对换合约方面有说明啊。换月合约的条件和原因能否说明。
2017-10-29
楼主粉丝要求~![funs.png][1]
[1]: https://image.joinquant.com/931c0db212f5fcdaf65c1fb336bd01b1
2017-10-31
# 合约
g.future_index = ['ZC','CU']
在这里添加编译也通不过去,
2017-10-31
开仓平仓好像有问题,例如多仓的情况下,依然开空仓,之后过几天平多仓。整个是乱的。
2017-12-26
开仓平仓好像有问题,例如多仓的情况下,依然开空仓,之后过几天平多仓。整个是乱的。@ScintiGimcki
2014-12-24 21:00 焦炭1505(J1505.XDCE) 开空 市价单 6手 1008.758 605,254.62 0.00 36.32
2014-12-25 21:00 焦炭1505(J1505.XDCE) 开空 市价单 6手 1003.764 602,258.34 0.00 36.14
2014-12-31 21:00 焦炭1505(J1505.XDCE) 开多 市价单 5手 1030.266 515,132.85 0.00 30.91
2015-01-05 21:00 焦炭1505(J1505.XDCE) 开多 市价单 4手 1030.266 412,106.28 0.00 24.73
2015-01-06 21:00 焦炭1505(J1505.XDCE) 开多 市价单 4手 1056.298 422,519.08 0.00 25.35
2015-01-07 21:00 焦炭1505(J1505.XDCE) 开多 市价单 4手 1057.299 422,919.56 0.00 25.38
2015-01-27 21:00 焦炭1505(J1505.XDCE) 开空 市价单 7手 1021.742 715,219.19 0.00 42.91
2015-01-27 21:00 焦炭1505(J1505.XDCE) 平多 市价单 -17手 1021.742 1,736,960.89 -35,716.88
2017-12-26
![J.jpg][1]
[1]: https://image.joinquant.com/58dcdc0c03dc684b25eac6428b02a5b2
这策略, 改成趋势性最强的焦炭试试, 效果是意想不到的差劲. 哈哈. 有趣.
2018-02-05
感谢分享!
不过看了日志之后发现策略好像有点问题,多头只能开仓、加仓和平仓,没有止损;空头只能开仓和止损,没有加仓和平仓。
是不是有什么问题?
2018-03-11
感谢作者的无私分享,写的特别详细,学习之后收获很大
2018-04-03
![猎豹截图20180625161608.png][1]
我没看错的话,这个鸡蛋交易单位是不是有问题? 应该是10,鸡蛋一手是5吨,但是报价是 x元/500kg
[1]: https://image.joinquant.com/eba80c2c29b8cca958a3e003dbba00e1
2018-06-25
@mxzhkahn 发现代码有问题,空头建仓后,建仓价格记录在last_prcie,而非last_price,导致加仓、止损都会有判断问题
2018-08-05
原版海龟中coef=标的的最小一个波动单位,期货的最少波动点位并不是1元
这里的coef用每手表示并不合适,最好用每手*最小价格波动点位
2018-11-18