示例#1
0
def test_normalize():
    assert jh.normalize(10, 0, 20) == 0.5
    assert jh.normalize(20, 0, 20) == 1
    assert jh.normalize(0, 0, 20) == 0
示例#2
0
    def fitness(self, dna) -> tuple:
        hp = jh.dna_to_hp(self.strategy_hp, dna)

        # init candle store
        store.candles.init_storage(5000)
        # inject required TRAINING candles to the candle store

        for num, c in enumerate(config['app']['considering_candles']):
            required_candles.inject_required_candles_to_store(
                self.training_initial_candles[num], c[0], c[1])

        # run backtest simulation
        simulator(self.training_candles, hp)

        log = ''

        # TODO: some of these have to be dynamic based on how many days it's trading for like for example "total"
        # I'm guessing we should accept "optimal" total from command line
        if store.completed_trades.count > 5:
            training_data = stats.trades(store.completed_trades.trades,
                                         store.app.daily_balance)
            total_effect_rate = log10(training_data['total']) / log10(
                self.optimal_total)
            if total_effect_rate > 1:
                total_effect_rate = 1
            win_rate = training_data['win_rate']

            ratio_config = jh.get_config('env.optimization.ratio', 'sharpe')
            if ratio_config == 'sharpe':
                ratio = training_data['sharpe_ratio']
            elif ratio_config == 'calmar':
                ratio = training_data['calmar_ratio']
            elif ratio_config == 'sortiono':
                ratio = training_data['sortino_ratio']
            elif ratio_config == 'omega':
                ratio = training_data['omega_ratio']
            else:
                raise ValueError(
                    'The entered ratio configuration `{}` for the optimization is unknown. Choose between sharpe, calmar, sortino and omega.'
                    .format(ratio_config))

            if ratio < 0:
                score = 0.0001
                # reset store
                store.reset()
                return score, log

            ratio_normalized = jh.normalize(ratio, -.5, 4)

            # log for debugging/monitoring
            log = 'win-rate: {}%, total: {}, PNL: {}%'.format(
                int(win_rate * 100),
                training_data['total'],
                round(training_data['net_profit_percentage'], 2),
            )

            score = total_effect_rate * ratio_normalized

            # perform backtest with testing data. this is using data
            # model hasn't trained for. if it works well, there is
            # high change it will do good with future data too.
            store.reset()
            store.candles.init_storage(5000)
            # inject required TESTING candles to the candle store

            for num, c in enumerate(config['app']['considering_candles']):
                required_candles.inject_required_candles_to_store(
                    self.testing_initial_candles[num], c[0], c[1])

            # run backtest simulation
            simulator(self.testing_candles, hp)
            testing_data = stats.trades(store.completed_trades.trades,
                                        store.app.daily_balance)

            # log for debugging/monitoring
            log += ' || '
            if store.completed_trades.count > 0:
                log += 'win-rate: {}%, total: {}, PNL: {}%'.format(
                    int(testing_data['win_rate'] * 100),
                    testing_data['total'],
                    round(testing_data['net_profit_percentage'], 2),
                )
                if testing_data['net_profit_percentage'] > 0 and training_data[
                        'net_profit_percentage'] > 0:
                    log = jh.style(log, 'bold')
            else:
                log += 'win-rate: -, total: -, PNL%: -'
        else:
            score = 0.0001

        # reset store
        store.reset()

        return score, log
示例#3
0
    def fitness(self, dna) -> tuple:
        hp = jh.dna_to_hp(self.strategy_hp, dna)

        # init candle store
        store.candles.init_storage(5000)
        # inject required TRAINING candles to the candle store
        required_candles.inject_required_candles_to_store(
            self.required_initial_training_candles, self.exchange, self.symbol)
        # run backtest simulation
        simulator(self.training_candles, hp)

        log = ''

        # TODO: some of these have to be dynamic based on how many days it's trading for like for example "total"
        # I'm guessing we should accept "optimal" total from command line
        if store.completed_trades.count > 5:
            training_data = stats.trades(store.completed_trades.trades)
            optimal_expected_total = 100
            total = jh.normalize(training_data['total'], 0, 200)
            total_effect_rate = log10(
                training_data['total']) / log10(optimal_expected_total)
            win_rate = training_data['win_rate']

            # log for debugging/monitoring
            log = 'win_rate:[{}-{}], total:[{}-{}], PNL%:[{}], TER:[{}]'.format(
                round(win_rate, 2), round(training_data['win_rate'], 2),
                round(total, 2), training_data['total'],
                round(training_data['pnl_percentage'], 2),
                round(total_effect_rate, 3))

            # the fitness score
            score = win_rate * total_effect_rate

            # perform backtest with testing data. this is using data
            # model hasn't trained for. if it works well, there is
            # high change it will do good with future data too.
            store.reset()
            store.candles.init_storage(5000)
            # inject required TESTING candles to the candle store
            required_candles.inject_required_candles_to_store(
                self.required_initial_testing_candles, self.exchange,
                self.symbol)
            # run backtest simulation
            simulator(self.testing_candles, hp)
            testing_data = stats.trades(store.completed_trades.trades)

            # log for debugging/monitoring
            log += ' | '
            log += 'win_rate:[{}], total:[{}], PNL%:[{}]'.format(
                round(testing_data['win_rate'], 2),
                testing_data['total'],
                round(testing_data['pnl_percentage'], 2),
            )
            if testing_data['pnl_percentage'] > 0 and training_data[
                    'pnl_percentage'] > 0:
                log = jh.style(log, 'bold')
        else:
            score = 0.0001

        # reset store
        store.reset()

        return score, log
示例#4
0
文件: fitness.py 项目: jesse-ai/jesse
def get_fitness(optimization_config: dict, routes: list, extra_routes: list,
                strategy_hp, dna: str, training_candles, testing_candles,
                optimal_total) -> tuple:
    """
    Notice that this function is likely to be executed inside workers, hence its inputs must
    have everything required for it to run. So it cannot access store, config, etc
    """
    hp = jh.dna_to_hp(strategy_hp, dna)

    # run backtest simulation
    try:
        training_data_metrics = isolated_backtest(
            _formatted_inputs_for_isolated_backtest(optimization_config,
                                                    routes),
            routes,
            extra_routes,
            training_candles,
            hyperparameters=hp)['metrics']
    except Exception as e:
        # get the main title of the exception
        log_text = e
        log_text = f"Exception in strategy execution:\n {log_text}"
        logger.log_optimize_mode(log_text)
        raise e

    training_log = {'win-rate': None, 'total': None, 'PNL': None}
    testing_log = {'win-rate': None, 'total': None, 'PNL': None}

    # TODO: some of these have to be dynamic based on how many days it's trading for like for example "total"
    if training_data_metrics['total'] > 5:
        total_effect_rate = log10(
            training_data_metrics['total']) / log10(optimal_total)
        total_effect_rate = min(total_effect_rate, 1)
        ratio_config = jh.get_config('env.optimization.ratio', 'sharpe')
        if ratio_config == 'sharpe':
            ratio = training_data_metrics['sharpe_ratio']
            ratio_normalized = jh.normalize(ratio, -.5, 5)
        elif ratio_config == 'calmar':
            ratio = training_data_metrics['calmar_ratio']
            ratio_normalized = jh.normalize(ratio, -.5, 30)
        elif ratio_config == 'sortino':
            ratio = training_data_metrics['sortino_ratio']
            ratio_normalized = jh.normalize(ratio, -.5, 15)
        elif ratio_config == 'omega':
            ratio = training_data_metrics['omega_ratio']
            ratio_normalized = jh.normalize(ratio, -.5, 5)
        elif ratio_config == 'serenity':
            ratio = training_data_metrics['serenity_index']
            ratio_normalized = jh.normalize(ratio, -.5, 15)
        elif ratio_config == 'smart sharpe':
            ratio = training_data_metrics['smart_sharpe']
            ratio_normalized = jh.normalize(ratio, -.5, 5)
        elif ratio_config == 'smart sortino':
            ratio = training_data_metrics['smart_sortino']
            ratio_normalized = jh.normalize(ratio, -.5, 15)
        else:
            raise ValueError(
                f'The entered ratio configuration `{ratio_config}` for the optimization is unknown. Choose between sharpe, calmar, sortino, serenity, smart shapre, smart sortino and omega.'
            )

        if ratio < 0:
            score = 0.0001
            logger.log_optimize_mode(
                f"NEGATIVE RATIO: DNA is not usable => {ratio_config}: {ratio}, total: {training_data_metrics['total']}"
            )
            return score, training_log, testing_log

        # log for debugging/monitoring
        training_log = {
            'win-rate': int(training_data_metrics['win_rate'] * 100),
            'total': training_data_metrics['total'],
            'PNL': round(training_data_metrics['net_profit_percentage'], 2)
        }

        score = total_effect_rate * ratio_normalized
        # if score is numpy nan, replace it with 0.0001
        if np.isnan(score):
            logger.log_optimize_mode(f'Score is nan. DNA is invalid')
            score = 0.0001
        # elif jh.is_debugging():
        else:
            logger.log_optimize_mode(
                f"DNA is usable => {ratio_config}: {round(ratio, 2)}, total: {training_data_metrics['total']}, PNL%: {round(training_data_metrics['net_profit_percentage'], 2)}%, win-rate: {round(training_data_metrics['win_rate']*100, 2)}%"
            )

        # run backtest simulation
        testing_data_metrics = isolated_backtest(
            _formatted_inputs_for_isolated_backtest(optimization_config,
                                                    routes),
            routes,
            extra_routes,
            testing_candles,
            hyperparameters=hp)['metrics']

        # log for debugging/monitoring
        if testing_data_metrics['total'] > 0:
            testing_log = {
                'win-rate': int(testing_data_metrics['win_rate'] * 100),
                'total': testing_data_metrics['total'],
                'PNL': round(testing_data_metrics['net_profit_percentage'], 2)
            }
    else:
        logger.log_optimize_mode(
            f'Less than 5 trades in the training data. DNA is invalid')
        score = 0.0001

    return score, training_log, testing_log
示例#5
0
文件: __init__.py 项目: xsa-dev/jesse
    def fitness(self, dna: str) -> tuple:
        hp = jh.dna_to_hp(self.strategy_hp, dna)

        # init candle store
        store.candles.init_storage(5000)
        # inject required TRAINING candles to the candle store

        for num, c in enumerate(config['app']['considering_candles']):
            required_candles.inject_required_candles_to_store(
                self.training_initial_candles[num],
                c[0],
                c[1]
            )

        # run backtest simulation
        simulator(self.training_candles, hp)

        training_data = {'win_rate': None, 'total': None,
                        'net_profit_percentage': None}
        testing_data = {'win_rate': None, 'total': None,
                       'net_profit_percentage': None}

        # TODO: some of these have to be dynamic based on how many days it's trading for like for example "total"
        # I'm guessing we should accept "optimal" total from command line
        if store.completed_trades.count > 5:
            training_data = stats.trades(store.completed_trades.trades, store.app.daily_balance)
            total_effect_rate = log10(training_data['total']) / log10(self.optimal_total)
            total_effect_rate = min(total_effect_rate, 1)
            ratio_config = jh.get_config('env.optimization.ratio', 'sharpe')
            if ratio_config == 'sharpe':
                ratio = training_data['sharpe_ratio']
                ratio_normalized = jh.normalize(ratio, -.5, 5)
            elif ratio_config == 'calmar':
                ratio = training_data['calmar_ratio']
                ratio_normalized = jh.normalize(ratio, -.5, 30)
            elif ratio_config == 'sortino':
                ratio = training_data['sortino_ratio']
                ratio_normalized = jh.normalize(ratio, -.5, 15)
            elif ratio_config == 'omega':
                ratio = training_data['omega_ratio']
                ratio_normalized = jh.normalize(ratio, -.5, 5)
            elif ratio_config == 'serenity':
                ratio = training_data['serenity_index']
                ratio_normalized = jh.normalize(ratio, -.5, 15)
            elif ratio_config == 'smart sharpe':
                ratio = training_data['smart_sharpe']
                ratio_normalized = jh.normalize(ratio, -.5, 5)
            elif ratio_config == 'smart sortino':
                ratio = training_data['smart_sortino']
                ratio_normalized = jh.normalize(ratio, -.5, 15)
            else:
                raise ValueError(
                    f'The entered ratio configuration `{ratio_config}` for the optimization is unknown. Choose between sharpe, calmar, sortino, serenity, smart shapre, smart sortino and omega.')

            if ratio < 0:
                score = 0.0001
                # reset store
                store.reset()
                return score, training_data, testing_data

            score = total_effect_rate * ratio_normalized

            # perform backtest with testing data. this is using data
            # model hasn't trained for. if it works well, there is
            # high change it will do good with future data too.
            store.reset()
            store.candles.init_storage(5000)
            # inject required TESTING candles to the candle store

            for num, c in enumerate(config['app']['considering_candles']):
                required_candles.inject_required_candles_to_store(
                    self.testing_initial_candles[num],
                    c[0],
                    c[1]
                )

            # run backtest simulation
            simulator(self.testing_candles, hp)

            # log for debugging/monitoring
            if store.completed_trades.count > 0:
                testing_data = stats.trades(store.completed_trades.trades, store.app.daily_balance)

        else:
            score = 0.0001

        # reset store
        store.reset()

        return score, training_data, testing_data