From a00f852cf99106b314a05d425b7ab6fcad9d158d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 28 Nov 2020 16:56:08 +0100 Subject: [PATCH 1/3] Add best / worst pair to summary statistics --- docs/backtesting.md | 12 ++++++------ freqtrade/optimize/optimize_reports.py | 15 +++++++++++---- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index 277b11083..01624e5c2 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -165,8 +165,8 @@ A backtesting result will look like that: | Max open trades | 3 | | | | | Total trades | 429 | -| First trade | 2019-01-01 18:30:00 | -| First trade Pair | EOS/USDT | +| Best Pair | LSK/BTC - 26.26% | +| Worst Pair | ZEC/BTC - -10.18% | | Total Profit % | 152.41% | | Trades per day | 3.575 | | Best day | 25.27% | @@ -238,8 +238,8 @@ It contains some useful key metrics about performance of your strategy on backte | Max open trades | 3 | | | | | Total trades | 429 | -| First trade | 2019-01-01 18:30:00 | -| First trade Pair | EOS/USDT | +| Best Pair | LSK/BTC - 26.26% | +| Worst Pair | ZEC/BTC - -10.18% | | Total Profit % | 152.41% | | Trades per day | 3.575 | | Best day | 25.27% | @@ -258,8 +258,8 @@ 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). - `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. -- `First trade`: First trade entered. -- `First trade pair`: Which pair was part of the first trade. +- `Best Pair`: Which pair performed best, and it's corresponding `Cum Profit %`. +- `Worst pair`: Which pair performed worst and it's corresponding `Cum Profit %`. - `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). - `Best day` / `Worst day`: Best and worst day based on daily profit. diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 6aef031d3..589e0ba1c 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -256,13 +256,18 @@ def generate_backtest_stats(btdata: Dict[str, DataFrame], results=results.loc[results['open_at_end']], skip_nan=True) 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['close_timestamp'] = results['close_date'].astype(int64) // 1e6 backtest_days = (max_date - min_date).days strat_stats = { 'trades': results.to_dict(orient='records'), + 'best_pair': best_pair, + 'worst_pair': worst_pair, 'results_per_pair': pair_results, 'sell_reason_summary': sell_reason_stats, 'left_open_trades': left_open_results, @@ -395,17 +400,19 @@ def text_table_strategy(strategy_results, stake_currency: str) -> str: def text_table_add_metrics(strat_results: Dict) -> str: if len(strat_results['trades']) > 0: - min_trade = min(strat_results['trades'], key=lambda x: x['open_date']) metrics = [ ('Backtesting from', strat_results['backtest_start'].strftime(DATETIME_PRINT_FORMAT)), ('Backtesting to', strat_results['backtest_end'].strftime(DATETIME_PRINT_FORMAT)), ('Max open trades', strat_results['max_open_trades']), ('', ''), # Empty line to improve readability ('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)}%"), ('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 day', f"{round(strat_results['backtest_best_day'] * 100, 2)}%"), ('Worst day', f"{round(strat_results['backtest_worst_day'] * 100, 2)}%"), ('Days win/draw/lose', f"{strat_results['winning_days']} / " From 5d3f59df90d97f1d96e7b4e9734dcc722b6bc7a4 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 28 Nov 2020 17:45:56 +0100 Subject: [PATCH 2/3] Add best / worst trade --- docs/backtesting.md | 18 ++++++++++++------ freqtrade/optimize/optimize_reports.py | 5 +++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index 01624e5c2..42de9bdc3 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -165,10 +165,13 @@ A backtesting result will look like that: | Max open trades | 3 | | | | | Total trades | 429 | -| Best Pair | LSK/BTC - 26.26% | -| Worst Pair | ZEC/BTC - -10.18% | | Total Profit % | 152.41% | | 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% | | Worst day | -30.67% | | 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 | | | | | Total trades | 429 | -| Best Pair | LSK/BTC - 26.26% | -| Worst Pair | ZEC/BTC - -10.18% | | Total Profit % | 152.41% | | 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% | | Worst day | -30.67% | | 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). - `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. -- `Best Pair`: Which pair performed best, and it's corresponding `Cum Profit %`. -- `Worst pair`: Which pair performed worst and it's corresponding `Cum Profit %`. - `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). +- `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. - `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). diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 589e0ba1c..3e44a6067 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -400,6 +400,8 @@ def text_table_strategy(strategy_results, stake_currency: str) -> str: def text_table_add_metrics(strat_results: Dict) -> str: if len(strat_results['trades']) > 0: + 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 = [ ('Backtesting from', strat_results['backtest_start'].strftime(DATETIME_PRINT_FORMAT)), ('Backtesting to', strat_results['backtest_end'].strftime(DATETIME_PRINT_FORMAT)), @@ -413,6 +415,9 @@ def text_table_add_metrics(strat_results: Dict) -> str: 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']} {round(worst_trade['profit_percent'] * 100, 2)}%"), + ('Best day', f"{round(strat_results['backtest_best_day'] * 100, 2)}%"), ('Worst day', f"{round(strat_results['backtest_worst_day'] * 100, 2)}%"), ('Days win/draw/lose', f"{strat_results['winning_days']} / " From e40d97e05e765c5946208b47b5519c47b79aa135 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 28 Nov 2020 17:52:29 +0100 Subject: [PATCH 3/3] Small formatting improvements --- docs/backtesting.md | 16 ++++++++-------- freqtrade/optimize/optimize_reports.py | 7 ++++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index 42de9bdc3..c841899a7 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -168,10 +168,10 @@ A backtesting result will look like that: | Total Profit % | 152.41% | | 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 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% | | Worst day | -30.67% | | Avg. Duration Winners | 4:23:00 | @@ -244,10 +244,10 @@ It contains some useful key metrics about performance of your strategy on backte | Total Profit % | 152.41% | | 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 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% | | Worst day | -30.67% | | Avg. Duration Winners | 4:23:00 | diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 3e44a6067..b3799856e 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -411,12 +411,13 @@ def text_table_add_metrics(strat_results: Dict) -> str: ('Total Profit %', f"{round(strat_results['profit_total'] * 100, 2)}%"), ('Trades per day', strat_results['trades_per_day']), ('', ''), # Empty line to improve readability - ('Best Pair', f"{strat_results['best_pair']['key']} - " + ('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']} - " + ('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']} {round(worst_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)}%"), ('Worst day', f"{round(strat_results['backtest_worst_day'] * 100, 2)}%"),