Пример #1
0
def test_print_epoch_details(capsys):
    test_result = {
        'params_details': {
            'trailing': {
                'trailing_stop': True,
                'trailing_stop_positive': 0.02,
                'trailing_stop_positive_offset': 0.04,
                'trailing_only_offset_is_reached': True
            },
            'roi': {
                0: 0.18,
                90: 0.14,
                225: 0.05,
                430: 0},
        },
        'results_explanation': 'foo result',
        'is_initial_point': False,
        'total_profit': 0,
        'current_epoch': 2,  # This starts from 1 (in a human-friendly manner)
        'is_best': True
    }

    HyperoptTools.print_epoch_details(test_result, 5, False, no_header=True)
    captured = capsys.readouterr()
    assert '# Trailing stop:' in captured.out
    # re.match(r"Pairs for .*", captured.out)
    assert re.search(r'^\s+trailing_stop = True$', captured.out, re.MULTILINE)
    assert re.search(r'^\s+trailing_stop_positive = 0.02$', captured.out, re.MULTILINE)
    assert re.search(r'^\s+trailing_stop_positive_offset = 0.04$', captured.out, re.MULTILINE)
    assert re.search(r'^\s+trailing_only_offset_is_reached = True$', captured.out, re.MULTILINE)

    assert '# ROI table:' in captured.out
    assert re.search(r'^\s+minimal_roi = \{$', captured.out, re.MULTILINE)
    assert re.search(r'^\s+\"90\"\:\s0.14,\s*$', captured.out, re.MULTILINE)
Пример #2
0
    def start(self) -> None:
        self.random_state = self._set_random_state(
            self.config.get('hyperopt_random_state', None))
        logger.info(f"Using optimizer random state: {self.random_state}")
        self.hyperopt_table_header = -1
        # Initialize spaces ...
        self.init_spaces()
        data, timerange = self.backtesting.load_bt_data()
        logger.info("Dataload complete. Calculating indicators")
        preprocessed = self.backtesting.strategy.ohlcvdata_to_dataframe(data)

        # Trim startup period from analyzed dataframe
        for pair, df in preprocessed.items():
            preprocessed[pair] = trim_dataframe(
                df,
                timerange,
                startup_candles=self.backtesting.required_startup)
        self.min_date, self.max_date = get_timerange(preprocessed)

        logger.info(
            f'Hyperopting with data from {self.min_date.strftime(DATETIME_PRINT_FORMAT)} '
            f'up to {self.max_date.strftime(DATETIME_PRINT_FORMAT)} '
            f'({(self.max_date - self.min_date).days} days)..')

        dump(preprocessed, self.data_pickle_file)

        # We don't need exchange instance anymore while running hyperopt
        self.backtesting.exchange.close()
        self.backtesting.exchange._api = None  # type: ignore
        self.backtesting.exchange._api_async = None  # type: ignore
        # self.backtesting.exchange = None  # type: ignore
        self.backtesting.pairlists = None  # type: ignore

        cpus = cpu_count()
        logger.info(f"Found {cpus} CPU cores. Let's make them scream!")
        config_jobs = self.config.get('hyperopt_jobs', -1)
        logger.info(f'Number of parallel jobs set as: {config_jobs}')

        self.opt = self.get_optimizer(self.dimensions, config_jobs)

        if self.print_colorized:
            colorama_init(autoreset=True)

        try:
            with Parallel(n_jobs=config_jobs) as parallel:
                jobs = parallel._effective_n_jobs()
                logger.info(
                    f'Effective number of parallel workers used: {jobs}')

                # Define progressbar
                if self.print_colorized:
                    widgets = [
                        ' [Epoch ',
                        progressbar.Counter(),
                        ' of ',
                        str(self.total_epochs),
                        ' (',
                        progressbar.Percentage(),
                        ')] ',
                        progressbar.Bar(marker=progressbar.AnimatedMarker(
                            fill='\N{FULL BLOCK}',
                            fill_wrap=Fore.GREEN + '{}' + Fore.RESET,
                            marker_wrap=Style.BRIGHT + '{}' + Style.RESET_ALL,
                        )),
                        ' [',
                        progressbar.ETA(),
                        ', ',
                        progressbar.Timer(),
                        ']',
                    ]
                else:
                    widgets = [
                        ' [Epoch ',
                        progressbar.Counter(),
                        ' of ',
                        str(self.total_epochs),
                        ' (',
                        progressbar.Percentage(),
                        ')] ',
                        progressbar.Bar(marker=progressbar.AnimatedMarker(
                            fill='\N{FULL BLOCK}', )),
                        ' [',
                        progressbar.ETA(),
                        ', ',
                        progressbar.Timer(),
                        ']',
                    ]
                with progressbar.ProgressBar(max_value=self.total_epochs,
                                             redirect_stdout=False,
                                             redirect_stderr=False,
                                             widgets=widgets) as pbar:
                    EVALS = ceil(self.total_epochs / jobs)
                    for i in range(EVALS):
                        # Correct the number of epochs to be processed for the last
                        # iteration (should not exceed self.total_epochs in total)
                        n_rest = (i + 1) * jobs - self.total_epochs
                        current_jobs = jobs - n_rest if n_rest > 0 else jobs

                        asked = self.opt.ask(n_points=current_jobs)
                        f_val = self.run_optimizer_parallel(parallel, asked, i)
                        self.opt.tell(asked, [v['loss'] for v in f_val])

                        # Calculate progressbar outputs
                        for j, val in enumerate(f_val):
                            # Use human-friendly indexes here (starting from 1)
                            current = i * jobs + j + 1
                            val['current_epoch'] = current
                            val['is_initial_point'] = current <= INITIAL_POINTS

                            logger.debug(f"Optimizer epoch evaluated: {val}")

                            is_best = HyperoptTools.is_best_loss(
                                val, self.current_best_loss)
                            # This value is assigned here and not in the optimization method
                            # to keep proper order in the list of results. That's because
                            # evaluations can take different time. Here they are aligned in the
                            # order they will be shown to the user.
                            val['is_best'] = is_best
                            self.print_results(val)

                            if is_best:
                                self.current_best_loss = val['loss']
                            self.epochs.append(val)

                            # Save results after each best epoch and every 100 epochs
                            if is_best or current % 100 == 0:
                                self._save_results()

                            pbar.update(current)

        except KeyboardInterrupt:
            print('User interrupted..')

        self._save_results()
        logger.info(
            f"{self.num_epochs_saved} {plural(self.num_epochs_saved, 'epoch')} "
            f"saved to '{self.results_file}'.")

        if self.epochs:
            sorted_epochs = sorted(self.epochs, key=itemgetter('loss'))
            best_epoch = sorted_epochs[0]
            HyperoptTools.print_epoch_details(best_epoch, self.total_epochs,
                                              self.print_json)
        else:
            # This is printed when Ctrl+C is pressed quickly, before first epochs have
            # a chance to be evaluated.
            print("No epochs evaluated yet, no best result.")
Пример #3
0
def start_hyperopt_show(args: Dict[str, Any]) -> None:
    """
    Show details of a hyperopt epoch previously evaluated
    """
    from freqtrade.optimize.hyperopt_tools import HyperoptTools

    config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)

    print_json = config.get('print_json', False)
    no_header = config.get('hyperopt_show_no_header', False)
    results_file = get_latest_hyperopt_file(
        config['user_data_dir'] / 'hyperopt_results',
        config.get('hyperoptexportfilename'))

    n = config.get('hyperopt_show_index', -1)

    filteroptions = {
        'only_best':
        config.get('hyperopt_list_best', False),
        'only_profitable':
        config.get('hyperopt_list_profitable', False),
        'filter_min_trades':
        config.get('hyperopt_list_min_trades', 0),
        'filter_max_trades':
        config.get('hyperopt_list_max_trades', 0),
        'filter_min_avg_time':
        config.get('hyperopt_list_min_avg_time', None),
        'filter_max_avg_time':
        config.get('hyperopt_list_max_avg_time', None),
        'filter_min_avg_profit':
        config.get('hyperopt_list_min_avg_profit', None),
        'filter_max_avg_profit':
        config.get('hyperopt_list_max_avg_profit', None),
        'filter_min_total_profit':
        config.get('hyperopt_list_min_total_profit', None),
        'filter_max_total_profit':
        config.get('hyperopt_list_max_total_profit', None),
        'filter_min_objective':
        config.get('hyperopt_list_min_objective', None),
        'filter_max_objective':
        config.get('hyperopt_list_max_objective', None)
    }

    # Previous evaluations
    epochs = HyperoptTools.load_previous_results(results_file)
    total_epochs = len(epochs)

    epochs = hyperopt_filter_epochs(epochs, filteroptions)
    filtered_epochs = len(epochs)

    if n > filtered_epochs:
        raise OperationalException(
            f"The index of the epoch to show should be less than {filtered_epochs + 1}."
        )
    if n < -filtered_epochs:
        raise OperationalException(
            f"The index of the epoch to show should be greater than {-filtered_epochs - 1}."
        )

    # Translate epoch index from human-readable format to pythonic
    if n > 0:
        n -= 1

    if epochs:
        val = epochs[n]
        HyperoptTools.print_epoch_details(val,
                                          total_epochs,
                                          print_json,
                                          no_header,
                                          header_str="Epoch details")
Пример #4
0
def start_hyperopt_list(args: Dict[str, Any]) -> None:
    """
    List hyperopt epochs previously evaluated
    """
    from freqtrade.optimize.hyperopt_tools import HyperoptTools

    config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)

    print_colorized = config.get('print_colorized', False)
    print_json = config.get('print_json', False)
    export_csv = config.get('export_csv', None)
    no_details = config.get('hyperopt_list_no_details', False)
    no_header = False

    filteroptions = {
        'only_best':
        config.get('hyperopt_list_best', False),
        'only_profitable':
        config.get('hyperopt_list_profitable', False),
        'filter_min_trades':
        config.get('hyperopt_list_min_trades', 0),
        'filter_max_trades':
        config.get('hyperopt_list_max_trades', 0),
        'filter_min_avg_time':
        config.get('hyperopt_list_min_avg_time', None),
        'filter_max_avg_time':
        config.get('hyperopt_list_max_avg_time', None),
        'filter_min_avg_profit':
        config.get('hyperopt_list_min_avg_profit', None),
        'filter_max_avg_profit':
        config.get('hyperopt_list_max_avg_profit', None),
        'filter_min_total_profit':
        config.get('hyperopt_list_min_total_profit', None),
        'filter_max_total_profit':
        config.get('hyperopt_list_max_total_profit', None),
        'filter_min_objective':
        config.get('hyperopt_list_min_objective', None),
        'filter_max_objective':
        config.get('hyperopt_list_max_objective', None),
    }

    results_file = get_latest_hyperopt_file(
        config['user_data_dir'] / 'hyperopt_results',
        config.get('hyperoptexportfilename'))

    # Previous evaluations
    epochs = HyperoptTools.load_previous_results(results_file)
    total_epochs = len(epochs)

    epochs = hyperopt_filter_epochs(epochs, filteroptions)

    if print_colorized:
        colorama_init(autoreset=True)

    if not export_csv:
        try:
            print(
                HyperoptTools.get_result_table(config, epochs, total_epochs,
                                               not filteroptions['only_best'],
                                               print_colorized, 0))
        except KeyboardInterrupt:
            print('User interrupted..')

    if epochs and not no_details:
        sorted_epochs = sorted(epochs, key=itemgetter('loss'))
        results = sorted_epochs[0]
        HyperoptTools.print_epoch_details(results, total_epochs, print_json,
                                          no_header)

    if epochs and export_csv:
        HyperoptTools.export_csv_file(config, epochs, total_epochs,
                                      not filteroptions['only_best'],
                                      export_csv)