Exemple #1
0
 def _init(self, loc):
     init_transformer = InitTransformer()
     init_transformer.visit(self.ast_root)
     # XXX 必须要一个module node作为根节点。
     exec(compile(wrap_with_module(init_transformer.init_node), "[Strategy:%s]" % self.__code.name, mode="exec")
          , dict(open=self.__strategy.open, print=self.__strategy.printer.print, **loc), loc)
     self.__globals.update(Globals(loc["init"](), {}))
Exemple #2
0
 def get_func_within_environment(self, ast_: ast.AST, allow_trading=True, filename=None):
     assert isinstance(ast_, ast.FunctionDef)
     self.set_environment(ast_, allow_trading=allow_trading)
     glb = self.get_globals(allow_trading=allow_trading)
     loc = {}
     if filename is None:
         filename = ast_.name
     exec(compile(wrap_with_module(ast_), filename=filename, mode="exec"), glb, loc)
     return loc[ast_.name]
Exemple #3
0
 def _init(self, loc):
     init_transformer = InitTransformer()
     init_transformer.visit(self.ast_root)
     # XXX 必须要一个module node作为根节点。
     exec(
         compile(wrap_with_module(init_transformer.init_node),
                 "[Strategy:%s]" % self.__code.name,
                 mode="exec"),
         dict(open=self.__strategy.open,
              print=self.__strategy.printer.print,
              **loc), loc)
     self.__globals.update(Globals(loc["init"](), {}))
Exemple #4
0
 def get_func_within_environment(self,
                                 ast_: ast.AST,
                                 allow_trading=True,
                                 filename=None):
     assert isinstance(ast_, ast.FunctionDef)
     self.set_environment(ast_, allow_trading=allow_trading)
     glb = self.get_globals(allow_trading=allow_trading)
     loc = {}
     if filename is None:
         filename = ast_.name
     exec(compile(wrap_with_module(ast_), filename=filename, mode="exec"),
          glb, loc)
     return loc[ast_.name]
Exemple #5
0
    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:
                    pass

        def upper_first_letter(string):
            return string[0].upper() + string[1:]

        # get the system functions in use
        ast_ = ast.parse(code)
        import_inspector = ImportInspector()
        import_inspector.visit(ast_)  # 模块导入检查
        signal_locals_ = {}
        function_locals = {}
        signal_globals_ = {'open': self.open}  # 可动态管理的全策略命名空间,禁用open
        function_globals_ = {'open': self.open}  # 可动态管理的系统函数命名空间,禁用open
        # 获取并检查一些全局变量的设定
        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(signal_locals_)
        signal_globals_.update(self.__glb)
        function_globals_.update(self.__glb)
        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)
        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_to_inject_init = {}
        function_to_inject_init = {}
        signal_to_inject_loop = {}
        function_to_inject_loop = {}
        code_lines = ["import functools", "__globals = globals()"]
        code_lines.extend(["{0} = __globals['{0}']".format(key) for key in self.__glb.keys()
                           if key not in ["Sell", "Buy", "SellShort", "BuyToCover"]])
        # init中可以设定全局变量,所以要以"global foo"的方式进行注入。
        if inspect.isfunction(signal_locals_.get('init', None)):
            init_transformer = InitTransformer()
            init_transformer.visit(ast_)
            # XXX 必须要一个module node作为根节点。
            exec(compile(wrap_with_module(init_transformer.init_node), "[Strategy:%s]" % self.name, mode="exec"),
                 signal_globals_, signal_locals_)
            self.handlers['init'] = signal_locals_['init']
            # 执行init并记录locals,之后注入信号
            init_globals = self.handlers['init']()
            signal_globals_.update(init_globals)
            init_to_inject_init = ["{0} = __globals['{0}']".format(key) for key in init_globals.keys()]
        else:
            init_to_inject_init = []

        for key, value in signal_locals_.items():
            if inspect.isfunction(value):
                if key == "init":
                    continue
                paras = inspect.signature(value).parameters.copy()  # 获取handler函数的参数列表
                is_handle = get_parameter_default(paras, "IsHandle", lambda x: isinstance(x, bool), True)
                if not is_handle:
                    continue
                custom = get_parameter_default(paras, "Custom", lambda x: isinstance(x, bool), False)
                if not custom:
                    # TODO加入真正的验证方法
                    # 转化为tuple是因为symbols要那来当做字典的键
                    symbols = tuple(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_cache_info(symbols, time_frame, max_length)
                    self.signals[key] = self.signal_factory.new(self.engine, self.user, self.name, key, symbols,
                                                                time_frame)
                    additional_instructions = ["{0} = system_functions['%s.%s'%('{1}','{0}')]".format(f, key)
                                               for f, s in funcs_in_use.items() if key in s] + ['del(system_functions)']
                    temp = []
                    # Begin open,high,low,close相关变量的注入
                    quotes = ["open", "high", "low", "close", "datetime", "timestamp", "volume"]
                    temp.extend(["{0} = __globals['Data']['{1}']['{3}']['{2}']"
                                .format(upper_first_letter(field), time_frame, symbols[0], field)
                                 for field in quotes])
                    temp.extend(["{0} = __globals['Data']['{1}']['{3}']['{2}']"
                                .format(field[0].upper(), time_frame, symbols[0], field)
                                 for field in quotes])
                    temp.extend(["{0}s = __globals['Data']['{1}']['{2}']"
                                .format(upper_first_letter(field), time_frame, field)
                                 for field in quotes])
                    # end
                    # get_current_bar 函数的注入,BarNum实际通过该函数维护
                    temp.append("{0} = __globals['signals']['{1}'].{0}".format('get_current_bar', key))
                    temp.append("Symbol = Symbols[0]")  # Symbol注入
                    temp.append("Point=Points[Symbol]")  # Points注入
                    function_to_inject_init[key] = code_lines + temp + ["del(functools)", "del(__globals)"] + \
                                                   additional_instructions
                    temp.extend(["{0} = functools.partial(__globals['{0}'],signal='{1}')".format(
                        field, key)
                                 for field in ["Sell", "Buy", "SellShort", "BuyToCover"]])
                    # TODO 现在是将init中的变量当做局部变量注入每个信号的初始化部分,其实这样并不等同于全局变量的概念,
                    # 只不过对于单个信号的策略是一样的。
                    signal_to_inject_init[key] = code_lines + temp + init_to_inject_init + \
                                                 ["del(functools)", "del(__globals)"] + additional_instructions
                    # 信号与函数中相比多出的就是交易指令
                    signal_to_inject_loop[key] = ["BarNum = get_current_bar()",
                                                  "Pos = Positions[Symbol]",
                                                  "MarketPosition = Pos.type",
                                                  "CurrentContracts= Pos.volume"]
                    function_to_inject_loop[key] = signal_to_inject_loop[key]
                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.signals[key].add_parameters(para_name, default)
        self.__points.update({key: value.point for key, value in self.engine.symbol_pool.items()})
        series_exporter = SeriesExporter()  # deal with the export syntax
        # export the system functions in use
        for func, signals in funcs_in_use.items():
            for signal in signals:
                fullname = os.path.join(sys_func_dir, func + ".py")
                with codecs.open(fullname, "r", "utf-8") as f:
                    func_ast = ast.parse(f.read())
                    f.close()
                import_inspector.visit(func_ast)  # 检查模块导入
                function_injector = LocalsInjector({func: function_to_inject_init[signal]},
                                                   {func: function_to_inject_loop[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_to_inject_init, signal_to_inject_loop)
        signal_injector.visit(ast_)
        ast_ = series_exporter.visit(ast_)
        exec(compile(ast_, "[Strategy:%s]" % self.name, mode="exec"), signal_globals_, signal_locals_)
        for key in signal_to_inject_init.keys():
            self.signals[key].set_generator(signal_locals_[key])
        self.log("<%s>策略添加成功" % self.name, logging.INFO)
        return True
Exemple #6
0
    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)

        def upper_first_letter(string):
            return string[0].upper() + string[1:]

        # get the system functions in use
        ast_ = ast.parse(code)
        import_inspector = ImportInspector()
        import_inspector.visit(ast_)  # 模块导入检查
        signal_locals_ = {}
        function_locals = {}
        signal_globals_ = {'open': self.open}  # 可动态管理的全策略命名空间,禁用open
        function_globals_ = {'open': self.open}  # 可动态管理的系统函数命名空间,禁用open
        # 获取并检查一些全局变量的设定
        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(signal_locals_)
        signal_globals_.update(self.__glb)
        function_globals_.update(self.__glb)
        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)
        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_to_inject_init = {}
        function_to_inject_init = {}
        signal_to_inject_loop = {}
        function_to_inject_loop = {}
        code_lines = ["import functools", "__globals = globals()"]
        code_lines.extend([
            "{0} = __globals['{0}']".format(key) for key in self.__glb.keys()
            if key not in ["Sell", "Buy", "SellShort", "BuyToCover"]
        ])
        # init中可以设定全局变量,所以要以"global foo"的方式进行注入。
        if inspect.isfunction(signal_locals_.get('init', None)):
            init_transformer = InitTransformer()
            init_transformer.visit(ast_)
            # XXX 必须要一个module node作为根节点。
            exec(
                compile(wrap_with_module(init_transformer.init_node),
                        "[Strategy:%s]" % self.name,
                        mode="exec"), signal_globals_, signal_locals_)
            self.handlers['init'] = signal_locals_['init']
            # 执行init并记录locals,之后注入信号
            init_globals = self.handlers['init']()
            signal_globals_.update(init_globals)
            init_to_inject_init = [
                "{0} = __globals['{0}']".format(key)
                for key in init_globals.keys()
            ]
        else:
            init_to_inject_init = []

        for key, value in signal_locals_.items():
            if inspect.isfunction(value):
                if key == "init":
                    continue
                paras = inspect.signature(
                    value).parameters.copy()  # 获取handler函数的参数列表
                is_handle = get_parameter_default(
                    paras, "IsHandle", lambda x: isinstance(x, bool), True)
                if not is_handle:
                    continue
                custom = get_parameter_default(paras, "Custom",
                                               lambda x: isinstance(x, bool),
                                               False)
                if not custom:
                    # TODO加入真正的验证方法
                    # 转化为tuple是为了去掉重复,而且symbols要那来当做字典的键
                    symbols = tuple(
                        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_cache_info(symbols, time_frame, max_length)
                    self.signals[key] = self.signal_factory.new(
                        self.engine, self.user, self.name, key, symbols,
                        time_frame)
                    additional_instructions = [
                        "{0} = system_functions['%s.%s'%('{1}','{0}')]".format(
                            f, key)
                        for f, s in funcs_in_use.items() if key in s
                    ] + ['del(system_functions)']
                    temp = []
                    # Begin open,high,low,close相关变量的注入
                    quotes = [
                        "open", "high", "low", "close", "datetime",
                        "timestamp", "volume"
                    ]
                    temp.extend([
                        "{0} = __globals['Data']['{1}']['{3}']['{2}']".format(
                            upper_first_letter(field), time_frame, symbols[0],
                            field) for field in quotes
                    ])
                    temp.extend([
                        "{0} = __globals['Data']['{1}']['{3}']['{2}']".format(
                            field[0].upper(), time_frame, symbols[0], field)
                        for field in quotes
                    ])
                    temp.extend([
                        "{0}s = __globals['Data']['{1}']['{2}']".format(
                            upper_first_letter(field), time_frame, field)
                        for field in quotes
                    ])
                    # end
                    # get_current_bar 函数的注入,BarNum实际通过该函数维护
                    temp.append("{0} = __globals['signals']['{1}'].{0}".format(
                        'get_current_bar', key))
                    temp.append("Symbol = Symbols[0]")  # Symbol注入
                    temp.append("Point=Points[Symbol]")  # Points注入
                    function_to_inject_init[key] = code_lines + temp + ["del(functools)", "del(__globals)"] + \
                                                   additional_instructions
                    temp.extend([
                        "{0} = functools.partial(__globals['{0}'],signal='{1}')"
                        .format(field, key) for field in
                        ["Sell", "Buy", "SellShort", "BuyToCover"]
                    ])
                    # TODO 现在是将init中的变量当做局部变量注入每个信号的初始化部分,其实这样并不等同于全局变量的概念,
                    # 只不过对于单个信号的策略是一样的。
                    signal_to_inject_init[key] = code_lines + temp + init_to_inject_init + \
                                                 ["del(functools)", "del(__globals)"] + additional_instructions
                    # 信号与函数中相比多出的就是交易指令
                    signal_to_inject_loop[key] = [
                        "BarNum = get_current_bar()",
                        "Pos = Positions[Symbol]", "MarketPosition = Pos.type",
                        "CurrentContracts= Pos.volume"
                    ]
                    function_to_inject_loop[key] = signal_to_inject_loop[key]
                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.signals[key].add_parameters(para_name, default)
        self.__points.update({
            key: value.point
            for key, value in self.engine.symbol_pool.items()
        })
        series_exporter = SeriesExporter()  # deal with the export syntax
        # export the system functions in use
        for func, signals in funcs_in_use.items():
            for signal in signals:
                fullname = os.path.join(sys_func_dir, func + ".py")
                with codecs.open(fullname, "r", "utf-8") as f:
                    func_ast = ast.parse(f.read())
                    f.close()
                import_inspector.visit(func_ast)  # 检查模块导入
                function_injector = LocalsInjector(
                    {func: function_to_inject_init[signal]},
                    {func: function_to_inject_loop[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_to_inject_init,
                                         signal_to_inject_loop)
        signal_injector.visit(ast_)
        ast_ = series_exporter.visit(ast_)
        exec(compile(ast_, "[Strategy:%s]" % self.name, mode="exec"),
             signal_globals_, signal_locals_)
        for key in signal_to_inject_init.keys():
            self.signals[key].set_generator(signal_locals_[key])
        print("<%s>信号添加成功" % self.name)
        return True