Add telegram pair unlocking
This commit is contained in:
		| @@ -146,6 +146,7 @@ official commands. You can ask at any moment for help with `/help`. | ||||
| | `/delete <trade_id>` | Delete a specific trade from the Database. Tries to close open orders. Requires manual handling of this trade on the exchange. | ||||
| | `/count` | Displays number of trades used and available | ||||
| | `/locks` | Show currently locked pairs. | ||||
| | `/unlock <pair | lock_id>` | Remove the lock for this pair (or for this lock id). | ||||
| | `/profit` | Display a summary of your profit/loss from close trades and some stats about your performance | ||||
| | `/forcesell <trade_id>` | Instantly sells the given trade  (Ignoring `minimum_roi`). | ||||
| | `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`). | ||||
|   | ||||
| @@ -11,13 +11,14 @@ from freqtrade.data.history import get_datahandler | ||||
| from freqtrade.exceptions import OperationalException | ||||
| from freqtrade.rpc import RPC | ||||
| from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload, | ||||
|                                                   BlacklistResponse, Count, Daily, DeleteLockRequest, DeleteTrade, | ||||
|                                                   ForceBuyPayload, ForceBuyResponse, | ||||
|                                                   ForceSellPayload, Locks, Logs, OpenTradeSchema, | ||||
|                                                   PairHistory, PerformanceEntry, Ping, PlotConfig, | ||||
|                                                   Profit, ResultMsg, ShowConfig, Stats, StatusMsg, | ||||
|                                                   StrategyListResponse, StrategyResponse, | ||||
|                                                   TradeResponse, Version, WhitelistResponse) | ||||
|                                                   BlacklistResponse, Count, Daily, | ||||
|                                                   DeleteLockRequest, DeleteTrade, ForceBuyPayload, | ||||
|                                                   ForceBuyResponse, ForceSellPayload, Locks, Logs, | ||||
|                                                   OpenTradeSchema, PairHistory, PerformanceEntry, | ||||
|                                                   Ping, PlotConfig, Profit, ResultMsg, ShowConfig, | ||||
|                                                   Stats, StatusMsg, StrategyListResponse, | ||||
|                                                   StrategyResponse, TradeResponse, Version, | ||||
|                                                   WhitelistResponse) | ||||
| from freqtrade.rpc.api_server.deps import get_config, get_rpc, get_rpc_optional | ||||
| from freqtrade.rpc.rpc import RPCException | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ This module manage Telegram communication | ||||
| import json | ||||
| import logging | ||||
| from datetime import timedelta | ||||
| from html import escape | ||||
| from itertools import chain | ||||
| from typing import Any, Callable, Dict, List, Union | ||||
|  | ||||
| @@ -144,6 +145,7 @@ class Telegram(RPCHandler): | ||||
|             CommandHandler('daily', self._daily), | ||||
|             CommandHandler('count', self._count), | ||||
|             CommandHandler('locks', self._locks), | ||||
|             CommandHandler(['unlock', 'delete_locks'], self._delete_locks), | ||||
|             CommandHandler(['reload_config', 'reload_conf'], self._reload_config), | ||||
|             CommandHandler(['show_config', 'show_conf'], self._show_config), | ||||
|             CommandHandler('stopbuy', self._stopbuy), | ||||
| @@ -722,17 +724,39 @@ class Telegram(RPCHandler): | ||||
|         try: | ||||
|             locks = self._rpc._rpc_locks() | ||||
|             message = tabulate([[ | ||||
|                 lock['id'], | ||||
|                 lock['pair'], | ||||
|                 lock['lock_end_time'], | ||||
|                 lock['reason']] for lock in locks['locks']], | ||||
|                 headers=['Pair', 'Until', 'Reason'], | ||||
|                 headers=['ID', 'Pair', 'Until', 'Reason'], | ||||
|                 tablefmt='simple') | ||||
|             message = "<pre>{}</pre>".format(message) | ||||
|             message = f"<pre>{escape(message)}</pre>" | ||||
|             logger.debug(message) | ||||
|             self._send_msg(message, parse_mode=ParseMode.HTML) | ||||
|         except RPCException as e: | ||||
|             self._send_msg(str(e)) | ||||
|  | ||||
|     @authorized_only | ||||
|     def _delete_locks(self, update: Update, context: CallbackContext) -> None: | ||||
|         """ | ||||
|         Handler for /delete_locks. | ||||
|         Returns the currently active locks | ||||
|         """ | ||||
|         try: | ||||
|             arg = context.args[0] if context.args and len(context.args) > 0 else None | ||||
|             lockid = None | ||||
|             pair = None | ||||
|             if arg: | ||||
|                 try: | ||||
|                     lockid = int(arg) | ||||
|                 except ValueError: | ||||
|                     pair = arg | ||||
|  | ||||
|             self._rpc._rpc_delete_lock(lockid=lockid, pair=pair) | ||||
|             self._locks(update, context) | ||||
|         except RPCException as e: | ||||
|             self._send_msg(str(e)) | ||||
|  | ||||
|     @authorized_only | ||||
|     def _whitelist(self, update: Update, context: CallbackContext) -> None: | ||||
|         """ | ||||
| @@ -850,6 +874,7 @@ class Telegram(RPCHandler): | ||||
|                    "Avg. holding durationsfor buys and sells.`\n" | ||||
|                    "*/count:* `Show number of active trades compared to allowed number of trades`\n" | ||||
|                    "*/locks:* `Show currently locked pairs`\n" | ||||
|                    "*/unlock <pair|id>:* `Unlock this Pair (or this lock id if it's numeric)`\n" | ||||
|                    "*/balance:* `Show account balance per currency`\n" | ||||
|                    "*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" | ||||
|                    "*/reload_config:* `Reload configuration file` \n" | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| # pragma pylint: disable=invalid-sequence-index, invalid-name, too-many-arguments | ||||
|  | ||||
| from datetime import datetime, timedelta, timezone | ||||
| from freqtrade.persistence.pairlock_middleware import PairLocks | ||||
| from unittest.mock import ANY, MagicMock, PropertyMock | ||||
|  | ||||
| import pytest | ||||
| @@ -11,6 +10,7 @@ from numpy import isnan | ||||
| from freqtrade.edge import PairInfo | ||||
| from freqtrade.exceptions import ExchangeError, InvalidOrderException, TemporaryError | ||||
| from freqtrade.persistence import Trade | ||||
| from freqtrade.persistence.pairlock_middleware import PairLocks | ||||
| from freqtrade.rpc import RPC, RPCException | ||||
| from freqtrade.rpc.fiat_convert import CryptoToFiatConverter | ||||
| from freqtrade.state import State | ||||
|   | ||||
| @@ -92,7 +92,8 @@ def test_telegram_init(default_conf, mocker, caplog) -> None: | ||||
|     message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], " | ||||
|                    "['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], ['trades'], " | ||||
|                    "['delete'], ['performance'], ['stats'], ['daily'], ['count'], ['locks'], " | ||||
|                    "['reload_config', 'reload_conf'], ['show_config', 'show_conf'], ['stopbuy'], " | ||||
|                    "['unlock', 'delete_locks'], ['reload_config', 'reload_conf'], " | ||||
|                    "['show_config', 'show_conf'], ['stopbuy'], " | ||||
|                    "['whitelist'], ['blacklist'], ['logs'], ['edge'], ['help'], ['version']" | ||||
|                    "]") | ||||
|  | ||||
| @@ -981,6 +982,16 @@ def test_telegram_lock_handle(default_conf, update, ticker, fee, mocker) -> None | ||||
|     assert 'deadbeef' in msg_mock.call_args_list[0][0][0] | ||||
|     assert 'randreason' in msg_mock.call_args_list[0][0][0] | ||||
|  | ||||
|     context = MagicMock() | ||||
|     context.args = ['XRP/BTC'] | ||||
|     msg_mock.reset_mock() | ||||
|     telegram._delete_locks(update=update, context=context) | ||||
|  | ||||
|     assert 'ETH/BTC' in msg_mock.call_args_list[0][0][0] | ||||
|     assert 'randreason' in msg_mock.call_args_list[0][0][0] | ||||
|     assert 'XRP/BTC' not in msg_mock.call_args_list[0][0][0] | ||||
|     assert 'deadbeef' not in msg_mock.call_args_list[0][0][0] | ||||
|  | ||||
|  | ||||
| def test_whitelist_static(default_conf, update, mocker) -> None: | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user