コード例 #1
0
ファイル: backtest.py プロジェクト: ghotiv/Bigfish
 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
コード例 #2
0
 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
コード例 #3
0
ファイル: backtest.py プロジェクト: testmana2/Bigfish
 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
コード例 #4
0
ファイル: backtest.py プロジェクト: ghotiv/Bigfish
 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
コード例 #5
0
ファイル: backtest.py プロジェクト: HandsomeDong/Bigfish
 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
コード例 #6
0
ファイル: backtest.py プロジェクト: tiw-xh138/Bigfish
 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
コード例 #7
0
ファイル: backtest.py プロジェクト: xingetouzi/Bigfish
 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
コード例 #8
0
ファイル: tracebacksignal.py プロジェクト: xingetouzi/Bigfish
 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
コード例 #9
0
ファイル: backtest.py プロジェクト: fagan2888/Bigfish
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)
コード例 #10
0
ファイル: backtest.py プロジェクト: testmana2/Bigfish
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)
コード例 #11
0
ファイル: backtest.py プロジェクト: xingetouzi/Bigfish
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)
コード例 #12
0
ファイル: backtest.py プロジェクト: morrisonwudi/Bigfish
 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()
コード例 #13
0
ファイル: backtest.py プロジェクト: tiw-xh138/Bigfish
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)
コード例 #14
0
ファイル: tracebacksignal.py プロジェクト: xingetouzi/Bigfish
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
コード例 #15
0
ファイル: backtest.py プロジェクト: ghotiv/Bigfish
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)
コード例 #16
0
ファイル: run_time_singal.py プロジェクト: testmana2/Bigfish
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)
コード例 #17
0
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
コード例 #18
0
ファイル: backtest.py プロジェクト: morrisonwudi/Bigfish
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()