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 }, {}))
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}, {}))
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