def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, data_generator=data_generator): self.__setting = { 'user': user, 'name': name, 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time } self.__strategy_engine = StrategyEngine(is_backtest=True) self.__strategy = Strategy(self.__strategy_engine, user, name, code, symbols, time_frame, start_time, end_time) self.__strategy_parameters = None self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = data_generator(self.__strategy_engine) self.__performance_manager = None self.__thread = None self.__is_alive = False
def init(self): if self.__initialized: return True assert isinstance(self._config, BfConfig) # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = TickDataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH)), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True
def init(self): if self.__initialized: return True bf_config = BfConfig(**self.__config) self.__strategy_engine = StrategyEngine(is_backtest=True, **self.__config) self.__strategy = Strategy(self.__strategy_engine, code=self.__code, logger=self._logger, **self.__config) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = DataGenerator(bf_config, lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH))) self.__initialized = True
def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, data_generator=data_generator): self.__setting = {'user': user, 'name': name, 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time} self.__strategy_engine = StrategyEngine(is_backtest=True) self.__strategy = Strategy(self.__strategy_engine, user, name, code, symbols, time_frame, start_time, end_time) self.__strategy_parameters = None self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = data_generator(self.__strategy_engine) self.__performance_manager = None self.__thread = None self.__is_alive = False
def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, commission=0, slippage=0): self.__config = {'user': user, 'name': name, 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time, 'commission': commission, 'slippage': slippage} self.__strategy_engine = StrategyEngine(is_backtest=True, **self.__config) self.__strategy = Strategy(self.__strategy_engine, user, name, code, symbols, time_frame, start_time, end_time) self.__strategy_parameters = None self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = self.dg_cls(self.__strategy_engine) self.__performance_manager = None self.__thread = None self.__is_alive = False
def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, data_generator=DataGeneratorMongoDB): self.__setting = { 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time } self.__strategy_engine = StrategyEngine(backtesting=True) self.__strategy = Strategy(self.__strategy_engine, user, name, code, symbols, time_frame, start_time, end_time) self.__strategy_parameters = None self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = data_generator(self.__strategy_engine) self.__performance_manager = None self.__performance = None
def init(self): if self.__initialized: return None assert self._config is not None # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = DataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH)), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True
def init(self): if self.__initialized: return True assert isinstance(self._config, BfConfig) # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__rt_data_generator = TickDataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), partial(self.__strategy_engine.put_event, Event(EVENT_FINISH)), parent=self) self.__tb_data_generator = DataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), partial(self.__strategy_engine.put_event, Event(EVENT_EMPTY, message="traceback over")), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True
class Backtesting(LoggerInterface, ConfigInterface): def __init__(self): LoggerInterface.__init__(self) ConfigInterface.__init__(self) self.__code = None self.__strategy = None self.__strategy_engine = None self.__data_generator = None self.__strategy_parameters = None self.__performance_manager = None self.__timer = Timer() self.__is_alive = False self.__initialized = False self.logger_name = "Backtesting" def init(self): if self.__initialized: return None assert self._config is not None # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = DataGenerator( lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH)), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True def set_config(self, config): assert isinstance(config, BfConfig) self._config = config self._config.running_mode = RunningMode.backtest def set_code(self, code): assert isinstance(code, str) self.__code = code.replace('\t', ' ') @property def is_finished(self): return self.__is_alive @property def progress(self): if not self.__is_alive: return 0 et = get_datetime(self._config['end_time']).timestamp() st = get_datetime(self._config['start_time']).timestamp() ct = self.__strategy_engine.current_time if ct: return min((ct - st) / (et - st) * 100, 100) else: return 0 @property def max_margin(self): return self.__strategy_engine.max_margin @profile def start(self, paras=None, refresh=True): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ self.logger.info("<%s>策略运算开始" % self._config['name']) self.init() gc.collect() self.__is_alive = True if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__data_generator.start() if refresh: self.__performance_manager = self.__strategy_engine.wait( self.__get_performance_manager) self.__data_generator.stop() if MEMORY_DEBUG: print('gb:\n%s' % sys.getsizeof(gc.garbage)) # 写日志,计算垃圾占用的内存等 gb_log = {} for gb in gc.garbage: type_ = type(gb) if type_ not in gb_log: gb_log[type_] = 0 gb_log[type_] += sys.getsizeof(gb) print(gb_log) result = self.__performance_manager else: result = self.__strategy_engine.wait() self.logger.info( self.__timer.time("<%s>策略运算完成,耗时:{0}" % self._config['name'])) return result def stop(self): self.__is_alive = False self.__timer.reset() self.__data_generator.stop() self.__strategy_engine.stop() def __get_performance_manager(self): # TODO 加入回测是否运行的判断 if False: raise ValueError('please run the backtest first') return StrategyPerformanceManagerOnline( self.__strategy_engine.profit_records, self.__strategy_engine.deals, self.__strategy_engine.positions) def get_profit_records(self): return self.__strategy_engine.profit_records def get_performance(self): return self.__performance_manager.get_performance() def get_output(self): return self.__strategy.get_output() def get_setting(self): return self._config.to_dict() def time(self, *args): return self.__timer.time(*args)
class Backtesting(LoggerInterface): def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, commission=0, slippage=0): super().__init__() self.__config = {'user': user, 'name': name, 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time, 'commission': commission, 'slippage': slippage} self.__code = code self.__strategy = None self.__strategy_engine = None self.__data_generator = None self.__strategy_parameters = None self._logger = None self.__performance_manager = None self.__timer = Timer() self.__is_alive = False self.__initialized = False def init(self): if self.__initialized: return True bf_config = BfConfig(**self.__config) self.__strategy_engine = StrategyEngine(is_backtest=True, **self.__config) self.__strategy = Strategy(self.__strategy_engine, code=self.__code, logger=self._logger, **self.__config) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = DataGenerator(bf_config, lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH))) self.__initialized = True def set_config(self, **kwargs): self.__config.update(kwargs) def set_logger(self, logger): self._logger = logger @property def is_finished(self): return self.__is_alive @property def progress(self): if not self.__initialized: return 0 et = get_datetime(self.__config['end_time']).timestamp() st = get_datetime(self.__config['start_time']).timestamp() ct = self.__strategy_engine.current_time if ct: return min((ct - st) / (et - st) * 100, 100) else: return 0 @profile def start(self, paras=None, refresh=True): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ if not self.__initialized: self.init() gc.collect() self.__is_alive = True if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__data_generator.start() if refresh: self.__performance_manager = self.__strategy_engine.wait(self.__get_performance_manager) self.__data_generator.stop() if MEMORY_DEBUG: print('gb:\n%s' % sys.getsizeof(gc.garbage)) # 写日志,计算垃圾占用的内存等 gb_log = {} for gb in gc.garbage: type_ = type(gb) if type_ not in gb_log: gb_log[type_] = 0 gb_log[type_] += sys.getsizeof(gb) print(gb_log) result = self.__performance_manager else: result = self.__strategy_engine.wait() self.log(self.__timer.time("策略运算完成,耗时:{0}"), logging.INFO) return result def stop(self): self.__is_alive = False self.__timer.reset() self.__data_generator.stop() self.__strategy_engine.stop() def __get_performance_manager(self): # TODO 加入回测是否运行的判断 if False: raise ValueError('please run the backtest first') return StrategyPerformanceManagerOnline(self.__strategy_engine.get_profit_records(), self.__strategy_engine.get_deals(), self.__strategy_engine.get_positions()) def get_profit_records(self): return self.__strategy_engine.get_profit_records() def get_performance(self): return self.__performance_manager.get_performance() def get_output(self): return self.__strategy.get_output() def get_setting(self): setting = self.__config.copy() setting.pop('user') return setting @staticmethod def get_optimize_goals(): return {'net_profit': '净利'} @staticmethod def get_optimize_types(): return {'enumerate': '枚举', 'genetic': '遗传'} def get_parameters(self): if self.__strategy_parameters is None: temp = self.__strategy.get_parameters() for handle_name in temp.keys(): for para_name, values in temp[handle_name].items(): temp[handle_name][para_name] = {'default': values, 'type': str(type(values))} self.__strategy_parameters = temp return self.__strategy_parameters def _enumerate_optimize(self, ranges, goal, num): stack = [] range_length = [] parameters = {} result = [] head_index = [] def get_range(range_info): return np.arange(range_info['start'], range_info['end'] + range_info['step'], range_info['step']) for handle, paras in ranges.items(): parameters[handle] = {} for para, value in paras.items(): range_value = get_range(value) stack.append({'handle': handle, 'para': para, 'range': range_value}) head_index.append('%s(%s)' % (para, handle)) range_length.append(len(range_value)) n = len(stack) index = [-1] * n head = [0] * n def set_paras(n, handle=None, para=None, range=None): nonlocal parameters, head, index parameters[handle][para] = head[n] = range[index[n]] i = 0 finished = False while 1: index[i] += 1 while index[i] >= range_length[i]: if i == 0: finished = True break index[i] = -1 i -= 1 index[i] += 1 if finished: break set_paras(i, **stack[i]) if i == n - 1: performance_manager = self.start(parameters, refresh=False) head = pd.Series(head, index=head_index) optimize_info = performance_manager.get_performance().optimize_info.copy() target = optimize_info[goal] del optimize_info[goal] result.append(pd.concat([head, pd.Series([target], index=[goal]), optimize_info])) else: i += 1 self.__data_generator.stop() # 释放数据资源 output = pd.DataFrame(result).sort_values(goal, ascending=False) result.clear() # 释放资源 output.index.name = '_' output = output.iloc[:num] return output def _genetic_optimize(self, ranges, goal): pass def optimize(self, ranges, type, goal, num=50): if not ranges: return if type is None: type = "enumerate" # TODO 不要使用硬编码 if goal is None: goal = "净利($)" goal = "净利($)" optimizer = getattr(self, '_%s_optimize' % type) return optimizer(ranges, goal, num) def time(self, *args): return self.__timer.time(*args)
class Backtesting(LoggerInterface, ConfigInterface): def __init__(self): LoggerInterface.__init__(self) ConfigInterface.__init__(self) self.__code = None self.__strategy = None self.__strategy_engine = None self.__data_generator = None self.__strategy_parameters = None self.__performance_manager = None self.__timer = Timer() self.__is_alive = False self.__initialized = False self.logger_name = "Backtesting" def init(self): if self.__initialized: return None assert self._config is not None # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = DataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH)), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True def set_config(self, config): assert isinstance(config, BfConfig) self._config = config self._config.running_mode = RunningMode.backtest def set_code(self, code): assert isinstance(code, str) self.__code = code.replace('\t', ' ') @property def is_finished(self): return self.__is_alive @property def progress(self): if not self.__is_alive: return 0 et = get_datetime(self._config['end_time']).timestamp() st = get_datetime(self._config['start_time']).timestamp() ct = self.__strategy_engine.current_time if ct: return min((ct - st) / (et - st) * 100, 100) else: return 0 @property def max_margin(self): return self.__strategy_engine.max_margin @profile def start(self, paras=None, refresh=True): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ self.logger.info("<%s>策略运算开始" % self._config['name']) self.init() gc.collect() self.__is_alive = True if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__data_generator.start() if refresh: self.__performance_manager = self.__strategy_engine.wait(self.__get_performance_manager) self.__data_generator.stop() if MEMORY_DEBUG: print('gb:\n%s' % sys.getsizeof(gc.garbage)) # 写日志,计算垃圾占用的内存等 gb_log = {} for gb in gc.garbage: type_ = type(gb) if type_ not in gb_log: gb_log[type_] = 0 gb_log[type_] += sys.getsizeof(gb) print(gb_log) result = self.__performance_manager else: result = self.__strategy_engine.wait() self.logger.info(self.__timer.time("<%s>策略运算完成,耗时:{0}" % self._config['name'])) return result def stop(self): self.__is_alive = False self.__timer.reset() self.__data_generator.stop() self.__strategy_engine.stop() def __get_performance_manager(self): # TODO 加入回测是否运行的判断 if False: raise ValueError('please run the backtest first') return StrategyPerformanceManagerOnline(self.__strategy_engine.profit_records, self.__strategy_engine.deals, self.__strategy_engine.positions) def get_profit_records(self): return self.__strategy_engine.profit_records def get_performance(self): return self.__performance_manager.get_performance() def get_output(self): return self.__strategy.get_output() def get_setting(self): return self._config.to_dict() def time(self, *args): return self.__timer.time(*args)
def __init__(self, id_, name, code): self.strategy_engine = StrategyEngine(backtesting=True) self.strategy = Strategy(self.strategy_engine, id_, name, code) self.strategy_engine.add_strategy(self.strategy) self.data_generator = DataGeneratorTushare(self.strategy_engine) self.strategy_engine.initialize()
class Backtesting: def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, data_generator=DataGeneratorMongoDB): self.__setting = { 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time } self.__strategy_engine = StrategyEngine(backtesting=True) self.__strategy = Strategy(self.__strategy_engine, user, name, code, symbols, time_frame, start_time, end_time) self.__strategy_parameters = None self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = data_generator(self.__strategy_engine) self.__performance_manager = None self.__performance = None def initialize(self): self.__strategy_engine.initialize() def start(self, paras=None, refresh=True): if paras is not None: self.__strategy.set_parameters(paras) self.initialize() self.__strategy_engine.start() self.__data_generator.start() self.__strategy_engine.wait() if refresh: self.__performance_manager = self.__get_performance_manager() def __get_performance_manager(self): # TODO 加入回测是否运行的判断 if False: raise ValueError('please run the backtest first') return StrategyPerformanceManagerOffline( self.__data_generator.get_dataframe(), self.__strategy_engine.get_deals(), self.__strategy_engine.get_positions()) def get_profit_records(self): return self.__strategy_engine.get_profit_records() def get_performance(self): return self.__performance_manager.get_performance() def get_output(self): return self.__strategy.get_output() def get_setting(self): return self.__setting @staticmethod def get_optimize_goals(): return {'net_profit': '净利'} @staticmethod def get_optimize_types(): return {'enumerate': '枚举', 'genetic': '遗传'} def get_parameters(self): if self.__strategy_parameters is None: temp = self.__strategy.get_parameters() for handle_name in temp.keys(): for para_name, values in temp[handle_name].items(): temp[handle_name][para_name] = { 'default': values, 'type': str(type(values)) } self.__strategy_parameters = temp return self.__strategy_parameters def _enumerate_optimize(self, ranges, goal, num): stack = [] range_length = [] parameters = {} result = [] head_index = [] def get_range(range_info): return np.arange(range_info['start'], range_info['end'] + range_info['step'], range_info['step']) for handle, paras in ranges.items(): parameters[handle] = {} for para, value in paras.items(): range_value = get_range(value) stack.append({ 'handle': handle, 'para': para, 'range': range_value }) head_index.append('%s(%s)' % (para, handle)) range_length.append(len(range_value)) n = len(stack) index = [-1] * n head = [0] * n def set_paras(n, handle=None, para=None, range=None): nonlocal parameters, head, index parameters[handle][para] = head[n] = range[index[n]] i = 0 finished = False while 1: index[i] += 1 while index[i] >= range_length[i]: if i == 0: finished = True break index[i] = -1 i -= 1 index[i] += 1 if finished: break set_paras(i, **stack[i]) if i == n - 1: self.start(parameters, refresh=False) head = pd.Series(head, index=head_index) performance_manager = self.__get_performance_manager() optimize_info = performance_manager.get_performance( ).optimize_info.copy() target = optimize_info[goal] del optimize_info[goal] result.append( pd.concat([ head, pd.Series([target], index=[goal]), optimize_info ])) else: i += 1 result = pd.DataFrame(result).sort_values(goal, ascending=False) result.index.name = '_' return result.iloc[:num] def _genetic_optimize(self, ranges, goal): pass def optimize(self, ranges, type, goal, num=50): if not ranges: return if type is None: type = "enumerate" # TODO 不要使用硬编码 if goal is None: goal = "净利($)" goal = "净利($)" optimizer = getattr(self, '_%s_optimize' % type) return optimizer(ranges, goal, num)
class TracebackSignal(LoggerInterface, ConfigInterface, Runnable): def __init__(self): LoggerInterface.__init__(self) ConfigInterface.__init__(self) Runnable.__init__(self) self.__code = None self.__strategy = None self.__strategy_engine = None self.__tb_data_generator = None self.__rt_data_generator = None self.__strategy_parameters = None self.__initialized = False self.logger_name = 'RuntimeSignal' def init(self): if self.__initialized: return True assert isinstance(self._config, BfConfig) # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__rt_data_generator = TickDataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), partial(self.__strategy_engine.put_event, Event(EVENT_FINISH)), parent=self) self.__tb_data_generator = DataGenerator(lambda x: self.__strategy_engine.put_event(x.to_event()), partial(self.__strategy_engine.put_event, Event(EVENT_EMPTY, message="traceback over")), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True def set_config(self, config): assert isinstance(config, BfConfig) self._config = config self._config.allow_trading = False self._config.running_mode = RunningMode.traceback @property def code(self): return self.__code @code.setter def code(self, value): assert isinstance(value, str) self.__code = value.replace('\t', ' ') def register_event(self, event_type, func): if self.__initialized: self.__strategy_engine.register_event(event_type, func) else: self.logger.warning("无效的事件注册,原因:未初始化") @property def is_finished(self): return self.__is_alive def _start(self, paras=None): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ try: self.logger.info("<%s>策略回溯运算开始" % self._config["name"]) if not self.__initialized: self.init() if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__tb_data_generator.start() self.__strategy_engine.register_event(EVENT_EMPTY, self._change_trading_mode) self.__strategy_engine.wait() except: self.logger.error("\n" + traceback.format_exc()) self.stop() def _change_trading_mode(self, event): if event.content["message"] == "traceback over": try: self.logger.info("<%s>策略回溯运算停止" % self._config["name"]) self._config.allow_trading = True self.logger.info("<%s>策略实时运算开始" % self._config["name"]) self.__rt_data_generator.start() except: self.logger.error("\n" + traceback.format_exc()) self.stop() def _stop(self): self.logger.info("<%s>策略实时运算停止" % self._config["name"]) self.__tb_data_generator.stop() self.__rt_data_generator.stop() self.__strategy_engine.stop() def get_output(self): return self.__strategy.get_output() def get_setting(self): return self._config.to_dict() def get_parameters(self): if self.__strategy_parameters is None: temp = self.__strategy.get_parameters() for handle_name in temp.keys(): for para_name, values in temp[handle_name].items(): temp[handle_name][para_name] = {'default': values, 'type': str(type(values))} self.__strategy_parameters = temp return self.__strategy_parameters
class Backtesting: def __init__(self, user, name, code, symbols=None, time_frame=None, start_time=None, end_time=None, data_generator=data_generator): self.__setting = { 'user': user, 'name': name, 'symbols': symbols, 'time_frame': time_frame, 'start_time': start_time, 'end_time': end_time } self.__strategy_engine = StrategyEngine(is_backtest=True) self.__strategy = Strategy(self.__strategy_engine, user, name, code, symbols, time_frame, start_time, end_time) self.__strategy_parameters = None self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = data_generator(self.__strategy_engine) self.__performance_manager = None self.__thread = None self.__is_alive = False @property def is_finished(self): return self.__is_alive @property def progress(self): et = get_datetime(self.__setting['end_time']).timestamp() st = get_datetime(self.__setting['start_time']).timestamp() ct = self.__strategy_engine.current_time if ct: return min((ct - st) / (et - st) * 100, 100) else: return 0 @profile def start(self, paras=None, refresh=True): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ gc.collect() self.__is_alive = True if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__data_generator.start(**self.__setting) if refresh: self.__performance_manager = self.__strategy_engine.wait( self.__get_performance_manager) self.__data_generator.stop() if MEMORY_DEBUG: print('gb:\n%s' % sys.getsizeof(gc.garbage)) # 写日志,计算垃圾占用的内存等 gb_log = {} for gb in gc.garbage: type_ = type(gb) if type_ not in gb_log: gb_log[type_] = 0 gb_log[type_] += sys.getsizeof(gb) print(gb_log) return self.__performance_manager else: return self.__strategy_engine.wait(self.__get_performance_manager) def stop(self): self.__is_alive = False self.__data_generator.stop() self.__strategy_engine.stop() def __get_performance_manager(self): # TODO 加入回测是否运行的判断 if False: raise ValueError('please run the backtest first') return StrategyPerformanceManagerOffline( self.__data_generator.get_dataframe(), self.__strategy_engine.get_deals(), self.__strategy_engine.get_positions(), self.__strategy_engine.symbol_pool) def get_profit_records(self): return self.__strategy_engine.get_profit_records() def get_performance(self): return self.__performance_manager.get_performance() def get_output(self): return self.__strategy.get_output() def get_setting(self): setting = self.__setting.copy() setting.pop('user') return setting @staticmethod def get_optimize_goals(): return {'net_profit': '净利'} @staticmethod def get_optimize_types(): return {'enumerate': '枚举', 'genetic': '遗传'} def get_parameters(self): if self.__strategy_parameters is None: temp = self.__strategy.get_parameters() for handle_name in temp.keys(): for para_name, values in temp[handle_name].items(): temp[handle_name][para_name] = { 'default': values, 'type': str(type(values)) } self.__strategy_parameters = temp return self.__strategy_parameters def _enumerate_optimize(self, ranges, goal, num): stack = [] range_length = [] parameters = {} result = [] head_index = [] def get_range(range_info): return np.arange(range_info['start'], range_info['end'] + range_info['step'], range_info['step']) for handle, paras in ranges.items(): parameters[handle] = {} for para, value in paras.items(): range_value = get_range(value) stack.append({ 'handle': handle, 'para': para, 'range': range_value }) head_index.append('%s(%s)' % (para, handle)) range_length.append(len(range_value)) n = len(stack) index = [-1] * n head = [0] * n def set_paras(n, handle=None, para=None, range=None): nonlocal parameters, head, index parameters[handle][para] = head[n] = range[index[n]] i = 0 finished = False while 1: index[i] += 1 while index[i] >= range_length[i]: if i == 0: finished = True break index[i] = -1 i -= 1 index[i] += 1 if finished: break set_paras(i, **stack[i]) if i == n - 1: performance_manager = self.start(parameters, refresh=False) head = pd.Series(head, index=head_index) optimize_info = performance_manager.get_performance( ).optimize_info.copy() target = optimize_info[goal] del optimize_info[goal] result.append( pd.concat([ head, pd.Series([target], index=[goal]), optimize_info ])) else: i += 1 self.__data_generator.stop() # 释放数据资源 output = pd.DataFrame(result).sort_values(goal, ascending=False) result.clear() # 释放资源 output.index.name = '_' output = output.iloc[:num] return output def _genetic_optimize(self, ranges, goal): pass def optimize(self, ranges, type, goal, num=50): if not ranges: return if type is None: type = "enumerate" # TODO 不要使用硬编码 if goal is None: goal = "净利($)" goal = "净利($)" optimizer = getattr(self, '_%s_optimize' % type) return optimizer(ranges, goal, num)
class RuntimeSignal(LoggerInterface): def __init__(self): super().__init__() self.__config = {} self.__code = None self.__strategy = None self.__strategy_engine = None self.__data_generator = None self.__strategy_parameters = None self._logger = None self.__performance_manager = None self.__timer = Timer() self._login = False self.__is_alive = False self.__initialized = False def init(self): if self.__initialized: return True bf_config = BfConfig(**self.__config) self.__strategy_engine = StrategyEngine(is_backtest=False, **self.__config) self.__strategy = Strategy(self.__strategy_engine, code=self.__code, logger=self._logger, **self.__config) self.__strategy_engine.add_strategy(self.__strategy) self.__data_generator = TickDataGenerator(bf_config, lambda x: self.__strategy_engine.put_event(x.to_event()), lambda: self.__strategy_engine.put_event(Event(EVENT_FINISH))) self.__initialized = True def set_config(self, **kwargs): self.__config.update(kwargs) def login(self): if not self._login: self._login = False def set_logger(self, logger): self._logger = logger @property def code(self): return self.__code @code.setter def code(self, code): if self.__code is None: self.__code = code @property def is_finished(self): return self.__is_alive @profile def start(self, paras=None, refresh=True): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ try: if not self.__initialized: self.init() gc.collect() self.__is_alive = True if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__data_generator.start() if refresh: self.__performance_manager = self.__strategy_engine.wait(self.__get_performance_manager) self.__data_generator.stop() if MEMORY_DEBUG: print('gb:\n%s' % sys.getsizeof(gc.garbage)) # 写日志,计算垃圾占用的内存等 gb_log = {} for gb in gc.garbage: type_ = type(gb) if type_ not in gb_log: gb_log[type_] = 0 gb_log[type_] += sys.getsizeof(gb) print(gb_log) result = self.__performance_manager else: result = self.__strategy_engine.wait() self.log(self.__timer.time("策略运算完成,耗时:{0}"), logging.INFO) return result except Exception as e: self.stop() raise e def stop(self): self.__is_alive = False self.__timer.reset() self.__data_generator.stop() self.__strategy_engine.stop() def __get_performance_manager(self): # TODO 加入回测是否运行的判断 if False: raise ValueError('please run the backtest first') return StrategyPerformanceManagerOnline(self.__strategy_engine.get_profit_records(), self.__strategy_engine.get_deals(), self.__strategy_engine.get_positions()) def get_profit_records(self): return self.__strategy_engine.get_profit_records() def get_performance(self): return self.__performance_manager.get_performance() def get_output(self): return self.__strategy.get_output() def get_setting(self): setting = self.__config.copy() return setting def get_parameters(self): if self.__strategy_parameters is None: temp = self.__strategy.get_parameters() for handle_name in temp.keys(): for para_name, values in temp[handle_name].items(): temp[handle_name][para_name] = {'default': values, 'type': str(type(values))} self.__strategy_parameters = temp return self.__strategy_parameters def time(self, *args): return self.__timer.time(*args)
class TracebackSignal(LoggerInterface, ConfigInterface, Runnable): def __init__(self): LoggerInterface.__init__(self) ConfigInterface.__init__(self) Runnable.__init__(self) self.__code = None self.__strategy = None self.__strategy_engine = None self.__tb_data_generator = None self.__rt_data_generator = None self.__strategy_parameters = None self.__initialized = False self.logger_name = 'RuntimeSignal' def init(self): if self.__initialized: return True assert isinstance(self._config, BfConfig) # 判断初始化前是否设置好了基本参数 self.__strategy_engine = StrategyEngine(parent=self) self.__strategy = Strategy(self.__strategy_engine, self.__code, parent=self) self.__strategy_engine.add_strategy(self.__strategy) self.__rt_data_generator = TickDataGenerator( lambda x: self.__strategy_engine.put_event(x.to_event()), partial(self.__strategy_engine.put_event, Event(EVENT_FINISH)), parent=self) self.__tb_data_generator = DataGenerator( lambda x: self.__strategy_engine.put_event(x.to_event()), partial(self.__strategy_engine.put_event, Event(EVENT_EMPTY, message="traceback over")), parent=self) if DEBUG: self.logger.setLevel(logging.DEBUG) else: self.logger.setLevel(logging.INFO) self.__initialized = True def set_config(self, config): assert isinstance(config, BfConfig) self._config = config self._config.allow_trading = False self._config.running_mode = RunningMode.traceback @property def code(self): return self.__code @code.setter def code(self, value): assert isinstance(value, str) self.__code = value.replace('\t', ' ') def register_event(self, event_type, func): if self.__initialized: self.__strategy_engine.register_event(event_type, func) else: self.logger.warning("无效的事件注册,原因:未初始化") @property def is_finished(self): return self.__is_alive def _start(self, paras=None): """ :param paras: :param refresh: True表示刷新绩效且需要释放资源,即用户一个完整的请求已经结束;False的情况主要是参数优化时批量运行回测。 """ try: self.logger.info("<%s>策略回溯运算开始" % self._config["name"]) if not self.__initialized: self.init() if paras is not None: self.__strategy.set_parameters(paras) self.__strategy_engine.start() self.__tb_data_generator.start() self.__strategy_engine.register_event(EVENT_EMPTY, self._change_trading_mode) self.__strategy_engine.wait() except: self.logger.error("\n" + traceback.format_exc()) self.stop() def _change_trading_mode(self, event): if event.content["message"] == "traceback over": try: self.logger.info("<%s>策略回溯运算停止" % self._config["name"]) self._config.allow_trading = True self.logger.info("<%s>策略实时运算开始" % self._config["name"]) self.__rt_data_generator.start() except: self.logger.error("\n" + traceback.format_exc()) self.stop() def _stop(self): self.logger.info("<%s>策略实时运算停止" % self._config["name"]) self.__tb_data_generator.stop() self.__rt_data_generator.stop() self.__strategy_engine.stop() def get_output(self): return self.__strategy.get_output() def get_setting(self): return self._config.to_dict() def get_parameters(self): if self.__strategy_parameters is None: temp = self.__strategy.get_parameters() for handle_name in temp.keys(): for para_name, values in temp[handle_name].items(): temp[handle_name][para_name] = { 'default': values, 'type': str(type(values)) } self.__strategy_parameters = temp return self.__strategy_parameters
class Backtesting: def __init__(self, id_, name, code): self.strategy_engine = StrategyEngine(backtesting=True) self.strategy = Strategy(self.strategy_engine, id_, name, code) self.strategy_engine.add_strategy(self.strategy) self.data_generator = DataGeneratorTushare(self.strategy_engine) self.strategy_engine.initialize() def start(self): self.strategy_engine.start() self.data_generator.start() self.strategy_engine.wait() def get_profit_records(self): return(self.strategy_engine.get_profit_records()) def stop(self): self.strategy_engine.stop()