本文采用唐奇安通道和海龟策略相结合的方式
# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
import numpy as np
import pandas as pd
from gm.api import *
'''
本策略基于海龟交易法的唐奇安通道。
以价格突破唐奇安通道的上下轨作为开仓信号,N倍ATR作为加仓或止损点。
'''
def init(context):
# 设置合约标的
context.symbol = 'DCE.I'
# 设置计算唐奇安通道的参数
context.n = 20
# 设置ATR倍数
context.atr_multiple = 0.5
# 设置单笔开仓数量
context.order_volume = 2
# 设置单笔加减仓数量
context.change_volume = 2
# 订阅数据
subscribe(symbols=context.symbol, frequency='60s', count=2)
# 定时函数,开盘时运行
schedule(schedule_func=algo, date_rule='1d', time_rule='09:00:00')
schedule(schedule_func=algo, date_rule='1d', time_rule='21:00:00')
def algo(context):
# 上一交易日
last_date = get_previous_trading_date(exchange='SHFE', date=context.now)
# 调取数据
data = history_n(symbol=context.symbol, frequency='1d', count=context.n + 1, end_time=last_date,
fields='close,high,low,bob', df=True) # 计算ATR
# 计算ATR
tr_list = []
for i in range(1, len(data) - 1):
tr = max(max((data['high'].iloc[i] - data['low'].iloc[i]),
abs(data['close'].shift(1).iloc[i] - data['high'].iloc[i])),
abs(data['close'].shift(1).iloc[i] - data['low'].iloc[i]))
tr_list.append(tr)
context.atr = int(np.floor(np.mean(tr_list)))
context.atr_half = int(np.floor(context.atr_multiple * context.atr))
# 计算唐奇安通道
context.don_upper = np.max(data['high'].values[-context.n - 1:-1])
context.don_lower = np.min(data['low'].values[-context.n - 1:-1])
# 计算加仓点和止损点
context.long_add_point = context.don_upper + context.atr_half # 多仓加仓点
context.long_stop_loss = context.don_upper - context.atr_half # 多仓止损点
context.short_add_point = context.don_lower - context.atr_half # 空仓加仓点
context.short_stop_loss = context.don_lower + context.atr_half # 空仓止损点
def on_bar(context, bars):
# 提取数据
symbol = bars[0]['symbol']
recent_data = context.data(symbol=context.symbol, frequency='60s', count=2, fields='close,high,low')
new_price = recent_data['close'].values[-1]
# 账户仓位情况
position_long = context.account().position(symbol=symbol, side=PositionSide_Long)
position_short = context.account().position(symbol=symbol, side=PositionSide_Short)
# 当无持仓时
if not position_long and not position_short:
# 如果向上突破唐奇安通道上轨,则开多
if new_price > context.don_upper:
order_volume(symbol=symbol, side=OrderSide_Buy, volume=context.order_volume, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
# 如果向下突破唐奇安通道下轨,则开空
if new_price < context.don_lower:
order_volume(symbol=symbol, side=OrderSide_Sell, volume=context.order_volume, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
# 有持仓时
# 持多仓
if position_long:
# 当突破加仓点时:加仓
if new_price > context.long_add_point:
order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
context.long_add_point += context.atr_half
context.long_stop_loss += context.atr_half
# 当跌破止损点时:减仓或清仓
if new_price < context.long_stop_loss:
volume_hold = position_long['volume']
if volume_hold > context.order_volume:
order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Sell,
order_type=OrderType_Market, position_effect=PositionEffect_Close)
else:
order_volume(symbol=symbol, volume=volume_hold, side=OrderSide_Sell, order_type=OrderType_Market,
position_effect=PositionEffect_Close)
context.long_add_point -= context.atr_half
context.long_stop_loss -= context.atr_half
# 持空仓
if position_short:
# 当跌破加仓点时:加仓
if new_price < context.short_add_point:
order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Sell, order_type=OrderType_Market,
position_effect=PositionEffect_Open)
context.short_add_point -= context.atr_half
context.short_stop_loss -= context.atr_half
# 当突破止损点时:减仓或清仓
if new_price > context.short_stop_loss:
volume_hold = position_short['volume']
if volume_hold > context.atr_half:
order_volume(symbol=symbol, volume=context.change_volume, side=OrderSide_Buy,
order_type=OrderType_Market, position_effect=PositionEffect_Close)
else:
order_volume(symbol=symbol, volume=volume_hold, side=OrderSide_Buy, order_type=OrderType_Market,
position_effect=PositionEffect_Close)
context.short_add_point += context.atr_half
context.short_stop_loss += context.atr_half
def on_order_status(context, order):
# 标的代码
symbol = order['symbol']
# 委托价格
price = order['price']
# 委托数量
volume = order['volume']
# 目标仓位
target_percent = order['target_percent']
# 查看下单后的委托状态,等于3代表委托全部成交
status = order['status']
# 买卖方向,1为买入,2为卖出
side = order['side']
# 开平仓类型,1为开仓,2为平仓
effect = order['position_effect']
# 委托类型,1为限价委托,2为市价委托
order_type = order['order_type']
if status == 3:
if effect == 1 and side == 1:
side_effect = '开多仓'
elif effect == 1 and side == 2:
side_effect = '开空仓'
elif effect == 2 and side == 1:
side_effect = '平空仓'
elif effect == 2 and side == 2:
side_effect = '平多仓'
order_type_word = '限价' if order_type == 1 else '市价'
print('{}:标的:{},操作:以{}{},委托价格:{},委托数量:{}'.format(context.now, symbol, order_type_word, side_effect, price,
volume))
def on_backtest_finished(context, indicator):
print('*' * 50)
print('回测已完成,请通过右上角“回测历史”功能查询详情。')
if __name__ == '__main__':
'''
strategy_id策略ID,由系统生成
filename文件名,请与本文件名保持一致
mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
token绑定计算机的ID,可在系统设置-密钥管理中生成
backtest_start_time回测开始时间
backtest_end_time回测结束时间
backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
backtest_initial_cash回测初始资金
backtest_commission_ratio回测佣金比例
backtest_slippage_ratio回测滑点比例
'''
run(strategy_id='99ff6300-f074-11ec-9359-a4c3f0c417b1',
filename='main.py',
mode=MODE_BACKTEST,
#这里填写你的token编码,这里不方便填写
token='**************************',
backtest_start_time='2020-03-01 09:00:00',
backtest_end_time='2020-06-30 15:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=1000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001)