From e5e3002d455ffb60900a238110f0910f0ad3afb0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Dec 2023 18:05:44 +0100 Subject: [PATCH 01/20] Simplify exit message --- freqtrade/rpc/telegram.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index c9e9a4733..f0d5af3a4 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -359,15 +359,15 @@ class Telegram(RPCHandler): if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 else "") - # Check if all sell properties are available. + # Check if all exit properties are available. # This might not be the case if the message origin is triggered by /forceexit + msg['profit_extra'] = '' if (all(prop in msg for prop in ['gain', 'fiat_currency', 'stake_currency']) and self._rpc._fiat_converter): msg['profit_fiat'] = self._rpc._fiat_converter.convert_amount( msg['profit_amount'], msg['stake_currency'], msg['fiat_currency']) msg['profit_extra'] = f" / {msg['profit_fiat']:.3f} {msg['fiat_currency']}" - else: - msg['profit_extra'] = '' + msg['profit_extra'] = ( f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}" f"{msg['profit_extra']})") From b62661d8cd6d3e6c963f55d7bde5eb8ded1f4448 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Dec 2023 18:15:37 +0100 Subject: [PATCH 02/20] Improve final exit message --- freqtrade/freqtradebot.py | 2 ++ freqtrade/rpc/rpc_types.py | 2 ++ freqtrade/rpc/telegram.py | 20 ++++++++++++++------ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index e09cf9bff..c75dc4e2c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1824,6 +1824,8 @@ class FreqtradeBot(LoggingMixin): 'fiat_currency': self.config.get('fiat_display_currency'), 'sub_trade': sub_trade, 'cumulative_profit': trade.realized_profit, + 'final_profit_ratio': trade.close_profit if not trade.is_open else None, + 'is_final_exit': trade.is_open is False, } # Send the message diff --git a/freqtrade/rpc/rpc_types.py b/freqtrade/rpc/rpc_types.py index c7403dc0f..8deb93067 100644 --- a/freqtrade/rpc/rpc_types.py +++ b/freqtrade/rpc/rpc_types.py @@ -86,6 +86,8 @@ class RPCExitMsg(__RPCEntryExitMsgBase): close_date: datetime # current_rate: Optional[float] order_rate: Optional[float] + final_profit_ratio: Optional[float] + is_final_exit: bool class RPCExitCancelMsg(__RPCEntryExitMsgBase): diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index f0d5af3a4..480a76361 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -373,21 +373,29 @@ class Telegram(RPCHandler): f"{msg['profit_extra']})") is_fill = msg['type'] == RPCMessageType.EXIT_FILL + is_final_exit = msg.get('is_final_exit', False) is_sub_trade = msg.get('sub_trade') is_sub_profit = msg['profit_amount'] != msg.get('cumulative_profit') profit_prefix = ('Sub ' if is_sub_profit else 'Cumulative ') if is_sub_trade else '' cp_extra = '' exit_wording = 'Exited' if is_fill else 'Exiting' - if is_sub_profit and is_sub_trade: + if (is_sub_profit and is_sub_trade) or is_final_exit: if self._rpc._fiat_converter: cp_fiat = self._rpc._fiat_converter.convert_amount( msg['cumulative_profit'], msg['stake_currency'], msg['fiat_currency']) cp_extra = f" / {cp_fiat:.3f} {msg['fiat_currency']}" - exit_wording = f"Partially {exit_wording.lower()}" - cp_extra = ( - f"*Cumulative Profit:* (`{msg['cumulative_profit']:.8f} " - f"{msg['stake_currency']}{cp_extra}`)\n" - ) + if is_final_exit: + profit_prefix = 'Sub ' + cp_extra = ( + f"*Final Profit:* `{msg['final_profit_ratio']:.2%} " + f"({msg['cumulative_profit']:.8f} {msg['stake_currency']}{cp_extra})`\n" + ) + else: + exit_wording = f"Partially {exit_wording.lower()}" + cp_extra = ( + f"*Cumulative Profit:* `({msg['cumulative_profit']:.8f} " + f"{msg['stake_currency']}{cp_extra})`\n" + ) message = ( f"{msg['emoji']} *{self._exchange_from_msg(msg)}:* " From 79e15591effd2855d48877f4498b82604aad3e74 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 29 Dec 2023 18:23:28 +0100 Subject: [PATCH 03/20] Improve condition for last exit (should only show if we had subprofits taken). --- freqtrade/rpc/telegram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 480a76361..33ccd3b7c 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -373,9 +373,9 @@ class Telegram(RPCHandler): f"{msg['profit_extra']})") is_fill = msg['type'] == RPCMessageType.EXIT_FILL - is_final_exit = msg.get('is_final_exit', False) is_sub_trade = msg.get('sub_trade') is_sub_profit = msg['profit_amount'] != msg.get('cumulative_profit') + is_final_exit = msg.get('is_final_exit', False) and is_sub_profit profit_prefix = ('Sub ' if is_sub_profit else 'Cumulative ') if is_sub_trade else '' cp_extra = '' exit_wording = 'Exited' if is_fill else 'Exiting' From e9c04debfb2246788270bd9811c98b01c030da5c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 30 Dec 2023 08:58:44 +0100 Subject: [PATCH 04/20] Fix tests due to new exit behavior --- tests/rpc/test_rpc_telegram.py | 8 +++++++- tests/test_freqtradebot.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 5d190dcc6..446bb3838 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1166,6 +1166,8 @@ async def test_telegram_forceexit_handle(default_conf, update, ticker, fee, 'stake_amount': 0.0009999999999054, 'sub_trade': False, 'cumulative_profit': 0.0, + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg @@ -1239,6 +1241,8 @@ async def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee 'stake_amount': 0.0009999999999054, 'sub_trade': False, 'cumulative_profit': 0.0, + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg @@ -1302,6 +1306,8 @@ async def test_forceexit_all_handle(default_conf, update, ticker, fee, mocker) - 'stake_amount': 0.0009999999999054, 'sub_trade': False, 'cumulative_profit': 0.0, + 'is_final_exit': False, + 'final_profit_ratio': None, } == msg @@ -2220,7 +2226,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Partially exiting KEY/ETH (#1)\n' '*Unrealized Sub Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n' - '*Cumulative Profit:* (`-0.15746268 ETH / -24.812 USD`)\n' + '*Cumulative Profit:* `(-0.15746268 ETH / -24.812 USD)`\n' '*Enter Tag:* `buy_signal1`\n' '*Exit Reason:* `stop_loss`\n' '*Direction:* `Long`\n' diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 06d40dfb0..b82bd0e2e 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -3777,6 +3777,8 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_ 'sub_trade': False, 'cumulative_profit': 0.0, 'stake_amount': pytest.approx(60), + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg @@ -3842,6 +3844,8 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd 'sub_trade': False, 'cumulative_profit': 0.0, 'stake_amount': pytest.approx(60), + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg @@ -3928,6 +3932,8 @@ def test_execute_trade_exit_custom_exit_price( 'sub_trade': False, 'cumulative_profit': 0.0, 'stake_amount': pytest.approx(60), + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg @@ -4001,6 +4007,8 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run( 'sub_trade': False, 'cumulative_profit': 0.0, 'stake_amount': pytest.approx(60), + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg @@ -4267,7 +4275,8 @@ def test_execute_trade_exit_market_order( 'sub_trade': False, 'cumulative_profit': 0.0, 'stake_amount': pytest.approx(60), - + 'is_final_exit': False, + 'final_profit_ratio': None, } == last_msg From 2bceb35b79a970ef3ea35fe84530a38eb070baea Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Jan 2024 19:10:43 +0100 Subject: [PATCH 05/20] Circumvent edge-case in exit notifications if order-amount == remaining amount, it caused a wrong exit msg --- freqtrade/freqtradebot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index c75dc4e2c..cb6d75f99 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1980,15 +1980,15 @@ class FreqtradeBot(LoggingMixin): self, trade: Trade, order: Order, stoploss_order: bool, send_msg: bool): """send "fill" notifications""" - sub_trade = not isclose(order.safe_amount_after_fee, - trade.amount, abs_tol=constants.MATH_CLOSE_PREC) if order.ft_order_side == trade.exit_side: # Exit notification if send_msg and not stoploss_order and order.order_id not in trade.open_orders_ids: - self._notify_exit(trade, '', fill=True, sub_trade=sub_trade, order=order) + self._notify_exit(trade, '', fill=True, sub_trade=trade.is_open, order=order) if not trade.is_open: self.handle_protections(trade.pair, trade.trade_direction) elif send_msg and order.order_id not in trade.open_orders_ids and not stoploss_order: + sub_trade = not isclose(order.safe_amount_after_fee, + trade.amount, abs_tol=constants.MATH_CLOSE_PREC) # Enter fill self._notify_enter(trade, order, order.order_type, fill=True, sub_trade=sub_trade) From 86a9968bdd4de539fa5cca14a57fda9dfd907909 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 5 Jan 2024 19:15:21 +0100 Subject: [PATCH 06/20] Fix bug in exit message formatting --- freqtrade/rpc/telegram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 33ccd3b7c..e5fbb1432 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -379,7 +379,7 @@ class Telegram(RPCHandler): profit_prefix = ('Sub ' if is_sub_profit else 'Cumulative ') if is_sub_trade else '' cp_extra = '' exit_wording = 'Exited' if is_fill else 'Exiting' - if (is_sub_profit and is_sub_trade) or is_final_exit: + if is_sub_trade or is_final_exit: if self._rpc._fiat_converter: cp_fiat = self._rpc._fiat_converter.convert_amount( msg['cumulative_profit'], msg['stake_currency'], msg['fiat_currency']) From 934e72656abb5f5caf8599a16dbedaf170105c04 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:23:21 +0100 Subject: [PATCH 07/20] Simplify exit message fiat handling --- freqtrade/rpc/telegram.py | 21 +++++++++++---------- tests/rpc/test_rpc_telegram.py | 2 ++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index e5fbb1432..f342f4709 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -347,6 +347,7 @@ class Telegram(RPCHandler): return message def _format_exit_msg(self, msg: Dict[str, Any]) -> str: + fiat_currency = msg['fiat_currency'] msg['amount'] = round(msg['amount'], 8) msg['profit_percent'] = round(msg['profit_ratio'] * 100, 2) msg['duration'] = msg['close_date'].replace( @@ -362,11 +363,11 @@ class Telegram(RPCHandler): # Check if all exit properties are available. # This might not be the case if the message origin is triggered by /forceexit msg['profit_extra'] = '' - if (all(prop in msg for prop in ['gain', 'fiat_currency', 'stake_currency']) - and self._rpc._fiat_converter): - msg['profit_fiat'] = self._rpc._fiat_converter.convert_amount( - msg['profit_amount'], msg['stake_currency'], msg['fiat_currency']) - msg['profit_extra'] = f" / {msg['profit_fiat']:.3f} {msg['fiat_currency']}" + + if self._rpc._fiat_converter and fiat_currency: + profit_fiat = self._rpc._fiat_converter.convert_amount( + msg['profit_amount'], msg['stake_currency'], fiat_currency) + msg['profit_extra'] = f" / {profit_fiat:.3f} {fiat_currency}" msg['profit_extra'] = ( f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}" @@ -382,8 +383,8 @@ class Telegram(RPCHandler): if is_sub_trade or is_final_exit: if self._rpc._fiat_converter: cp_fiat = self._rpc._fiat_converter.convert_amount( - msg['cumulative_profit'], msg['stake_currency'], msg['fiat_currency']) - cp_extra = f" / {cp_fiat:.3f} {msg['fiat_currency']}" + msg['cumulative_profit'], msg['stake_currency'], fiat_currency) + cp_extra = f" / {cp_fiat:.3f} {fiat_currency}" if is_final_exit: profit_prefix = 'Sub ' cp_extra = ( @@ -421,14 +422,14 @@ class Telegram(RPCHandler): if is_sub_trade: if self._rpc._fiat_converter: msg['stake_amount_fiat'] = self._rpc._fiat_converter.convert_amount( - msg['stake_amount'], msg['stake_currency'], msg['fiat_currency']) + msg['stake_amount'], msg['stake_currency'], fiat_currency) else: msg['stake_amount_fiat'] = 0 rem = round_coin_value(msg['stake_amount'], msg['stake_currency']) message += f"\n*Remaining:* `({rem}" - if msg.get('fiat_currency', None): - message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" + if fiat_currency: + message += f", {round_coin_value(msg['stake_amount_fiat'], fiat_currency)}" message += ")`" else: diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 446bb3838..54f346cad 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2253,6 +2253,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: 'profit_amount': -0.05746268, 'profit_ratio': -0.57405275, 'stake_currency': 'ETH', + 'fiat_currency': None, 'enter_tag': 'buy_signal1', 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': dt_now() - timedelta(days=1, hours=2, minutes=30), @@ -2335,6 +2336,7 @@ def test_send_msg_sell_fill_notification(default_conf, mocker, direction, 'profit_amount': -0.05746268, 'profit_ratio': -0.57405275, 'stake_currency': 'ETH', + 'fiat_currency': None, 'enter_tag': enter_signal, 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': dt_now() - timedelta(days=1, hours=2, minutes=30), From 0ab54b88cfed9c424fe5a2bba35ba72ea94d13da Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:26:49 +0100 Subject: [PATCH 08/20] Improve leverage formatting --- freqtrade/rpc/telegram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index f342f4709..a345641e0 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -330,7 +330,7 @@ class Telegram(RPCHandler): message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message += f"*Amount:* `{msg['amount']:.8f}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0: - message += f"*Leverage:* `{msg['leverage']}`\n" + message += f"*Leverage:* `{msg['leverage']:.1g}`\n" if msg['type'] in [RPCMessageType.ENTRY_FILL]: message += f"*Open Rate:* `{msg['open_rate']:.8f}`\n" @@ -356,7 +356,7 @@ class Telegram(RPCHandler): msg['enter_tag'] = msg['enter_tag'] if "enter_tag" in msg.keys() else None msg['emoji'] = self._get_sell_emoji(msg) - msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1f}`\n" + msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1g}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 else "") From c3ce11c222373d66860b92cf982cccea3558210c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:28:17 +0100 Subject: [PATCH 09/20] Simplify enter_tag call --- freqtrade/rpc/telegram.py | 1 - 1 file changed, 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index a345641e0..81b148846 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -354,7 +354,6 @@ class Telegram(RPCHandler): microsecond=0) - msg['open_date'].replace(microsecond=0) msg['duration_min'] = msg['duration'].total_seconds() / 60 - msg['enter_tag'] = msg['enter_tag'] if "enter_tag" in msg.keys() else None msg['emoji'] = self._get_sell_emoji(msg) msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1g}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 From 5e9a929e9e9c6cdcdcb90b952c17ab8dffae93a8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:31:03 +0100 Subject: [PATCH 10/20] Further simplify msg formatting --- freqtrade/rpc/telegram.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 81b148846..533dbafe5 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -348,7 +348,6 @@ class Telegram(RPCHandler): def _format_exit_msg(self, msg: Dict[str, Any]) -> str: fiat_currency = msg['fiat_currency'] - msg['amount'] = round(msg['amount'], 8) msg['profit_percent'] = round(msg['profit_ratio'] * 100, 2) msg['duration'] = msg['close_date'].replace( microsecond=0) - msg['open_date'].replace(microsecond=0) @@ -408,7 +407,7 @@ class Telegram(RPCHandler): f"*Exit Reason:* `{msg['exit_reason']}`\n" f"*Direction:* `{msg['direction']}`\n" f"{msg['leverage_text']}" - f"*Amount:* `{msg['amount']:.8f}`\n" + f"*Amount:* `{round(msg['amount'], 8):.8f}`\n" f"*Open Rate:* `{msg['open_rate']:.8f}`\n" ) if msg['type'] == RPCMessageType.EXIT: From 8726d63923f1ef4cb98b5d76caaf5ecd7561c157 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:33:18 +0100 Subject: [PATCH 11/20] Remove unnecessary calculations for exit msg --- freqtrade/rpc/telegram.py | 11 +++++------ tests/rpc/test_rpc_telegram.py | 14 +++++++------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 533dbafe5..e51842d0a 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -348,10 +348,9 @@ class Telegram(RPCHandler): def _format_exit_msg(self, msg: Dict[str, Any]) -> str: fiat_currency = msg['fiat_currency'] - msg['profit_percent'] = round(msg['profit_ratio'] * 100, 2) - msg['duration'] = msg['close_date'].replace( + duration = msg['close_date'].replace( microsecond=0) - msg['open_date'].replace(microsecond=0) - msg['duration_min'] = msg['duration'].total_seconds() / 60 + duration_min = duration.total_seconds() / 60 msg['emoji'] = self._get_sell_emoji(msg) msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1g}`\n" @@ -431,7 +430,7 @@ class Telegram(RPCHandler): message += ")`" else: - message += f"\n*Duration:* `{msg['duration']} ({msg['duration_min']:.1f} min)`" + message += f"\n*Duration:* `{duration} ({duration_min:.1f} min)`" return message def compose_message(self, msg: Dict[str, Any], msg_type: RPCMessageType) -> Optional[str]: @@ -513,9 +512,9 @@ class Telegram(RPCHandler): Get emoji for sell-side """ - if float(msg['profit_percent']) >= 5.0: + if float(msg['profit_ratio']) >= 0.05: return "\N{ROCKET}" - elif float(msg['profit_percent']) >= 0.0: + elif float(msg['profit_ratio']) >= 0.0: return "\N{EIGHT SPOKED ASTERISK}" elif msg['exit_reason'] == "stop_loss": return "\N{WARNING SIGN}" diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 54f346cad..f98990990 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2497,13 +2497,13 @@ def test_send_msg_sell_notification_no_fiat( @pytest.mark.parametrize('msg,expected', [ - ({'profit_percent': 20.1, 'exit_reason': 'roi'}, "\N{ROCKET}"), - ({'profit_percent': 5.1, 'exit_reason': 'roi'}, "\N{ROCKET}"), - ({'profit_percent': 2.56, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), - ({'profit_percent': 1.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), - ({'profit_percent': 0.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), - ({'profit_percent': -5.0, 'exit_reason': 'stop_loss'}, "\N{WARNING SIGN}"), - ({'profit_percent': -2.0, 'exit_reason': 'sell_signal'}, "\N{CROSS MARK}"), + ({'profit_ratio': 0.201, 'exit_reason': 'roi'}, "\N{ROCKET}"), + ({'profit_ratio': 0.051, 'exit_reason': 'roi'}, "\N{ROCKET}"), + ({'profit_ratio': 0.0256, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_ratio': 0.01, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_ratio': 0.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_ratio': -0.05, 'exit_reason': 'stop_loss'}, "\N{WARNING SIGN}"), + ({'profit_ratio': -0.02, 'exit_reason': 'sell_signal'}, "\N{CROSS MARK}"), ]) def test__sell_emoji(default_conf, mocker, msg, expected): del default_conf['fiat_display_currency'] From 7b78e66e7d51f6c626b468a3315a958e9aba606d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:46:01 +0100 Subject: [PATCH 12/20] Ajust some leverage calls --- tests/rpc/test_rpc_telegram.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index f98990990..055aad15f 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2014,7 +2014,7 @@ def test_send_msg_enter_notification(default_conf, mocker, caplog, message_type, telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) telegram.send_msg(msg) - leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else '' + leverage_text = f'*Leverage:* `{leverage:.1g}`\n' if leverage and leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( f'\N{LARGE BLUE CIRCLE} *Binance (dry):* {enter} ETH/BTC (#1)\n' @@ -2118,7 +2118,7 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en 'amount': 1333.3333333333335, 'open_date': dt_now() - timedelta(hours=1) }) - leverage_text = f'*Leverage:* `{leverage}`\n' if leverage != 1.0 else '' + leverage_text = f'*Leverage:* `{leverage:.1g}`\n' if leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( f'\N{CHECK MARK} *Binance (dry):* {entered}ed ETH/BTC (#1)\n' f'*Enter Tag:* `{enter_signal}`\n' @@ -2343,7 +2343,7 @@ def test_send_msg_sell_fill_notification(default_conf, mocker, direction, 'close_date': dt_now(), }) - leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else '' + leverage_text = f'*Leverage:* `{leverage:.1g}`\n' if leverage and leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Exited KEY/ETH (#1)\n' '*Profit:* `-57.41% (loss: -0.05746268 ETH)`\n' @@ -2433,7 +2433,7 @@ def test_send_msg_buy_notification_no_fiat( 'open_date': dt_now() - timedelta(hours=1) }) - leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else '' + leverage_text = f'*Leverage:* `{leverage:.1g}`\n' if leverage and leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( f'\N{LARGE BLUE CIRCLE} *Binance:* {enter} ETH/BTC (#1)\n' f'*Enter Tag:* `{enter_signal}`\n' @@ -2480,7 +2480,7 @@ def test_send_msg_sell_notification_no_fiat( 'close_date': dt_now(), }) - leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else '' + leverage_text = f'*Leverage:* `{leverage:.1g}`\n' if leverage and leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n' '*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH)`\n' From e4977d4cbd8f545fbbf5e8559a2a0d5cabb4f696 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 10:55:00 +0100 Subject: [PATCH 13/20] Don't assign the original message dict for no reason --- freqtrade/rpc/telegram.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index e51842d0a..91ac6e7ce 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -352,23 +352,23 @@ class Telegram(RPCHandler): microsecond=0) - msg['open_date'].replace(microsecond=0) duration_min = duration.total_seconds() / 60 - msg['emoji'] = self._get_sell_emoji(msg) - msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1g}`\n" - if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 - else "") + emoji = self._get_sell_emoji(msg) + leverage_text = (f"*Leverage:* `{msg['leverage']:.1g}`\n" + if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 + else "") # Check if all exit properties are available. # This might not be the case if the message origin is triggered by /forceexit - msg['profit_extra'] = '' + profit_extra = '' if self._rpc._fiat_converter and fiat_currency: profit_fiat = self._rpc._fiat_converter.convert_amount( msg['profit_amount'], msg['stake_currency'], fiat_currency) - msg['profit_extra'] = f" / {profit_fiat:.3f} {fiat_currency}" + profit_extra = f" / {profit_fiat:.3f} {fiat_currency}" - msg['profit_extra'] = ( + profit_extra = ( f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}" - f"{msg['profit_extra']})") + f"{profit_extra})") is_fill = msg['type'] == RPCMessageType.EXIT_FILL is_sub_trade = msg.get('sub_trade') @@ -396,16 +396,16 @@ class Telegram(RPCHandler): ) message = ( - f"{msg['emoji']} *{self._exchange_from_msg(msg)}:* " + f"{emoji} *{self._exchange_from_msg(msg)}:* " f"{exit_wording} {msg['pair']} (#{msg['trade_id']})\n" f"{self._add_analyzed_candle(msg['pair'])}" f"*{f'{profit_prefix}Profit' if is_fill else f'Unrealized {profit_prefix}Profit'}:* " - f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n" + f"`{msg['profit_ratio']:.2%}{profit_extra}`\n" f"{cp_extra}" f"*Enter Tag:* `{msg['enter_tag']}`\n" f"*Exit Reason:* `{msg['exit_reason']}`\n" f"*Direction:* `{msg['direction']}`\n" - f"{msg['leverage_text']}" + f"{leverage_text}" f"*Amount:* `{round(msg['amount'], 8):.8f}`\n" f"*Open Rate:* `{msg['open_rate']:.8f}`\n" ) From 690a3599d07f864ae1aa962cc9a7b9f4b4334f01 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:06:05 +0100 Subject: [PATCH 14/20] Simplify exit msg method further --- freqtrade/rpc/telegram.py | 52 ++++++++++++++-------------------- tests/rpc/test_rpc_telegram.py | 2 +- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 91ac6e7ce..c9b0d0a4b 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -347,28 +347,19 @@ class Telegram(RPCHandler): return message def _format_exit_msg(self, msg: Dict[str, Any]) -> str: - fiat_currency = msg['fiat_currency'] duration = msg['close_date'].replace( microsecond=0) - msg['open_date'].replace(microsecond=0) duration_min = duration.total_seconds() / 60 - emoji = self._get_sell_emoji(msg) leverage_text = (f"*Leverage:* `{msg['leverage']:.1g}`\n" if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0 else "") - # Check if all exit properties are available. - # This might not be the case if the message origin is triggered by /forceexit - profit_extra = '' - - if self._rpc._fiat_converter and fiat_currency: - profit_fiat = self._rpc._fiat_converter.convert_amount( - msg['profit_amount'], msg['stake_currency'], fiat_currency) - profit_extra = f" / {profit_fiat:.3f} {fiat_currency}" + profit_fiat_extra = self.__format_profit_fiat(msg, 'profit_amount') profit_extra = ( f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}" - f"{profit_extra})") + f"{profit_fiat_extra})") is_fill = msg['type'] == RPCMessageType.EXIT_FILL is_sub_trade = msg.get('sub_trade') @@ -378,25 +369,23 @@ class Telegram(RPCHandler): cp_extra = '' exit_wording = 'Exited' if is_fill else 'Exiting' if is_sub_trade or is_final_exit: - if self._rpc._fiat_converter: - cp_fiat = self._rpc._fiat_converter.convert_amount( - msg['cumulative_profit'], msg['stake_currency'], fiat_currency) - cp_extra = f" / {cp_fiat:.3f} {fiat_currency}" + cp_fiat = self.__format_profit_fiat(msg, 'cumulative_profit') + if is_final_exit: profit_prefix = 'Sub ' cp_extra = ( f"*Final Profit:* `{msg['final_profit_ratio']:.2%} " - f"({msg['cumulative_profit']:.8f} {msg['stake_currency']}{cp_extra})`\n" + f"({msg['cumulative_profit']:.8f} {msg['stake_currency']}{cp_fiat})`\n" ) else: exit_wording = f"Partially {exit_wording.lower()}" cp_extra = ( f"*Cumulative Profit:* `({msg['cumulative_profit']:.8f} " - f"{msg['stake_currency']}{cp_extra})`\n" + f"{msg['stake_currency']}{cp_fiat})`\n" ) message = ( - f"{emoji} *{self._exchange_from_msg(msg)}:* " + f"{self._get_sell_emoji(msg)} *{self._exchange_from_msg(msg)}:* " f"{exit_wording} {msg['pair']} (#{msg['trade_id']})\n" f"{self._add_analyzed_candle(msg['pair'])}" f"*{f'{profit_prefix}Profit' if is_fill else f'Unrealized {profit_prefix}Profit'}:* " @@ -413,26 +402,29 @@ class Telegram(RPCHandler): message += f"*Current Rate:* `{msg['current_rate']:.8f}`\n" if msg['order_rate']: message += f"*Exit Rate:* `{msg['order_rate']:.8f}`" - elif msg['type'] == RPCMessageType.EXIT_FILL: message += f"*Exit Rate:* `{msg['close_rate']:.8f}`" + if is_sub_trade: - if self._rpc._fiat_converter: - msg['stake_amount_fiat'] = self._rpc._fiat_converter.convert_amount( - msg['stake_amount'], msg['stake_currency'], fiat_currency) - else: - msg['stake_amount_fiat'] = 0 + stake_amount_fiat = self.__format_profit_fiat(msg, 'stake_amount') + rem = round_coin_value(msg['stake_amount'], msg['stake_currency']) - message += f"\n*Remaining:* `({rem}" - - if fiat_currency: - message += f", {round_coin_value(msg['stake_amount_fiat'], fiat_currency)}" - - message += ")`" + message += f"\n*Remaining:* `({rem}{stake_amount_fiat})`" else: message += f"\n*Duration:* `{duration} ({duration_min:.1f} min)`" return message + def __format_profit_fiat(self, msg: Dict[str, Any], key: str) -> str: + """ + Format Fiat currency to append to regular profit output + """ + profit_fiat_extra = '' + if self._rpc._fiat_converter and (fiat_currency := msg.get('fiat_currency')): + profit_fiat = self._rpc._fiat_converter.convert_amount( + msg[key], msg['stake_currency'], fiat_currency) + profit_fiat_extra = f" / {profit_fiat:.3f} {fiat_currency}" + return profit_fiat_extra + def compose_message(self, msg: Dict[str, Any], msg_type: RPCMessageType) -> Optional[str]: if msg_type in [RPCMessageType.ENTRY, RPCMessageType.ENTRY_FILL]: message = self._format_entry_msg(msg) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 055aad15f..88ce6393e 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2234,7 +2234,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' '*Exit Rate:* `0.00003201`\n' - '*Remaining:* `(0.01 ETH, -24.812 USD)`' + '*Remaining:* `(0.01 ETH / -24.812 USD)`' ) msg_mock.reset_mock() From 685fef1ee85db4f28c86bfbb080b4d14f8a87b86 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:22:37 +0100 Subject: [PATCH 15/20] Improve buy message FIAT formatting --- freqtrade/rpc/telegram.py | 13 ++++--------- tests/rpc/test_rpc_telegram.py | 8 ++++---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index c9b0d0a4b..daecad465 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -311,11 +311,7 @@ class Telegram(RPCHandler): return '' def _format_entry_msg(self, msg: Dict[str, Any]) -> str: - if self._rpc._fiat_converter: - msg['stake_amount_fiat'] = self._rpc._fiat_converter.convert_amount( - msg['stake_amount'], msg['stake_currency'], msg['fiat_currency']) - else: - msg['stake_amount_fiat'] = 0 + is_fill = msg['type'] in [RPCMessageType.ENTRY_FILL] emoji = '\N{CHECK MARK}' if is_fill else '\N{LARGE BLUE CIRCLE}' @@ -338,12 +334,11 @@ class Telegram(RPCHandler): message += f"*Open Rate:* `{msg['open_rate']:.8f}`\n"\ f"*Current Rate:* `{msg['current_rate']:.8f}`\n" - message += f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}" + profit_fiat_extra = self.__format_profit_fiat(msg, 'stake_amount') + total = round_coin_value(msg['stake_amount'], msg['stake_currency']) - if msg.get('fiat_currency'): - message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" + message += f"*Total:* `{total}{profit_fiat_extra}`" - message += ")`" return message def _format_exit_msg(self, msg: Dict[str, Any]) -> str: diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 88ce6393e..bef7b62e7 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2024,7 +2024,7 @@ def test_send_msg_enter_notification(default_conf, mocker, caplog, message_type, f'{leverage_text}' '*Open Rate:* `0.00001099`\n' '*Current Rate:* `0.00001099`\n' - '*Total:* `(0.01465333 BTC, 180.895 USD)`' + '*Total:* `0.01465333 BTC / 180.895 USD`' ) freqtradebot.config['telegram']['notification_settings'] = {'buy': 'off'} @@ -2125,7 +2125,7 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en '*Amount:* `1333.33333333`\n' f"{leverage_text}" '*Open Rate:* `0.00001099`\n' - '*Total:* `(0.01465333 BTC, 180.895 USD)`' + '*Total:* `0.01465333 BTC / 180.895 USD`' ) msg_mock.reset_mock() @@ -2152,7 +2152,7 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en '*Amount:* `1333.33333333`\n' f"{leverage_text}" '*Open Rate:* `0.00001099`\n' - '*Total:* `(0.01465333 BTC, 180.895 USD)`' + '*Total:* `0.01465333 BTC / 180.895 USD`' ) @@ -2441,7 +2441,7 @@ def test_send_msg_buy_notification_no_fiat( f'{leverage_text}' '*Open Rate:* `0.00001099`\n' '*Current Rate:* `0.00001099`\n' - '*Total:* `(0.01465333 BTC)`' + '*Total:* `0.01465333 BTC`' ) From 59ec3fd8601cf3f32fb518fd1425ed1a171aca16 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:29:02 +0100 Subject: [PATCH 16/20] Always send order-type to exit notifications --- freqtrade/freqtradebot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index cb6d75f99..c4806b2b0 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1983,7 +1983,8 @@ class FreqtradeBot(LoggingMixin): if order.ft_order_side == trade.exit_side: # Exit notification if send_msg and not stoploss_order and order.order_id not in trade.open_orders_ids: - self._notify_exit(trade, '', fill=True, sub_trade=trade.is_open, order=order) + self._notify_exit(trade, order.order_type, fill=True, + sub_trade=trade.is_open, order=order) if not trade.is_open: self.handle_protections(trade.pair, trade.trade_direction) elif send_msg and order.order_id not in trade.open_orders_ids and not stoploss_order: From 2a11597ad3803087c26abae646f8b6ab0a5d7b3a Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:30:45 +0100 Subject: [PATCH 17/20] Improve exit message wording --- freqtrade/rpc/telegram.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index daecad465..10b0420bc 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -360,7 +360,7 @@ class Telegram(RPCHandler): is_sub_trade = msg.get('sub_trade') is_sub_profit = msg['profit_amount'] != msg.get('cumulative_profit') is_final_exit = msg.get('is_final_exit', False) and is_sub_profit - profit_prefix = ('Sub ' if is_sub_profit else 'Cumulative ') if is_sub_trade else '' + profit_prefix = 'Sub ' if is_sub_trade else '' cp_extra = '' exit_wording = 'Exited' if is_fill else 'Exiting' if is_sub_trade or is_final_exit: @@ -374,11 +374,12 @@ class Telegram(RPCHandler): ) else: exit_wording = f"Partially {exit_wording.lower()}" - cp_extra = ( - f"*Cumulative Profit:* `({msg['cumulative_profit']:.8f} " - f"{msg['stake_currency']}{cp_fiat})`\n" - ) - + if msg['cumulative_profit']: + cp_extra = ( + f"*Cumulative Profit:* `({msg['cumulative_profit']:.8f} " + f"{msg['stake_currency']}{cp_fiat})`\n" + ) + enter_tag = f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message = ( f"{self._get_sell_emoji(msg)} *{self._exchange_from_msg(msg)}:* " f"{exit_wording} {msg['pair']} (#{msg['trade_id']})\n" @@ -386,7 +387,7 @@ class Telegram(RPCHandler): f"*{f'{profit_prefix}Profit' if is_fill else f'Unrealized {profit_prefix}Profit'}:* " f"`{msg['profit_ratio']:.2%}{profit_extra}`\n" f"{cp_extra}" - f"*Enter Tag:* `{msg['enter_tag']}`\n" + f"{enter_tag}" f"*Exit Reason:* `{msg['exit_reason']}`\n" f"*Direction:* `{msg['direction']}`\n" f"{leverage_text}" From 3237cad8c8a24bb41bb8d01b77d544ae4aba4eff Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:32:58 +0100 Subject: [PATCH 18/20] Fix test naming from sell to exit --- freqtrade/rpc/telegram.py | 6 +++--- tests/rpc/test_rpc_telegram.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 10b0420bc..6c0572467 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -381,7 +381,7 @@ class Telegram(RPCHandler): ) enter_tag = f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message = ( - f"{self._get_sell_emoji(msg)} *{self._exchange_from_msg(msg)}:* " + f"{self._get_exit_emoji(msg)} *{self._exchange_from_msg(msg)}:* " f"{exit_wording} {msg['pair']} (#{msg['trade_id']})\n" f"{self._add_analyzed_candle(msg['pair'])}" f"*{f'{profit_prefix}Profit' if is_fill else f'Unrealized {profit_prefix}Profit'}:* " @@ -495,9 +495,9 @@ class Telegram(RPCHandler): self._send_msg(message, disable_notification=(noti == 'silent')), self._loop) - def _get_sell_emoji(self, msg): + def _get_exit_emoji(self, msg): """ - Get emoji for sell-side + Get emoji for exit-messages """ if float(msg['profit_ratio']) >= 0.05: diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index bef7b62e7..8058fa99c 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2156,7 +2156,7 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en ) -def test_send_msg_sell_notification(default_conf, mocker) -> None: +def test_send_msg_exit_notification(default_conf, mocker) -> None: with time_machine.travel("2022-09-01 05:00:00 +00:00", tick=False): telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -2275,7 +2275,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: telegram._rpc._fiat_converter.convert_amount = old_convamount -async def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: +async def test_send_msg_exit_cancel_notification(default_conf, mocker) -> None: telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -2313,7 +2313,7 @@ async def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: ('Long', 'long_signal_01', 1.0), ('Long', 'long_signal_01', 5.0), ('Short', 'short_signal_01', 2.0)]) -def test_send_msg_sell_fill_notification(default_conf, mocker, direction, +def test_send_msg_exit_fill_notification(default_conf, mocker, direction, enter_signal, leverage) -> None: default_conf['telegram']['notification_settings']['exit_fill'] = 'on' @@ -2451,7 +2451,7 @@ def test_send_msg_buy_notification_no_fiat( ('Long', 'long_signal_01', 5.0), ('Short', 'short_signal_01', 2.0), ]) -def test_send_msg_sell_notification_no_fiat( +def test_send_msg_exit_notification_no_fiat( default_conf, mocker, direction, enter_signal, leverage, time_machine) -> None: del default_conf['fiat_display_currency'] time_machine.move_to('2022-05-02 00:00:00 +00:00', tick=False) @@ -2505,12 +2505,12 @@ def test_send_msg_sell_notification_no_fiat( ({'profit_ratio': -0.05, 'exit_reason': 'stop_loss'}, "\N{WARNING SIGN}"), ({'profit_ratio': -0.02, 'exit_reason': 'sell_signal'}, "\N{CROSS MARK}"), ]) -def test__sell_emoji(default_conf, mocker, msg, expected): +def test__exit_emoji(default_conf, mocker, msg, expected): del default_conf['fiat_display_currency'] telegram, _, _ = get_telegram_testobject(mocker, default_conf) - assert telegram._get_sell_emoji(msg) == expected + assert telegram._get_exit_emoji(msg) == expected async def test_telegram__send_msg(default_conf, mocker, caplog) -> None: From 90df6bcd5437898474d68edc131d410ecc5692c5 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:48:25 +0100 Subject: [PATCH 19/20] Remove pointless parenteses --- freqtrade/rpc/telegram.py | 6 +++--- tests/rpc/test_rpc_telegram.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 6c0572467..5467bf1d5 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -376,8 +376,8 @@ class Telegram(RPCHandler): exit_wording = f"Partially {exit_wording.lower()}" if msg['cumulative_profit']: cp_extra = ( - f"*Cumulative Profit:* `({msg['cumulative_profit']:.8f} " - f"{msg['stake_currency']}{cp_fiat})`\n" + f"*Cumulative Profit:* `{msg['cumulative_profit']:.8f} " + f"{msg['stake_currency']}{cp_fiat}`\n" ) enter_tag = f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else "" message = ( @@ -405,7 +405,7 @@ class Telegram(RPCHandler): stake_amount_fiat = self.__format_profit_fiat(msg, 'stake_amount') rem = round_coin_value(msg['stake_amount'], msg['stake_currency']) - message += f"\n*Remaining:* `({rem}{stake_amount_fiat})`" + message += f"\n*Remaining:* `{rem}{stake_amount_fiat}`" else: message += f"\n*Duration:* `{duration} ({duration_min:.1f} min)`" return message diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 8058fa99c..33a47d295 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -2226,7 +2226,7 @@ def test_send_msg_exit_notification(default_conf, mocker) -> None: assert msg_mock.call_args[0][0] == ( '\N{WARNING SIGN} *Binance (dry):* Partially exiting KEY/ETH (#1)\n' '*Unrealized Sub Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n' - '*Cumulative Profit:* `(-0.15746268 ETH / -24.812 USD)`\n' + '*Cumulative Profit:* `-0.15746268 ETH / -24.812 USD`\n' '*Enter Tag:* `buy_signal1`\n' '*Exit Reason:* `stop_loss`\n' '*Direction:* `Long`\n' @@ -2234,7 +2234,7 @@ def test_send_msg_exit_notification(default_conf, mocker) -> None: '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' '*Exit Rate:* `0.00003201`\n' - '*Remaining:* `(0.01 ETH / -24.812 USD)`' + '*Remaining:* `0.01 ETH / -24.812 USD`' ) msg_mock.reset_mock() From 7f84996c1ed1eb99a300b9144afaf159aadb01b1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jan 2024 11:53:14 +0100 Subject: [PATCH 20/20] Send correct Profit for both exit types --- freqtrade/freqtradebot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index c4806b2b0..879f66af2 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -1810,7 +1810,7 @@ class FreqtradeBot(LoggingMixin): 'open_rate': trade.open_rate, 'close_rate': order_rate, 'current_rate': current_rate, - 'profit_amount': profit.profit_abs if fill else profit.total_profit, + 'profit_amount': profit.profit_abs, 'profit_ratio': profit.profit_ratio, 'buy_tag': trade.enter_tag, 'enter_tag': trade.enter_tag,