From 235c1afd09dccbc714828e1618f7545ca3dfd776 Mon Sep 17 00:00:00 2001 From: kevinjulian Date: Thu, 22 Jul 2021 01:53:15 +0700 Subject: [PATCH] add buy_tag on telegram --- freqtrade/freqtradebot.py | 3 ++ freqtrade/rpc/telegram.py | 27 +++++++++++----- freqtrade/strategy/interface.py | 6 ++-- tests/conftest.py | 2 +- tests/rpc/test_rpc.py | 34 ++++++++++---------- tests/rpc/test_rpc_apiserver.py | 24 +++++++-------- tests/rpc/test_rpc_telegram.py | 53 ++++++++++++++++++-------------- tests/strategy/test_interface.py | 14 ++++----- tests/test_freqtradebot.py | 42 ++++++++++++------------- tests/test_persistence.py | 4 +-- 10 files changed, 115 insertions(+), 94 deletions(-) diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index cb9157d33..7756aa1d7 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -595,6 +595,7 @@ class FreqtradeBot(LoggingMixin): msg = { 'trade_id': trade.id, 'type': RPCMessageType.BUY, + 'buy_tag': trade.buy_tag, 'exchange': self.exchange.name.capitalize(), 'pair': trade.pair, 'limit': trade.open_rate, @@ -619,6 +620,7 @@ class FreqtradeBot(LoggingMixin): msg = { 'trade_id': trade.id, 'type': RPCMessageType.BUY_CANCEL, + 'buy_tag': trade.buy_tag, 'exchange': self.exchange.name.capitalize(), 'pair': trade.pair, 'limit': trade.open_rate, @@ -639,6 +641,7 @@ class FreqtradeBot(LoggingMixin): msg = { 'trade_id': trade.id, 'type': RPCMessageType.BUY_FILL, + 'buy_tag': trade.buy_tag, 'exchange': self.exchange.name.capitalize(), 'pair': trade.pair, 'open_rate': trade.open_rate, diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 263a3fc6d..a1f6a7e33 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -208,15 +208,25 @@ class Telegram(RPCHandler): else: msg['stake_amount_fiat'] = 0 - message = (f"\N{LARGE BLUE CIRCLE} *{msg['exchange']}:* Buying {msg['pair']}" - f" (#{msg['trade_id']})\n" - f"*Amount:* `{msg['amount']:.8f}`\n" - f"*Open Rate:* `{msg['limit']:.8f}`\n" - f"*Current Rate:* `{msg['current_rate']:.8f}`\n" - f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}") - + content = [] + content.append( + f"\N{LARGE BLUE CIRCLE} *{msg['exchange']}:* Buying {msg['pair']}" + f" (#{msg['trade_id']})\n" + ) + if msg.get('buy_tag', None): + content.append(f"*Buy Tag:* `{msg['buy_tag']}`\n") + content.append(f"*Amount:* `{msg['amount']:.8f}`\n") + content.append(f"*Open Rate:* `{msg['limit']:.8f}`\n") + content.append(f"*Current Rate:* `{msg['current_rate']:.8f}`\n") + content.append( + f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}" + ) if msg.get('fiat_currency', None): - message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" + content.append( + f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}" + ) + + message = ''.join(content) message += ")`" return message @@ -354,6 +364,7 @@ class Telegram(RPCHandler): "*Trade ID:* `{trade_id}` `(since {open_date_hum})`", "*Current Pair:* {pair}", "*Amount:* `{amount} ({stake_amount} {base_currency})`", + "*Buy Tag:* `{buy_tag}`" if r['buy_tag'] else "", "*Open Rate:* `{open_rate:.8f}`", "*Close Rate:* `{close_rate}`" if r['close_rate'] else "", "*Current Rate:* `{current_rate:.8f}`", diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index a5517403d..0206e8839 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -508,7 +508,7 @@ class IStrategy(ABC, HyperStrategyMixin): """ if not isinstance(dataframe, DataFrame) or dataframe.empty: logger.warning(f'Empty candle (OHLCV) data for pair {pair}') - return False, False, '' + return False, False, None latest_date = dataframe['date'].max() latest = dataframe.loc[dataframe['date'] == latest_date].iloc[-1] @@ -523,11 +523,11 @@ class IStrategy(ABC, HyperStrategyMixin): 'Outdated history for pair %s. Last tick is %s minutes old', pair, int((arrow.utcnow() - latest_date).total_seconds() // 60) ) - return False, False, '' + return False, False, None (buy, sell, buy_tag) = latest[SignalType.BUY.value] == 1,\ latest[SignalType.SELL.value] == 1,\ - latest.get(SignalTagType.BUY_TAG.value, '') + latest.get(SignalTagType.BUY_TAG.value, None) logger.debug('trigger: %s (pair=%s) buy=%s sell=%s', latest['date'], pair, str(buy), str(sell)) timeframe_seconds = timeframe_to_seconds(timeframe) diff --git a/tests/conftest.py b/tests/conftest.py index 139d989a9..5f3a63c39 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -182,7 +182,7 @@ def get_patched_worker(mocker, config) -> Worker: return Worker(args=None, config=config) -def patch_get_signal(freqtrade: FreqtradeBot, value=(True, False, '')) -> None: +def patch_get_signal(freqtrade: FreqtradeBot, value=(True, False, None)) -> None: """ :param mocker: mocker to patch IStrategy class :param value: which value IStrategy.get_signal() must return diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 889aa05cf..1e8d38841 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -35,7 +35,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) freqtradebot.state = State.RUNNING @@ -192,7 +192,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: ) del default_conf['fiat_display_currency'] freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) freqtradebot.state = State.RUNNING @@ -239,7 +239,7 @@ def test_rpc_daily_profit(default_conf, update, ticker, fee, ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) stake_currency = default_conf['stake_currency'] fiat_display_currency = default_conf['fiat_display_currency'] @@ -371,7 +371,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee, ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) stake_currency = default_conf['stake_currency'] fiat_display_currency = default_conf['fiat_display_currency'] @@ -459,7 +459,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) stake_currency = default_conf['stake_currency'] fiat_display_currency = default_conf['fiat_display_currency'] @@ -526,7 +526,7 @@ def test_rpc_balance_handle_error(default_conf, mocker): ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) rpc._fiat_converter = CryptoToFiatConverter() with pytest.raises(RPCException, match="Error getting current tickers."): @@ -567,7 +567,7 @@ def test_rpc_balance_handle(default_conf, mocker, tickers): ) default_conf['dry_run'] = False freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) rpc._fiat_converter = CryptoToFiatConverter() @@ -612,7 +612,7 @@ def test_rpc_start(mocker, default_conf) -> None: ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) freqtradebot.state = State.STOPPED @@ -633,7 +633,7 @@ def test_rpc_stop(mocker, default_conf) -> None: ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) freqtradebot.state = State.RUNNING @@ -655,7 +655,7 @@ def test_rpc_stopbuy(mocker, default_conf) -> None: ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) freqtradebot.state = State.RUNNING @@ -687,7 +687,7 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker) -> None: mocker.patch('freqtrade.wallets.Wallets.get_free', return_value=1000) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) freqtradebot.state = State.STOPPED @@ -805,7 +805,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee, ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) # Create some test data @@ -838,7 +838,7 @@ def test_rpc_count(mocker, default_conf, ticker, fee) -> None: ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) counts = rpc._rpc_count() @@ -863,7 +863,7 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order_open) -> ) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) pair = 'ETH/BTC' trade = rpc._rpc_forcebuy(pair, None) @@ -889,7 +889,7 @@ def test_rpcforcebuy(mocker, default_conf, ticker, fee, limit_buy_order_open) -> # Test not buying freqtradebot = get_patched_freqtradebot(mocker, default_conf) freqtradebot.config['stake_amount'] = 0 - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) pair = 'TKN/BTC' trade = rpc._rpc_forcebuy(pair, None) @@ -902,7 +902,7 @@ def test_rpcforcebuy_stopped(mocker, default_conf) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) pair = 'ETH/BTC' with pytest.raises(RPCException, match=r'trader is not running'): @@ -913,7 +913,7 @@ def test_rpcforcebuy_disabled(mocker, default_conf) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) freqtradebot = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) rpc = RPC(freqtradebot) pair = 'ETH/BTC' with pytest.raises(RPCException, match=r'Forcebuy not enabled.'): diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 74d40b611..f7d935b64 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -442,7 +442,7 @@ def test_api_balance(botclient, mocker, rpc_balance): def test_api_count(botclient, mocker, ticker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -504,7 +504,7 @@ def test_api_locks(botclient): def test_api_show_config(botclient, mocker): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) rc = client_get(client, f"{BASE_URI}/show_config") assert_response(rc) @@ -522,7 +522,7 @@ def test_api_show_config(botclient, mocker): def test_api_daily(botclient, mocker, ticker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -540,7 +540,7 @@ def test_api_daily(botclient, mocker, ticker, fee, markets): def test_api_trades(botclient, mocker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', markets=PropertyMock(return_value=markets) @@ -568,7 +568,7 @@ def test_api_trades(botclient, mocker, fee, markets): def test_api_trade_single(botclient, mocker, fee, ticker, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', markets=PropertyMock(return_value=markets), @@ -588,7 +588,7 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets): def test_api_delete_trade(botclient, mocker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) stoploss_mock = MagicMock() cancel_mock = MagicMock() mocker.patch.multiple( @@ -662,7 +662,7 @@ def test_api_logs(botclient): def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -678,7 +678,7 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets): @pytest.mark.usefixtures("init_persistence") def test_api_profit(botclient, mocker, ticker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -729,7 +729,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets): @pytest.mark.usefixtures("init_persistence") def test_api_stats(botclient, mocker, ticker, fee, markets,): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -757,7 +757,7 @@ def test_api_stats(botclient, mocker, ticker, fee, markets,): def test_api_performance(botclient, fee): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) trade = Trade( pair='LTC/ETH', @@ -803,7 +803,7 @@ def test_api_performance(botclient, fee): def test_api_status(botclient, mocker, ticker, fee, markets): freqtrade, client = botclient - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) mocker.patch.multiple( 'freqtrade.exchange.Exchange', get_balances=MagicMock(return_value=ticker), @@ -1044,7 +1044,7 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets): markets=PropertyMock(return_value=markets), _is_dry_limit_order_filled=MagicMock(return_value=False), ) - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) rc = client_post(client, f"{BASE_URI}/forcesell", data='{"tradeid": "1"}') diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index df624e136..ab66d18e8 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -119,7 +119,7 @@ def test_authorized_only(default_conf, mocker, caplog, update) -> None: rpc = RPC(freqtrade) dummy = DummyCls(rpc, default_conf) - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) dummy.dummy_handler(update=update, context=MagicMock()) assert dummy.state['called'] is True assert log_has('Executing handler: dummy_handler for chat_id: 0', caplog) @@ -139,7 +139,7 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None: rpc = RPC(freqtrade) dummy = DummyCls(rpc, default_conf) - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) dummy.dummy_handler(update=update, context=MagicMock()) assert dummy.state['called'] is False assert not log_has('Executing handler: dummy_handler for chat_id: 3735928559', caplog) @@ -155,7 +155,7 @@ def test_authorized_only_exception(default_conf, mocker, caplog, update) -> None freqtrade = FreqtradeBot(default_conf) rpc = RPC(freqtrade) dummy = DummyCls(rpc, default_conf) - patch_get_signal(freqtrade, (True, False, '')) + patch_get_signal(freqtrade, (True, False, None)) dummy.dummy_exception(update=update, context=MagicMock()) assert dummy.state['called'] is False @@ -185,6 +185,7 @@ def test_telegram_status(default_conf, update, mocker) -> None: 'current_rate': 1.098e-05, 'amount': 90.99181074, 'stake_amount': 90.99181074, + 'buy_tag': None, 'close_profit_pct': None, 'profit': -0.0059, 'profit_pct': -0.59, @@ -228,7 +229,7 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None: telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) freqtradebot.state = State.STOPPED # Status is also enabled when stopped @@ -285,7 +286,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None: telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) freqtradebot.state = State.STOPPED # Status table is also enabled when stopped @@ -329,7 +330,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee, telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Create some test data freqtradebot.enter_positions() @@ -400,7 +401,7 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None: ) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Try invalid data msg_mock.reset_mock() @@ -432,7 +433,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee, ) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) telegram._profit(update=update, context=MagicMock()) assert msg_mock.call_count == 1 @@ -487,7 +488,7 @@ def test_telegram_stats(default_conf, update, ticker, ticker_sell_up, fee, get_fee=fee, ) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) telegram._stats(update=update, context=MagicMock()) assert msg_mock.call_count == 1 @@ -513,7 +514,7 @@ def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tick side_effect=lambda a, b: f"{a}/{b}") telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) telegram._balance(update=update, context=MagicMock()) result = msg_mock.call_args_list[0][0][0] @@ -536,7 +537,7 @@ def test_balance_handle_empty_response(default_conf, update, mocker) -> None: mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value={}) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) freqtradebot.config['dry_run'] = False telegram._balance(update=update, context=MagicMock()) @@ -549,7 +550,7 @@ def test_balance_handle_empty_response_dry(default_conf, update, mocker) -> None mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value={}) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) telegram._balance(update=update, context=MagicMock()) result = msg_mock.call_args_list[0][0][0] @@ -578,7 +579,7 @@ def test_balance_handle_too_large_response(default_conf, update, mocker) -> None }) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) telegram._balance(update=update, context=MagicMock()) assert msg_mock.call_count > 1 @@ -677,7 +678,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee, freqtradebot = FreqtradeBot(default_conf) rpc = RPC(freqtradebot) telegram = Telegram(rpc, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Create some test data freqtradebot.enter_positions() @@ -736,7 +737,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee, freqtradebot = FreqtradeBot(default_conf) rpc = RPC(freqtradebot) telegram = Telegram(rpc, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Create some test data freqtradebot.enter_positions() @@ -797,7 +798,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None freqtradebot = FreqtradeBot(default_conf) rpc = RPC(freqtradebot) telegram = Telegram(rpc, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Create some test data freqtradebot.enter_positions() @@ -838,7 +839,7 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None: return_value=15000.0) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Trader is not running freqtradebot.state = State.STOPPED @@ -876,7 +877,7 @@ def test_forcebuy_handle(default_conf, update, mocker) -> None: mocker.patch('freqtrade.rpc.RPC._rpc_forcebuy', fbuy_mock) telegram, freqtradebot, _ = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # /forcebuy ETH/BTC context = MagicMock() @@ -905,7 +906,7 @@ def test_forcebuy_handle_exception(default_conf, update, mocker) -> None: mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) update.message.text = '/forcebuy ETH/Nonepair' telegram._forcebuy(update=update, context=MagicMock()) @@ -922,7 +923,7 @@ def test_forcebuy_no_pair(default_conf, update, mocker) -> None: telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) context = MagicMock() context.args = [] @@ -950,7 +951,7 @@ def test_performance_handle(default_conf, update, ticker, fee, get_fee=fee, ) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) # Create some test data freqtradebot.enter_positions() @@ -978,7 +979,7 @@ def test_count_handle(default_conf, update, ticker, fee, mocker) -> None: get_fee=fee, ) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) freqtradebot.state = State.STOPPED telegram._count(update=update, context=MagicMock()) @@ -1007,7 +1008,7 @@ def test_telegram_lock_handle(default_conf, update, ticker, fee, mocker) -> None get_fee=fee, ) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) - patch_get_signal(freqtradebot, (True, False, '')) + patch_get_signal(freqtradebot, (True, False, None)) telegram._locks(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'No active locks.' in msg_mock.call_args_list[0][0][0] @@ -1253,6 +1254,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog) -> None: msg = { 'type': RPCMessageType.BUY, 'trade_id': 1, + 'buy_tag': 'buy_signal_01', 'exchange': 'Binance', 'pair': 'ETH/BTC', 'limit': 1.099e-05, @@ -1270,6 +1272,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog) -> None: telegram.send_msg(msg) assert msg_mock.call_args[0][0] \ == '\N{LARGE BLUE CIRCLE} *Binance:* Buying ETH/BTC (#1)\n' \ + '*Buy Tag:* `buy_signal_01`\n' \ '*Amount:* `1333.33333333`\n' \ '*Open Rate:* `0.00001099`\n' \ '*Current Rate:* `0.00001099`\n' \ @@ -1297,6 +1300,7 @@ def test_send_msg_buy_cancel_notification(default_conf, mocker) -> None: telegram.send_msg({ 'type': RPCMessageType.BUY_CANCEL, + 'buy_tag': 'buy_signal_01', 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/BTC', @@ -1314,6 +1318,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker) -> None: telegram.send_msg({ 'type': RPCMessageType.BUY_FILL, + 'buy_tag': 'buy_signal_01', 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/USDT', @@ -1498,6 +1503,7 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None: telegram.send_msg({ 'type': RPCMessageType.BUY, + 'buy_tag': 'buy_signal_01', 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/BTC', @@ -1512,6 +1518,7 @@ def test_send_msg_buy_notification_no_fiat(default_conf, mocker) -> None: 'open_date': arrow.utcnow().shift(hours=-1) }) assert msg_mock.call_args[0][0] == ('\N{LARGE BLUE CIRCLE} *Binance:* Buying ETH/BTC (#1)\n' + '*Buy Tag:* `buy_signal_01`\n' '*Amount:* `1333.33333333`\n' '*Open Rate:* `0.00001099`\n' '*Current Rate:* `0.00001099`\n' diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index c812f3007..792353f7a 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -38,15 +38,15 @@ def test_returns_latest_signal(mocker, default_conf, ohlcv_history): mocked_history['buy'] = 0 mocked_history.loc[1, 'sell'] = 1 - assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, True, '') + assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, True, None) mocked_history.loc[1, 'sell'] = 0 mocked_history.loc[1, 'buy'] = 1 - assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, '') + assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, None) mocked_history.loc[1, 'sell'] = 0 mocked_history.loc[1, 'buy'] = 0 - assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False, '') + assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False, None) mocked_history.loc[1, 'sell'] = 0 mocked_history.loc[1, 'buy'] = 1 mocked_history.loc[1, 'buy_tag'] = 'buy_signal_01' @@ -68,15 +68,15 @@ def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history): def test_get_signal_empty(default_conf, mocker, caplog): - assert (False, False, '') == _STRATEGY.get_signal('foo', default_conf['timeframe'], DataFrame()) + assert (False, False, None) == _STRATEGY.get_signal('foo', default_conf['timeframe'], DataFrame()) assert log_has('Empty candle (OHLCV) data for pair foo', caplog) caplog.clear() - assert (False, False, '') == _STRATEGY.get_signal('bar', default_conf['timeframe'], None) + assert (False, False, None) == _STRATEGY.get_signal('bar', default_conf['timeframe'], None) assert log_has('Empty candle (OHLCV) data for pair bar', caplog) caplog.clear() - assert (False, False, '') == _STRATEGY.get_signal( + assert (False, False, None) == _STRATEGY.get_signal( 'baz', default_conf['timeframe'], DataFrame([]) @@ -116,7 +116,7 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history): caplog.set_level(logging.INFO) mocker.patch.object(_STRATEGY, 'assert_df') - assert (False, False, '') == _STRATEGY.get_signal( + assert (False, False, None) == _STRATEGY.get_signal( 'xyz', default_conf['timeframe'], mocked_history diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 6372e6d36..abbef7858 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -536,7 +536,7 @@ def test_create_trade_no_signal(default_conf, fee, mocker) -> None: ) default_conf['stake_amount'] = 10 freqtrade = FreqtradeBot(default_conf) - patch_get_signal(freqtrade, value=(False, False, '')) + patch_get_signal(freqtrade, value=(False, False, None)) Trade.query = MagicMock() Trade.query.filter = MagicMock() @@ -1860,7 +1860,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order_open, limi assert trade.is_open is True freqtrade.wallets.update() - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is True assert trade.open_order_id == limit_sell_order['id'] @@ -1885,7 +1885,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open, ) freqtrade = FreqtradeBot(default_conf) - patch_get_signal(freqtrade, value=(True, True, '')) + patch_get_signal(freqtrade, value=(True, True, None)) freqtrade.strategy.min_roi_reached = MagicMock(return_value=False) freqtrade.enter_positions() @@ -1896,7 +1896,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open, assert nb_trades == 0 # Buy is triggering, so buying ... - patch_get_signal(freqtrade, value=(True, False, '')) + patch_get_signal(freqtrade, value=(True, False, None)) freqtrade.enter_positions() trades = Trade.query.all() nb_trades = len(trades) @@ -1904,7 +1904,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open, assert trades[0].is_open is True # Buy and Sell are not triggering, so doing nothing ... - patch_get_signal(freqtrade, value=(False, False, '')) + patch_get_signal(freqtrade, value=(False, False, None)) assert freqtrade.handle_trade(trades[0]) is False trades = Trade.query.all() nb_trades = len(trades) @@ -1912,7 +1912,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open, assert trades[0].is_open is True # Buy and Sell are triggering, so doing nothing ... - patch_get_signal(freqtrade, value=(True, True, '')) + patch_get_signal(freqtrade, value=(True, True, None)) assert freqtrade.handle_trade(trades[0]) is False trades = Trade.query.all() nb_trades = len(trades) @@ -1920,7 +1920,7 @@ def test_handle_overlapping_signals(default_conf, ticker, limit_buy_order_open, assert trades[0].is_open is True # Sell is triggering, guess what : we are Selling! - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) trades = Trade.query.all() assert freqtrade.handle_trade(trades[0]) is True @@ -1938,7 +1938,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open, ) freqtrade = get_patched_freqtradebot(mocker, default_conf) - patch_get_signal(freqtrade, value=(True, False, '')) + patch_get_signal(freqtrade, value=(True, False, None)) freqtrade.strategy.min_roi_reached = MagicMock(return_value=True) freqtrade.enter_positions() @@ -1951,7 +1951,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open, # we might just want to check if we are in a sell condition without # executing # if ROI is reached we must sell - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) assert log_has("ETH/BTC - Required profit reached. sell_type=SellType.ROI", caplog) @@ -1977,10 +1977,10 @@ def test_handle_trade_use_sell_signal( trade = Trade.query.first() trade.is_open = True - patch_get_signal(freqtrade, value=(False, False, '')) + patch_get_signal(freqtrade, value=(False, False, None)) assert not freqtrade.handle_trade(trade) - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) assert log_has("ETH/BTC - Sell signal received. sell_type=SellType.SELL_SIGNAL", caplog) @@ -3016,7 +3016,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, limit_buy trade = Trade.query.first() trade.update(limit_buy_order) freqtrade.wallets.update() - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is False freqtrade.strategy.sell_profit_offset = 0.0 @@ -3051,7 +3051,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, limit_bu trade = Trade.query.first() trade.update(limit_buy_order) freqtrade.wallets.update() - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is True assert trade.sell_reason == SellType.SELL_SIGNAL.value @@ -3082,7 +3082,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, limit_buy_o trade = Trade.query.first() trade.update(limit_buy_order) - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is False @@ -3114,7 +3114,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, limit_buy_ trade = Trade.query.first() trade.update(limit_buy_order) freqtrade.wallets.update() - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is True assert trade.sell_reason == SellType.SELL_SIGNAL.value @@ -3143,7 +3143,7 @@ def test_sell_not_enough_balance(default_conf, limit_buy_order, limit_buy_order_ trade = Trade.query.first() amnt = trade.amount trade.update(limit_buy_order) - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) mocker.patch('freqtrade.wallets.Wallets.get_free', MagicMock(return_value=trade.amount * 0.985)) assert freqtrade.handle_trade(trade) is True @@ -3262,11 +3262,11 @@ def test_ignore_roi_if_buy_signal(default_conf, limit_buy_order, limit_buy_order trade = Trade.query.first() trade.update(limit_buy_order) freqtrade.wallets.update() - patch_get_signal(freqtrade, value=(True, True, '')) + patch_get_signal(freqtrade, value=(True, True, None)) assert freqtrade.handle_trade(trade) is False # Test if buy-signal is absent (should sell due to roi = true) - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is True assert trade.sell_reason == SellType.ROI.value @@ -3527,11 +3527,11 @@ def test_disable_ignore_roi_if_buy_signal(default_conf, limit_buy_order, limit_b trade = Trade.query.first() trade.update(limit_buy_order) # Sell due to min_roi_reached - patch_get_signal(freqtrade, value=(True, True, '')) + patch_get_signal(freqtrade, value=(True, True, None)) assert freqtrade.handle_trade(trade) is True # Test if buy-signal is absent - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is True assert trade.sell_reason == SellType.SELL_SIGNAL.value @@ -4059,7 +4059,7 @@ def test_order_book_ask_strategy(default_conf, limit_buy_order_open, limit_buy_o freqtrade.wallets.update() assert trade.is_open is True - patch_get_signal(freqtrade, value=(False, True, '')) + patch_get_signal(freqtrade, value=(False, True, None)) assert freqtrade.handle_trade(trade) is True assert trade.close_rate_requested == order_book_l2.return_value['asks'][0][0] diff --git a/tests/test_persistence.py b/tests/test_persistence.py index af4979919..8b927be8b 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -861,7 +861,7 @@ def test_to_json(default_conf, fee): open_date=arrow.utcnow().shift(hours=-2).datetime, open_rate=0.123, exchange='binance', - buy_tag='', + buy_tag=None, open_order_id='dry_run_buy_12345' ) result = trade.to_json() @@ -911,7 +911,7 @@ def test_to_json(default_conf, fee): 'min_rate': None, 'max_rate': None, 'strategy': None, - 'buy_tag': '', + 'buy_tag': None, 'timeframe': None, 'exchange': 'binance', }