代码拉取完成,页面将自动刷新
# 克隆自聚宽文章:https://www.joinquant.com/post/33203
# 标题:300ETF非对称,自动调整网格策略
# 作者:晓航
# 原文章:https://www.joinquant.com/post/31723
# 标题:一种经过优化的ETF网格交易策略
# 作者:Tenny-X,
'''
晓航 修改
基本思路,跑赢300etf不容易,网格策略价格上升或下降过多容易脱离区间而失效。
设计了一个简单的自动调整网格算法,标的为300etf,回测效果比较稳定,回撤也控制合理,收益在300etf之上。
1. 价格突破网格上限,网格自动向上移动,因为已经空仓,网格上移不影响网格工作
2. 价格突破网格下限,网格不再向下移动,因为已经满仓,策划保持仓位,等待价格回归后继续交易。由于300etf长期来看价格会回归,本策略依靠国运。
3. 非对称网格,底部网格较小,上部网格较大。300etf的关键的地点建仓多些,非对称网格有效。3%,5%是目前测试后比较理想的网格,大家可以尝试下,哪位高人有学习算法的话可以进一步研究下。
'''
# 导入函数库
from jqdata import *
# 初始化函数,设定基准等等
def initialize(context):
g.security = '510300.XSHG'#沪深300
#g.bottom_price = attribute_history(g.security, 1, '1d', ['close'])['close'][0]
#设定自身走势作为基准
set_benchmark(g.security)
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 输出内容到日志 log.info()
log.info('初始函数开始运行且全局只运行一次')
# 过滤掉order系列API产生的比error级别低的log
# log.set_level('order', 'error')
### 股票相关设定 ###
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=1), type='stock')
#初始底仓
#cash = context.portfolio.available_cash
g.count=0
#价格为现金的1/10, 也就是10个网格
#order_target_value(g.security,cash*0.2)
## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
# 开盘前运行
#run_daily(before_market_open, time='before_open')
# 开盘时运行
run_daily(market_open, time='14:30')
# 收盘后运行
#run_daily(after_market_close, time='after_close')
## 开盘前运行函数
def before_market_open(context):
# 输出运行时间
log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))
# 给微信发送消息(添加模拟交易,并绑定微信生效)
#send_message('美好的一天~')
## 开盘时运行函数
def market_open(context):
#log.info('函数运行时间(market_open):'+str(context.current_dt.time()))
security = g.security
# 获取股票的收盘价
close_data = get_bars(security, count=30, unit='1d', fields=['close'])
# 取得上一时间点价格
if g.count == 0:
current_data = get_current_data()
current_price = current_data[security].last_price
g.bottom_price = current_price
cash = context.portfolio.available_cash
order_target_value(g.security,cash*0.5)
g.count+=1
current_data = get_current_data()
current_price = current_data[security].last_price
#current_price = close_data['close'][-1]
#bottom_price= g.initial_price['close'][0]
# 取得当前的现金
#cash = context.portfolio.cash
#单次交易资金
unit_value = context.portfolio.total_value*0.1
#amount = context.portfolio.positions[g.security].amount
returns = (current_price-g.bottom_price)/g.bottom_price
bench_buy,bench_sell=bench_switch(context)
current_value = context.portfolio.positions_value
#网格交易
#网格卖出
if returns > bench_sell:
if current_value>unit_value:
order_value(security,-unit_value)
print('===网格完整卖出=',unit_value)
else:
order_value(security,-current_value)
print('===网格部分卖出=',current_value)
print('current_price=',current_price)
print('bottom_price=',g.bottom_price)
#网格基准上移一格,空仓网格会上移
g.bottom_price=current_price
#网格买入
if returns < bench_buy:
if context.portfolio.available_cash>unit_value:
order_value(security,unit_value)
print('===网格完整买入=',unit_value)
print('current_price=',current_price)
print('bottom_price=',g.bottom_price)
g.bottom_price=current_price
elif context.portfolio.available_cash>0 :
order_value(security,context.portfolio.available_cash)
print('===网格部分买入=',context.portfolio.available_cash)
#满仓没有资金,网格不再下移
g.bottom_price=current_price
## 收盘后运行函数
def after_market_close(context):
log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
#得到当天所有成交记录
trades = get_trades()
for _trade in trades.values():
log.info('成交记录:'+str(_trade))
log.info('一天结束')
log.info('现金:',context.portfolio.cash)
log.info('##############################################################')
#网格大小的选取,非对称网格,底部网格较小,上部网格较大。
def bench_switch(context):
bench_buy = -0.02
bench_sell = 0.02
return bench_buy,bench_sell
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。