From 10ef0f54ac7847e34fc4f096a50b63144bafb42e Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 11:12:11 +0300 Subject: [PATCH 1/7] Total row for telegram "/status table" command --- freqtrade/rpc/telegram.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 2e288ee33..157a2b9a5 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -5,6 +5,7 @@ This module manage Telegram communication """ import json import logging +import re from datetime import timedelta from html import escape from itertools import chain @@ -354,19 +355,33 @@ class Telegram(RPCHandler): :return: None """ try: + fiat_currency = self._config.get('fiat_display_currency', '') statlist, head = self._rpc._rpc_status_table( - self._config['stake_currency'], self._config.get('fiat_display_currency', '')) + self._config['stake_currency'], fiat_currency) + show_total = fiat_currency != '' + total_sum = 0 + if show_total: + total_sum = sum(map(lambda m: float(m[1]) if m else 0, map(lambda trade: re.compile(".*\((-?\d*\.\d*)\)").match(trade[-1]), statlist))) max_trades_per_msg = 50 """ Calculate the number of messages of 50 trades per message 0.99 is used to make sure that there are no extra (empty) messages As an example with 50 trades, there will be int(50/50 + 0.99) = 1 message """ - for i in range(0, max(int(len(statlist) / max_trades_per_msg + 0.99), 1)): + messages_count = max(int(len(statlist) / max_trades_per_msg + 0.99), 1) + for i in range(0, messages_count): + if show_total and i == messages_count - 1: + # append total line + trades.append(["Total", "", "", f"{total_sum:.2f} {fiat_currency}"]) + message = tabulate(statlist[i * max_trades_per_msg:(i + 1) * max_trades_per_msg], headers=head, tablefmt='simple') + if show_total and i == messages_count - 1: + # insert separators line between Total + lines = message.split("\n") + message = "\n".join(lines[:-1] + [lines[1]] + [lines[-1]]) self._send_msg(f"
{message}
", parse_mode=ParseMode.HTML) except RPCException as e: self._send_msg(str(e)) From 0abb9cfe2854ba02d02a048e74ee09667f5846a2 Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 12:41:44 +0300 Subject: [PATCH 2/7] Total row for telegram "/status table" command --- freqtrade/rpc/telegram.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 157a2b9a5..d4a79e860 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -371,11 +371,12 @@ class Telegram(RPCHandler): """ messages_count = max(int(len(statlist) / max_trades_per_msg + 0.99), 1) for i in range(0, messages_count): + trades = statlist[i * max_trades_per_msg:(i + 1) * max_trades_per_msg] if show_total and i == messages_count - 1: # append total line trades.append(["Total", "", "", f"{total_sum:.2f} {fiat_currency}"]) - message = tabulate(statlist[i * max_trades_per_msg:(i + 1) * max_trades_per_msg], + message = tabulate(trades, headers=head, tablefmt='simple') if show_total and i == messages_count - 1: From d7479fda1fbc12bd1e48c40e1f4d0a4e0d79f22f Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 12:53:57 +0300 Subject: [PATCH 3/7] Total row for telegram "/status table" command fix compiler warnings --- freqtrade/rpc/telegram.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index d4a79e860..11b84de19 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -362,7 +362,11 @@ class Telegram(RPCHandler): show_total = fiat_currency != '' total_sum = 0 if show_total: - total_sum = sum(map(lambda m: float(m[1]) if m else 0, map(lambda trade: re.compile(".*\((-?\d*\.\d*)\)").match(trade[-1]), statlist))) + total_sum = sum( + map(lambda m: float(m[1]) if m else 0, + map(lambda trade: re.compile(".*\\((-?\\d*\\.\\d*)\\)").match(trade[-1]), + statlist)) + ) max_trades_per_msg = 50 """ Calculate the number of messages of 50 trades per message From 915ff7e1bf1887795b4a561d737c9b2f56b2eba8 Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 13:03:20 +0300 Subject: [PATCH 4/7] Total row for telegram "/status table" command fix mypy warnings --- 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 11b84de19..6a12488d1 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -363,7 +363,7 @@ class Telegram(RPCHandler): total_sum = 0 if show_total: total_sum = sum( - map(lambda m: float(m[1]) if m else 0, + map(lambda m: float(m[1]) if m else 0.0, map(lambda trade: re.compile(".*\\((-?\\d*\\.\\d*)\\)").match(trade[-1]), statlist)) ) From 196fde44e070274dca17b2c219c790100d8ec691 Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 14:45:54 +0300 Subject: [PATCH 5/7] Total row for telegram "/status table" command work around mypy warning --- freqtrade/rpc/telegram.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 6a12488d1..1e0fad8fd 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -360,13 +360,14 @@ class Telegram(RPCHandler): self._config['stake_currency'], fiat_currency) show_total = fiat_currency != '' - total_sum = 0 + total_sum = 0.0 if show_total: - total_sum = sum( - map(lambda m: float(m[1]) if m else 0.0, - map(lambda trade: re.compile(".*\\((-?\\d*\\.\\d*)\\)").match(trade[-1]), - statlist)) - ) + r = re.compile(".*\\((-?\\d*\\.\\d*)\\)") + for trade in statlist: + m = r.match(trade[-1]) + if m is not None: + total_sum += float(m[1]) + max_trades_per_msg = 50 """ Calculate the number of messages of 50 trades per message From 3ad8fa2f38cdd28322b2839e53674a17b66a610e Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 15:59:03 +0300 Subject: [PATCH 6/7] Total row for telegram "/status table" command moved sum calculation to API --- freqtrade/rpc/rpc.py | 6 ++++-- freqtrade/rpc/telegram.py | 16 ++++------------ tests/rpc/test_rpc.py | 9 ++++++--- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 2c54d743e..9b0ef2ad0 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -220,12 +220,13 @@ class RPC: return results def _rpc_status_table(self, stake_currency: str, - fiat_display_currency: str) -> Tuple[List, List]: + fiat_display_currency: str) -> Tuple[List, List, float]: trades = Trade.get_open_trades() if not trades: raise RPCException('no active trade') else: trades_list = [] + fiat_profit_sum = NAN for trade in trades: # calculate profit and send message to user try: @@ -243,6 +244,7 @@ class RPC: ) if fiat_profit and not isnan(fiat_profit): profit_str += f" ({fiat_profit:.2f})" + fiat_profit_sum = fiat_profit if isnan(fiat_profit_sum) else fiat_profit_sum + fiat_profit trades_list.append([ trade.id, trade.pair + ('*' if (trade.open_order_id is not None @@ -256,7 +258,7 @@ class RPC: profitcol += " (" + fiat_display_currency + ")" columns = ['ID', 'Pair', 'Since', profitcol] - return trades_list, columns + return trades_list, columns, fiat_profit_sum def _rpc_daily_profit( self, timescale: int, diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 1e0fad8fd..bdb1590a5 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -5,10 +5,10 @@ This module manage Telegram communication """ import json import logging -import re from datetime import timedelta from html import escape from itertools import chain +from math import isnan from typing import Any, Callable, Dict, List, Union import arrow @@ -356,18 +356,10 @@ class Telegram(RPCHandler): """ try: fiat_currency = self._config.get('fiat_display_currency', '') - statlist, head = self._rpc._rpc_status_table( + statlist, head, fiat_profit_sum = self._rpc._rpc_status_table( self._config['stake_currency'], fiat_currency) - show_total = fiat_currency != '' - total_sum = 0.0 - if show_total: - r = re.compile(".*\\((-?\\d*\\.\\d*)\\)") - for trade in statlist: - m = r.match(trade[-1]) - if m is not None: - total_sum += float(m[1]) - + show_total = not isnan(fiat_profit_sum) and len(statlist) > 1 max_trades_per_msg = 50 """ Calculate the number of messages of 50 trades per message @@ -379,7 +371,7 @@ class Telegram(RPCHandler): trades = statlist[i * max_trades_per_msg:(i + 1) * max_trades_per_msg] if show_total and i == messages_count - 1: # append total line - trades.append(["Total", "", "", f"{total_sum:.2f} {fiat_currency}"]) + trades.append(["Total", "", "", f"{fiat_profit_sum:.2f} {fiat_currency}"]) message = tabulate(trades, headers=head, diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 6d31e7635..0ae214615 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -199,28 +199,31 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: freqtradebot.enter_positions() - result, headers = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') + result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') assert "Since" in headers assert "Pair" in headers assert 'instantly' == result[0][2] assert 'ETH/BTC' in result[0][1] assert '-0.41%' == result[0][3] + assert isnan(fiat_profit_sum) # Test with fiatconvert rpc._fiat_converter = CryptoToFiatConverter() - result, headers = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') + result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') assert "Since" in headers assert "Pair" in headers assert 'instantly' == result[0][2] assert 'ETH/BTC' in result[0][1] assert '-0.41% (-0.06)' == result[0][3] + assert -0.06 == fiat_profit_sum mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate', MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available"))) - result, headers = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') + result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') assert 'instantly' == result[0][2] assert 'ETH/BTC' in result[0][1] assert 'nan%' == result[0][3] + assert isnan(fiat_profit_sum) def test_rpc_daily_profit(default_conf, update, ticker, fee, From 459fae6d80608f45b5f34dcfb61a0de388035d5f Mon Sep 17 00:00:00 2001 From: Eugene Schava Date: Mon, 17 May 2021 16:22:48 +0300 Subject: [PATCH 7/7] Total row for telegram "/status table" command fixes --- freqtrade/rpc/rpc.py | 3 ++- tests/rpc/test_rpc.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 9b0ef2ad0..3f26619a9 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -244,7 +244,8 @@ class RPC: ) if fiat_profit and not isnan(fiat_profit): profit_str += f" ({fiat_profit:.2f})" - fiat_profit_sum = fiat_profit if isnan(fiat_profit_sum) else fiat_profit_sum + fiat_profit + fiat_profit_sum = fiat_profit if isnan(fiat_profit_sum) \ + else fiat_profit_sum + fiat_profit trades_list.append([ trade.id, trade.pair + ('*' if (trade.open_order_id is not None diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 0ae214615..b005fb105 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -215,7 +215,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: assert 'instantly' == result[0][2] assert 'ETH/BTC' in result[0][1] assert '-0.41% (-0.06)' == result[0][3] - assert -0.06 == fiat_profit_sum + assert '-0.06' == f'{fiat_profit_sum:.2f}' mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate', MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available")))