量化投资学习笔记83——实现量化交易经典策略:海龟交易法

先改了一下参数优化的程序,现在能输出更多的回测结果指标了。具体就不赘述了。
这次来实现一下海龟交易法。有人实现过的,照着来就行了。
https://zhuanlan.zhihu.com/p/114782214
https://blog.csdn.net/ndhtou222/article/details/107479277
特此感谢原作者!
海龟交易法的策略为:
入场:当收盘价突破20日价格高点时,买入一单元股票。
加仓:价格大于上一次买入价格的0.5个ATR(平均波幅,backtrader里有相应的Indicator的),买入一单元股票,加仓次数不超过3次。
止损条件:价格小于上一次买入价格的2个ATR时清仓。
离场条件:当价格跌破10日价格低点时清仓。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# coding:utf-8
# 海龟策略实现


import backtrader as bt
import backtrader.indicators as bi
import backtest
import pandas as pd
import math


class TurtleStrategy(bt.Strategy):
params = (
("long_period", 20),
("short_period", 10),
("printlog", False),
)

def __init__(self):
self.order = None
self.buyprice = 0
self.comm = 0
self.buy_size = 0
self.buy_count = 0
# 用到的指标
self.H_line = bi.Highest(self.data.high(-1), period = self.p.long_period)
self.L_line = bi.Lowest(self.data.low(-1), period = self.p.long_period)
self.TR = bi.Max((self.data.high(0) - self.data.low(0)), abs(self.data.close(-1) - self.data.high(0)), abs(self.data.close(-1) - self.data.low(0)))
self.ATR = bi.SimpleMovingAverage(self.TR, period = 14)
# 价格与上下轨线交叉
self.buy_signal = bt.ind.CrossOver(self.data.close(0), self.H_line)
self.sell_signal = bt.ind.CrossOver(self.data.close(0), self.L_line)

def next(self):
if self.order:
return

# 入场:价格突破上轨线且空仓时
if self.buy_signal > 0 and self.buy_count == 0:
self.buy_size = math.ceil((self.broker.getvalue() * 0.01 / self.ATR) / 100) * 100
self.sizer.p.stake = self.buy_size
self.buy_count = 1
self.order = self.buy()
self.log("入场")

# 加仓: 价格上涨了买入价的0.5ATR且加仓次数少于3次(含)
elif self.data.close > self.buyprice + 0.5*self.ATR[0] and self.buy_count > 0 and self.buy_count <= 4:
self.buy_size = math.ceil((self.broker.get_cash() * 0.01 / self.ATR) / 100) * 100
self.sizer.p.stake = self.buy_size
self.order = self.buy()
self.buy_count += 1
self.log("加仓")

# 离场: 价格跌破下轨线且持仓时
elif self.sell_signal < 0 and self.buy_count > 0:
self.order = self.sell()
self.buy_count = 0
self.log("离场")

# 止损: 价格跌破买入价的2个ATR且持仓时
elif self.data.close < (self.buyprice - 2*self.ATR[0]) and self.buy_count > 0:
self.order = self.sell()
self.buy_count = 0
self.log("止损")


# 输出交易记录
def log(self, txt, dt = None, doprint = False):
if self.params.printlog or doprint:
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))

def notify_order(self, order):
# 有交易提交/被接受,啥也不做
if order.status in [order.Submitted, order.Accepted]:
return
# 交易完成,报告结果
if order.status in [order.Completed]:
if order.isbuy():
self.log(
'执行买入, 价格: %.2f, 成本: %.2f, 手续费 %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
self.buyprice = order.executed.price
self.comm += order.executed.comm
else:
self.log(
'执行卖出, 价格: %.2f, 成本: %.2f, 手续费 %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
self.comm += order.executed.comm
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log("交易失败")
self.order = None

# 输出手续费
def stop(self):
self.log("手续费:%.2f 成本比例:%.5f" % (self.comm, self.comm/self.broker.getvalue()))


if __name__ == "__main__":
start = "2018-01-01"
end = "2020-07-05"
name = ["nasetf"]
code = ["513100"]
backtest = backtest.BackTest(TurtleStrategy, start, end, code, name, 100000)
result = backtest.run()
# backtest.output()
print(result)



结果蛮不错的,年化收益21%,但夏普值并不高。换个股票看看。


这就很差了,年化1.7%,还是买余额宝吧……
用参数优化功能看看。

1
2
3
4
5
result = backtest.optRun(long_period = range(20, 60))
print(result)
plt.figure()
plt.plot(result.年化收益率)
plt.savefig("海龟策略参数优化.png")

上轨周期在40时收益率最高,输出一下看看。

1
2
3
4
ret = result.loc[:, "年化收益率"]
maxindex = ret[ret == ret.max()].index
bestResult = result.loc[maxindex,:]
print(bestResult.loc[:, ["夏普比率", "年化收益率"]])


搞定,还有个问题是策略有两个可变参数,优化的时候能不能一起变?再研究一下吧。先到这了。
代码地址还是: https://github.com/zwdnet/MyQuant/tree/master/47
策略文件为Turtle.py。

我发文章的三个地方,欢迎大家在朋友圈等地方分享,欢迎点“在看”。
我的个人博客地址:https://zwdnet.github.io
我的知乎文章地址: https://www.zhihu.com/people/zhao-you-min/posts
我的微信个人订阅号:赵瑜敏的口腔医学学习园地

欢迎打赏!感谢支持!