Ejemplo n.º 1
0
class CodeParser:
    """
    代码解析器,负责将策略代码拆分成Init,Signal,全局变量定义等部分
    抽取出Signal的局部设置以及语法树
    """
    def __init__(self, code: StrategyCode, strategy: Strategy):
        self.__strategy = strategy
        self.__code = code
        self.__signals_setting = {}
        self.__signals_ast = {}
        self.__ast_root = ast.parse(self.__code.code,
                                    filename="[Strategy:%s]" %
                                    self.__code.name,
                                    mode="exec")
        self.__globals = Globals({}, {})
        self._parse()

    @property
    def ast_root(self) -> ast.AST:
        return self.__ast_root

    @property
    def signals(self) -> list:
        return list(self.__signals_setting.keys())

    @property
    def globals(self) -> Globals:
        return self.__globals

    def get_signal_setting(self, signal) -> SignalLocalSetting:
        return self.__signals_setting[signal]

    def get_signal_ast(self, signal) -> ast.AST:
        return self.__signals_ast[signal]

    @staticmethod
    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

    # TODO 这里最好也使用Environment对象来设置
    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"](), {}))

    def _extract_signal_setting(self, name, func):
        paras = inspect.signature(func).parameters.copy()  # 获取handler函数的参数列表
        is_handle = self._get_parameter_default(paras, "IsHandle",
                                                lambda x: isinstance(x, bool),
                                                True)
        custom = self._get_parameter_default(paras, "Custom",
                                             lambda x: isinstance(x, bool),
                                             False)
        if not is_handle:
            return
        if not custom:
            # TODO加入真正的验证方法
            # 转化为tuple是因为symbols要那来当做字典的键
            symbols = tuple(
                self._get_parameter_default(paras, "Symbols", lambda x: True,
                                            self.__strategy.symbols))
            time_frame = self._get_parameter_default(
                paras, "TimeFrame", check_time_frame,
                self.__strategy.time_frame)
            max_length = self._get_parameter_default(
                paras, "MaxLen", lambda x: isinstance(x, int) and (x > 0),
                None)
            setting = SignalLocalSetting(symbols, time_frame, max_length)
            for para_name in paras.keys():
                # TODO加入类型检测
                default = self._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)
                setting.paras[para_name] = default
            self.__signals_setting[name] = setting

    def _parse(self):
        glb = {}
        loc = {}
        exec(
            compile(self.__code.code,
                    "[Strategy:%s]" % self.__code.name,
                    mode="exec"), glb, loc)
        for key, value in loc.items():
            if inspect.isfunction(value):
                if key == "init":
                    self._init(loc)
                else:
                    self._extract_signal_setting(key, value)
        self.__signals_ast = find_func_in_module(self.signals, self.__ast_root)
        self.__globals.update(
            Globals(
                {
                    key: value
                    for key, value in loc.items() if key not in self.signals
                }, {}))
Ejemplo n.º 2
0
class CodeParser:
    """
    代码解析器,负责将策略代码拆分成Init,Signal,全局变量定义等部分
    抽取出Signal的局部设置以及语法树
    """

    def __init__(self, code: StrategyCode, strategy: Strategy):
        self.__strategy = strategy
        self.__code = code
        self.__signals_setting = {}
        self.__signals_ast = {}
        self.__ast_root = ast.parse(self.__code.code, filename="[Strategy:%s]" % self.__code.name, mode="exec")
        self.__globals = Globals({}, {})
        self._parse()

    @property
    def ast_root(self) -> ast.AST:
        return self.__ast_root

    @property
    def signals(self) -> list:
        return list(self.__signals_setting.keys())

    @property
    def globals(self) -> Globals:
        return self.__globals

    def get_signal_setting(self, signal) -> SignalLocalSetting:
        return self.__signals_setting[signal]

    def get_signal_ast(self, signal) -> ast.AST:
        return self.__signals_ast[signal]

    @staticmethod
    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

    # TODO 这里最好也使用Environment对象来设置
    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"](), {}))

    def _extract_signal_setting(self, name, func):
        paras = inspect.signature(func).parameters.copy()  # 获取handler函数的参数列表
        is_handle = self._get_parameter_default(paras, "IsHandle", lambda x: isinstance(x, bool), True)
        custom = self._get_parameter_default(paras, "Custom", lambda x: isinstance(x, bool), False)
        if not is_handle:
            return
        if not custom:
            # TODO加入真正的验证方法
            # 转化为tuple是因为symbols要那来当做字典的键
            symbols = tuple(
                self._get_parameter_default(paras, "Symbols", lambda x: True, self.__strategy.symbols))
            time_frame = self._get_parameter_default(paras, "TimeFrame", check_time_frame,
                                                     self.__strategy.time_frame)
            max_length = self._get_parameter_default(paras, "MaxLen", lambda x: isinstance(x, int) and (x > 0), None)
            setting = SignalLocalSetting(symbols, time_frame, max_length)
            for para_name in paras.keys():
                # TODO加入类型检测
                default = self._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)
                setting.paras[para_name] = default
            self.__signals_setting[name] = setting

    def _parse(self):
        glb = {}
        loc = {}
        exec(compile(self.__code.code, "[Strategy:%s]" % self.__code.name, mode="exec"), glb, loc)
        for key, value in loc.items():
            if inspect.isfunction(value):
                if key == "init":
                    self._init(loc)
                else:
                    self._extract_signal_setting(key, value)
        self.__signals_ast = find_func_in_module(self.signals, self.__ast_root)
        self.__globals.update(Globals({key: value for key, value in loc.items() if key not in self.signals}, {}))
Ejemplo n.º 3
0
 def get_APIs(self, strategy=None, signal=None, symbols=None, time_frame=None) -> Globals:
     APIs = Globals({}, {})
     APIs.update(self.__account_manager.get_APIs())
     APIs.update(self.__quotation_manager.get_APIs(symbols=symbols, time_frame=time_frame))
     APIs.update(self.__trading_manager.get_APIs(strategy=strategy, signal=signal, symbol=symbols[0]))
     return APIs