Add telegram pair unlocking

This commit is contained in:
Matthias 2021-03-01 20:08:49 +01:00
parent 6640156ac7
commit 007ac7abb5
5 changed files with 49 additions and 11 deletions

View File

@ -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. | `/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 | `/count` | Displays number of trades used and available
| `/locks` | Show currently locked pairs. | `/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 | `/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 <trade_id>` | Instantly sells the given trade (Ignoring `minimum_roi`).
| `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`). | `/forcesell all` | Instantly sells all open trades (Ignoring `minimum_roi`).

View File

@ -11,13 +11,14 @@ from freqtrade.data.history import get_datahandler
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.rpc import RPC from freqtrade.rpc import RPC
from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload, from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload,
BlacklistResponse, Count, Daily, DeleteLockRequest, DeleteTrade, BlacklistResponse, Count, Daily,
ForceBuyPayload, ForceBuyResponse, DeleteLockRequest, DeleteTrade, ForceBuyPayload,
ForceSellPayload, Locks, Logs, OpenTradeSchema, ForceBuyResponse, ForceSellPayload, Locks, Logs,
PairHistory, PerformanceEntry, Ping, PlotConfig, OpenTradeSchema, PairHistory, PerformanceEntry,
Profit, ResultMsg, ShowConfig, Stats, StatusMsg, Ping, PlotConfig, Profit, ResultMsg, ShowConfig,
StrategyListResponse, StrategyResponse, Stats, StatusMsg, StrategyListResponse,
TradeResponse, Version, WhitelistResponse) StrategyResponse, TradeResponse, Version,
WhitelistResponse)
from freqtrade.rpc.api_server.deps import get_config, get_rpc, get_rpc_optional from freqtrade.rpc.api_server.deps import get_config, get_rpc, get_rpc_optional
from freqtrade.rpc.rpc import RPCException from freqtrade.rpc.rpc import RPCException

View File

@ -6,6 +6,7 @@ This module manage Telegram communication
import json import json
import logging import logging
from datetime import timedelta from datetime import timedelta
from html import escape
from itertools import chain from itertools import chain
from typing import Any, Callable, Dict, List, Union from typing import Any, Callable, Dict, List, Union
@ -144,6 +145,7 @@ class Telegram(RPCHandler):
CommandHandler('daily', self._daily), CommandHandler('daily', self._daily),
CommandHandler('count', self._count), CommandHandler('count', self._count),
CommandHandler('locks', self._locks), CommandHandler('locks', self._locks),
CommandHandler(['unlock', 'delete_locks'], self._delete_locks),
CommandHandler(['reload_config', 'reload_conf'], self._reload_config), CommandHandler(['reload_config', 'reload_conf'], self._reload_config),
CommandHandler(['show_config', 'show_conf'], self._show_config), CommandHandler(['show_config', 'show_conf'], self._show_config),
CommandHandler('stopbuy', self._stopbuy), CommandHandler('stopbuy', self._stopbuy),
@ -722,17 +724,39 @@ class Telegram(RPCHandler):
try: try:
locks = self._rpc._rpc_locks() locks = self._rpc._rpc_locks()
message = tabulate([[ message = tabulate([[
lock['id'],
lock['pair'], lock['pair'],
lock['lock_end_time'], lock['lock_end_time'],
lock['reason']] for lock in locks['locks']], lock['reason']] for lock in locks['locks']],
headers=['Pair', 'Until', 'Reason'], headers=['ID', 'Pair', 'Until', 'Reason'],
tablefmt='simple') tablefmt='simple')
message = "<pre>{}</pre>".format(message) message = f"<pre>{escape(message)}</pre>"
logger.debug(message) logger.debug(message)
self._send_msg(message, parse_mode=ParseMode.HTML) self._send_msg(message, parse_mode=ParseMode.HTML)
except RPCException as e: except RPCException as e:
self._send_msg(str(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 @authorized_only
def _whitelist(self, update: Update, context: CallbackContext) -> None: def _whitelist(self, update: Update, context: CallbackContext) -> None:
""" """
@ -850,6 +874,7 @@ class Telegram(RPCHandler):
"Avg. holding durationsfor buys and sells.`\n" "Avg. holding durationsfor buys and sells.`\n"
"*/count:* `Show number of active trades compared to allowed number of trades`\n" "*/count:* `Show number of active trades compared to allowed number of trades`\n"
"*/locks:* `Show currently locked pairs`\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" "*/balance:* `Show account balance per currency`\n"
"*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" "*/stopbuy:* `Stops buying, but handles open trades gracefully` \n"
"*/reload_config:* `Reload configuration file` \n" "*/reload_config:* `Reload configuration file` \n"

View File

@ -2,7 +2,6 @@
# pragma pylint: disable=invalid-sequence-index, invalid-name, too-many-arguments # pragma pylint: disable=invalid-sequence-index, invalid-name, too-many-arguments
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from freqtrade.persistence.pairlock_middleware import PairLocks
from unittest.mock import ANY, MagicMock, PropertyMock from unittest.mock import ANY, MagicMock, PropertyMock
import pytest import pytest
@ -11,6 +10,7 @@ from numpy import isnan
from freqtrade.edge import PairInfo from freqtrade.edge import PairInfo
from freqtrade.exceptions import ExchangeError, InvalidOrderException, TemporaryError from freqtrade.exceptions import ExchangeError, InvalidOrderException, TemporaryError
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.persistence.pairlock_middleware import PairLocks
from freqtrade.rpc import RPC, RPCException from freqtrade.rpc import RPC, RPCException
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
from freqtrade.state import State from freqtrade.state import State

View File

@ -92,7 +92,8 @@ def test_telegram_init(default_conf, mocker, caplog) -> None:
message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], " message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], "
"['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], ['trades'], " "['balance'], ['start'], ['stop'], ['forcesell'], ['forcebuy'], ['trades'], "
"['delete'], ['performance'], ['stats'], ['daily'], ['count'], ['locks'], " "['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']" "['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 'deadbeef' in msg_mock.call_args_list[0][0][0]
assert 'randreason' 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: def test_whitelist_static(default_conf, update, mocker) -> None: