海龟交易法操作商品期货

上了三个小象学院的量化交易网课,是时候写点东西了。按照进阶课的内容,先把宋战江老师第一课针对商品期货的海龟交易法写一下,他是在TB上写的,我想将代码改到聚宽上。

先上聚宽搜商品期货数据的信息,看到有个帖子直接给出了海龟交易法,由于第一次用聚宽,先逐字敲一下代码

  1 # 克隆自聚宽文章:https://www.joinquant.com/post/9184
  2 # 标题:商品期货策略——海龟交易法
  3 # 作者:ScintiGimcki
  4
  5 # 导入函数库
  6 import jqdata
  7 #import statsmodels.api as sm
  8 #from statsmodels.tsa.stattools import adfuller
  9
 10 ## 初始化函数,设定基准等等
 11 def initialize(context):
 12     # 设置参数
 13     set_params(context)
 14     # 设定基准
 15     set_benchmark(get_future_code(g.future_index))
 16     # 开启动态复权模式(真实价格)
 17     set_option(‘use_real_price‘, True)
 18     # 过滤掉order系列API产生的比error级别低的log
 19     log.set_level(‘order‘, ‘error‘)
 20     # 初始化标的
 21     g.future = get_future_code(g.future_index)
 22
 23
 24     ### 期货相关设定 ###
 25     # 设定账户为金融账户
 26     set_subportfolios([SubPortfolioConfig(cash=context.portfolio.starting_cash, type=‘index_futures‘)])
 27     # 期货类每笔交易时的手续费是:买入时万分之0.23,卖出时万分之0.23,平今仓为万分之23
 28     set_order_cost(OrderCost(open_commission=0.000023, close_commission=0.000023,close_today_commission=0.0023), type=‘index_futures‘)
 29     # 设定保证金比例
 30     set_option(‘futures_margin_rate‘, 0.15)
 31
 32     # 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入‘IF1512.CCFX‘或‘IH1602.CCFX‘是一样的)
 33       # 开盘前运行
 34     run_daily( before_market_open, time=‘before_open‘, reference_security=get_future_code(g.future_index))
 35       # 开盘时运行
 36     run_daily( while_open, time=‘open‘, reference_security=get_future_code(g.future_index))
 37       # 收盘后运行
 38     run_daily( after_market_close, time=‘after_close‘, reference_security=get_future_code(g.future_index))
 39
 40
 41 def set_params(context):
 42     # 设置唐奇安通道时间窗口
 43     g.window = 10
 44     # 最大unit数目
 45     g.limit_unit = 6
 46     # 每次交易unit数目
 47     g.unit = 0
 48     # 加仓次数
 49     g.add_time = 0
 50     # 持仓状态
 51     g.position = 0
 52     # 最高价指标,用作移动止损
 53     g.price_mark = 0
 54     # 最近一次交易的合约
 55     g.last_future = None
 56     # 上一次交易的价格
 57     g.last_price = 0
 58     # 合约
 59     g.future_index = ‘CU‘
 60
 61
 62
 63 ## 开盘前运行函数
 64 def before_market_open(context):
 65     ## 获取要操作的期货(g.为全局变量)
 66       # 获取当月期货合约
 67     g.future = get_dominant_future(g.future_index)
 68
 69
 70
 71
 72
 73
 74 ## 开盘时运行函数
 75 def while_open(context):
 76     # 如果期货标的改变,重置参数
 77     if g.last_future == None:
 78         g.last_future = g.future
 79     elif g.last_future != g.future:
 80         if g.position == -1:
 81             order_target(g.last_future,0,side=‘short‘)
 82             g.position == 0
 83         elif g.position == 1:
 84             order_target(g.last_future,0,side=‘long‘)
 85             g.position == 0
 86         g.last_future = g.future
 87         re_set()
 88         log.info("主力合约改变,平仓!")
 89
 90     # 当月合约
 91     future = g.future
 92     # 获取当月合约交割日期
 93     end_date = get_CCFX_end_date(future)
 94     # 当月合约交割日当天不开仓
 95     if (context.current_dt.date() == end_date):
 96         return
 97     price_list = attribute_history(future,g.window+1,‘1d‘,[‘close‘,‘high‘,‘low‘])
 98     # 如果没有数据,返回
 99     if len(price_list) == 0:
100         return
101     close_price = price_list[‘close‘].iloc[-1]
102     # 计算ATR
103     ATR = get_ATR(price_list,g.window)
104
105     ## 判断加仓或止损
106       # 先判断是否持仓
107     #g.position = get_position(context)
108     if g.position != 0 :
109         signal = get_next_signal(close_price,g.last_price,ATR,g.position)
110         # 判断加仓且持仓没有达到上限
111         if signal == 1 and g.add_time < g.limit_unit:
112             g.unit = get_unit(context.portfolio.total_value,ATR,g.future_index)
113             # 多头加仓
114             if g.position == 1:
115                 order(future,g.unit,side=‘long‘)
116                 log.info( ‘多头加仓成功:‘,context.current_dt.time(),future,g.unit)
117                 g.last_prcie = close_price
118                 g.add_time += 1
119             # 空头加仓
120             elif g.position == -1:
121                 order(future,g.unit,side=‘short‘)
122                 log.info( ‘空头加仓成功:‘,context.current_dt.time(),future,g.unit)
123                 g.last_prcie = close_price
124                 g.add_time += 1
125         # 判断平仓止损
126         elif signal == -1:
127             # 多头平仓
128             if g.position == 1:
129                 order_target(future,0,side=‘long‘)
130                 g.price_mark = 0
131                 g.position = 0
132                 log.info( ‘多头止损成功:‘,context.current_dt.time(),future)
133                 log.info(‘----------------------------------------------------------‘)
134             # 空头平仓
135             elif g.position == -1:
136                 order_target(future,0,side=‘long‘)
137                 g.price_mark = 0
138                 g.position = 0
139                 log.info( ‘空头止损成功:‘,context.current_dt.time(),future)
140                 log.info(‘----------------------------------------------------------‘)
141             # 重新初始化参数
142             re_set()
143
144     ## 开仓
145       # 得到开仓信号
146     open_signal = check_break(price_list,close_price,g.window)
147     # 多头开仓
148     if open_signal ==1 and g.position !=1:
149         # 检测否需要空头平仓
150         if g.position == -1:
151             order_target(future,0,side=‘short‘)
152             if context.portfolio.short_positions[future].total_amount==0:
153                 g.price_mark = 0
154                 # 重新初始化参数
155                 re_set()
156                 log.info( ‘空头平仓成功:‘,context.current_dt.time(),future)
157                 log.info(‘----------------------------------------------------------‘)
158         # 多头开仓
159         g.unit = get_unit(context.portfolio.total_value,ATR,g.future_index)
160         order(future,g.unit,side=‘long‘)
161         if context.portfolio.positions[future].total_amount>0:
162             g.position = 1
163             g.price_mark = context.portfolio.long_positions[future].price
164             log.info( ‘多头建仓成功:‘,context.current_dt.time(),future,g.unit)
165             log.info(‘++++++++++++++++++++++++++++++++++++++++++++++++++++++++++‘)
166             g.add_time = 1
167             g.last_prcie = close_price
168             g.last_future= future
169     # 空头开仓
170     elif open_signal == -1 and g.position != -1:
171         # 检测否需要多头平仓
172         if g.position == 1:
173             order_target(future,0,side=‘long‘)
174             if context.portfolio.positions[future].total_amount==0:
175                 g.price_mark = 0
176                 # 重新初始化参数
177                 re_set()
178                 log.info( ‘多头平仓成功:‘,context.current_dt.time(),future)
179                 log.info(‘----------------------------------------------------------‘)
180         # 空头开仓
181         g.unit = get_unit(context.portfolio.total_value,ATR,g.future_index)
182         order(future,g.unit,side=‘short‘)
183         if context.portfolio.short_positions[future].total_amount > 0:
184             g.position = -1
185             g.price_mark = context.portfolio.short_positions[future].price
186             log.info( ‘空头建仓成功:‘,context.current_dt.time(),future,g.unit)
187             log.info(‘++++++++++++++++++++++++++++++++++++++++++++++++++++++++++‘)
188             g.add_time = 1
189             g.last_prcie = close_price
190             g.last_future= future
191
192     # 判断今日是否出现最高价
193     if g.position != 0:
194         set_price_mark(context,future)
195     # 得到止损信号
196     signal = get_risk_signal(context,future)
197     # 止损平仓
198     if signal:
199         order_target(future, 0, side=‘short‘)
200         order_target(future, 0, side=‘long‘)
201         if context.portfolio.positions[future].total_amount==0 and context.portfolio.short_positions[future].total_amount==0:
202             log.info("止损平仓!")
203             g.position = 0
204             g.price_mark = 0
205     return
206
207
208
209 ## 收盘后运行函数
210 def after_market_close(context):
211     pass
212
213
214 ########################## 自定义函数 #################################
215 # 重置参数
216 def re_set():
217     # 每次交易unit数目
218     g.unit = 0
219     # 加仓次数
220     g.add_time = 0
221     # 持仓状态
222     g.position = 0
223
224 def check_break(price_list,price,T):
225     up = max(price_list[‘high‘].iloc[-T-1:-2])
226     down = min(price_list[‘low‘].iloc[-T-1:-2])
227     if price>up:
228         return 1
229     elif price<down:
230         return -1
231     else:
232         return 0
233
234 def get_ATR(price_list,T):
235     TR_list = [max(price_list[‘high‘].iloc[i]-price_list[‘low‘].iloc[i],abs(price_list[‘high‘].iloc[i]-price_list[‘close‘].iloc[i-1]),abs(price_list[‘close‘].iloc[i-1]-price_list[‘low‘].iloc[i])) for i in range(1,T+1)]
236     ATR = np.array(TR_list).mean()
237     return ATR
238
239 def get_next_signal(price,last_price,ATR,position):# 加仓或止损
240     if (price >= last_price + 0.5*ATR and position==1) or (price <= last_price - 0.5*ATR and position==-1): # 多头加仓或空头加仓
241         return 1
242     elif (price <= last_price - 2*ATR and position==1) or (price >= last_price + 2*ATR and position==-1):  # 多头止损或空头止损
243         return -1
244     else:
245         return 0
246
247 def get_position(context): # 0为未持仓,1为持多,-1为持空
248     try:
249         tmp = context.portfolio.positions.keys()[0]
250         if not context.portfolio.long_positions[tmp].total_amount and not context.portfolio.short_positions[tmp].total_amount:
251             return 0
252         elif context.portfolio.long_positions[tmp].total_amount:
253             return 1
254         elif context.portfolio.short_positions[tmp].total_amount:
255             return -1
256         else:
257             return 0
258     except:
259         return 0
260
261 def get_unit(cash,ATR,symbol):
262     future_coef_list = {‘A‘:10, ‘AG‘:15, ‘AL‘:5, ‘AU‘:1000,
263                         ‘B‘:10, ‘BB‘:500, ‘BU‘:10, ‘C‘:10,
264                         ‘CF‘:5, ‘CS‘:10, ‘CU‘:5, ‘ER‘:10,
265                         ‘FB‘:500, ‘FG‘:20, ‘FU‘:50, ‘GN‘:10,
266                         ‘HC‘:10, ‘I‘:100, ‘IC‘:200, ‘IF‘:300,
267                         ‘IH‘:300, ‘J‘:100, ‘JD‘:5, ‘JM‘:60,
268                         ‘JR‘:20, ‘L‘:5, ‘LR‘:10, ‘M‘:10,
269                         ‘MA‘:10, ‘ME‘:10, ‘NI‘:1, ‘OI‘:10,
270                         ‘P‘:10, ‘PB‘:5, ‘PM‘:50, ‘PP‘:5,
271                         ‘RB‘:10, ‘RI‘:20, ‘RM‘:10, ‘RO‘:10,
272                         ‘RS‘:10, ‘RU‘:10, ‘SF‘:5, ‘SM‘:5,
273                         ‘SN‘:1, ‘SR‘:10, ‘T‘:10000, ‘TA‘:5,
274                         ‘TC‘:100, ‘TF‘:10000, ‘V‘:5, ‘WH‘:20,
275                         ‘WR‘:10, ‘WS‘:50, ‘WT‘:10, ‘Y‘:10,
276                         ‘ZC‘:100, ‘ZN‘:5}
277     return (cash*0.01/ATR)/future_coef_list[symbol]
278
279 def set_price_mark(context,future):
280     if g.position == -1:
281         g.price_mark = min(context.portfolio.short_positions[future].price,g.price_mark)
282     elif g.position == 1:
283         g.price_mark = max(context.portfolio.long_positions[future].price,g.price_mark)
284
285 def get_risk_signal(context,future):
286     if g.position == -1:
287         if context.portfolio.short_positions[future].price >=1.05*g.price_mark:
288             log.info("空头仓位止损,时间: "+str(context.current_dt.time()))
289             return True
290         else:
291             return False
292     elif g.position == 1:
293         if context.portfolio.long_positions[future].price <= 0.95*g.price_mark:
294             log.info("多头仓位止损,时间: "+str(context.current_dt.time()))
295             return True
296         else:
297             return False
298
299 ########################## 获取期货合约信息,请保留 #################################
300 # 获取当天时间正在交易的期货主力合约
301 def get_future_code(symbol):
302     future_code_list = {‘A‘:‘A9999.XDCE‘, ‘AG‘:‘AG9999.XSGE‘, ‘AL‘:‘AL9999.XSGE‘, ‘AU‘:‘AU9999.XSGE‘,
303                         ‘B‘:‘B9999.XDCE‘, ‘BB‘:‘BB9999.XDCE‘, ‘BU‘:‘BU9999.XSGE‘, ‘C‘:‘C9999.XDCE‘,
304                         ‘CF‘:‘CF9999.XZCE‘, ‘CS‘:‘CS9999.XDCE‘, ‘CU‘:‘CU9999.XSGE‘, ‘ER‘:‘ER9999.XZCE‘,
305                         ‘FB‘:‘FB9999.XDCE‘, ‘FG‘:‘FG9999.XZCE‘, ‘FU‘:‘FU9999.XSGE‘, ‘GN‘:‘GN9999.XZCE‘,
306                         ‘HC‘:‘HC9999.XSGE‘, ‘I‘:‘I9999.XDCE‘, ‘IC‘:‘IC9999.CCFX‘, ‘IF‘:‘IF9999.CCFX‘,
307                         ‘IH‘:‘IH9999.CCFX‘, ‘J‘:‘J9999.XDCE‘, ‘JD‘:‘JD9999.XDCE‘, ‘JM‘:‘JM9999.XDCE‘,
308                         ‘JR‘:‘JR9999.XZCE‘, ‘L‘:‘L9999.XDCE‘, ‘LR‘:‘LR9999.XZCE‘, ‘M‘:‘M9999.XDCE‘,
309                         ‘MA‘:‘MA9999.XZCE‘, ‘ME‘:‘ME9999.XZCE‘, ‘NI‘:‘NI9999.XSGE‘, ‘OI‘:‘OI9999.XZCE‘,
310                         ‘P‘:‘P9999.XDCE‘, ‘PB‘:‘PB9999.XSGE‘, ‘PM‘:‘PM9999.XZCE‘, ‘PP‘:‘PP9999.XDCE‘,
311                         ‘RB‘:‘RB9999.XSGE‘, ‘RI‘:‘RI9999.XZCE‘, ‘RM‘:‘RM9999.XZCE‘, ‘RO‘:‘RO9999.XZCE‘,
312                         ‘RS‘:‘RS9999.XZCE‘, ‘RU‘:‘RU9999.XSGE‘, ‘SF‘:‘SF9999.XZCE‘, ‘SM‘:‘SM9999.XZCE‘,
313                         ‘SN‘:‘SN9999.XSGE‘, ‘SR‘:‘SR9999.XZCE‘, ‘T‘:‘T9999.CCFX‘, ‘TA‘:‘TA9999.XZCE‘,
314                         ‘TC‘:‘TC9999.XZCE‘, ‘TF‘:‘TF9999.CCFX‘, ‘V‘:‘V9999.XDCE‘, ‘WH‘:‘WH9999.XZCE‘,
315                         ‘WR‘:‘WR9999.XSGE‘, ‘WS‘:‘WS9999.XZCE‘, ‘WT‘:‘WT9999.XZCE‘, ‘Y‘:‘Y9999.XDCE‘,
316                         ‘ZC‘:‘ZC9999.XZCE‘, ‘ZN‘:‘ZN9999.XSGE‘}
317     try:
318         return future_code_list[symbol]
319     except:
320         return ‘WARNING: 无此合约‘
321
322
323 # 获取当天时间正在交易的股指期货合约
324 def get_stock_index_futrue_code(context,symbol,month=‘current_month‘):
325     ‘‘‘
326     获取当天时间正在交易的股指期货合约。其中:
327     symbol:
328             ‘IF‘ #沪深300指数期货
329             ‘IC‘ #中证500股指期货
330             ‘IH‘ #上证50股指期货
331     month:
332             ‘current_month‘ #当月
333             ‘next_month‘    #隔月
334             ‘next_quarter‘  #下季
335             ‘skip_quarter‘  #隔季
336     ‘‘‘
337     display_name_dict = {‘IC‘:‘中证500股指期货‘,‘IF‘:‘沪深300指数期货‘,‘IH‘:‘上证50股指期货‘}
338     month_dict = {‘current_month‘:0, ‘next_month‘:1, ‘next_quarter‘:2, ‘skip_quarter‘:3}
339
340     display_name = display_name_dict[symbol]
341     n = month_dict[month]
342     dt = context.current_dt.date()
343     a = get_all_securities(types=[‘futures‘], date=dt)
344     try:
345         df = a[(a.display_name == display_name) & (a.start_date <= dt) & (a.end_date >= dt)]
346         return df.index[n]
347     except:
348         return ‘WARRING: 无此合约‘
349
350 # 获取当天时间正在交易的国债期货合约
351 def get_treasury_futrue_code(context,symbol,month=‘current‘):
352     ‘‘‘
353     获取当天时间正在交易的国债期货合约。其中:
354     symbol:
355             ‘T‘ #10年期国债期货
356             ‘TF‘ #5年期国债期货
357     month:
358             ‘current‘ #最近期
359             ‘next‘    #次近期
360             ‘skip‘    #最远期
361     ‘‘‘
362     display_name_dict = {‘T‘:‘10年期国债期货‘,‘TF‘:‘5年期国债期货‘}
363     month_dict = {‘current‘:0, ‘next‘:1, ‘skip‘:2}
364
365     display_name = display_name_dict[symbol]
366     n = month_dict[month]
367     dt = context.current_dt.date()
368     a = get_all_securities(types=[‘futures‘], date=dt)
369     try:
370         df = a[(a.display_name == display_name) & (a.start_date <= dt) & (a.end_date >= dt)]
371         return df.index[n]
372     except:
373         return ‘WARRING: 无此合约‘
374
375 # 获取金融期货合约到期日
376 def get_CCFX_end_date(fature_code):
377     # 获取金融期货合约到期日
378     return get_security_info(fature_code).end_date

发现有低级错误,是第189行中空头建仓后,建仓价格记录在last_prcie,而非last_price,导致后续的加仓、止损都会有判断问题

但回测帖子所给的时间段、资金量以及相同的期货品种,发现收益差了很多,原有代码是47%的年化收益,修改后只有18%了

于是觉得代码可能还是哪里有坑,拿不准那个才是正确,于是还是想原来的老路,改宋老师TB的代码,这样可以对照宋老师的回测结果(后面看也是不行,宋博的回测时间是2009年开始的,聚宽只能提供2010年以后的数据)。我将其简化版海龟策略(就是缺了加仓和反向头寸止损的操作)的TB的代码改成可以在聚宽上跑了。

  1 # 导入函数库
  2 from jqdata import *
  3 import pandas as pd
  4 import numpy as np
  5
  6 ## 初始化函数,设定基准等等
  7 def initialize(context):
  8     set_params(context)
  9     # 设定所交易期货指数作为基准
 10     set_benchmark(get_future_code(g.future_index))
 11     # 开启动态复权模式(真实价格)
 12     set_option(‘use_real_price‘, True)
 13     # 过滤掉order系列API产生的比error级别低的log
 14     # log.set_level(‘order‘, ‘error‘)
 15     # 输出内容到日志 log.info()
 16     log.info(‘初始函数开始运行且全局只运行一次‘)
 17
 18     ### 期货相关设定 ###
 19     # 设定账户为金融账户
 20     set_subportfolios([SubPortfolioConfig(cash=context.portfolio.starting_cash, type=‘index_futures‘)])
 21     # 期货类每笔交易时的手续费是:买入时万分之0.23,卖出时万分之0.23,平今仓为万分之23
 22     set_order_cost(OrderCost(open_commission=0.000023, close_commission=0.000023,close_today_commission=0.0023), type=‘index_futures‘)
 23     # 设定保证金比例
 24     set_option(‘futures_margin_rate‘, 0.15)
 25
 26     # 设置期货交易的滑点
 27     set_slippage(FixedSlippage(0.2))
 28     # 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入‘IF1512.CCFX‘或‘IH1602.CCFX‘是一样的)
 29       # 开盘前运行
 30     run_daily( before_market_open, time=‘before_open‘, reference_security=get_future_code(g.future_index))
 31       # 开盘时运行
 32     run_daily( market_open, time=‘open‘, reference_security=get_future_code(g.future_index))
 33       # 收盘后运行
 34     run_daily( after_market_close, time=‘after_close‘, reference_security=get_future_code(g.future_index))
 35
 36
 37 ## 开盘前运行函数
 38 def before_market_open(context):
 39     # 输出运行时间
 40     log.info(‘函数运行时间(before_market_open):‘+str(context.current_dt.time()))
 41
 42     # 给微信发送消息(添加模拟交易,并绑定微信生效)
 43     #send_message(‘美好的一天~‘)
 44
 45     ## 获取要操作的股票(g.为全局变量)
 46       # 获取当月期货合约
 47     g.future = get_dominant_future(g.future_index)
 48
 49
 50 ## 开盘时运行函数
 51 def market_open(context):
 52     calc_window = int(3.45*(g.ATRLength + 1))
 53     price_list = attribute_history(g.future, calc_window + 1, ‘1d‘, [‘close‘,‘high‘,‘low‘])
 54
 55     if len(price_list) == 0:
 56         return # 如果没有数据,返回
 57
 58     AvgTR = XAverage(TrueRange(price_list, calc_window),g.ATRLength)
 59     N = AvgTR[-2]
 60     TurtleUnits = get_unit(context.portfolio.total_value, N, g.future_index, g.RiskRatio)
 61
 62     DonchianHi = HighestFC(price_list[‘high‘], g.boLength)
 63     DonchianLo = LowestFC(price_list[‘low‘], g.boLength)
 64
 65     ExitLowestPrice = LowestFC(price_list[‘low‘], g.teLength)
 66     ExitHighestPrice = HighestFC(price_list[‘high‘], g.teLength)
 67
 68     High = price_list[‘high‘].iloc[-1]
 69     Low = price_list[‘low‘].iloc[-1]
 70
 71     # 当不使用过滤条件,或者使用过滤条件并且条件为PreBreakoutFailure为True进行后续操作
 72     if g.MarketPosition == 0:
 73         log.info(context.current_dt.time(), ‘ High:‘, High, ‘ DonchianHi:‘, DonchianHi, ‘ Low:‘, Low, ‘ DonchianLo:‘, DonchianLo)
 74         # 突破开仓
 75         if High > DonchianHi and TurtleUnits >= 1:
 76             # 开仓价格取突破上轨+一个价位和最高价之间的较小值,这样能更接近真实情况,并能尽量保证成交
 77             # myEntryPrice = min(High, DonchianHi)# + MinPoint)
 78             # myEntryPrice = Open if myEntryPrice < Open else myEntryPrice # 大跳空的时候用开盘价代替
 79             order(g.future, TurtleUnits, side=‘long‘)
 80             g.MarketPosition = 1
 81
 82         if Low < DonchianLo and TurtleUnits >= 1:
 83             # 开仓价格取突破下轨-一个价位和最低价之间的较大值,这样能更接近真实情况,并能尽量保证成交
 84             # myEntryPrice = max(Low,DonchianLo)# - MinPoint)
 85             # myEntryPrice = Open if myEntryPrice > Open else myEntryPrice # 大跳空的时候用开盘价代替
 86             order(g.future, TurtleUnits, side=‘short‘)
 87             g.MarketPosition = -1
 88
 89     if g.MarketPosition == 1:
 90         # 有多仓的情况
 91         log.info(‘ExitLowestPrice=‘, ExitLowestPrice)
 92         if Low < ExitLowestPrice:
 93             # myExitPrice = max(Low,ExitLowestPrice)# - MinPoint)
 94             # myExitPrice = Open if myExitPrice > Open else myExitPrice # 大跳空的时候用开盘价代替
 95             order_target(g.future, 0, side=‘long‘) # 数量用0的情况下将全部平仓
 96             g.MarketPosition = 0
 97     elif g.MarketPosition == -1:
 98         # 有空仓的情况
 99         log.info(‘ExitHighestPrice=‘, ExitHighestPrice)
100         if High > ExitHighestPrice:
101             # myExitPrice = Min(High,ExitHighestPrice)# + MinPoint)
102             # myExitPrice = Open if myExitPrice < Open else myExitPrice # 大跳空的时候用开盘价代替
103             order_target(g.future, 0, side=‘short‘) # 数量用0的情况下将全部平仓
104             g.MarketPosition = 0
105
106 ## 收盘后运行函数
107 def after_market_close(context):
108     log.info(‘函数运行时间(after_market_close):‘, context.current_dt.time())
109     # 得到当天所有成交记录
110     trades = get_trades()
111     for _trade in trades.values():
112         log.info(‘成交记录:‘+str(_trade))
113     log.info(‘一天结束‘)
114     log.info(‘##############################################################‘)
115
116
117 ########################## 自定义函数 #################################
118 def set_params(context):
119     g.RiskRatio = 10 # % Risk Per N ( 0 - 100)
120     g.ATRLength = 6 # 平均波动周期 ATR Length
121     g.boLength = 0 # 短周期 BreakOut Length
122     g.teLength = 0 # 离市周期 Trailing Exit Length
123     g.future_index = ‘RB‘ # 合约
124     g.MarketPosition = 0
125
126 # 求指数平均
127 def XAverage(Price, Length):
128     alpha = 2 / (Length + 1)
129     res = []
130     for i in range(0, len(Price)):
131         res.append(ema_calc(alpha, Price, i))
132     return res
133
134 def ema_calc(alpha, price, t):
135     if (t == 0):
136         return price[t]
137     else:
138         return alpha*price[t] + (1-alpha) * ema_calc(alpha, price, t-1)
139
140 def TrueRange(price_list, T):
141     return [max(price_list[‘high‘].iloc[i]-price_list[‘low‘].iloc[i], abs(price_list[‘high‘].iloc[i]-price_list[‘close‘].iloc[i-1]), abs(price_list[‘close‘].iloc[i-1]-price_list[‘low‘].iloc[i])) for i in range(1, T+1)]
142
143 def get_unit(cash, ATR, symbol, RiskRatio):
144     # 各品种期货的交易单位(一手合约包含多少计量单位,如CU:5即铜合约交易单位为5吨/手)
145     future_contract_size = {‘A‘:10, ‘AG‘:15, ‘AL‘:5, ‘AU‘:1000,
146                         ‘B‘:10, ‘BB‘:500, ‘BU‘:10, ‘C‘:10,
147                         ‘CF‘:5, ‘CS‘:10, ‘CU‘:5, ‘ER‘:10,
148                         ‘FB‘:500, ‘FG‘:20, ‘FU‘:50, ‘GN‘:10,
149                         ‘HC‘:10, ‘I‘:100, ‘IC‘:200, ‘IF‘:300,
150                         ‘IH‘:300, ‘J‘:100, ‘JD‘:5, ‘JM‘:60,
151                         ‘JR‘:20, ‘L‘:5, ‘LR‘:10, ‘M‘:10,
152                         ‘MA‘:10, ‘ME‘:10, ‘NI‘:1, ‘OI‘:10,
153                         ‘P‘:10, ‘PB‘:5, ‘PM‘:50, ‘PP‘:5,
154                         ‘RB‘:10, ‘RI‘:20, ‘RM‘:10, ‘RO‘:10,
155                         ‘RS‘:10, ‘RU‘:10, ‘SF‘:5, ‘SM‘:5,
156                         ‘SN‘:1, ‘SR‘:10, ‘T‘:10000, ‘TA‘:5,
157                         ‘TC‘:100, ‘TF‘:10000, ‘V‘:5, ‘WH‘:20,
158                         ‘WR‘:10, ‘WS‘:50, ‘WT‘:10, ‘Y‘:10,
159                         ‘ZC‘:100, ‘ZN‘:5}
160     TurtleUnits = (cash*RiskRatio) / (100.0 * ATR * future_contract_size[symbol])
161     TurtleUnits = int(TurtleUnits) # 对小数取整
162     print(‘TurtleUnits: ‘, TurtleUnits)
163     return TurtleUnits
164
165 def HighestFC(Prices, Length):
166     highest = Prices[-2]
167     for i in range(-2, -Length-2):
168         if highest < Prices[i]:
169             highest = Prices
170     return highest
171
172 def LowestFC(Prices, Length):
173     lowest = Prices[-2]
174     for i in range(-2, -Length-2):
175         if lowest > Prices[i]:
176             lowest = Prices
177     return lowest
178
179 ########################## 获取期货合约信息,请保留 #################################
180 # 获得当天时间正在交易的期货主力合约
181 def get_future_code(symbol):
182     future_code_list = {‘A‘:‘A9999.XDCE‘, ‘AG‘:‘AG9999.XSGE‘, ‘AL‘:‘AL9999.XSGE‘, ‘AU‘:‘AU9999.XSGE‘,
183                         ‘B‘:‘B9999.XDCE‘, ‘BB‘:‘BB9999.XDCE‘, ‘BU‘:‘BU9999.XSGE‘, ‘C‘:‘C9999.XDCE‘,
184                         ‘CF‘:‘CF9999.XZCE‘, ‘CS‘:‘CS9999.XDCE‘, ‘CU‘:‘CU9999.XSGE‘, ‘ER‘:‘ER9999.XZCE‘,
185                         ‘FB‘:‘FB9999.XDCE‘, ‘FG‘:‘FG9999.XZCE‘, ‘FU‘:‘FU9999.XSGE‘, ‘GN‘:‘GN9999.XZCE‘,
186                         ‘HC‘:‘HC9999.XSGE‘, ‘I‘:‘I9999.XDCE‘, ‘IC‘:‘IC9999.CCFX‘, ‘IF‘:‘IF9999.CCFX‘,
187                         ‘IH‘:‘IH9999.CCFX‘, ‘J‘:‘J9999.XDCE‘, ‘JD‘:‘JD9999.XDCE‘, ‘JM‘:‘JM9999.XDCE‘,
188                         ‘JR‘:‘JR9999.XZCE‘, ‘L‘:‘L9999.XDCE‘, ‘LR‘:‘LR9999.XZCE‘, ‘M‘:‘M9999.XDCE‘,
189                         ‘MA‘:‘MA9999.XZCE‘, ‘ME‘:‘ME9999.XZCE‘, ‘NI‘:‘NI9999.XSGE‘, ‘OI‘:‘OI9999.XZCE‘,
190                         ‘P‘:‘P9999.XDCE‘, ‘PB‘:‘PB9999.XSGE‘, ‘PM‘:‘PM9999.XZCE‘, ‘PP‘:‘PP9999.XDCE‘,
191                         ‘RB‘:‘RB9999.XSGE‘, ‘RI‘:‘RI9999.XZCE‘, ‘RM‘:‘RM9999.XZCE‘, ‘RO‘:‘RO9999.XZCE‘,
192                         ‘RS‘:‘RS9999.XZCE‘, ‘RU‘:‘RU9999.XSGE‘, ‘SF‘:‘SF9999.XZCE‘, ‘SM‘:‘SM9999.XZCE‘,
193                         ‘SN‘:‘SN9999.XSGE‘, ‘SR‘:‘SR9999.XZCE‘, ‘T‘:‘T9999.CCFX‘, ‘TA‘:‘TA9999.XZCE‘,
194                         ‘TC‘:‘TC9999.XZCE‘, ‘TF‘:‘TF9999.CCFX‘, ‘V‘:‘V9999.XDCE‘, ‘WH‘:‘WH9999.XZCE‘,
195                         ‘WR‘:‘WR9999.XSGE‘, ‘WS‘:‘WS9999.XZCE‘, ‘WT‘:‘WT9999.XZCE‘, ‘Y‘:‘Y9999.XDCE‘,
196                         ‘ZC‘:‘ZC9999.XZCE‘, ‘ZN‘:‘ZN9999.XSGE‘}
197     try:
198         return future_code_list[symbol]
199     except:
200         return ‘WARNING : 无此合约‘
201
202
203 # 获取金融期货合约到期日
204 def get_CCFX_end_date(fature_code):
205     # 获取金融期货合约到期日
206     return get_security_info(fature_code).end_date

在改代码的过程中遇到多个问题,包括:

1. TB提供一个XAverage的函数计算指数平均,也就是EMA,聚宽下需要我自行实现,关于其计算公式,我有疑问,也发到小象去问老师了:

想问问关于ema计算公式的问题,如果我要得到某个股票今天的ema(20)值,是不是要回溯到这个股票上市开始一直算这个ema(20)算到今天,还是说只需要回退到20天前就开始算这个ema值?

举个例子,就是价格序列是[0,1,2,3,4,5,6,7],对应第一天、第二天、...第八天,想问问求ema(3),其alpha是2 / (3+1) = 0.5,那么第六天的ema(3),应该是4.25,还是4.03125,还是说我两个计算方式都不对?

A. 只需往前倒2天:

ema(3)1=3

ema(3)2=0.5*4 + 0.5*3 = 3.5

ema(3)3=0.5*5+0.5*3.5=4.25

还是B. 从价格序列最开始算ema

ema(3)1=0

ema(3)2=0.5*1 + 0.5*0 = 0.5

ema(3)3=0.5*2+0.5*0.5=1.25

ema(3)4=0.5*3 + 0.5*1.25 = 2.125

ema(3)5=0.5*4+0.5*2.125 = 3.0625

ema(3)6=0.5*5+0.5*3.0625=4.03125

主要是我看这里https://www.zybuluo.com/Channelchan/note/1081375中的“2. Pandas递归函数”例子,里面算第10天的ema(6),我按只往前倒5天(第5天,数值为4)算,应该是6.4335948,而非页面上面算的(9*2/7)+(5.669401*5/7)=6.621001,所以比较疑惑。

不知道如果我要算某个时期,例如17年整年,某股票的ema(20),我在计算17年6月1号的ema(20)时应该是,将往前倒20天就用公式开始算,还是由17年1月1日这个我开始算ema的时期代入公式开始求,还是要追溯会股价第一天开始来代入计算公式?

网上搜索还看到,https://zh.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87,说ema(N)要往前算到3.45*(N+1),能包含99.9%的加权,那是应该这样么?

而且听老师的课,这个第10天的ema(6)应该是往前倒6天,由第4天(数值为3)那个开始算,那应该是5.56640515。我的理解有错么?

暂时没有回复,我自己的判断是应该往前算3.45*(N+1)即可,代码上也是这样实现的。

2. 现在的回测结果是收益-85%,觉得是代码有问题。碰到一个困难是,宋博的TB代码是算出交易的量和价格,但聚宽的交易接口只提供交易量,不能设置其交易价格,很奇怪。然后我也看到一些log,说一开始就全仓买进,甚至买到资金不够,估计是代码逻辑有问题,或者是TB跟聚宽用的单位不同。总之是这些导致策略收益是亏损。后面要去好好调试,将bug抓出来。

原文地址:https://www.cnblogs.com/alonecat06/p/9503331.html

时间: 2024-11-13 04:14:38

海龟交易法操作商品期货的相关文章

海龟交易

海龟交易法是用于期货等带杠杆操作的标的上的.但是其中一些理念能否用于股票市场呢? 一.市场选择: 海龟的市场选择注重在流通性上,即不会被少数人操纵,从而价格大起大落.对应的股票市场,应选择流通股相对大的股票.这种股票走势相对平稳.我现在暂时确定在流通股大于1亿. 二.头寸规模 完全采取海龟模式: 以下为抄录:―――――――――――――――――――――――――――――――― <海龟交易法则>中的仓位管理方法,是以ATR指标为核心的.ATR,即平均真实波幅.要计算这个指标,就要先会计算真实波幅.真

大奖章基金网格交易法的由来

大奖章基金成立于1988年3月,是美国私募基金公司文艺复兴科技公司的第一支基金产品,产品的基金经理是两位美国著名的数学家:西蒙斯和埃克斯,他们分别于1967年和1976年获得学界最高荣誉,美国数学学会5年一度的伟布伦奖,这就是大奖章基金名称的由来. 网格交易法的诞生: 第一年刚开始亏损30%.然后西蒙斯做了个决定,将过去模型中有关宏观经济数据的部分完全剔除,只留下技术性数据,同时把注意力都集中在短线交易时间上.这次修正被称为大奖章基金的“遵义会议”,当时制定的投资战略被保留至今,成为大奖章长盛不

私募为何大都在做量化投资,有哪些优势?

量化投资已经成为私募基金发展最快的策略.逐步从定性投资向量化投资转型,是私募基金等机构投资者的不二选择. 什么是量化投资 量化投资概念具有狭义和广义两个不同的含义. 通常意义的量化投资指狭义量化投资,是指使用数量化方法做出投资决策,实现既定投资策略的投资方式.量化投资区别于定性投资的鲜明特征是使用数学模型做出投资决策,往往但非必然由计算机程序批量发出交易指令. 从广义角度看,量化投资及其分析方法已经有100余年历史,在投资过程中的作用无处不在,日趋广泛深入. 纵观全球投资学发展史,就是各种量化投

2种方法筛选出多因子量化选股模型

多因子选股模型在模型搭建中,往往会涉及到非常多的股价影响因子,并可能导出数量极多的备选模型.因此,对于多因子选股模型的评价和筛选,就显得尤为关键. 对于专业的量化投资人而言,就需要进一步了解多因子选股模型的两种主要的评价判断方法——打分法和回归法. 打分法的评价原理和流程 所谓打分法,就是根据各个因子的大小对股票进行打分,然后按照一定的权重加权得到一个总分,最后根据总分再对股票进行筛选. 对于多因子模型的评价而言,实际通过评分法回测出的股票组合收益率,就能够对备选的选股模型做出优劣评价. 打分法

python基础10 字符串操作,字典操作,集合操作

本节内容: 字符串操作 字典操作 集合操作 字符串操作 概述 字符串是以''或""括起来的任意文本,比如'abc',"xyz"等等.请注意,''或""本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'只有a,b,c这3个字符. 如果字符串本身包含'怎么办?比如我们要表示字符串 I'm OK ,这时,可以用" "括起来表示: "I'm OK" 类似的,如果字符串包含",我们就可以用'

由一则豆瓣书评看《海龟交易法则》

本文作者:我的剑会笑 在读这本书之前,我已经多次听闻过理查德丹尼斯的海龟计划.网上流传的原版海龟法则我也曾拜读过,但是对于当时的我来说,收获不多.这次决定买下这本书,并且在2天之内就读完这本书(我读书很少有这么快),是因为经过6年的市场锻炼,我强烈得觉得,一个简单有效.可执行度高的交易系统是长期盈利的有力保证.老实说,我在读之前并没有对这本书抱有太大的希望,因为众所周知,海龟交易法则已经是一个被市场研究了无数遍的东西,这几年我也看过不少的投资.投机方面的书,我不认为我还能从中找出一些在其他书里面

python课程设计笔记(三)turtle绘图库(海龟库)

实例:绘制一条蟒蛇 #turtle:绘图库(海龟库) import turtle turtle.setup(650,350,200,200) turtle.penup() turtle.fd(-250) turtle.pendown() turtle.pensize(25) turtle.pencolor("purple") turtle.seth(-40) for i in range(4): turtle.circle(40,80) turtle.circle(-40,80) tu

通过海龟绘图学习Python-01

作为一名Python初学者,看教程死记硬背理论知识固然是必要的,也可以通过海龟绘图的方式进行实践操作.在实践的过程中加深对理论知识的理解.接下来,本人将通过海龟绘图的方式开启Python的学习之路.注:Python的基本理论知识可以通过官网网站进行学习,网上也有很多的教材,本人假定读者已经学习了入门知识. 什么是海龟绘图海龟绘图是Python内置的turtle 模块(源码: Lib/turtle.py),使用海龟绘图可以编写重复执行简单动作的程序画出精细复杂的形状.例如下图 2.如何使用导入tu

常见商品期货量化交易策略

商品期货套利策略 套利策略一般包括期现套利.跨期套利.跨市场套利.跨品种套利等. 对于商品期货而言,期现套利必须交易大量的商品实物,这对大多数机构投资者而言并不合适.因此,我们仅介绍跨期套利.跨市场套利和跨品种套利. 1.跨期套利 跨期套利的思路一般如下:对某一品种主力合约和次主力合约的价差做统计(一般是厚尾分布),然后选取恰当的分位数设定阈值,则可进行反转套利.我们前期的报告<趋强避弱商品期货套利策略>中对其已有详细的研究,在此就不赘述了. 2.跨市场套利 跨市场套利即对同一期货品种在不同市