Merge pull request #4012 from freqtrade/best_worst_pair
Enhance backtesting summary report
This commit is contained in:
		| @@ -165,10 +165,13 @@ A backtesting result will look like that: | |||||||
| | Max open trades       | 3                   | | | Max open trades       | 3                   | | ||||||
| |                       |                     | | |                       |                     | | ||||||
| | Total trades          | 429                 | | | Total trades          | 429                 | | ||||||
| | First trade           | 2019-01-01 18:30:00 | |  | ||||||
| | First trade Pair      | EOS/USDT            | |  | ||||||
| | Total Profit %        | 152.41%             | | | Total Profit %        | 152.41%             | | ||||||
| | Trades per day        | 3.575               | | | Trades per day        | 3.575               | | ||||||
|  | |                       |                     | | ||||||
|  | | Best Pair             | LSK/BTC 26.26%      | | ||||||
|  | | Worst Pair            | ZEC/BTC -10.18%     | | ||||||
|  | | Best Trade            | LSK/BTC 4.25%       | | ||||||
|  | | Worst Trade           | ZEC/BTC -10.25%     | | ||||||
| | Best day              | 25.27%              | | | Best day              | 25.27%              | | ||||||
| | Worst day             | -30.67%             | | | Worst day             | -30.67%             | | ||||||
| | Avg. Duration Winners | 4:23:00             | | | Avg. Duration Winners | 4:23:00             | | ||||||
| @@ -238,10 +241,13 @@ It contains some useful key metrics about performance of your strategy on backte | |||||||
| | Max open trades       | 3                   | | | Max open trades       | 3                   | | ||||||
| |                       |                     | | |                       |                     | | ||||||
| | Total trades          | 429                 | | | Total trades          | 429                 | | ||||||
| | First trade           | 2019-01-01 18:30:00 | |  | ||||||
| | First trade Pair      | EOS/USDT            | |  | ||||||
| | Total Profit %        | 152.41%             | | | Total Profit %        | 152.41%             | | ||||||
| | Trades per day        | 3.575               | | | Trades per day        | 3.575               | | ||||||
|  | |                       |                     | | ||||||
|  | | Best Pair             | LSK/BTC 26.26%      | | ||||||
|  | | Worst Pair            | ZEC/BTC -10.18%     | | ||||||
|  | | Best Trade            | LSK/BTC 4.25%       | | ||||||
|  | | Worst Trade           | ZEC/BTC -10.25%     | | ||||||
| | Best day              | 25.27%              | | | Best day              | 25.27%              | | ||||||
| | Worst day             | -30.67%             | | | Worst day             | -30.67%             | | ||||||
| | Avg. Duration Winners | 4:23:00             | | | Avg. Duration Winners | 4:23:00             | | ||||||
| @@ -258,10 +264,10 @@ It contains some useful key metrics about performance of your strategy on backte | |||||||
| - `Backtesting from` / `Backtesting to`: Backtesting range (usually defined with the `--timerange` option). | - `Backtesting from` / `Backtesting to`: Backtesting range (usually defined with the `--timerange` option). | ||||||
| - `Max open trades`: Setting of `max_open_trades` (or `--max-open-trades`) - to clearly see settings for this. | - `Max open trades`: Setting of `max_open_trades` (or `--max-open-trades`) - to clearly see settings for this. | ||||||
| - `Total trades`: Identical to the total trades of the backtest output table. | - `Total trades`: Identical to the total trades of the backtest output table. | ||||||
| - `First trade`: First trade entered. |  | ||||||
| - `First trade pair`: Which pair was part of the first trade. |  | ||||||
| - `Total Profit %`: Total profit per stake amount. Aligned to the TOTAL column of the first table. | - `Total Profit %`: Total profit per stake amount. Aligned to the TOTAL column of the first table. | ||||||
| - `Trades per day`: Total trades divided by the backtesting duration in days (this will give you information about how many trades to expect from the strategy). | - `Trades per day`: Total trades divided by the backtesting duration in days (this will give you information about how many trades to expect from the strategy). | ||||||
|  | - `Best Pair` / `Worst Pair`: Best and worst performing pair, and it's corresponding `Cum Profit %`. | ||||||
|  | - `Best Trade` / `Worst Trade`: Biggest winning trade and biggest losing trade | ||||||
| - `Best day` / `Worst day`: Best and worst day based on daily profit. | - `Best day` / `Worst day`: Best and worst day based on daily profit. | ||||||
| - `Avg. Duration Winners` / `Avg. Duration Loser`: Average durations for winning and losing trades. | - `Avg. Duration Winners` / `Avg. Duration Loser`: Average durations for winning and losing trades. | ||||||
| - `Max Drawdown`: Maximum drawdown experienced. For example, the value of 50% means that from highest to subsequent lowest point, a 50% drop was experienced). | - `Max Drawdown`: Maximum drawdown experienced. For example, the value of 50% means that from highest to subsequent lowest point, a 50% drop was experienced). | ||||||
|   | |||||||
| @@ -256,13 +256,18 @@ def generate_backtest_stats(btdata: Dict[str, DataFrame], | |||||||
|                                                   results=results.loc[results['open_at_end']], |                                                   results=results.loc[results['open_at_end']], | ||||||
|                                                   skip_nan=True) |                                                   skip_nan=True) | ||||||
|         daily_stats = generate_daily_stats(results) |         daily_stats = generate_daily_stats(results) | ||||||
|  |         best_pair = max([pair for pair in pair_results if pair['key'] != 'TOTAL'], | ||||||
|  |                         key=lambda x: x['profit_sum']) if len(pair_results) > 1 else None | ||||||
|  |         worst_pair = min([pair for pair in pair_results if pair['key'] != 'TOTAL'], | ||||||
|  |                          key=lambda x: x['profit_sum']) if len(pair_results) > 1 else None | ||||||
|         results['open_timestamp'] = results['open_date'].astype(int64) // 1e6 |         results['open_timestamp'] = results['open_date'].astype(int64) // 1e6 | ||||||
|         results['close_timestamp'] = results['close_date'].astype(int64) // 1e6 |         results['close_timestamp'] = results['close_date'].astype(int64) // 1e6 | ||||||
|  |  | ||||||
|         backtest_days = (max_date - min_date).days |         backtest_days = (max_date - min_date).days | ||||||
|         strat_stats = { |         strat_stats = { | ||||||
|             'trades': results.to_dict(orient='records'), |             'trades': results.to_dict(orient='records'), | ||||||
|  |             'best_pair': best_pair, | ||||||
|  |             'worst_pair': worst_pair, | ||||||
|             'results_per_pair': pair_results, |             'results_per_pair': pair_results, | ||||||
|             'sell_reason_summary': sell_reason_stats, |             'sell_reason_summary': sell_reason_stats, | ||||||
|             'left_open_trades': left_open_results, |             'left_open_trades': left_open_results, | ||||||
| @@ -395,17 +400,25 @@ def text_table_strategy(strategy_results, stake_currency: str) -> str: | |||||||
|  |  | ||||||
| def text_table_add_metrics(strat_results: Dict) -> str: | def text_table_add_metrics(strat_results: Dict) -> str: | ||||||
|     if len(strat_results['trades']) > 0: |     if len(strat_results['trades']) > 0: | ||||||
|         min_trade = min(strat_results['trades'], key=lambda x: x['open_date']) |         best_trade = max(strat_results['trades'], key=lambda x: x['profit_percent']) | ||||||
|  |         worst_trade = min(strat_results['trades'], key=lambda x: x['profit_percent']) | ||||||
|         metrics = [ |         metrics = [ | ||||||
|             ('Backtesting from', strat_results['backtest_start'].strftime(DATETIME_PRINT_FORMAT)), |             ('Backtesting from', strat_results['backtest_start'].strftime(DATETIME_PRINT_FORMAT)), | ||||||
|             ('Backtesting to', strat_results['backtest_end'].strftime(DATETIME_PRINT_FORMAT)), |             ('Backtesting to', strat_results['backtest_end'].strftime(DATETIME_PRINT_FORMAT)), | ||||||
|             ('Max open trades', strat_results['max_open_trades']), |             ('Max open trades', strat_results['max_open_trades']), | ||||||
|             ('', ''),  # Empty line to improve readability |             ('', ''),  # Empty line to improve readability | ||||||
|             ('Total trades', strat_results['total_trades']), |             ('Total trades', strat_results['total_trades']), | ||||||
|             ('First trade', min_trade['open_date'].strftime(DATETIME_PRINT_FORMAT)), |  | ||||||
|             ('First trade Pair', min_trade['pair']), |  | ||||||
|             ('Total Profit %', f"{round(strat_results['profit_total'] * 100, 2)}%"), |             ('Total Profit %', f"{round(strat_results['profit_total'] * 100, 2)}%"), | ||||||
|             ('Trades per day', strat_results['trades_per_day']), |             ('Trades per day', strat_results['trades_per_day']), | ||||||
|  |             ('', ''),  # Empty line to improve readability | ||||||
|  |             ('Best Pair', f"{strat_results['best_pair']['key']} " | ||||||
|  |                           f"{round(strat_results['best_pair']['profit_sum_pct'], 2)}%"), | ||||||
|  |             ('Worst Pair', f"{strat_results['worst_pair']['key']} " | ||||||
|  |                            f"{round(strat_results['worst_pair']['profit_sum_pct'], 2)}%"), | ||||||
|  |             ('Best trade', f"{best_trade['pair']} {round(best_trade['profit_percent'] * 100, 2)}%"), | ||||||
|  |             ('Worst trade', f"{worst_trade['pair']} " | ||||||
|  |                             f"{round(worst_trade['profit_percent'] * 100, 2)}%"), | ||||||
|  |  | ||||||
|             ('Best day', f"{round(strat_results['backtest_best_day'] * 100, 2)}%"), |             ('Best day', f"{round(strat_results['backtest_best_day'] * 100, 2)}%"), | ||||||
|             ('Worst day', f"{round(strat_results['backtest_worst_day'] * 100, 2)}%"), |             ('Worst day', f"{round(strat_results['backtest_worst_day'] * 100, 2)}%"), | ||||||
|             ('Days win/draw/lose', f"{strat_results['winning_days']} / " |             ('Days win/draw/lose', f"{strat_results['winning_days']} / " | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user