网格交易策略简介
什么是网格交易策略?
网格交易是利用市场震荡行情获利的一种主动交易策略,其本质是利用投资标的在一段震荡行情中价格在网格区间内的反复运动以进行加仓减仓的操作以达到投资收益最大化的目的。通俗点讲就是根据建立不同数量.不同大小的网格,在突破网格的时候建仓,回归网格的时候减仓,力求能够捕捉到价格的震荡变化趋势,达到盈利的目的。
网格的设置与建仓
网格交易策略至关重要的一点就是网格的数量.间隔还有每个网格仓位数量的设置,但这会因不同的行情和相应判断而有所不同,建仓的数量不应过多,以防到多次触发网格建仓导致资金不足的情况。
行业轮动策略实现(基于掘金量化平台)
策略思想
本策略首先计算了SHFE.rb1801过去300个1min收盘价的均值和标准差
并用均值加减2和3个标准差得到网格的区间分界线,分别配以0.3和0.5的仓位权重
随后根据上突破区间开多仓,下突破区间开空仓,反向突破反向操作和回归平仓来进行相应仓位的调整
网格设置
context.band = np.mean(timeseries) + np.array([-40, -3, -2, 2, 3, 40]) * np.std(timeseries) context.weight = [0.5, 0.3, 0.0, 0.3, 0.5] grid = pd.cut([bar.close], context.band, labels=[0, 1, 2, 3, 4])[0]
获取网格区间分界线和设置相应的仓位权重并得到相应的区间
获取多仓仓位
position_long = context.account().position(symbol=context.symbol, side=PositionSide_Long)
获取上一交易日可调用get_previous_trading_date
函数,返回值为字符串格式:
symbol
需要设置标的代码。side
需要设置枚举常量,PositionSide_Long
为多仓,PositionSide_Short
为空仓。
下单到目标比例
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market, position_side=PositionSide_Long)
固定时间调仓可使用schedule
函数进行定时任务配置:
symbol
需要设置标的代码。percent
为比例,此处设置为相应网格对应的权重order_type
需要设置枚举常量,OrderType_Market
为市价单,OrderType_Limit
为限价单side
需要设置枚举常量,PositionSide_Long
为多仓,PositionSide_Short
为空仓。
策略回测分析
分析
我们选取了2017年7月至2016年9月作为回测周期,可以看出:
胜率(具有盈利的平仓次数与总平仓次数之比)达到了87%。
卡玛比率(年化收益率与历史最大回撤之比)是使用最大回撤率来衡量风险。采用最大回撤率来衡量风险,关注的是最极端的情况。卡玛比率越高表示策略承受每单位最大损失获得的报酬越高。在这里卡玛比率超过了9.1。
夏普比率(年化收益率与波动率之比)超过1.29,也即承受1单位的风险,会有超过1.29个单位的收益回报
策略收益曲线较为稳定,在无止损条件的情况下,最大回撤控制在承受范围,并成功跑赢沪深300指数。
网格交易策略源码(期货):
# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
import numpy as np
import pandas as pd
from gm.api import *
'''
本策略首先计算了过去300个价格数据的均值和标准差
并根据均值加减1和2个标准差得到网格的区间分界线,
并分别配以0.3和0.5的仓位权重
然后根据价格所在的区间来配置仓位(+/-40为上下界,无实际意义):
(-40,-3],(-3,-2],(-2,2],(2,3],(3,40](具体价格等于均值+数字倍标准差)
[-0.5, -0.3, 0.0, 0.3, 0.5](资金比例,此处负号表示开空仓)
回测数据为:SHFE.rb1801的1min数据
回测时间为:2017-07-01 08:00:00到2017-10-01 16:00:00
'''
def init(context):
context.symbol = 'SHFE.rb1801'
# 订阅SHFE.rb1801, bar频率为1min
subscribe(symbols=context.symbol, frequency='60s')
# 获取过去300个价格数据
timeseries = history_n(symbol=context.symbol, frequency='60s', count=300, fields='close', fill_missing='Last',
end_time='2017-07-01 08:00:00', df=True)['close'].values
# 获取网格区间分界线
context.band = np.mean(timeseries) + np.array([-40, -3, -2, 2, 3, 40]) * np.std(timeseries)
# 设置网格的仓位
context.weight = [0.5, 0.3, 0.0, 0.3, 0.5]
def on_bar(context, bars):
bar = bars[0]
# 根据价格落在(-40,-3],(-3,-2],(-2,2],(2,3],(3,40]的区间范围来获取最新收盘价所在的价格区间
grid = pd.cut([bar.close], context.band, labels=[0, 1, 2, 3, 4])[0]
# 获取多仓仓位
position_long = context.account().position(symbol=context.symbol, side=PositionSide_Long)
# 获取空仓仓位
position_short = context.account().position(symbol=context.symbol, side=PositionSide_Short)
# 若无仓位且价格突破则按照设置好的区间开仓
if not position_long and not position_short and grid != 2:
# 大于3为在中间网格的上方,做多
if grid >= 3:
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,
position_side=PositionSide_Long)
print(context.symbol, '以市价单开多仓到仓位', context.weight[grid])
if grid <= 1:
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,
position_side=PositionSide_Short)
print(context.symbol, '以市价单开空仓到仓位', context.weight[grid])
# 持有多仓的处理
elif position_long:
if grid >= 3:
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,
position_side=PositionSide_Long)
print(context.symbol, '以市价单调多仓到仓位', context.weight[grid])
# 等于2为在中间网格,平仓
elif grid == 2:
order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,
position_side=PositionSide_Long)
print(context.symbol, '以市价单全平多仓')
# 小于1为在中间网格的下方,做空
elif grid <= 1:
order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,
position_side=PositionSide_Long)
print(context.symbol, '以市价单全平多仓')
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,
position_side=PositionSide_Short)
print(context.symbol, '以市价单开空仓到仓位', context.weight[grid])
# 持有空仓的处理
elif position_short:
# 小于1为在中间网格的下方,做空
if grid <= 1:
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,
position_side=PositionSide_Short)
print(context.symbol, '以市价单调空仓到仓位', context.weight[grid])
# 等于2为在中间网格,平仓
elif grid == 2:
order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,
position_side=PositionSide_Short)
print(context.symbol, '以市价单全平空仓')
# 大于3为在中间网格的上方,做多
elif grid >= 3:
order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,
position_side=PositionSide_Short)
print(context.symbol, '以市价单全平空仓')
order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,
position_side=PositionSide_Long)
print(context.symbol, '以市价单开多仓到仓位', context.weight[grid])
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='strategy_id',
filename='main.py',
mode=MODE_BACKTEST,
token='token_id',
backtest_start_time='2017-07-01 08:00:00',
backtest_end_time='2017-10-01 16:00:00',
backtest_adjust=ADJUST_PREV,
backtest_initial_cash=10000000,
backtest_commission_ratio=0.0001,
backtest_slippage_ratio=0.0001)
文章来源:掘金量化交易平台 ,转载请注明出处!