From 1b271d08404b59f4ab4d30b0d44a4cacecf6e7ab Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 11 Nov 2021 12:58:38 +0100 Subject: [PATCH 1/3] Improve % outputs to not use explicit "pct" entries --- freqtrade/rpc/api_server/api_schemas.py | 1 + freqtrade/rpc/rpc.py | 3 +- freqtrade/rpc/telegram.py | 38 ++++++++++++------------- tests/rpc/test_rpc_apiserver.py | 1 + tests/rpc/test_rpc_telegram.py | 10 +++---- 5 files changed, 28 insertions(+), 25 deletions(-) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index 5dbd1f637..c9ff0ddaf 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -95,6 +95,7 @@ class Profit(BaseModel): avg_duration: str best_pair: str best_rate: float + best_pair_profit_ratio: float winning_trades: int losing_trades: int diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 97a0def0b..db021029b 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -534,7 +534,8 @@ class RPC: 'latest_trade_timestamp': int(last_date.timestamp() * 1000) if last_date else 0, 'avg_duration': str(timedelta(seconds=sum(durations) / num)).split('.')[0], 'best_pair': best_pair[0] if best_pair else '', - 'best_rate': round(best_pair[1] * 100, 2) if best_pair else 0, + 'best_rate': round(best_pair[1] * 100, 2) if best_pair else 0, # Deprecated + 'best_pair_profit_ratio': best_pair[1] if best_pair else 0, 'winning_trades': winning_trades, 'losing_trades': losing_trades, } diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 1dea5fae7..f53154dff 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -264,7 +264,7 @@ class Telegram(RPCHandler): msg['profit_extra'] = '' message = ("{emoji} *{exchange}:* Selling {pair} (#{trade_id})\n" - "*Profit:* `{profit_percent:.2f}%{profit_extra}`\n" + "*Profit:* `{profit_ratio:.2%}{profit_extra}`\n" "*Buy Tag:* `{buy_tag}`\n" "*Sell Reason:* `{sell_reason}`\n" "*Duration:* `{duration} ({duration_min:.1f} min)`\n" @@ -397,19 +397,19 @@ class Telegram(RPCHandler): "*Close Rate:* `{close_rate}`" if r['close_rate'] else "", "*Current Rate:* `{current_rate:.8f}`", ("*Current Profit:* " if r['is_open'] else "*Close Profit: *") - + "`{profit_pct:.2f}%`", + + "`{profit_ratio:.2%}`", ] if (r['stop_loss_abs'] != r['initial_stop_loss_abs'] - and r['initial_stop_loss_pct'] is not None): + and r['initial_stop_loss_ratio'] is not None): # Adding initial stoploss only if it is different from stoploss lines.append("*Initial Stoploss:* `{initial_stop_loss_abs:.8f}` " - "`({initial_stop_loss_pct:.2f}%)`") + "`({initial_stop_loss_ratio:.2%})`") # Adding stoploss and stoploss percentage only if it is not None lines.append("*Stoploss:* `{stop_loss_abs:.8f}` " + - ("`({stop_loss_pct:.2f}%)`" if r['stop_loss_pct'] else "")) + ("`({stop_loss_ratio:.2%})`" if r['stop_loss_ratio'] else "")) lines.append("*Stoploss distance:* `{stoploss_current_dist:.8f}` " - "`({stoploss_current_dist_pct:.2f}%)`") + "`({stoploss_current_dist_ratio:.2%})`") if r['open_order']: if r['sell_order_status']: lines.append("*Open Order:* `{open_order}` - `{sell_order_status}`") @@ -612,11 +612,11 @@ class Telegram(RPCHandler): fiat_disp_cur, start_date) profit_closed_coin = stats['profit_closed_coin'] - profit_closed_percent_mean = stats['profit_closed_percent_mean'] + profit_closed_ratio_mean = stats['profit_closed_ratio_mean'] profit_closed_percent = stats['profit_closed_percent'] profit_closed_fiat = stats['profit_closed_fiat'] profit_all_coin = stats['profit_all_coin'] - profit_all_percent_mean = stats['profit_all_percent_mean'] + profit_all_ratio_mean = stats['profit_all_ratio_mean'] profit_all_percent = stats['profit_all_percent'] profit_all_fiat = stats['profit_all_fiat'] trade_count = stats['trade_count'] @@ -624,7 +624,7 @@ class Telegram(RPCHandler): latest_trade_date = stats['latest_trade_date'] avg_duration = stats['avg_duration'] best_pair = stats['best_pair'] - best_rate = stats['best_rate'] + best_pair_profit_ratio = stats['best_pair_profit_ratio'] if stats['trade_count'] == 0: markdown_msg = 'No trades yet.' else: @@ -632,7 +632,7 @@ class Telegram(RPCHandler): if stats['closed_trade_count'] > 0: markdown_msg = ("*ROI:* Closed trades\n" f"∙ `{round_coin_value(profit_closed_coin, stake_cur)} " - f"({profit_closed_percent_mean:.2f}%) " + f"({profit_closed_ratio_mean:.2%}) " f"({profit_closed_percent} \N{GREEK CAPITAL LETTER SIGMA}%)`\n" f"∙ `{round_coin_value(profit_closed_fiat, fiat_disp_cur)}`\n") else: @@ -641,7 +641,7 @@ class Telegram(RPCHandler): markdown_msg += ( f"*ROI:* All trades\n" f"∙ `{round_coin_value(profit_all_coin, stake_cur)} " - f"({profit_all_percent_mean:.2f}%) " + f"({profit_all_ratio_mean:.2%}) " f"({profit_all_percent} \N{GREEK CAPITAL LETTER SIGMA}%)`\n" f"∙ `{round_coin_value(profit_all_fiat, fiat_disp_cur)}`\n" f"*Total Trade Count:* `{trade_count}`\n" @@ -652,7 +652,7 @@ class Telegram(RPCHandler): ) if stats['closed_trade_count'] > 0: markdown_msg += (f"\n*Avg. Duration:* `{avg_duration}`\n" - f"*Best Performing:* `{best_pair}: {best_rate:.2f}%`") + f"*Best Performing:* `{best_pair}: {best_pair_profit_ratio:.2%}`") self._send_msg(markdown_msg, reload_able=True, callback_path="update_profit", query=update.callback_query) @@ -755,10 +755,10 @@ class Telegram(RPCHandler): output += ("\n*Estimated Value*:\n" f"\t`{result['stake']}: " f"{round_coin_value(result['total'], result['stake'], False)}`" - f" `({result['starting_capital_pct']}%)`\n" + f" `({result['starting_capital_ratio']:.2%})`\n" f"\t`{result['symbol']}: " f"{round_coin_value(result['value'], result['symbol'], False)}`" - f" `({result['starting_capital_fiat_pct']}%)`\n") + f" `({result['starting_capital_fiat_ratio']:.2%})`\n") self._send_msg(output, reload_able=True, callback_path="update_balance", query=update.callback_query) except RPCException as e: @@ -893,7 +893,7 @@ class Telegram(RPCHandler): trades_tab = tabulate( [[arrow.get(trade['close_date']).humanize(), trade['pair'] + " (#" + str(trade['trade_id']) + ")", - f"{(100 * trade['close_profit']):.2f}% ({trade['close_profit_abs']})"] + f"{(trade['close_profit']):.2%} ({trade['close_profit_abs']})"] for trade in trades['trades']], headers=[ 'Close Date', @@ -945,7 +945,7 @@ class Telegram(RPCHandler): stat_line = ( f"{i+1}.\t {trade['pair']}\t" f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} " - f"({trade['profit_pct']:.2f}%) " + f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: @@ -980,7 +980,7 @@ class Telegram(RPCHandler): stat_line = ( f"{i+1}.\t {trade['buy_tag']}\t" f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} " - f"({trade['profit_pct']:.2f}%) " + f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: @@ -1015,7 +1015,7 @@ class Telegram(RPCHandler): stat_line = ( f"{i+1}.\t {trade['sell_reason']}\t" f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} " - f"({trade['profit_pct']:.2f}%) " + f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: @@ -1050,7 +1050,7 @@ class Telegram(RPCHandler): stat_line = ( f"{i+1}.\t {trade['mix_tag']}\t" f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} " - f"({trade['profit']:.2f}%) " + f"({trade['profit']:.2%}) " f"({trade['count']})\n") if len(output + stat_line) >= MAX_TELEGRAM_MESSAGE_LENGTH: diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 3f908377b..e650e5142 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -717,6 +717,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets): assert rc.json() == {'avg_duration': ANY, 'best_pair': 'XRP/BTC', 'best_rate': 1.0, + 'best_pair_profit_ratio': 0.01, 'first_trade_date': ANY, 'first_trade_timestamp': ANY, 'latest_trade_date': '5 minutes ago', diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 74c33d2af..68f7457d5 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -189,16 +189,16 @@ def test_telegram_status(default_conf, update, mocker) -> None: 'amount': 90.99181074, 'stake_amount': 90.99181074, 'buy_tag': None, - 'close_profit_pct': None, + 'close_profit_ratio': None, 'profit': -0.0059, - 'profit_pct': -0.59, + 'profit_ratio': -0.0059, 'initial_stop_loss_abs': 1.098e-05, 'stop_loss_abs': 1.099e-05, 'sell_order_status': None, - 'initial_stop_loss_pct': -0.05, + 'initial_stop_loss_ratio': -0.0005, 'stoploss_current_dist': 1e-08, - 'stoploss_current_dist_pct': -0.02, - 'stop_loss_pct': -0.01, + 'stoploss_current_dist_ratio': -0.0002, + 'stop_loss_ratio': -0.0001, 'open_order': '(limit buy rem=0.00000000)', 'is_open': True }]), From 4eb903835839dfb1d52a218415d447f6f90f4f80 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 11 Nov 2021 13:55:55 +0100 Subject: [PATCH 2/3] Some more fixes to % formatting --- freqtrade/optimize/hyperopt_tools.py | 8 ++++---- freqtrade/optimize/optimize_reports.py | 10 +++++----- freqtrade/persistence/models.py | 3 ++- freqtrade/plot/plotting.py | 4 ++-- freqtrade/plugins/pairlist/PriceFilter.py | 2 +- freqtrade/plugins/pairlist/SpreadFilter.py | 2 +- freqtrade/rpc/rpc.py | 3 +-- freqtrade/strategy/interface.py | 2 +- tests/rpc/test_rpc.py | 10 +++++----- tests/test_freqtradebot.py | 4 ++-- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 0b2efa5c2..1204320da 100755 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -284,10 +284,10 @@ class HyperoptTools(): return (f"{results_metrics['total_trades']:6d} trades. " f"{results_metrics['wins']}/{results_metrics['draws']}" f"/{results_metrics['losses']} Wins/Draws/Losses. " - f"Avg profit {results_metrics['profit_mean'] * 100: 6.2f}%. " - f"Median profit {results_metrics['profit_median'] * 100: 6.2f}%. " - f"Total profit {results_metrics['profit_total_abs']: 11.8f} {stake_currency} " - f"({results_metrics['profit_total'] * 100: 7.2f}%). " + f"Avg profit {results_metrics['profit_mean']:7.2%}. " + f"Median profit {results_metrics['profit_median']:7.2%}. " + f"Total profit {results_metrics['profit_total_abs']:11.8f} {stake_currency} " + f"({results_metrics['profit_total']:8.2%}). " f"Avg duration {results_metrics['holding_avg']} min." ) diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 14d928e54..417bb54ae 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -725,7 +725,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: strat_results['stake_currency'])), ('Absolute profit ', round_coin_value(strat_results['profit_total_abs'], strat_results['stake_currency'])), - ('Total profit %', f"{round(strat_results['profit_total'] * 100, 2)}%"), + ('Total profit %', f"{strat_results['profit_total']:.2%}"), ('Trades per day', strat_results['trades_per_day']), ('Avg. daily profit %', f"{round(strat_results['profit_total'] / strat_results['backtest_days'] * 100, 2)}%"), @@ -738,9 +738,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_ratio'] * 100, 2)}%"), + ('Best trade', f"{best_trade['pair']} {best_trade['profit_ratio']:.2%}"), ('Worst trade', f"{worst_trade['pair']} " - f"{round(worst_trade['profit_ratio'] * 100, 2)}%"), + f"{worst_trade['profit_ratio']:.2%}"), ('Best day', round_coin_value(strat_results['backtest_best_day_abs'], strat_results['stake_currency'])), @@ -758,7 +758,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: ('Max balance', round_coin_value(strat_results['csum_max'], strat_results['stake_currency'])), - ('Drawdown', f"{round(strat_results['max_drawdown'] * 100, 2)}%"), + ('Drawdown', f"{strat_results['max_drawdown']:.2%}"), ('Drawdown', round_coin_value(strat_results['max_drawdown_abs'], strat_results['stake_currency'])), ('Drawdown high', round_coin_value(strat_results['max_drawdown_high'], @@ -767,7 +767,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: strat_results['stake_currency'])), ('Drawdown Start', strat_results['drawdown_start']), ('Drawdown End', strat_results['drawdown_end']), - ('Market change', f"{round(strat_results['market_change'] * 100, 2)}%"), + ('Market change', f"{strat_results['market_change']:.2%}"), ] return tabulate(metrics, headers=["Metric", "Value"], tablefmt="orgtbl") diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py index df3b71acb..2fcdd58bb 100644 --- a/freqtrade/persistence/models.py +++ b/freqtrade/persistence/models.py @@ -972,6 +972,7 @@ class Trade(_DECL_BASE, LocalTrade): if not any(item["mix_tag"] == mix_tag for item in return_list): return_list.append({'mix_tag': mix_tag, 'profit': profit, + 'profit_pct': round(profit * 100, 2), 'profit_abs': profit_abs, 'count': count}) else: @@ -980,11 +981,11 @@ class Trade(_DECL_BASE, LocalTrade): return_list[i] = { 'mix_tag': mix_tag, 'profit': profit + return_list[i]["profit"], + 'profit_pct': round(profit + return_list[i]["profit"] * 100, 2), 'profit_abs': profit_abs + return_list[i]["profit_abs"], 'count': 1 + return_list[i]["count"]} i += 1 - [x.update({'profit': round(x['profit'] * 100, 2)}) for x in return_list] return return_list @staticmethod diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index 509c03e90..d2b51f3a2 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -169,8 +169,8 @@ def add_max_drawdown(fig, row, trades: pd.DataFrame, df_comb: pd.DataFrame, df_comb.loc[timeframe_to_prev_date(timeframe, lowdate), 'cum_profit'], ], mode='markers', - name=f"Max drawdown {max_drawdown * 100:.2f}%", - text=f"Max drawdown {max_drawdown * 100:.2f}%", + name=f"Max drawdown {max_drawdown:.2%}", + text=f"Max drawdown {max_drawdown:.2%}", marker=dict( symbol='square-open', size=9, diff --git a/freqtrade/plugins/pairlist/PriceFilter.py b/freqtrade/plugins/pairlist/PriceFilter.py index 5b5afb557..7704ea9aa 100644 --- a/freqtrade/plugins/pairlist/PriceFilter.py +++ b/freqtrade/plugins/pairlist/PriceFilter.py @@ -82,7 +82,7 @@ class PriceFilter(IPairList): changeperc = compare / ticker['last'] if changeperc > self._low_price_ratio: self.log_once(f"Removed {pair} from whitelist, " - f"because 1 unit is {changeperc * 100:.3f}%", logger.info) + f"because 1 unit is {changeperc:.3%}", logger.info) return False # Perform low_amount check diff --git a/freqtrade/plugins/pairlist/SpreadFilter.py b/freqtrade/plugins/pairlist/SpreadFilter.py index 1b152774b..20cc97c6a 100644 --- a/freqtrade/plugins/pairlist/SpreadFilter.py +++ b/freqtrade/plugins/pairlist/SpreadFilter.py @@ -47,7 +47,7 @@ class SpreadFilter(IPairList): spread = 1 - ticker['bid'] / ticker['ask'] if spread > self._max_spread_ratio: self.log_once(f"Removed {pair} from whitelist, because spread " - f"{spread * 100:.3f}% > {self._max_spread_ratio * 100}%", + f"{spread * 100:.3%} > {self._max_spread_ratio:.3%}", logger.info) return False else: diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index db021029b..de066d123 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -224,9 +224,8 @@ class RPC: trade.pair, refresh=False, side="sell") except (PricingError, ExchangeError): current_rate = NAN - trade_percent = (100 * trade.calc_profit_ratio(current_rate)) trade_profit = trade.calc_profit(current_rate) - profit_str = f'{trade_percent:.2f}%' + profit_str = f'{trade.calc_profit_ratio(current_rate):.2%}' if self._fiat_converter: fiat_profit = self._fiat_converter.convert_amount( trade_profit, diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 47a226f16..d4b496ed0 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -765,7 +765,7 @@ class IStrategy(ABC, HyperStrategyMixin): if self.trailing_stop_positive is not None and high_profit > sl_offset: stop_loss_value = self.trailing_stop_positive logger.debug(f"{trade.pair} - Using positive stoploss: {stop_loss_value} " - f"offset: {sl_offset:.4g} profit: {current_profit:.4f}%") + f"offset: {sl_offset:.4g} profit: {current_profit:.2%}") trade.adjust_stop_loss(high or current_rate, stop_loss_value) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 945217b8a..2852ada81 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -1004,7 +1004,7 @@ def test_mix_tag_performance_handle(default_conf, ticker, limit_buy_order, fee, assert len(res) == 1 assert res[0]['mix_tag'] == 'Other Other' assert res[0]['count'] == 1 - assert prec_satoshi(res[0]['profit'], 6.2) + assert prec_satoshi(res[0]['profit_pct'], 6.2) trade.buy_tag = "TESTBUY" trade.sell_reason = "TESTSELL" @@ -1013,7 +1013,7 @@ def test_mix_tag_performance_handle(default_conf, ticker, limit_buy_order, fee, assert len(res) == 1 assert res[0]['mix_tag'] == 'TESTBUY TESTSELL' assert res[0]['count'] == 1 - assert prec_satoshi(res[0]['profit'], 6.2) + assert prec_satoshi(res[0]['profit_pct'], 6.2) def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee): @@ -1032,10 +1032,10 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee): assert len(res) == 2 assert res[0]['mix_tag'] == 'TEST1 sell_signal' assert res[0]['count'] == 1 - assert prec_satoshi(res[0]['profit'], 0.5) + assert prec_satoshi(res[0]['profit_pct'], 0.5) assert res[1]['mix_tag'] == 'Other roi' assert res[1]['count'] == 1 - assert prec_satoshi(res[1]['profit'], 1.0) + assert prec_satoshi(res[1]['profit_pct'], 1.0) # Test for a specific pair res = rpc._rpc_mix_tag_performance('ETC/BTC') @@ -1043,7 +1043,7 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee): assert len(res) == 1 assert res[0]['count'] == 1 assert res[0]['mix_tag'] == 'TEST1 sell_signal' - assert prec_satoshi(res[0]['profit'], 0.5) + assert prec_satoshi(res[0]['profit_pct'], 0.5) def test_rpc_count(mocker, default_conf, ticker, fee) -> None: diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 1f9b1d6b3..629fed76b 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3352,7 +3352,7 @@ def test_trailing_stop_loss_positive( ) # stop-loss not reached, adjusted stoploss assert freqtrade.handle_trade(trade) is False - caplog_text = f"ETH/USDT - Using positive stoploss: 0.01 offset: {offset} profit: 0.0249%" + caplog_text = f"ETH/USDT - Using positive stoploss: 0.01 offset: {offset} profit: 2.49%" if trail_if_reached: assert not log_has(caplog_text, caplog) assert not log_has("ETH/USDT - Adjusting stoploss...", caplog) @@ -3372,7 +3372,7 @@ def test_trailing_stop_loss_positive( ) assert freqtrade.handle_trade(trade) is False assert log_has( - f"ETH/USDT - Using positive stoploss: 0.01 offset: {offset} profit: 0.0572%", + f"ETH/USDT - Using positive stoploss: 0.01 offset: {offset} profit: 5.72%", caplog ) assert log_has("ETH/USDT - Adjusting stoploss...", caplog) From e0fd880c11572ff83aa444008c33805964426a41 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 11 Nov 2021 15:58:30 +0100 Subject: [PATCH 3/3] Improve some more pct formattings --- freqtrade/data/converter.py | 2 +- freqtrade/optimize/optimize_reports.py | 8 ++++---- freqtrade/plot/plotting.py | 2 +- freqtrade/plugins/pairlist/PriceFilter.py | 2 +- freqtrade/plugins/pairlist/SpreadFilter.py | 2 +- tests/test_plotting.py | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/freqtrade/data/converter.py b/freqtrade/data/converter.py index ca6464965..d592b4990 100644 --- a/freqtrade/data/converter.py +++ b/freqtrade/data/converter.py @@ -113,7 +113,7 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, timeframe: str, pair: str) pct_missing = (len_after - len_before) / len_before if len_before > 0 else 0 if len_before != len_after: message = (f"Missing data fillup for {pair}: before: {len_before} - after: {len_after}" - f" - {round(pct_missing * 100, 2)}%") + f" - {pct_missing:.2%}") if pct_missing > 0.01: logger.info(message) else: diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 417bb54ae..c4002fcbe 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -728,16 +728,16 @@ def text_table_add_metrics(strat_results: Dict) -> str: ('Total profit %', f"{strat_results['profit_total']:.2%}"), ('Trades per day', strat_results['trades_per_day']), ('Avg. daily profit %', - f"{round(strat_results['profit_total'] / strat_results['backtest_days'] * 100, 2)}%"), + f"{(strat_results['profit_total'] / strat_results['backtest_days']):.2%}"), ('Avg. stake amount', round_coin_value(strat_results['avg_stake_amount'], strat_results['stake_currency'])), ('Total trade volume', round_coin_value(strat_results['total_volume'], strat_results['stake_currency'])), ('', ''), # Empty line to improve readability ('Best Pair', f"{strat_results['best_pair']['key']} " - f"{round(strat_results['best_pair']['profit_sum_pct'], 2)}%"), + f"{strat_results['best_pair']['profit_sum']:.2%}"), ('Worst Pair', f"{strat_results['worst_pair']['key']} " - f"{round(strat_results['worst_pair']['profit_sum_pct'], 2)}%"), + f"{strat_results['worst_pair']['profit_sum']:.2%}"), ('Best trade', f"{best_trade['pair']} {best_trade['profit_ratio']:.2%}"), ('Worst trade', f"{worst_trade['pair']} " f"{worst_trade['profit_ratio']:.2%}"), @@ -864,5 +864,5 @@ def show_sorted_pairlist(config: Dict, backtest_stats: Dict): print(f"Pairs for Strategy {strategy}: \n[") for result in results['results_per_pair']: if result["key"] != 'TOTAL': - print(f'"{result["key"]}", // {round(result["profit_mean_pct"], 2)}%') + print(f'"{result["key"]}", // {result["profit_mean"]:.2%}') print("]") diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index d2b51f3a2..6d44d56b1 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -192,7 +192,7 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: # Trades can be empty if trades is not None and len(trades) > 0: # Create description for sell summarizing the trade - trades['desc'] = trades.apply(lambda row: f"{round(row['profit_ratio'] * 100, 1)}%, " + trades['desc'] = trades.apply(lambda row: f"{row['profit_ratio']:.2%}, " f"{row['sell_reason']}, " f"{row['trade_duration']} min", axis=1) diff --git a/freqtrade/plugins/pairlist/PriceFilter.py b/freqtrade/plugins/pairlist/PriceFilter.py index 7704ea9aa..63623d8c8 100644 --- a/freqtrade/plugins/pairlist/PriceFilter.py +++ b/freqtrade/plugins/pairlist/PriceFilter.py @@ -50,7 +50,7 @@ class PriceFilter(IPairList): """ active_price_filters = [] if self._low_price_ratio != 0: - active_price_filters.append(f"below {self._low_price_ratio * 100}%") + active_price_filters.append(f"below {self._low_price_ratio:.1%}") if self._min_price != 0: active_price_filters.append(f"below {self._min_price:.8f}") if self._max_price != 0: diff --git a/freqtrade/plugins/pairlist/SpreadFilter.py b/freqtrade/plugins/pairlist/SpreadFilter.py index 20cc97c6a..2d6e728ec 100644 --- a/freqtrade/plugins/pairlist/SpreadFilter.py +++ b/freqtrade/plugins/pairlist/SpreadFilter.py @@ -34,7 +34,7 @@ class SpreadFilter(IPairList): Short whitelist method description - used for startup-messages """ return (f"{self.name} - Filtering pairs with ask/bid diff above " - f"{self._max_spread_ratio * 100}%.") + f"{self._max_spread_ratio:.2%}.") def _validate_pair(self, pair: str, ticker: Dict[str, Any]) -> bool: """ diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 8cbe7f863..8a40f4a20 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -171,7 +171,7 @@ def test_plot_trades(testdatadir, caplog): assert len(trades) == len(trade_buy.x) assert trade_buy.marker.color == 'cyan' assert trade_buy.marker.symbol == 'circle-open' - assert trade_buy.text[0] == '4.0%, roi, 15 min' + assert trade_buy.text[0] == '3.99%, roi, 15 min' trade_sell = find_trace_in_fig_data(figure.data, 'Sell - Profit') assert isinstance(trade_sell, go.Scatter) @@ -179,7 +179,7 @@ def test_plot_trades(testdatadir, caplog): assert len(trades.loc[trades['profit_ratio'] > 0]) == len(trade_sell.x) assert trade_sell.marker.color == 'green' assert trade_sell.marker.symbol == 'square-open' - assert trade_sell.text[0] == '4.0%, roi, 15 min' + assert trade_sell.text[0] == '3.99%, roi, 15 min' trade_sell_loss = find_trace_in_fig_data(figure.data, 'Sell - Loss') assert isinstance(trade_sell_loss, go.Scatter) @@ -187,7 +187,7 @@ def test_plot_trades(testdatadir, caplog): assert len(trades.loc[trades['profit_ratio'] <= 0]) == len(trade_sell_loss.x) assert trade_sell_loss.marker.color == 'red' assert trade_sell_loss.marker.symbol == 'square-open' - assert trade_sell_loss.text[5] == '-10.4%, stop_loss, 720 min' + assert trade_sell_loss.text[5] == '-10.45%, stop_loss, 720 min' def test_generate_candlestick_graph_no_signals_no_trades(default_conf, mocker, testdatadir, caplog):