From 0dc1a8e0379852c01289e851cb36a4c9f13b6327 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 3 Jun 2020 19:40:30 +0200 Subject: [PATCH 01/15] Add profit sum to api response --- freqtrade/rpc/rpc.py | 20 +++++++++++++++----- freqtrade/rpc/telegram.py | 13 +++++++++---- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 91b35e9ad..d3fef7041 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -283,8 +283,9 @@ class RPC: # Prepare data to display profit_closed_coin_sum = round(sum(profit_closed_coin), 8) - profit_closed_percent = (round(mean(profit_closed_ratio) * 100, 2) if profit_closed_ratio - else 0.0) + profit_closed_ratio_mean = mean(profit_closed_ratio) if profit_closed_ratio else 0.0 + profit_closed_ratio_sum = sum(profit_closed_ratio) if profit_closed_ratio else 0.0 + profit_closed_fiat = self._fiat_converter.convert_amount( profit_closed_coin_sum, stake_currency, @@ -292,7 +293,8 @@ class RPC: ) if self._fiat_converter else 0 profit_all_coin_sum = round(sum(profit_all_coin), 8) - profit_all_percent = round(mean(profit_all_ratio) * 100, 2) if profit_all_ratio else 0.0 + profit_all_ratio_mean = mean(profit_all_ratio) if profit_all_ratio else 0.0 + profit_all_ratio_sum = sum(profit_all_ratio) if profit_all_ratio else 0.0 profit_all_fiat = self._fiat_converter.convert_amount( profit_all_coin_sum, stake_currency, @@ -304,10 +306,18 @@ class RPC: num = float(len(durations) or 1) return { 'profit_closed_coin': profit_closed_coin_sum, - 'profit_closed_percent': profit_closed_percent, + 'profit_closed_percent': round(profit_closed_ratio_mean * 100, 2), # DEPRECATED + 'profit_closed_percent_mean': round(profit_closed_ratio_mean * 100, 2), + 'profit_closed_ratio_mean': profit_closed_ratio_mean, + 'profit_closed_percent_sum': round(profit_closed_ratio_sum * 100, 2), + 'profit_closed_ratio_sum': profit_closed_ratio_sum, 'profit_closed_fiat': profit_closed_fiat, 'profit_all_coin': profit_all_coin_sum, - 'profit_all_percent': profit_all_percent, + 'profit_all_percent': round(profit_all_ratio_mean * 100, 2), # DEPRECATED + 'profit_all_percent_mean': round(profit_all_ratio_mean * 100, 2), + 'profit_all_ratio_mean': profit_all_ratio_mean, + 'profit_all_percent_sum': round(profit_all_ratio_sum * 100, 2), + 'profit_all_ratio_sum': profit_all_ratio_sum, 'profit_all_fiat': profit_all_fiat, 'trade_count': len(trades), 'closed_trade_count': len([t for t in trades if not t.is_open]), diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 8fa973d73..02c580ebd 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -315,10 +315,12 @@ class Telegram(RPC): stake_cur, fiat_disp_cur) profit_closed_coin = stats['profit_closed_coin'] - profit_closed_percent = stats['profit_closed_percent'] + profit_closed_percent_mean = stats['profit_closed_percent_mean'] + profit_closed_percent_sum = stats['profit_closed_percent_sum'] profit_closed_fiat = stats['profit_closed_fiat'] profit_all_coin = stats['profit_all_coin'] - profit_all_percent = stats['profit_all_percent'] + profit_all_percent_mean = stats['profit_all_percent_mean'] + profit_all_percent_sum = stats['profit_all_percent_sum'] profit_all_fiat = stats['profit_all_fiat'] trade_count = stats['trade_count'] first_trade_date = stats['first_trade_date'] @@ -333,13 +335,16 @@ class Telegram(RPC): if stats['closed_trade_count'] > 0: markdown_msg = ("*ROI:* Closed trades\n" f"∙ `{profit_closed_coin:.8f} {stake_cur} " - f"({profit_closed_percent:.2f}%)`\n" + f"({profit_closed_percent_mean:.2f}%) " + f"({profit_closed_percent_sum} \N{GREEK CAPITAL LETTER SIGMA}%)`\n" f"∙ `{profit_closed_fiat:.3f} {fiat_disp_cur}`\n") else: markdown_msg = "`No closed trade` \n" markdown_msg += (f"*ROI:* All trades\n" - f"∙ `{profit_all_coin:.8f} {stake_cur} ({profit_all_percent:.2f}%)`\n" + f"∙ `{profit_all_coin:.8f} {stake_cur} " + f"({profit_all_percent_mean:.2f}%) " + f"({profit_all_percent_sum} \N{GREEK CAPITAL LETTER SIGMA}%)`\n" f"∙ `{profit_all_fiat:.3f} {fiat_disp_cur}`\n" f"*Total Trade Count:* `{trade_count}`\n" f"*First Trade opened:* `{first_trade_date}`\n" From 6997524a04f27334bf383b3e07a6267b4f8d6923 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 3 Jun 2020 19:40:49 +0200 Subject: [PATCH 02/15] Fix tests for additional info --- tests/rpc/test_rpc_apiserver.py | 8 ++++++++ tests/rpc/test_rpc_telegram.py | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index cacf49f62..70a06557f 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -428,9 +428,17 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, limit_buy_order, li 'profit_all_coin': 6.217e-05, 'profit_all_fiat': 0, 'profit_all_percent': 6.2, + 'profit_all_percent_mean': 6.2, + 'profit_all_ratio_mean': 0.06201058, + 'profit_all_percent_sum': 6.2, + 'profit_all_ratio_sum': 0.06201058, 'profit_closed_coin': 6.217e-05, 'profit_closed_fiat': 0, 'profit_closed_percent': 6.2, + 'profit_closed_ratio_mean': 0.06201058, + 'profit_closed_percent_mean': 6.2, + 'profit_closed_ratio_sum': 0.06201058, + 'profit_closed_percent_sum': 6.2, 'trade_count': 1, 'closed_trade_count': 1, } diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index f81127c4c..4895d67e4 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -434,7 +434,8 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee, assert msg_mock.call_count == 1 assert 'No closed trade' in msg_mock.call_args_list[-1][0][0] assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0] - assert '∙ `-0.00000500 BTC (-0.50%)`' in msg_mock.call_args_list[-1][0][0] + assert ('∙ `-0.00000500 BTC (-0.50%) (-0.5 \N{GREEK CAPITAL LETTER SIGMA}%)`' + in msg_mock.call_args_list[-1][0][0]) msg_mock.reset_mock() # Update the ticker with a market going up @@ -447,10 +448,12 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee, telegram._profit(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert '*ROI:* Closed trades' in msg_mock.call_args_list[-1][0][0] - assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0] + assert ('∙ `0.00006217 BTC (6.20%) (6.2 \N{GREEK CAPITAL LETTER SIGMA}%)`' + in msg_mock.call_args_list[-1][0][0]) assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0] assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0] - assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0] + assert ('∙ `0.00006217 BTC (6.20%) (6.2 \N{GREEK CAPITAL LETTER SIGMA}%)`' + in msg_mock.call_args_list[-1][0][0]) assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0] assert '*Best Performing:* `ETH/BTC: 6.20%`' in msg_mock.call_args_list[-1][0][0] From 5c5dc6fffe67decf8df285cfc28733c0bd07567a Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Jun 2020 06:56:30 +0200 Subject: [PATCH 03/15] Update test to reflect real trade after one cycle --- tests/rpc/test_rpc_apiserver.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index cacf49f62..8743ec7ba 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -495,6 +495,10 @@ def test_api_status(botclient, mocker, ticker, fee, markets): assert rc.json == [] ftbot.enter_positions() + trades = Trade.get_open_trades() + trades[0].open_order_id = None + ftbot.exit_positions(trades) + rc = client_get(client, f"{BASE_URI}/status") assert_response(rc) assert len(rc.json) == 1 @@ -509,25 +513,26 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'close_rate': None, 'current_profit': -0.00408133, 'current_profit_pct': -0.41, + 'current_profit_abs': -4.09e-06, 'current_rate': 1.099e-05, 'open_date': ANY, 'open_date_hum': 'just now', 'open_timestamp': ANY, - 'open_order': '(limit buy rem=0.00000000)', + 'open_order': None, 'open_rate': 1.098e-05, 'pair': 'ETH/BTC', 'stake_amount': 0.001, - 'stop_loss': 0.0, - 'stop_loss_abs': 0.0, - 'stop_loss_pct': None, - 'stop_loss_ratio': None, + 'stop_loss': 9.882e-06, + 'stop_loss_abs': 9.882e-06, + 'stop_loss_pct': -10.0, + 'stop_loss_ratio': -0.1, 'stoploss_order_id': None, - 'stoploss_last_update': None, - 'stoploss_last_update_timestamp': None, - 'initial_stop_loss': 0.0, - 'initial_stop_loss_abs': 0.0, - 'initial_stop_loss_pct': None, - 'initial_stop_loss_ratio': None, + 'stoploss_last_update': ANY, + 'stoploss_last_update_timestamp': ANY, + 'initial_stop_loss': 9.882e-06, + 'initial_stop_loss_abs': 9.882e-06, + 'initial_stop_loss_pct': -10.0, + 'initial_stop_loss_ratio': -0.1, 'trade_id': 1, 'close_rate_requested': None, 'current_rate': 1.099e-05, @@ -539,9 +544,9 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'fee_open_currency': None, 'open_date': ANY, 'is_open': True, - 'max_rate': 0.0, - 'min_rate': None, - 'open_order_id': ANY, + 'max_rate': 1.099e-05, + 'min_rate': 1.098e-05, + 'open_order_id': None, 'open_rate_requested': 1.098e-05, 'open_trade_price': 0.0010025, 'sell_reason': None, From 412b50dac5471e5392395c771298fbb118dcc8bb Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Jun 2020 06:56:59 +0200 Subject: [PATCH 04/15] Add current stoploss calculations --- freqtrade/rpc/rpc.py | 13 +++++++++++++ tests/rpc/test_rpc_apiserver.py | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 91b35e9ad..dd6b084a2 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -130,6 +130,14 @@ class RPC: except DependencyException: current_rate = NAN current_profit = trade.calc_profit_ratio(current_rate) + current_profit_abs = trade.calc_profit(current_rate) + # Calculate guaranteed profit (in case of trailing stop) + stoploss_entrypoint_dist = trade.open_rate - trade.stop_loss + stoploss_entrypoint_dist_ratio = stoploss_entrypoint_dist / trade.stop_loss + # calculate distance to stoploss + stoploss_current_dist = trade.stop_loss - current_rate + stoploss_current_dist_ratio = stoploss_current_dist / current_rate + fmt_close_profit = (f'{round(trade.close_profit * 100, 2):.2f}%' if trade.close_profit is not None else None) trade_dict = trade.to_json() @@ -140,6 +148,11 @@ class RPC: current_rate=current_rate, current_profit=current_profit, current_profit_pct=round(current_profit * 100, 2), + current_profit_abs=current_profit_abs, + stoploss_current_dist=stoploss_current_dist, + stoploss_current_dist_ratio=round(stoploss_current_dist_ratio, 8), + stoploss_entrypoint_dist=stoploss_entrypoint_dist, + stoploss_entrypoint_dist_ratio=round(stoploss_entrypoint_dist_ratio, 8), open_order='({} {} rem={:.8f})'.format( order['type'], order['side'], order['remaining'] ) if order else None, diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 8743ec7ba..906e9f2fe 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -533,6 +533,10 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'initial_stop_loss_abs': 9.882e-06, 'initial_stop_loss_pct': -10.0, 'initial_stop_loss_ratio': -0.1, + 'stoploss_current_dist': -1.1080000000000002e-06, + 'stoploss_current_dist_ratio': -0.10081893, + 'stoploss_entrypoint_dist': 1.0980000000000003e-06, + 'stoploss_entrypoint_dist_ratio': 0.11111111, 'trade_id': 1, 'close_rate_requested': None, 'current_rate': 1.099e-05, From 7bd55aa2f1c6c60c6b50ffd7d8965146c633f4e7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Jun 2020 07:04:32 +0200 Subject: [PATCH 05/15] Use correct calcuation for "locked in profit" --- freqtrade/rpc/rpc.py | 8 ++++---- tests/rpc/test_rpc_apiserver.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index dd6b084a2..fc774ded2 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -132,8 +132,8 @@ class RPC: current_profit = trade.calc_profit_ratio(current_rate) current_profit_abs = trade.calc_profit(current_rate) # Calculate guaranteed profit (in case of trailing stop) - stoploss_entrypoint_dist = trade.open_rate - trade.stop_loss - stoploss_entrypoint_dist_ratio = stoploss_entrypoint_dist / trade.stop_loss + stoploss_entry_dist = trade.calc_profit(trade.stop_loss) + stoploss_entry_dist_ratio = trade.calc_profit_ratio(trade.stop_loss) # calculate distance to stoploss stoploss_current_dist = trade.stop_loss - current_rate stoploss_current_dist_ratio = stoploss_current_dist / current_rate @@ -151,8 +151,8 @@ class RPC: current_profit_abs=current_profit_abs, stoploss_current_dist=stoploss_current_dist, stoploss_current_dist_ratio=round(stoploss_current_dist_ratio, 8), - stoploss_entrypoint_dist=stoploss_entrypoint_dist, - stoploss_entrypoint_dist_ratio=round(stoploss_entrypoint_dist_ratio, 8), + stoploss_entry_dist=stoploss_entry_dist, + stoploss_entry_dist_ratio=round(stoploss_entry_dist_ratio, 8), open_order='({} {} rem={:.8f})'.format( order['type'], order['side'], order['remaining'] ) if order else None, diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 906e9f2fe..3555057a9 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -535,8 +535,8 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'initial_stop_loss_ratio': -0.1, 'stoploss_current_dist': -1.1080000000000002e-06, 'stoploss_current_dist_ratio': -0.10081893, - 'stoploss_entrypoint_dist': 1.0980000000000003e-06, - 'stoploss_entrypoint_dist_ratio': 0.11111111, + 'stoploss_entry_dist': -0.00010475, + 'stoploss_entry_dist_ratio': -0.10448878, 'trade_id': 1, 'close_rate_requested': None, 'current_rate': 1.099e-05, From 6a88eb603bde0eea17aa18bd318e50345b70baed Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 Jun 2020 07:20:50 +0200 Subject: [PATCH 06/15] Update failing test --- tests/rpc/test_rpc.py | 73 +++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 1de73ada9..ef1c1bc16 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -42,8 +42,12 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: rpc._rpc_trade_status() freqtradebot.enter_positions() + trades = Trade.get_open_trades() + trades[0].open_order_id = None + freqtradebot.exit_positions(trades) + results = rpc._rpc_trade_status() - assert { + assert results[0] == { 'trade_id': 1, 'pair': 'ETH/BTC', 'base_currency': 'BTC', @@ -54,11 +58,11 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'fee_open': ANY, 'fee_open_cost': ANY, 'fee_open_currency': ANY, - 'fee_close': ANY, + 'fee_close': fee.return_value, 'fee_close_cost': ANY, 'fee_close_currency': ANY, 'open_rate_requested': ANY, - 'open_trade_price': ANY, + 'open_trade_price': 0.0010025, 'close_rate_requested': ANY, 'sell_reason': ANY, 'sell_order_status': ANY, @@ -80,28 +84,32 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'close_profit_abs': None, 'current_profit': -0.00408133, 'current_profit_pct': -0.41, - 'stop_loss': 0.0, - 'stop_loss_abs': 0.0, - 'stop_loss_pct': None, - 'stop_loss_ratio': None, + 'current_profit_abs': -4.09e-06, + 'stop_loss': 9.882e-06, + 'stop_loss_abs': 9.882e-06, + 'stop_loss_pct': -10.0, + 'stop_loss_ratio': -0.1, 'stoploss_order_id': None, - 'stoploss_last_update': None, - 'stoploss_last_update_timestamp': None, - 'initial_stop_loss': 0.0, - 'initial_stop_loss_abs': 0.0, - 'initial_stop_loss_pct': None, - 'initial_stop_loss_ratio': None, - 'open_order': '(limit buy rem=0.00000000)', + 'stoploss_last_update': ANY, + 'stoploss_last_update_timestamp': ANY, + 'initial_stop_loss': 9.882e-06, + 'initial_stop_loss_abs': 9.882e-06, + 'initial_stop_loss_pct': -10.0, + 'initial_stop_loss_ratio': -0.1, + 'stoploss_current_dist': -1.1080000000000002e-06, + 'stoploss_current_dist_ratio': -0.10081893, + 'stoploss_entry_dist': -0.00010475, + 'stoploss_entry_dist_ratio': -0.10448878, + 'open_order': None, 'exchange': 'bittrex', - - } == results[0] + } mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate', MagicMock(side_effect=DependencyException("Pair 'ETH/BTC' not available"))) results = rpc._rpc_trade_status() assert isnan(results[0]['current_profit']) assert isnan(results[0]['current_rate']) - assert { + assert results[0] == { 'trade_id': 1, 'pair': 'ETH/BTC', 'base_currency': 'BTC', @@ -112,7 +120,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'fee_open': ANY, 'fee_open_cost': ANY, 'fee_open_currency': ANY, - 'fee_close': ANY, + 'fee_close': fee.return_value, 'fee_close_cost': ANY, 'fee_close_currency': ANY, 'open_rate_requested': ANY, @@ -138,20 +146,25 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'close_profit_abs': None, 'current_profit': ANY, 'current_profit_pct': ANY, - 'stop_loss': 0.0, - 'stop_loss_abs': 0.0, - 'stop_loss_pct': None, - 'stop_loss_ratio': None, + 'current_profit_abs': ANY, + 'stop_loss': 9.882e-06, + 'stop_loss_abs': 9.882e-06, + 'stop_loss_pct': -10.0, + 'stop_loss_ratio': -0.1, 'stoploss_order_id': None, - 'stoploss_last_update': None, - 'stoploss_last_update_timestamp': None, - 'initial_stop_loss': 0.0, - 'initial_stop_loss_abs': 0.0, - 'initial_stop_loss_pct': None, - 'initial_stop_loss_ratio': None, - 'open_order': '(limit buy rem=0.00000000)', + 'stoploss_last_update': ANY, + 'stoploss_last_update_timestamp': ANY, + 'initial_stop_loss': 9.882e-06, + 'initial_stop_loss_abs': 9.882e-06, + 'initial_stop_loss_pct': -10.0, + 'initial_stop_loss_ratio': -0.1, + 'stoploss_current_dist': ANY, + 'stoploss_current_dist_ratio': ANY, + 'stoploss_entry_dist': -0.00010475, + 'stoploss_entry_dist_ratio': -0.10448878, + 'open_order': None, 'exchange': 'bittrex', - } == results[0] + } def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: From ff289a71776239e2ac0dd35e2fb40cfa44a83e83 Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Fri, 5 Jun 2020 19:08:54 +0200 Subject: [PATCH 07/15] Updated tests to work with Telegram emojis --- tests/rpc/test_rpc_telegram.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index f81127c4c..2cecc35d1 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1221,8 +1221,9 @@ def test_send_msg_buy_notification(default_conf, mocker) -> None: 'amount': 1333.3333333333335, 'open_date': arrow.utcnow().shift(hours=-1) }) + '🔵'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ - == '*Bittrex:* Buying ETH/BTC\n' \ + == '\N{LARGE BLUE CIRCLE} *Bittrex:* Buying ETH/BTC\n' \ '*Amount:* `1333.33333333`\n' \ '*Open Rate:* `0.00001099`\n' \ '*Current Rate:* `0.00001099`\n' \ @@ -1243,8 +1244,9 @@ def test_send_msg_buy_cancel_notification(default_conf, mocker) -> None: 'exchange': 'Bittrex', 'pair': 'ETH/BTC', }) + '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ - == ('*Bittrex:* Cancelling Open Buy Order for ETH/BTC') + == ('\N{WARNING SIGN} *Bittrex:* Cancelling Open Buy Order for ETH/BTC') def test_send_msg_sell_notification(default_conf, mocker) -> None: @@ -1276,8 +1278,9 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: 'open_date': arrow.utcnow().shift(hours=-1), 'close_date': arrow.utcnow(), }) + '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ - == ('*Binance:* Selling KEY/ETH\n' + == ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n' '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' @@ -1305,7 +1308,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: 'close_date': arrow.utcnow(), }) assert msg_mock.call_args[0][0] \ - == ('*Binance:* Selling KEY/ETH\n' + == ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n' '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00007500`\n' '*Current Rate:* `0.00003201`\n' @@ -1334,8 +1337,9 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: 'pair': 'KEY/ETH', 'reason': 'Cancelled on exchange' }) + '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ - == ('*Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: Cancelled on exchange') + == ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: Cancelled on exchange') msg_mock.reset_mock() telegram.send_msg({ @@ -1345,7 +1349,7 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: 'reason': 'timeout' }) assert msg_mock.call_args[0][0] \ - == ('*Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: timeout') + == ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: timeout') # Reset singleton function to avoid random breaks telegram._fiat_converter.convert_amount = old_convamount @@ -1379,7 +1383,8 @@ def test_warning_notification(default_conf, mocker) -> None: 'type': RPCMessageType.WARNING_NOTIFICATION, 'status': 'message' }) - assert msg_mock.call_args[0][0] == '*Warning:* `message`' + '⚠'.encode('ascii', 'namereplace') + assert msg_mock.call_args[0][0] == '\N{WARNING SIGN} *Warning:* `message`' def test_custom_notification(default_conf, mocker) -> None: @@ -1437,8 +1442,9 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None: 'amount': 1333.3333333333335, 'open_date': arrow.utcnow().shift(hours=-1) }) + '🔵'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ - == '*Bittrex:* Buying ETH/BTC\n' \ + == '\N{LARGE BLUE CIRCLE} *Bittrex:* Buying ETH/BTC\n' \ '*Amount:* `1333.33333333`\n' \ '*Open Rate:* `0.00001099`\n' \ '*Current Rate:* `0.00001099`\n' \ @@ -1473,8 +1479,9 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None: 'open_date': arrow.utcnow().shift(hours=-2, minutes=-35, seconds=-3), 'close_date': arrow.utcnow(), }) + '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ - == '*Binance:* Selling KEY/ETH\n' \ + == '\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n' \ '*Amount:* `1333.33333333`\n' \ '*Open Rate:* `0.00007500`\n' \ '*Current Rate:* `0.00003201`\n' \ From 080efd1102835367f135827c9a7dc4be1623be84 Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Fri, 5 Jun 2020 19:09:49 +0200 Subject: [PATCH 08/15] Added unicoded emoji's to Telegram messages --- freqtrade/rpc/telegram.py | 61 +++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 8fa973d73..e496d3fa6 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -19,7 +19,6 @@ logger = logging.getLogger(__name__) logger.debug('Included module rpc.telegram ...') - MAX_TELEGRAM_MESSAGE_LENGTH = 4096 @@ -29,6 +28,7 @@ def authorized_only(command_handler: Callable[..., None]) -> Callable[..., Any]: :param command_handler: Telegram CommandHandler :return: decorated function """ + def wrapper(self, *args, **kwargs): """ Decorator logic """ update = kwargs.get('update') or args[0] @@ -126,6 +126,12 @@ class Telegram(RPC): def send_msg(self, msg: Dict[str, Any]) -> None: """ Send a message to telegram channel """ + '🔵'.encode('ascii', 'namereplace') + '🚀'.encode('ascii', 'namereplace') + '✳'.encode('ascii', 'namereplace') + '❌'.encode('ascii', 'namereplace') + '⚠'.encode('ascii', 'namereplace') + if msg['type'] == RPCMessageType.BUY_NOTIFICATION: if self._fiat_converter: msg['stake_amount_fiat'] = self._fiat_converter.convert_amount( @@ -133,7 +139,7 @@ class Telegram(RPC): else: msg['stake_amount_fiat'] = 0 - message = ("*{exchange}:* Buying {pair}\n" + message = ("\N{LARGE BLUE CIRCLE} *{exchange}:* Buying {pair}\n" "*Amount:* `{amount:.8f}`\n" "*Open Rate:* `{limit:.8f}`\n" "*Current Rate:* `{current_rate:.8f}`\n" @@ -144,7 +150,7 @@ class Telegram(RPC): message += ")`" elif msg['type'] == RPCMessageType.BUY_CANCEL_NOTIFICATION: - message = "*{exchange}:* Cancelling Open Buy Order for {pair}".format(**msg) + message = "\N{WARNING SIGN} *{exchange}:* Cancelling Open Buy Order for {pair}".format(**msg) elif msg['type'] == RPCMessageType.SELL_NOTIFICATION: msg['amount'] = round(msg['amount'], 8) @@ -153,33 +159,44 @@ class Telegram(RPC): microsecond=0) - msg['open_date'].replace(microsecond=0) msg['duration_min'] = msg['duration'].total_seconds() / 60 - message = ("*{exchange}:* Selling {pair}\n" - "*Amount:* `{amount:.8f}`\n" - "*Open Rate:* `{open_rate:.8f}`\n" - "*Current Rate:* `{current_rate:.8f}`\n" - "*Close Rate:* `{limit:.8f}`\n" - "*Sell Reason:* `{sell_reason}`\n" - "*Duration:* `{duration} ({duration_min:.1f} min)`\n" - "*Profit:* `{profit_percent:.2f}%`").format(**msg) + if float(msg['profit_percent']) >= 5.0: + message = ("\N{ROCKET} *{exchange}:* Selling {pair}\n").format(**msg) + + elif float(msg['profit_percent']) >= 0.0: + message = "\N{EIGHT SPOKED ASTERISK} *{exchange}:* Selling {pair}\n" + + elif msg['sell_reason'] == "stop_loss": + message = ("\N{WARNING SIGN} *{exchange}:* Selling {pair}\n").format(**msg) + + else: + message = ("\N{CROSS MARK} *{exchange}:* Selling {pair}\n").format(**msg) + + message += ("*Amount:* `{amount:.8f}`\n" + "*Open Rate:* `{open_rate:.8f}`\n" + "*Current Rate:* `{current_rate:.8f}`\n" + "*Close Rate:* `{limit:.8f}`\n" + "*Sell Reason:* `{sell_reason}`\n" + "*Duration:* `{duration} ({duration_min:.1f} min)`\n" + "*Profit:* `{profit_percent:.2f}%`").format(**msg) # Check if all sell properties are available. # This might not be the case if the message origin is triggered by /forcesell if (all(prop in msg for prop in ['gain', 'fiat_currency', 'stake_currency']) - and self._fiat_converter): + and self._fiat_converter): msg['profit_fiat'] = self._fiat_converter.convert_amount( msg['profit_amount'], msg['stake_currency'], msg['fiat_currency']) message += (' `({gain}: {profit_amount:.8f} {stake_currency}' ' / {profit_fiat:.3f} {fiat_currency})`').format(**msg) elif msg['type'] == RPCMessageType.SELL_CANCEL_NOTIFICATION: - message = ("*{exchange}:* Cancelling Open Sell Order " + message = ("\N{WARNING SIGN} *{exchange}:* Cancelling Open Sell Order " "for {pair}. Reason: {reason}").format(**msg) elif msg['type'] == RPCMessageType.STATUS_NOTIFICATION: message = '*Status:* `{status}`'.format(**msg) elif msg['type'] == RPCMessageType.WARNING_NOTIFICATION: - message = '*Warning:* `{status}`'.format(**msg) + message = '\N{WARNING SIGN} *Warning:* `{status}`'.format(**msg) elif msg['type'] == RPCMessageType.CUSTOM_NOTIFICATION: message = '{status}'.format(**msg) @@ -222,8 +239,8 @@ class Telegram(RPC): # Adding initial stoploss only if it is different from stoploss "*Initial Stoploss:* `{initial_stop_loss:.8f}` " + ("`({initial_stop_loss_pct:.2f}%)`") if ( - r['stop_loss'] != r['initial_stop_loss'] - and r['initial_stop_loss_pct'] is not None) else "", + r['stop_loss'] != r['initial_stop_loss'] + and r['initial_stop_loss_pct'] is not None) else "", # Adding stoploss and stoploss percentage only if it is not None "*Stoploss:* `{stop_loss:.8f}` " + @@ -363,14 +380,14 @@ class Telegram(RPC): "This mode is still experimental!\n" "Starting capital: " f"`{self._config['dry_run_wallet']}` {self._config['stake_currency']}.\n" - ) + ) for currency in result['currencies']: if currency['est_stake'] > 0.0001: curr_output = "*{currency}:*\n" \ - "\t`Available: {free: .8f}`\n" \ - "\t`Balance: {balance: .8f}`\n" \ - "\t`Pending: {used: .8f}`\n" \ - "\t`Est. {stake}: {est_stake: .8f}`\n".format(**currency) + "\t`Available: {free: .8f}`\n" \ + "\t`Balance: {balance: .8f}`\n" \ + "\t`Pending: {used: .8f}`\n" \ + "\t`Est. {stake}: {est_stake: .8f}`\n".format(**currency) else: curr_output = "*{currency}:* not showing <1$ amount \n".format(**currency) @@ -587,7 +604,7 @@ class Telegram(RPC): "*/profit:* `Lists cumulative profit from all finished trades`\n" \ "*/forcesell |all:* `Instantly sells the given trade or all trades, " \ "regardless of profit`\n" \ - f"{forcebuy_text if self._config.get('forcebuy_enable', False) else '' }" \ + f"{forcebuy_text if self._config.get('forcebuy_enable', False) else ''}" \ "*/performance:* `Show performance of each finished trade grouped by pair`\n" \ "*/daily :* `Shows profit or loss per day, over the last n days`\n" \ "*/count:* `Show number of trades running compared to allowed number of trades`" \ From 4c6a7a354dfae8d0a60f8243aefa91f400a01604 Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Fri, 5 Jun 2020 20:04:11 +0200 Subject: [PATCH 09/15] Removed '.encode' lines, unessecary --- freqtrade/rpc/telegram.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index e496d3fa6..6b1450472 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -126,12 +126,6 @@ class Telegram(RPC): def send_msg(self, msg: Dict[str, Any]) -> None: """ Send a message to telegram channel """ - '🔵'.encode('ascii', 'namereplace') - '🚀'.encode('ascii', 'namereplace') - '✳'.encode('ascii', 'namereplace') - '❌'.encode('ascii', 'namereplace') - '⚠'.encode('ascii', 'namereplace') - if msg['type'] == RPCMessageType.BUY_NOTIFICATION: if self._fiat_converter: msg['stake_amount_fiat'] = self._fiat_converter.convert_amount( From 08b9abed3aeb722357ced69fe67489acc05e3eaa Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Fri, 5 Jun 2020 20:05:55 +0200 Subject: [PATCH 10/15] Removed '.encode', unecessary --- tests/rpc/test_rpc_telegram.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 2cecc35d1..129bdf9d1 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1221,7 +1221,6 @@ def test_send_msg_buy_notification(default_conf, mocker) -> None: 'amount': 1333.3333333333335, 'open_date': arrow.utcnow().shift(hours=-1) }) - '🔵'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ == '\N{LARGE BLUE CIRCLE} *Bittrex:* Buying ETH/BTC\n' \ '*Amount:* `1333.33333333`\n' \ @@ -1244,7 +1243,6 @@ def test_send_msg_buy_cancel_notification(default_conf, mocker) -> None: 'exchange': 'Bittrex', 'pair': 'ETH/BTC', }) - '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ == ('\N{WARNING SIGN} *Bittrex:* Cancelling Open Buy Order for ETH/BTC') @@ -1278,7 +1276,6 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: 'open_date': arrow.utcnow().shift(hours=-1), 'close_date': arrow.utcnow(), }) - '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ == ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n' '*Amount:* `1333.33333333`\n' @@ -1337,7 +1334,6 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: 'pair': 'KEY/ETH', 'reason': 'Cancelled on exchange' }) - '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ == ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: Cancelled on exchange') @@ -1383,7 +1379,6 @@ def test_warning_notification(default_conf, mocker) -> None: 'type': RPCMessageType.WARNING_NOTIFICATION, 'status': 'message' }) - '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] == '\N{WARNING SIGN} *Warning:* `message`' @@ -1442,7 +1437,6 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None: 'amount': 1333.3333333333335, 'open_date': arrow.utcnow().shift(hours=-1) }) - '🔵'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ == '\N{LARGE BLUE CIRCLE} *Bittrex:* Buying ETH/BTC\n' \ '*Amount:* `1333.33333333`\n' \ @@ -1479,7 +1473,6 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None: 'open_date': arrow.utcnow().shift(hours=-2, minutes=-35, seconds=-3), 'close_date': arrow.utcnow(), }) - '⚠'.encode('ascii', 'namereplace') assert msg_mock.call_args[0][0] \ == '\N{WARNING SIGN} *Binance:* Selling KEY/ETH\n' \ '*Amount:* `1333.33333333`\n' \ From 6694ac50779619eec4f761a3f28175833d4080c9 Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Fri, 5 Jun 2020 20:10:52 +0200 Subject: [PATCH 11/15] Splitted a line that was too long, resulting in flake8 error --- tests/rpc/test_rpc_telegram.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 129bdf9d1..15fe0eaf9 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1335,7 +1335,8 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: 'reason': 'Cancelled on exchange' }) assert msg_mock.call_args[0][0] \ - == ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. Reason: Cancelled on exchange') + == ('\N{WARNING SIGN} *Binance:* Cancelling Open Sell Order for KEY/ETH. ' + 'Reason: Cancelled on exchange') msg_mock.reset_mock() telegram.send_msg({ From f34bcc5fd3b629acfaeb55cd51854b1e719f44f8 Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Fri, 5 Jun 2020 20:15:22 +0200 Subject: [PATCH 12/15] Splitted a line that was too long, resulting in error for flake8 --- 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 6b1450472..7dbd9cd83 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -144,7 +144,8 @@ class Telegram(RPC): message += ")`" elif msg['type'] == RPCMessageType.BUY_CANCEL_NOTIFICATION: - message = "\N{WARNING SIGN} *{exchange}:* Cancelling Open Buy Order for {pair}".format(**msg) + message = "\N{WARNING SIGN} *{exchange}:* " \ + "Cancelling Open Buy Order for {pair}".format(**msg) elif msg['type'] == RPCMessageType.SELL_NOTIFICATION: msg['amount'] = round(msg['amount'], 8) From b2316cdd00fd1f946a8bd07cb55e39e0a8720859 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 6 Jun 2020 13:32:06 +0200 Subject: [PATCH 13/15] Extract sell_smoij logic into it's own function --- freqtrade/rpc/telegram.py | 41 +++++++++++++++++++--------------- tests/rpc/test_rpc_telegram.py | 23 +++++++++++++++++++ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 7dbd9cd83..0dc57e5b9 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -154,25 +154,16 @@ class Telegram(RPC): microsecond=0) - msg['open_date'].replace(microsecond=0) msg['duration_min'] = msg['duration'].total_seconds() / 60 - if float(msg['profit_percent']) >= 5.0: - message = ("\N{ROCKET} *{exchange}:* Selling {pair}\n").format(**msg) + msg['emoij'] = self._get_sell_emoij(msg) - elif float(msg['profit_percent']) >= 0.0: - message = "\N{EIGHT SPOKED ASTERISK} *{exchange}:* Selling {pair}\n" - - elif msg['sell_reason'] == "stop_loss": - message = ("\N{WARNING SIGN} *{exchange}:* Selling {pair}\n").format(**msg) - - else: - message = ("\N{CROSS MARK} *{exchange}:* Selling {pair}\n").format(**msg) - - message += ("*Amount:* `{amount:.8f}`\n" - "*Open Rate:* `{open_rate:.8f}`\n" - "*Current Rate:* `{current_rate:.8f}`\n" - "*Close Rate:* `{limit:.8f}`\n" - "*Sell Reason:* `{sell_reason}`\n" - "*Duration:* `{duration} ({duration_min:.1f} min)`\n" - "*Profit:* `{profit_percent:.2f}%`").format(**msg) + message = ("{emoij} *{exchange}:* Selling {pair}\n" + "*Amount:* `{amount:.8f}`\n" + "*Open Rate:* `{open_rate:.8f}`\n" + "*Current Rate:* `{current_rate:.8f}`\n" + "*Close Rate:* `{limit:.8f}`\n" + "*Sell Reason:* `{sell_reason}`\n" + "*Duration:* `{duration} ({duration_min:.1f} min)`\n" + "*Profit:* `{profit_percent:.2f}%`").format(**msg) # Check if all sell properties are available. # This might not be the case if the message origin is triggered by /forcesell @@ -201,6 +192,20 @@ class Telegram(RPC): self._send_msg(message) + def _get_sell_emoij(self, msg): + """ + Get emoji for sell-side + """ + + if float(msg['profit_percent']) >= 5.0: + return "\N{ROCKET}" + elif float(msg['profit_percent']) >= 0.0: + return "\N{EIGHT SPOKED ASTERISK}" + elif msg['sell_reason'] == "stop_loss": + return"\N{WARNING SIGN}" + else: + return "\N{CROSS MARK}" + @authorized_only def _status(self, update: Update, context: CallbackContext) -> None: """ diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 15fe0eaf9..7fea19fa9 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1485,6 +1485,29 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None: '*Profit:* `-57.41%`' +@pytest.mark.parametrize('msg,expected', [ + ({'profit_percent': 20.1, 'sell_reason': 'roi'}, "\N{ROCKET}"), + ({'profit_percent': 5.1, 'sell_reason': 'roi'}, "\N{ROCKET}"), + ({'profit_percent': 2.56, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_percent': 1.0, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_percent': 0.0, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_percent': -5.0, 'sell_reason': 'stop_loss'}, "\N{WARNING SIGN}"), + ({'profit_percent': -2.0, 'sell_reason': 'sell_signal'}, "\N{CROSS MARK}"), +]) +def test__sell_emoji(default_conf, mocker, msg, expected): + del default_conf['fiat_display_currency'] + msg_mock = MagicMock() + mocker.patch.multiple( + 'freqtrade.rpc.telegram.Telegram', + _init=MagicMock(), + _send_msg=msg_mock + ) + freqtradebot = get_patched_freqtradebot(mocker, default_conf) + telegram = Telegram(freqtradebot) + + assert telegram._get_sell_emoij(msg) == expected + + def test__send_msg(default_conf, mocker) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock()) bot = MagicMock() From 172ca761f2c472bc405e2933f0c4b0b81612e668 Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Sat, 6 Jun 2020 15:38:42 +0200 Subject: [PATCH 14/15] Fixed typo 'emoij' --- 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 0dc57e5b9..09be7793e 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -154,9 +154,9 @@ class Telegram(RPC): microsecond=0) - msg['open_date'].replace(microsecond=0) msg['duration_min'] = msg['duration'].total_seconds() / 60 - msg['emoij'] = self._get_sell_emoij(msg) + msg['emoji'] = self._get_sell_emoji(msg) - message = ("{emoij} *{exchange}:* Selling {pair}\n" + message = ("{emoji} *{exchange}:* Selling {pair}\n" "*Amount:* `{amount:.8f}`\n" "*Open Rate:* `{open_rate:.8f}`\n" "*Current Rate:* `{current_rate:.8f}`\n" @@ -192,7 +192,7 @@ class Telegram(RPC): self._send_msg(message) - def _get_sell_emoij(self, msg): + def _get_sell_emoji(self, msg): """ Get emoji for sell-side """ From d20762aa01c9f3e2ab61dca97d260737e93c6c4c Mon Sep 17 00:00:00 2001 From: Theagainmen <24569139+Theagainmen@users.noreply.github.com> Date: Sat, 6 Jun 2020 15:46:19 +0200 Subject: [PATCH 15/15] Fixed typo 'emoij' in test file too --- tests/rpc/test_rpc_telegram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index 7fea19fa9..423f27441 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -1505,7 +1505,7 @@ def test__sell_emoji(default_conf, mocker, msg, expected): freqtradebot = get_patched_freqtradebot(mocker, default_conf) telegram = Telegram(freqtradebot) - assert telegram._get_sell_emoij(msg) == expected + assert telegram._get_sell_emoji(msg) == expected def test__send_msg(default_conf, mocker) -> None: