def short(self, symbol, volume=1, price=None, stop=False, limit=False, strategy=None, listener=None): if self.__backtesting: time_ = self.__data[symbol][SymbolsListener.get_by_id( listener).get_time_frame()]['time'][0] else: time_ = time.time() position = self.__current_positions.get(symbol, None) if position and position.type > 0: order = Order(symbol, ORDER_TYPE_SELL, strategy, listener) order.volume_initial = position.volume order.time_setup = int(time_) order.time_setup_msc = int((time_ - int(time_)) * (10**6)) # TODO 这里应该要支持事务性的下单操作 self.send_order(order) if volume == 0: return order = Order(symbol, ORDER_TYPE_SELL, strategy, listener) order.volume_initial = volume order.time_setup = int(time_) order.time_setup_msc = int((time_ - int(time_)) * (10**6)) return self.send_order(order)
def cover(self, symbol, volume=1, price=None, stop=False, limit=False, strategy=None, listener=None): if volume == 0: return position = self.__current_positions.get(symbol,None) order = Order(symbol, ORDER_TYPE_BUY, strategy, listener) if not position or position.type >= 0: return#XXX可能的返回值 order.volume_initial = volume if self.__backtesting: time_ = self.__datas[symbol][SymbolsListener.get_by_id(listener).get_time_frame()]['time'][0] else: time_ = time.time() order.time_setup = int(time_) order.time_setup_msc = int((time_ - int(time_))*(10**6)) return(self.send_order(order))
def __send_order_to_broker(self,order): if self.__backtesting: time_frame = SymbolsListener.get_by_id(order.handle).get_time_frame() time_ = self.__datas[order.symbol][time_frame]["time"][0] order.time_done = int(time_) order.time_done_msc = int((time_-int(time_))*(10**6)) order.volume_current = order.volume_initial deal = Deal(order.symbol, order.strategy, order.handle) deal.volume = order.volume_current deal.time = order.time_done deal.time_msc = order.time_done_msc deal.type = 1-((order.type&1)<<1) #参见ENUM_ORDER_TYPE和ENUM_DEAL_TYPE的定义 deal.price = self.__datas[order.symbol][time_frame]["close"][0] #TODO加入手续费等 order.deal = deal.get_id() deal.order = order.get_id() return([deal],{}) #TODO 市价单成交 else: pass
def cover(self, symbol, volume=1, price=None, stop=False, limit=False, strategy=None, listener=None): if volume == 0: return position = self.__current_positions.get(symbol, None) order = Order(symbol, ORDER_TYPE_BUY, strategy, listener) if not position or position.type >= 0: return # XXX可能的返回值 order.volume_initial = volume if self.__backtesting: time_ = self.__data[symbol][SymbolsListener.get_by_id( listener).get_time_frame()]['time'][0] else: time_ = time.time() order.time_setup = int(time_) order.time_setup_msc = int((time_ - int(time_)) * (10**6)) return self.send_order(order)
def __send_order_to_broker(self, order): if self.__backtesting: time_frame = SymbolsListener.get_by_id( order.handle).get_time_frame() time_ = self.__data[order.symbol][time_frame]["time"][ 0] + time_frame_to_seconds(time_frame) order.time_done = int(time_) order.time_done_msc = int((time_ - int(time_)) * (10**6)) order.volume_current = order.volume_initial deal = Deal(order.symbol, order.strategy, order.handle) deal.volume = order.volume_current deal.time = order.time_done deal.time_msc = order.time_done_msc deal.type = 1 - ( (order.type & 1) << 1) # 参见ENUM_ORDER_TYPE和ENUM_DEAL_TYPE的定义 deal.price = self.__data[order.symbol][time_frame]["close"][0] # TODO加入手续费等 order.deal = deal.get_id() deal.order = order.get_id() return [deal], {} # TODO 市价单成交 else: pass
def bind_code_to_strategy(self, code): def get_parameter_default(paras, name, check, default, pop=True): if pop: para = paras.pop(name, None) else: para = paras.get(name, None) if para: temp = para.default if temp == inspect._empty: # TODO未给定值的处理 return default elif check(temp): return temp else: raise KeyError("变量%s所赋值不合法", name) else: return default def get_global_attrs(locals_): for name, attr in self.ATTR_MAP.items(): if getattr(self, attr) is None: setattr(self, attr, locals_.get(name)) def set_global_attrs(globals_): for name, attr in self.ATTR_MAP.items(): value = getattr(self, attr) if value is not None: globals_[name] = value else: raise ValueError('全局变量%s未被赋值' % name) signal_locals_ = {} function_locals = {} signal_globals_ = {} # 可动态管理的全策略命名空间 function_globals_ = {} # 可动态管理的系统函数命名空间 # 获取并检查一些全局变量的设定 exec(compile(code, "[Strategy:%s]" % self.name, mode="exec"), signal_globals_, signal_locals_) get_global_attrs(signal_locals_) set_global_attrs(signal_globals_) set_global_attrs(function_globals_) signal_globals_.update(self.__locals_) function_globals_.update(self.__locals_) self.engine.set_capital_base(self.capital_base) self.engine.start_time = self.start_time self.engine.end_time = self.end_time check_time_frame(self.time_frame) # get the system functions in use ast_ = ast.parse(code) sys_func_detector = SystemFunctionsDetector() sys_func_detector.visit(ast_) sys_func_dir = self.user_dir.get_sys_func_dir() funcs_in_use = sys_func_detector.get_funcs_in_use() # get the instructions to inject to every handle signal_instructions = {} function_instructions = {} code_lines = ["import functools", "__globals = globals()"] code_lines.extend([ "{0} = __globals['{0}']".format(key) for key in self.__locals_.keys() if key not in ["sell", "buy", "short", "cover"] ]) for key, value in signal_locals_.items(): if inspect.isfunction(value): if key == "init": self.handlers['init'] = value # TODO init中可以设定全局变量,所以要以"global foo"的方式进行注入,监听的事件不同所以要改写SymbolsListener continue paras = inspect.signature(value).parameters.copy() ishandle = get_parameter_default(paras, "ishandle", lambda x: isinstance(x, bool), True) if not ishandle: continue custom = get_parameter_default(paras, "custom", lambda x: isinstance(x, bool), False) if not custom: # TODO加入真正的验证方法 symbols = get_parameter_default(paras, "symbols", lambda x: True, self.symbols) time_frame = get_parameter_default(paras, "timeframe", check_time_frame, self.time_frame) max_length = get_parameter_default( paras, "maxlen", lambda x: isinstance(x, int) and (x > 0), self.max_length) self.engine.add_symbols(symbols, time_frame, max_length) self.listeners[key] = SymbolsListener( self.engine, symbols, time_frame) additional_instructions = [ "{0} = system_functions['%s.%s'%('{1}','{0}')]".format( f, key) for f in funcs_in_use.keys() ] + ['del(system_functions)'] temp = [] # TODO 加入opens等,这里字典的嵌套结构 temp.extend([ "%s = __globals['data']()['%s']['%s']['%s']" % (field, symbols[0], time_frame, field) for field in ["open", "high", "low", "close", "time", "volume"] ]) temp.extend([ "{0} = __globals['listeners']['{1}'].{0}".format( 'get_current_bar', key) ]) function_instructions[key] = code_lines + temp + ["del(functools)", "del(__globals)"] + \ additional_instructions temp.extend([ "{0} = functools.partial(__globals['{0}'],listener={1})" .format(field, self.listeners[key].get_id()) for field in ["buy", "short", "sell", "cover"] ]) signal_instructions[key] = code_lines + temp + ["del(functools)", "del(__globals)"] + \ additional_instructions else: # TODO自定义事件处理 pass for para_name in paras.keys(): # TODO加入类型检测 default = get_parameter_default(paras, para_name, lambda x: True, None, pop=False) if default is None: raise ValueError('参数%s未指定初始值' % para_name) elif not isinstance(default, (int, float)): raise ValueError('参数%s的值必须为整数或浮点数', para_name) self.listeners[key].add_parameters(para_name, default) series_exporter = SeriesExporter() # deal with the export syntax # export the system functions in use for func, signal in funcs_in_use.items(): fullname = os.path.join(sys_func_dir, func + ".py") with open(fullname) as f: func_ast = ast.parse(f.read()) f.close() function_injector = LocalsInjector( {func: function_instructions[signal]}) function_injector.visit(func_ast) func_ast = series_exporter.visit(func_ast) # TODO 多个handle时需要对每个handle调用的系统函数建立独立的系统函数 exec(compile(func_ast, "[SysFunctions:%s]" % func, mode="exec"), function_globals_, function_locals) self.system_functions['%s.%s' % (signal, func)] = SeriesFunction( function_locals[func], signal) # new方法是对__init__的封装,创建SeriesFunction对象所需信息有其所在的函数体本身,signal和其运行时传入的参数, # 编译时所能确定的只有前者,采用偏函数的方式将两者结合到一起 # inject global vars into locals of handler signal_injector = LocalsInjector(signal_instructions) signal_injector.visit(ast_) ast_ = series_exporter.visit(ast_) # TODO 解决行号的问题 exec(compile(ast_, "[Strategy:%s]" % self.name, mode="exec"), signal_globals_, signal_locals_) for key in signal_instructions.keys(): self.listeners[key].set_generator(signal_locals_[key]) print("<%s>信号添加成功" % self.name) if 'init' in self.handlers: self.handlers['init']() return True