
```
code
```# 导入函数库
# 策略逻辑是做多前N个交易日上涨的品种,做空前N个交易日下跌的品种,每隔H个交易日调整一次,品种
# 最好选择主力合约前20个交易日日均成交量大于1万手的期货标的
from jqdata import *
import talib
## 初始化函数,设定基准等等
def initialize(context):
# 设定沪深300作为基准
set_parameter(context)
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 过滤掉order系列API产生的比error级别低的log
log.set_level('order', 'error')
# 输出内容到日志 log.info()
log.info('初始函数开始运行且全局只运行一次')
### 期货相关设定 ###
# 设定账户为金融账户
set_subportfolios([SubPortfolioConfig(cash=context.portfolio.starting_cash, type='futures')])
# 期货类每笔交易时的手续费是:买入时万分之0.23,卖出时万分之0.23,平今仓为万分之23
set_order_cost(OrderCost(open_commission=0.00005, close_commission=0.00005,close_today_commission=0.00005), type='index_futures')
# 设定保证金比例
set_option('futures_margin_rate', 0.15)
# 设置期货交易的滑点
set_slippage(StepRelatedSlippage(0.001),type = 'futures')
# 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'IF8888.CCFX'或'IH1602.CCFX'是一样的)
# 注意:before_open/open/close/after_close等相对时间不可用于有夜盘的交易品种,有夜盘的交易品种请指定绝对时间(如9:30)
# 开盘前运行
run_daily( before_market_open, time='before_open', reference_security=get_future_code('RB'))
# 开盘时运行
run_weekly( market_open, 1,time='open', reference_security=get_future_code('RB'))
# 交易运行
run_weekly(Trade, 1, time='open', reference_security=get_future_code('RB'))
# 收盘后运行
run_daily( after_market_close, time='after_close', reference_security=get_future_code('RB'))
def set_parameter(context):
g.LastRealPrice = {} # 最新真实合约价格字典(用于吊灯止损)
g.HighPrice = {} # 各品种最高价字典(用于吊灯止损)
g.LowPrice = {} # 各品种最低价字典(用于吊灯止损)
g.future_list = [] # 设置期货品种列表
g.TradeLots = {} # 各品种的交易手数信息
g.PriceArray = {} # 信号计算价格字典
g.Price_dict = {} # 各品种价格列表字典
g.MappingReal = {} # 真实合约映射(key为symbol,value为主力合约)
g.MappingIndex = {} # 指数合约映射 (key为 symbol,value为指数合约
g.ATR = {}
g.CurrentPrice = {}
g.Price_DaysAgo = {}
g.Momentum = {}
g.Signal = {}
g.ClosePrice = {}
#######参数设置########
g.HoldingWeek = 1 # 持有窗口长度
g.BackWindow = 10 # 回溯窗口长度
g.MarginRate = 0.15
# 交易的期货品种信息
g.instruments = ['AL','PB','NI','CU','ZN','AG','AU','RU','MA','PP','TA','L','V','M','A','B','P','Y','OI','C','CS','JD','SR','HC','J','JM','I','SC','RB','ZC','FG','BU','FU','EG','AP','CF','CJ','SP']
# 价格列表初始化
set_future_list(context)
# 封装主力合约进入future——list里面
def set_future_list(context):
for ins in g.instruments:
idx = get_future_code(ins)
dom = get_dominant_future(ins)
g.MappingIndex[ins] = idx
g.MappingReal[ins] = dom
if dom == '':
pass
else:
if dom not in g.future_list:
g.future_list.append(dom)
# 获取指数合约函数
def get_future_code(symbol):
future_code_list = {'A':'A8888.XDCE', 'AG':'AG8888.XSGE', 'AL':'AL8888.XSGE', 'AU':'AU8888.XSGE',
'B':'B8888.XDCE', 'BU':'BU8888.XSGE', 'C':'C8888.XDCE',
'CF':'CF8888.XZCE', 'CS':'CS8888.XDCE', 'CU':'CU8888.XSGE', 'EG':'ER8888.XDCE',
'FG':'FG8888.XZCE', 'FU':'FU8888.XSGE',
'HC':'HC8888.XSGE', 'I':'I8888.XDCE', 'SC':'IC8888.XINE',
'J':'J8888.XDCE', 'JD':'JD8888.XDCE', 'JM':'JM8888.XDCE',
'L':'L8888.XDCE', 'M':'M8888.XDCE',
'MA':'MA8888.XZCE', 'NI':'NI8888.XSGE', 'OI':'OI8888.XZCE',
'P':'P8888.XDCE', 'PB':'PB8888.XSGE', 'PP':'PP8888.XDCE',
'RB':'RB8888.XSGE',
'RU':'RU8888.XSGE', 'SP':'SP8888.XSGE',
'SR':'SR8888.XZCE', 'TA':'TA8888.XZCE',
'V':'V8888.XDCE',
'CJ':'CJ8888.XZCE', 'Y':'Y8888.XDCE',
'ZC':'ZC8888.XZCE', 'ZN':'ZN8888.XSGE','AP':'AP8888.XZCE'}
try:
return future_code_list[symbol]
except:
return 'WARNING: 无此合约'
# 开盘前,筛选主力合约进行过滤,不是主力合约的话,需要进行换月,开盘需要计算好交易手数
def before_market_open(context):
log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))
send_message('开始交易')
for ins in g.instruments:
dom = get_dominant_future(ins)
if dom =='':
pass
else:
if dom == g.MappingReal[ins]:
pass
else:
replace_old_futures(context,ins,dom)
g.future_list.append(dom)
g.TradeLots[dom] = get_lots(context.portfolio.starting_cash/len(g.instruments),ins)
def market_open(context):
log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))
for ins in g.instruments:
if g.MappingReal[ins] != '':
IndexFuture = g.MappingIndex[ins]
RealFuture = g.MappingReal[ins]
# 获取当月合约交割日期
end_date = get_security_info(RealFuture).end_date
# 当月合约交割日当天不开仓
if (context.current_dt.date() == end_date):
return
else:
g.LastRealPrice[RealFuture] = attribute_history(RealFuture,1,'1d',['close'])['close'][-1]
# 获取价格list
g.PriceArray[IndexFuture] = attribute_history(IndexFuture,g.BackWindow+5,'1d',['close','open','high','low'])
# 如果没有数据,返回
if len(g.PriceArray[IndexFuture]) < 1:
return
else:
g.ClosePrice[ins] = g.PriceArray[IndexFuture]['close']
g.CurrentPrice[ins] = g.ClosePrice[ins][-1]
g.Price_DaysAgo[ins] = g.ClosePrice[ins][-g.BackWindow]
# 计算动量标记
if g.CurrentPrice[ins] > g.Price_DaysAgo[ins] :
g.Momentum[ins] = 1
elif g.CurrentPrice[ins] < g.Price_DaysAgo[ins] :
g.Momentum[ins] = -1
else:
g.Momentum[ins] = 0
#判断交易信号:动量g.Momentum[ins] == 1多头,-1为空头
if g.Momentum[ins] == 1 :
g.Signal[ins] = 1
elif g.Momentum[ins] == -1 :
g.Signal[ins] = -1
else:
g.Signal[ins] = 0
## 收盘后运行函数
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('##############################################################')
def Trade(context):
for ins in g.instruments:
RealFuture = g.MappingReal[ins]
if ins in g.Signal.keys() and RealFuture in g.LastRealPrice.keys():
if g.Signal[ins] == 1 and RealFuture not in context.portfolio.long_positions:
if RealFuture in context.portfolio.short_positions:
log.info('空头有持仓:%s'%(RealFuture))
order_target(RealFuture,0,side='short')
order_target(RealFuture,g.TradeLots[RealFuture],side='long')
log.info('正常买多合约:%s'%(RealFuture))
# `if context.portfolio.long_positions[RealFuture].total_amount == 0`错误语句
elif g.Signal[ins] == -1 and RealFuture not in context.portfolio.short_positions:
if RealFuture in context.portfolio.long_positions:
log.info('多头有持仓:%s'%(RealFuture))
order_target(RealFuture,0,side ='long')
order_target(RealFuture,g.TradeLots[RealFuture],side='short')
log.info('正常卖空合约:%s'%(RealFuture))
# 移仓模块:当主力合约更换时,平当前持仓,更换为最新主力合约
def replace_old_futures(context,ins,dom):
LastFuture = g.MappingReal[ins]
if LastFuture in context.portfolio.long_positions.keys():
lots_long = context.portfolio.long_positions[LastFuture].total_amount
order_target(LastFuture,0,side='long')
order_target(dom,lots_long,side='long')
print('主力合约更换,平多仓换新仓')
if LastFuture in context.portfolio.short_positions.keys():
lots_short = context.portfolio.short_positions[dom].total_amount # 这个代码跟上面不太一致,可能有问题,是dom和lastfuture
order_target(LastFuture,0,side='short')
order_target(dom,lots_short,side='short')
print('主力合约更换,平空仓换新仓')
g.MappingReal[ins] = dom
# 获得交易手数函数(无ATR版本)
def get_lots(cash,symbol):
future_contract_size = {'A':10, 'AG':15, 'AL':5, 'AU':1000,'B':10, 'BU':10, 'C':10,
'CF':5, 'CS':10, 'CU':5, 'EG':10, 'FG':20, 'FU':10, 'HC':10, 'I':100,
'SC':1000, 'J':100, 'JD':5, 'JM':60, 'L':5, 'M':10,
'MA':10, 'NI':1, 'OI':10,
'P':10, 'PB':5, 'PP':5, 'RB':10,'RU':10, 'SP':10,
'SR':10, 'TA':5, 'V':5, 'CJ':5, 'Y':10,
'ZC':100, 'ZN':5,'AP':10}
future = get_dominant_future(symbol)
Price_dict = attribute_history(future,10,'1d',['open'])
if len(Price_dict) == 0:
return
else:
open_price = Price_dict.iloc[-1]
return cash/(open_price*future_contract_size(symbol)*g.MarginRate)
2019-12-06