》先复习下海龟策略逻辑,完整策略代码及回测报告在最下面。
1、投机标的选择
投机者虽然是风险偏好者,但需要注意流动性风险和价格风险。海龟交易法则认为投机者在选择投资标的时,一定要选择活跃度高,成交量大的品种。用5日atr幅度作为过滤,波动率大于2%才允许开仓。
2、建仓头寸计算
每次建仓的头寸和加仓头寸与波动率atr相关,计算如下。
日atr计算:
头寸计算:
3、入市位置选择
海龟交易法则的入市判断方式是以查理德唐奇安的通道突破系统为基础。
海龟系统认为:价格突破20日唐奇安通道为入市信号(包含向上突破和向下突破,即做多和做空)。
4、加仓
海龟交易法则和所有交易大师一样,对加仓和止损有着严格要求,只有盈利时才能加仓,一旦价格到达止损位需要交易者无条件止损。
海龟交易法加仓位置为建仓后,价格向盈利方向突破0.5倍atr时加仓,最多4个单位;
4、止损
止损位置为亏损2atr,即达到平均真实振幅值的两倍。如果有加仓情况,每一次加仓止损位就提高0.5atr。
5、止盈(离场)位置
在没有止损的前提下,海龟交易法则同样给出了止盈位置。止盈位置为:
多头头寸在突破过10日最低处止盈离场;空头头寸在突破过10日最高处止盈离场。
》策略完整代码,策略和回测工作区都已放入软件,欢迎下载使用,软件使用方法:鑫程序化交易系统
from tool.kxianhuizhi2 import open_kxiantu, load_data, get_suoyougupiaoxinxi
from tool.gongju import *
from tool.zhibiao import ma_z, ema_z, atr_z
from tool.yujingWin import YuyinBobao, pyttsx3 # 导入语音播报
import tqsdk.ta as tqzb
import tool.MyTT as myttzb
import talib
def __一天有多少k线(cl):
qriqi = cl.get_riqi(0)
k线数量 = 0
bz1 = 0
for k in range(800):
riqi2 = cl.get_riqi(k)
if bz1 == 2:
break
if bz1 == 1:
k线数量 = k线数量 + 1
if riqi2 != qriqi:
bz1 = bz1 + 1
qriqi = riqi2
return k线数量
def 海龟策略_v1(cl):
"""
海龟策略,在主连复权上用最准确
:param cl策略类
:param cl.klines: k线数据,为df表,0层数据用klines[0]表示订阅的第一个合约,klines[1]是订阅的第二个合约
:param cl.openingdata: 交易数据,为字典,里面有持仓状态,理论持仓数量,开仓价格,开仓时间等,
:param cl.zhanghu: 账户列表,按软件登录账户顺序排列
:param cl.jiaoyishezhi: 为交易设置数据,算法交易,交易合约,其他功能参数都在里面
:param cl.jiaoyiqidong: 是否启动了交易,为TRUS表示启动
:return: 输出要在软件上和K线图上显示的指标,设置为"w"为不显示,运行策略时刻节约计算机资源
"""
if len(cl.klines[0]) < 210: return 0, 0, 0, 0
# 数据提取区
Open = cl.klines[0].open.values # 开盘价np列表
High = cl.klines[0].high.values # 最高价np列表
Low = cl.klines[0].low.values # 最低价np列表
Close = cl.klines[0].close.values # 收盘价np列表
# 参数设置区
总资金 = cl.jiaoyishezhi[5][0]*10000 # 单位万
开加仓资金比例 = cl.jiaoyishezhi[5][1]/100 # 为百分比,设置为1为用总资金的百分之1
允许加仓次数 = cl.jiaoyishezhi[5][2]
开仓通道周期 = cl.jiaoyishezhi[5][3]
止盈通道周期 = cl.jiaoyishezhi[5][4]
# 全局变量的初始化,为空的时候执行
if '最小变动' not in cl.sjb: # 每次策略初始化或更新数据时执行一次,用于在策略运行期间想持久化的数据
账户 = cl.zhanghu[cl.jiaoyishezhi[0][0]] # 设置的交易账户对象
交易合约 = cl.jiaoyishezhi[3][0]
cl.sjb['一天k线数量'] = __一天有多少k线(cl)
cl.sjb['最小变动'] = 账户.get_zuixiaobiandong(交易合约)
cl.sjb['乘值'] = 账户.get_chengzhi(交易合约)
cl.sjb["指定附图指标"] = ["zhibiao1"]
cl.sjb['总资金'] = cl.jiaoyishezhi[5][0]
cl.sjb['加仓计数'] = 1
cl.sjb['加仓价格'] = Open[-1]
# 指标计算区
n = cl.sjb['一天k线数量']
atr = ma_z(HHV(cl.klines[0].high.iloc[-200:-1], n) - LLV(cl.klines[0].low.iloc[-200:-1], n), n*5) # 策略加载在小周期上所以要跨周期计算atr
atrn = atr[-1]/Open[-1]*100
n = -cl.sjb['一天k线数量'] * 开仓通道周期
开仓高点 = max(High[n:-1])
开仓低点 = min(Low[n:-1])
n = -cl.sjb['一天k线数量'] * 止盈通道周期
止盈高点 = max(High[n:-1])
止盈低点 = min(Low[n:-1])
if cl.bargengxin: # 更新k线时执行,一般用与收盘需要计算的指标
if cl.lishijiaoyijilu["leijiyingkui"]:
cl.sjb['总资金'] = 总资金+cl.lishijiaoyijilu["leijiyingkui"][-1] # 设置资金加减前面平仓利润
else:
cl.sjb['总资金'] = 总资金 # 当没有开仓时就等于设置资金
开仓手数 = round((cl.sjb['总资金']*开加仓资金比例*0.1)/(atr[-1] * cl.sjb['乘值']))
# 交易逻辑执行区
if 开仓手数 > 0:
atrn = atr[-1] / Open[-1] * 100
if atrn >2 :
if cl.openingdata['kaicangzhuangtai'] == 0 and High[-1] >= 开仓高点:
# if 开仓手数 <= 0: 开仓手数 = 1
Buy(开仓手数, max(Open[-1], 开仓高点), cl)
cl.sjb['加仓计数'] = 1
else:
if cl.openingdata['kaicangzhuangtai'] == 0 and Low[-1] <= 开仓低点:
# if 开仓手数 <= 0: 开仓手数 = 1
SellShort(开仓手数, min(Open[-1], 开仓低点), cl)
cl.sjb['加仓计数'] = 1
# 加仓
if cl.sjb['加仓计数']<= 允许加仓次数 and cl.shoucikaicangjuli > 0 and cl.openingdata['kaicangzhuangtai'] != 0:
if cl.openingdata['kaicangzhuangtai'] == 1:
cl.sjb['加仓价格'] = cl.openingdata['kaicangjia']+atr[-1]*0.5
else:
cl.sjb['加仓价格'] = cl.openingdata['kaicangjia']-atr[-1]*0.5
# 经测试用收盘价作为加仓基准更有效
if cl.openingdata['kaicangzhuangtai'] == 1 and Close[-2] >= cl.sjb['加仓价格']:
Buy_jjc(开仓手数, Open[-1], cl)
cl.sjb['加仓计数'] += 1
else:
if cl.openingdata['kaicangzhuangtai'] == -1 and Close[-2] <= cl.sjb['加仓价格']:
SellShort_jjc(开仓手数, Open[-1], cl)
cl.sjb['加仓计数'] += 1
# 止损和出场
if cl.shoucikaicangjuli > 0 and cl.openingdata['kaicangzhuangtai'] != 0:
# 止盈出场
if cl.openingdata['kaicangzhuangtai'] > 0 and Low[-1] <= 止盈低点:
Sell(cl.openingdata['kaicangshuliang'], min(Open[-1], 止盈低点), cl)
else:
if cl.openingdata['kaicangzhuangtai'] < 0 and High[-1] >= 止盈高点:
BuyToCover(cl.openingdata['kaicangshuliang'], max(Open[-1], 止盈高点), cl)
# 止损出场
if cl.openingdata['kaicangzhuangtai'] == 1:
止损价格 = cl.openingdata['kaicangjia'] - atr[-1] * 2
else:
止损价格 = cl.openingdata['kaicangjia'] + atr[-1] * 2
if cl.openingdata['kaicangzhuangtai'] > 0 and Low[-1] <= 止损价格:
Sell(cl.openingdata['kaicangshuliang'], min(Open[-1], 止损价格), cl)
else:
if cl.openingdata['kaicangzhuangtai'] < 0 and High[-1] >= 止损价格:
BuyToCover(cl.openingdata['kaicangshuliang'], max(Open[-1], 止损价格), cl)
return atrn, cl.sjb['总资金'], 开仓高点, 开仓低点 # 此处输出的指标会在k线图中和监控界面中显示
》回测报告如下,绩效一般