More forceenter updates

This commit is contained in:
Matthias 2022-01-27 06:40:41 +01:00
parent 6e72effbf0
commit c4f71cc103
4 changed files with 38 additions and 21 deletions

View File

@ -731,7 +731,7 @@ class RPC:
raise RPCException('trader is not running') raise RPCException('trader is not running')
if order_side == SignalDirection.SHORT and self._freqtrade.trading_mode == TradingMode.SPOT: if order_side == SignalDirection.SHORT and self._freqtrade.trading_mode == TradingMode.SPOT:
raise RPCException("Can't go short on Spot markets") raise RPCException("Can't go short on Spot markets.")
# Check if pair quote currency equals to the stake currency. # Check if pair quote currency equals to the stake currency.
stake_currency = self._freqtrade.config.get('stake_currency') stake_currency = self._freqtrade.config.get('stake_currency')

View File

@ -155,8 +155,10 @@ class Telegram(RPCHandler):
CommandHandler('start', self._start), CommandHandler('start', self._start),
CommandHandler('stop', self._stop), CommandHandler('stop', self._stop),
CommandHandler(['forcesell', 'forceexit'], self._forceexit), CommandHandler(['forcesell', 'forceexit'], self._forceexit),
CommandHandler(['forcebuy', 'forcelong'], partial(self._forceenter, order_side=SignalDirection.LONG)), CommandHandler(['forcebuy', 'forcelong'], partial(
CommandHandler('forceshort', partial(self._forceenter, order_side=SignalDirection.SHORT)), self._forceenter, order_side=SignalDirection.LONG)),
CommandHandler('forceshort', partial(
self._forceenter, order_side=SignalDirection.SHORT)),
CommandHandler('trades', self._trades), CommandHandler('trades', self._trades),
CommandHandler('delete', self._delete_trade), CommandHandler('delete', self._delete_trade),
CommandHandler('performance', self._performance), CommandHandler('performance', self._performance),
@ -195,7 +197,7 @@ class Telegram(RPCHandler):
pattern='update_sell_reason_performance'), pattern='update_sell_reason_performance'),
CallbackQueryHandler(self._mix_tag_performance, pattern='update_mix_tag_performance'), CallbackQueryHandler(self._mix_tag_performance, pattern='update_mix_tag_performance'),
CallbackQueryHandler(self._count, pattern='update_count'), CallbackQueryHandler(self._count, pattern='update_count'),
CallbackQueryHandler(self._forcebuy_inline), CallbackQueryHandler(self._forceenter_inline),
] ]
for handle in handles: for handle in handles:
self._updater.dispatcher.add_handler(handle) self._updater.dispatcher.add_handler(handle)
@ -877,14 +879,15 @@ class Telegram(RPCHandler):
except RPCException as e: except RPCException as e:
self._send_msg(str(e)) self._send_msg(str(e))
def _forcebuy_inline(self, update: Update, _: CallbackContext) -> None: def _forceenter_inline(self, update: Update, _: CallbackContext) -> None:
if update.callback_query: if update.callback_query:
query = update.callback_query query = update.callback_query
pair, side = query.data.split('_||_') if query.data and '_||_' in query.data:
order_side = SignalDirection(side) pair, side = query.data.split('_||_')
query.answer() order_side = SignalDirection(side)
query.edit_message_text(text=f"Manually entering {order_side} for {pair}") query.answer()
self._forceenter_action(pair, None, order_side) query.edit_message_text(text=f"Manually entering {order_side} for {pair}")
self._forceenter_action(pair, None, order_side)
@staticmethod @staticmethod
def _layout_inline_keyboard(buttons: List[InlineKeyboardButton], def _layout_inline_keyboard(buttons: List[InlineKeyboardButton],
@ -1281,14 +1284,14 @@ class Telegram(RPCHandler):
:param update: message update :param update: message update
:return: None :return: None
""" """
forcebuy_text = ("*/forcelong <pair> [<rate>]:* `Instantly buys the given pair. " forceenter_text = ("*/forcelong <pair> [<rate>]:* `Instantly buys the given pair. "
"Optionally takes a rate at which to buy " "Optionally takes a rate at which to buy "
"(only applies to limit orders).` \n" "(only applies to limit orders).` \n"
) )
if self._rpc._freqtrade.trading_mode != TradingMode.SPOT: if self._rpc._freqtrade.trading_mode != TradingMode.SPOT:
forcebuy_text += ("*/forceshort <pair> [<rate>]:* `Instantly shorts the given pair. " forceenter_text += ("*/forceshort <pair> [<rate>]:* `Instantly shorts the given pair. "
"Optionally takes a rate at which to sell " "Optionally takes a rate at which to sell "
"(only applies to limit orders).` \n") "(only applies to limit orders).` \n")
message = ( message = (
"_BotControl_\n" "_BotControl_\n"
"------------\n" "------------\n"
@ -1297,7 +1300,7 @@ class Telegram(RPCHandler):
"*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" "*/stopbuy:* `Stops buying, but handles open trades gracefully` \n"
"*/forceexit <trade_id>|all:* `Instantly exits the given trade or all trades, " "*/forceexit <trade_id>|all:* `Instantly exits the given trade or all trades, "
"regardless of profit`\n" "regardless of profit`\n"
f"{forcebuy_text if self._config.get('forcebuy_enable', False) else ''}" f"{forceenter_text if self._config.get('forcebuy_enable', False) else ''}"
"*/delete <trade_id>:* `Instantly delete the given trade in the database`\n" "*/delete <trade_id>:* `Instantly delete the given trade in the database`\n"
"*/whitelist:* `Show current whitelist` \n" "*/whitelist:* `Show current whitelist` \n"
"*/blacklist [pair]:* `Show current blacklist, or adds one or more pairs " "*/blacklist [pair]:* `Show current blacklist, or adds one or more pairs "

View File

@ -9,6 +9,7 @@ from numpy import isnan
from freqtrade.edge import PairInfo from freqtrade.edge import PairInfo
from freqtrade.enums import State, TradingMode from freqtrade.enums import State, TradingMode
from freqtrade.enums.signaltype import SignalDirection
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.persistence.pairlock_middleware import PairLocks
@ -1165,6 +1166,18 @@ def test_rpc_forceentry_disabled(mocker, default_conf) -> None:
rpc._rpc_force_entry(pair, None) rpc._rpc_force_entry(pair, None)
def test_rpc_forceentry_wrong_mode(mocker, default_conf) -> None:
default_conf['forcebuy_enable'] = True
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
patch_get_signal(freqtradebot)
rpc = RPC(freqtradebot)
pair = 'ETH/BTC'
with pytest.raises(RPCException, match="Can't go short on Spot markets."):
rpc._rpc_force_entry(pair, None, order_side=SignalDirection.SHORT)
@pytest.mark.usefixtures("init_persistence") @pytest.mark.usefixtures("init_persistence")
def test_rpc_delete_lock(mocker, default_conf): def test_rpc_delete_lock(mocker, default_conf):
freqtradebot = get_patched_freqtradebot(mocker, default_conf) freqtradebot = get_patched_freqtradebot(mocker, default_conf)

View File

@ -1145,7 +1145,7 @@ def test_forceenter_handle(default_conf, update, mocker) -> None:
telegram, freqtradebot, _ = get_telegram_testobject(mocker, default_conf) telegram, freqtradebot, _ = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot) patch_get_signal(freqtradebot)
# /forcebuy ETH/BTC # /forcelong ETH/BTC
context = MagicMock() context = MagicMock()
context.args = ["ETH/BTC"] context.args = ["ETH/BTC"]
telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG) telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG)
@ -1153,11 +1153,12 @@ def test_forceenter_handle(default_conf, update, mocker) -> None:
assert fbuy_mock.call_count == 1 assert fbuy_mock.call_count == 1
assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC' assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC'
assert fbuy_mock.call_args_list[0][0][1] is None assert fbuy_mock.call_args_list[0][0][1] is None
assert fbuy_mock.call_args_list[0][1]['order_side'] == SignalDirection.LONG
# Reset and retry with specified price # Reset and retry with specified price
fbuy_mock = MagicMock(return_value=None) fbuy_mock = MagicMock(return_value=None)
mocker.patch('freqtrade.rpc.RPC._rpc_force_entry', fbuy_mock) mocker.patch('freqtrade.rpc.RPC._rpc_force_entry', fbuy_mock)
# /forcebuy ETH/BTC 0.055 # /forcelong ETH/BTC 0.055
context = MagicMock() context = MagicMock()
context.args = ["ETH/BTC", "0.055"] context.args = ["ETH/BTC", "0.055"]
telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG) telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG)
@ -1204,7 +1205,7 @@ def test_forceenter_no_pair(default_conf, update, mocker) -> None:
update = MagicMock() update = MagicMock()
update.callback_query = MagicMock() update.callback_query = MagicMock()
update.callback_query.data = 'XRP/USDT_||_long' update.callback_query.data = 'XRP/USDT_||_long'
telegram._forcebuy_inline(update, None) telegram._forceenter_inline(update, None)
assert fbuy_mock.call_count == 1 assert fbuy_mock.call_count == 1