Exemple #1
0
def portfolio_metrics():
    data = stats.trades(store.completed_trades.trades, store.app.daily_balance)
    return [['Total Closed Trades', data['total']],
            [
                'Total Net Profit',
                '{} ({})'.format(round(data['net_profit'], 4),
                                 str(data['net_profit_percentage']) + '%')
            ],
            [
                'Starting => Finishing Balance',
                '{} => {}'.format(round(data['starting_balance'], 2),
                                  round(data['finishing_balance'], 2))
            ], ['Total Open Trades', data['total_open_trades']],
            ['Open PL', round(data['open_pl'], 2)],
            ['Total Paid Fees', round(data['fee'], 2)],
            ['Max Drawdown', '{}%'.format(data['max_drawdown'])],
            ['Sharpe Ratio', data['sharpe_ratio']],
            ['Annual Return', '{}%'.format(data['annual_return'])],
            [
                'Expectancy', '{} ({})'.format(
                    round(data['expectancy'], 2),
                    str(round(data['expectancy_percentage'], 2)) + '%')
            ],
            [
                'Avg Win | Avg Loss',
                '{} | {}'.format(round(data['average_win'], 2),
                                 round(data['average_loss'], 2))
            ],
            ['Ratio Avg Win / Avg Loss',
             round(data['ratio_avg_win_loss'], 2)],
            ['Percent Profitable',
             str(round(data['win_rate'] * 100)) + '%'],
            [
                'Longs | Shorts',
                '{}% | {}%'.format(round(data['longs_percentage']),
                                   round(data['short_percentage']))
            ],
            [
                'Avg Holding Time',
                jh.readable_duration(data['average_holding_period'], 3)
            ],
            [
                'Winning Trades Avg Holding Time',
                np.nan if np.isnan(data['average_winning_holding_period']) else
                jh.readable_duration(data['average_winning_holding_period'], 3)
            ],
            [
                'Losing Trades Avg Holding Time',
                np.nan if np.isnan(data['average_losing_holding_period']) else
                jh.readable_duration(data['average_losing_holding_period'], 3)
            ]]
Exemple #2
0
def portfolio_metrics():
    data = stats.trades(store.completed_trades.trades, store.app.daily_balance)

    metrics = [
        ['Total Closed Trades', data['total']],
        ['Total Net Profit',
         '{} ({})'.format(jh.format_currency(round(data['net_profit'], 4)), str(data['net_profit_percentage']) + '%')],
        ['Starting => Finishing Balance',
         '{} => {}'.format(jh.format_currency(round(data['starting_balance'], 2)), jh.format_currency(round(data['finishing_balance'], 2)))],
        ['Total Open Trades', data['total_open_trades']],
        ['Open PL', jh.format_currency(round(data['open_pl'], 2))],
        ['Total Paid Fees', jh.format_currency(round(data['fee'], 2))],
        ['Max Drawdown', '{}%'.format(data['max_drawdown'])],
        ['Annual Return', '{}%'.format(data['annual_return'])],
        ['Expectancy',
         '{} ({})'.format(jh.format_currency(round(data['expectancy'], 2)), str(round(data['expectancy_percentage'], 2)) + '%')],
        ['Avg Win | Avg Loss', '{} | {}'.format(jh.format_currency(round(data['average_win'], 2)), jh.format_currency(round(data['average_loss'], 2)))],
        ['Ratio Avg Win / Avg Loss', round(data['ratio_avg_win_loss'], 2)],
        ['Percent Profitable', str(round(data['win_rate'] * 100)) + '%'],
        ['Longs | Shorts', '{}% | {}%'.format(round(data['longs_percentage']), round(data['short_percentage']))],
        ['Avg Holding Time', jh.readable_duration(data['average_holding_period'], 3)],
        ['Winning Trades Avg Holding Time',
         np.nan if np.isnan(data['average_winning_holding_period']) else jh.readable_duration(
             data['average_winning_holding_period'], 3)],
        ['Losing Trades Avg Holding Time',
         np.nan if np.isnan(data['average_losing_holding_period']) else jh.readable_duration(
             data['average_losing_holding_period'], 3)]
    ]

    if jh.get_config('env.metrics.sharpe_ratio', True):
        metrics.append(['Sharpe Ratio', data['sharpe_ratio']])
    if jh.get_config('env.metrics.calmar_ratio', False):
        metrics.append(['Calmar Ratio', data['calmar_ratio']])
    if jh.get_config('env.metrics.sortino_ratio', False):
        metrics.append(['Sortino Ratio', data['sortino_ratio']])
    if jh.get_config('env.metrics.omega_ratio', False):
        metrics.append(['Omega Ratio', data['omega_ratio']])
    if jh.get_config('env.metrics.winning_streak', False):
        metrics.append(['Winning Streak', data['winning_streak']])
    if jh.get_config('env.metrics.losing_streak', False):
        metrics.append(['Losing Streak', data['losing_streak']])
    if jh.get_config('env.metrics.largest_winning_trade', False):
        metrics.append(['Largest Winning Trade', jh.format_currency(data['largest_winning_trade'])])
    if jh.get_config('env.metrics.largest_losing_trade', False):
        metrics.append(['Largest Losing Trade', jh.format_currency(data['largest_losing_trade'])])
    if jh.get_config('env.metrics.total_winning_trades', False):
        metrics.append(['Total Winning Trades', data['total_winning_trades']])
    if jh.get_config('env.metrics.total_losing_trades', False):
        metrics.append(['Total Losing Trades', data['total_losing_trades']])

    return metrics
Exemple #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

        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
Exemple #4
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