use dict as argument for rpc.send_msg
This commit is contained in:
parent
96a405feb7
commit
4cb1aa1d97
@ -91,7 +91,9 @@ class FreqtradeBot(object):
|
|||||||
# Log state transition
|
# Log state transition
|
||||||
state = self.state
|
state = self.state
|
||||||
if state != old_state:
|
if state != old_state:
|
||||||
self.rpc.send_msg(f'*Status:* `{state.name.lower()}`')
|
self.rpc.send_msg({
|
||||||
|
'status': f'{state.name.lower()}'
|
||||||
|
})
|
||||||
logger.info('Changing state to: %s', state.name)
|
logger.info('Changing state to: %s', state.name)
|
||||||
|
|
||||||
if state == State.STOPPED:
|
if state == State.STOPPED:
|
||||||
@ -167,9 +169,9 @@ class FreqtradeBot(object):
|
|||||||
except OperationalException:
|
except OperationalException:
|
||||||
tb = traceback.format_exc()
|
tb = traceback.format_exc()
|
||||||
hint = 'Issue `/start` if you think it is safe to restart.'
|
hint = 'Issue `/start` if you think it is safe to restart.'
|
||||||
self.rpc.send_msg(
|
self.rpc.send_msg({
|
||||||
f'*Status:* OperationalException:\n```\n{tb}```{hint}'
|
'status': f'OperationalException:\n```\n{tb}```{hint}'
|
||||||
)
|
})
|
||||||
logger.exception('OperationalException. Stopping trader ...')
|
logger.exception('OperationalException. Stopping trader ...')
|
||||||
self.state = State.STOPPED
|
self.state = State.STOPPED
|
||||||
return state_changed
|
return state_changed
|
||||||
@ -362,11 +364,12 @@ class FreqtradeBot(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Create trade entity and return
|
# Create trade entity and return
|
||||||
self.rpc.send_msg(
|
self.rpc.send_msg({
|
||||||
|
'status':
|
||||||
f"""*{exc_name}:* Buying [{pair_s}]({pair_url}) \
|
f"""*{exc_name}:* Buying [{pair_s}]({pair_url}) \
|
||||||
with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
||||||
{stake_currency}, {stake_amount_fiat:.3f} {fiat_currency})`"""
|
{stake_currency}, {stake_amount_fiat:.3f} {fiat_currency})`"""
|
||||||
)
|
})
|
||||||
# Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
|
# Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
|
||||||
fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker')
|
fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker')
|
||||||
trade = Trade(
|
trade = Trade(
|
||||||
@ -551,7 +554,9 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
|||||||
Trade.session.delete(trade)
|
Trade.session.delete(trade)
|
||||||
Trade.session.flush()
|
Trade.session.flush()
|
||||||
logger.info('Buy order timeout for %s.', trade)
|
logger.info('Buy order timeout for %s.', trade)
|
||||||
self.rpc.send_msg(f'*Timeout:* Unfilled buy order for {pair_s} cancelled')
|
self.rpc.send_msg({
|
||||||
|
'status': f'Unfilled buy order for {pair_s} cancelled due to timeout'
|
||||||
|
})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# if trade is partially complete, edit the stake details for the trade
|
# if trade is partially complete, edit the stake details for the trade
|
||||||
@ -560,7 +565,9 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
|||||||
trade.stake_amount = trade.amount * trade.open_rate
|
trade.stake_amount = trade.amount * trade.open_rate
|
||||||
trade.open_order_id = None
|
trade.open_order_id = None
|
||||||
logger.info('Partial buy order timeout for %s.', trade)
|
logger.info('Partial buy order timeout for %s.', trade)
|
||||||
self.rpc.send_msg(f'*Timeout:* Remaining buy order for {pair_s} cancelled')
|
self.rpc.send_msg({
|
||||||
|
'status': f'Remaining buy order for {pair_s} cancelled due to timeout'
|
||||||
|
})
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# FIX: 20180110, should cancel_order() be cond. or unconditionally called?
|
# FIX: 20180110, should cancel_order() be cond. or unconditionally called?
|
||||||
@ -578,7 +585,9 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
|||||||
trade.close_date = None
|
trade.close_date = None
|
||||||
trade.is_open = True
|
trade.is_open = True
|
||||||
trade.open_order_id = None
|
trade.open_order_id = None
|
||||||
self.rpc.send_msg(f'*Timeout:* Unfilled sell order for {pair_s} cancelled')
|
self.rpc.send_msg({
|
||||||
|
'status': f'Unfilled sell order for {pair_s} cancelled due to timeout'
|
||||||
|
})
|
||||||
logger.info('Sell order timeout for %s.', trade)
|
logger.info('Sell order timeout for %s.', trade)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -634,5 +643,5 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
|||||||
gain = "profit" if fmt_exp_profit > 0 else "loss"
|
gain = "profit" if fmt_exp_profit > 0 else "loss"
|
||||||
message += f'` ({gain}: {fmt_exp_profit:.2f}%, {profit_trade:.8f})`'
|
message += f'` ({gain}: {fmt_exp_profit:.2f}%, {profit_trade:.8f})`'
|
||||||
# Send the message
|
# Send the message
|
||||||
self.rpc.send_msg(message)
|
self.rpc.send_msg({'status': message})
|
||||||
Trade.session.flush()
|
Trade.session.flush()
|
||||||
|
@ -59,7 +59,9 @@ def main(sysargv: List[str]) -> None:
|
|||||||
logger.exception('Fatal exception!')
|
logger.exception('Fatal exception!')
|
||||||
finally:
|
finally:
|
||||||
if freqtrade:
|
if freqtrade:
|
||||||
freqtrade.rpc.send_msg('*Status:* `Process died ...`')
|
freqtrade.rpc.send_msg({
|
||||||
|
'status': 'process died'
|
||||||
|
})
|
||||||
freqtrade.cleanup()
|
freqtrade.cleanup()
|
||||||
sys.exit(return_code)
|
sys.exit(return_code)
|
||||||
|
|
||||||
@ -73,8 +75,9 @@ def reconfigure(freqtrade: FreqtradeBot, args: Namespace) -> FreqtradeBot:
|
|||||||
|
|
||||||
# Create new instance
|
# Create new instance
|
||||||
freqtrade = FreqtradeBot(Configuration(args).get_config())
|
freqtrade = FreqtradeBot(Configuration(args).get_config())
|
||||||
freqtrade.rpc.send_msg(
|
freqtrade.rpc.send_msg({
|
||||||
'*Status:* `Config reloaded {freqtrade.state.name.lower()}...`')
|
'status': 'config reloaded'
|
||||||
|
})
|
||||||
return freqtrade
|
return freqtrade
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class RPC(object):
|
|||||||
""" Cleanup pending module resources """
|
""" Cleanup pending module resources """
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def send_msg(self, msg: str) -> None:
|
def send_msg(self, msg: Dict[str, str]) -> None:
|
||||||
""" Sends a message to all registered rpc modules """
|
""" Sends a message to all registered rpc modules """
|
||||||
|
|
||||||
def _rpc_trade_status(self) -> List[Dict]:
|
def _rpc_trade_status(self) -> List[Dict]:
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
This module contains class to manage RPC communications (Telegram, Slack, ...)
|
This module contains class to manage RPC communications (Telegram, Slack, ...)
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from typing import List
|
from typing import List, Dict
|
||||||
|
|
||||||
from freqtrade.rpc.rpc import RPC
|
from freqtrade.rpc.rpc import RPC
|
||||||
|
|
||||||
@ -32,11 +32,14 @@ class RPCManager(object):
|
|||||||
mod.cleanup()
|
mod.cleanup()
|
||||||
del mod
|
del mod
|
||||||
|
|
||||||
def send_msg(self, msg: str) -> None:
|
def send_msg(self, msg: Dict[str, str]) -> None:
|
||||||
"""
|
"""
|
||||||
Send given markdown message to all registered rpc modules
|
Send given message to all registered rpc modules.
|
||||||
:param msg: message
|
A message consists of one or more key value pairs of strings.
|
||||||
:return: None
|
e.g.:
|
||||||
|
{
|
||||||
|
'status': 'stopping bot'
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
logger.info('Sending rpc message: %s', msg)
|
logger.info('Sending rpc message: %s', msg)
|
||||||
for mod in self.registered_modules:
|
for mod in self.registered_modules:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
This module manage Telegram communication
|
This module manage Telegram communication
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable, Dict
|
||||||
|
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update
|
from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update
|
||||||
@ -110,9 +110,9 @@ class Telegram(RPC):
|
|||||||
"""
|
"""
|
||||||
self._updater.stop()
|
self._updater.stop()
|
||||||
|
|
||||||
def send_msg(self, msg: str) -> None:
|
def send_msg(self, msg: Dict[str, str]) -> None:
|
||||||
""" Send a message to telegram channel """
|
""" Send a message to telegram channel """
|
||||||
self._send_msg(msg)
|
self._send_msg('*Status:* `{status}`'.format(**msg))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _status(self, bot: Bot, update: Update) -> None:
|
def _status(self, bot: Bot, update: Update) -> None:
|
||||||
|
@ -102,9 +102,9 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, conf)
|
freqtradebot = get_patched_freqtradebot(mocker, conf)
|
||||||
rpc_manager = RPCManager(freqtradebot)
|
rpc_manager = RPCManager(freqtradebot)
|
||||||
rpc_manager.send_msg('test')
|
rpc_manager.send_msg({'status': 'test'})
|
||||||
|
|
||||||
assert log_has('Sending rpc message: test', caplog.record_tuples)
|
assert log_has("Sending rpc message: {'status': 'test'}", caplog.record_tuples)
|
||||||
assert telegram_mock.call_count == 0
|
assert telegram_mock.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None:
|
|||||||
|
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
rpc_manager = RPCManager(freqtradebot)
|
rpc_manager = RPCManager(freqtradebot)
|
||||||
rpc_manager.send_msg('test')
|
rpc_manager.send_msg({'status': 'test'})
|
||||||
|
|
||||||
assert log_has('Sending rpc message: test', caplog.record_tuples)
|
assert log_has("Sending rpc message: {'status': 'test'}", caplog.record_tuples)
|
||||||
assert telegram_mock.call_count == 1
|
assert telegram_mock.call_count == 1
|
||||||
|
@ -757,12 +757,13 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
|
|||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
telegram._forcesell(bot=MagicMock(), update=update)
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
last_call = rpc_mock.call_args_list[-1][0][0]['status']
|
||||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling' in last_call
|
||||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
assert '[ETH/BTC]' in last_call
|
||||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Amount' in last_call
|
||||||
assert 'profit: 6.11%, 0.00006126' in rpc_mock.call_args_list[-1][0][0]
|
assert '0.00001172' in last_call
|
||||||
assert '0.919 USD' in rpc_mock.call_args_list[-1][0][0]
|
assert 'profit: 6.11%, 0.00006126' in last_call
|
||||||
|
assert '0.919 USD' in last_call
|
||||||
|
|
||||||
|
|
||||||
def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
||||||
@ -802,13 +803,14 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
|||||||
update.message.text = '/forcesell 1'
|
update.message.text = '/forcesell 1'
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
telegram._forcesell(bot=MagicMock(), update=update)
|
||||||
|
|
||||||
|
last_call = rpc_mock.call_args_list[-1][0][0]['status']
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling' in last_call
|
||||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
assert '[ETH/BTC]' in last_call
|
||||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Amount' in last_call
|
||||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
assert '0.00001044' in last_call
|
||||||
assert 'loss: -5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
assert 'loss: -5.48%, -0.00005492' in last_call
|
||||||
assert '-0.824 USD' in rpc_mock.call_args_list[-1][0][0]
|
assert '-0.824 USD' in last_call
|
||||||
|
|
||||||
|
|
||||||
def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
||||||
@ -842,9 +844,9 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker
|
|||||||
|
|
||||||
assert rpc_mock.call_count == 4
|
assert rpc_mock.call_count == 4
|
||||||
for args in rpc_mock.call_args_list:
|
for args in rpc_mock.call_args_list:
|
||||||
assert '0.00001098' in args[0][0]
|
assert '0.00001098' in args[0][0]['status']
|
||||||
assert 'loss: -0.59%, -0.00000591 BTC' in args[0][0]
|
assert 'loss: -0.59%, -0.00000591 BTC' in args[0][0]['status']
|
||||||
assert '-0.089 USD' in args[0][0]
|
assert '-0.089 USD' in args[0][0]['status']
|
||||||
|
|
||||||
|
|
||||||
def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
|
def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
|
||||||
|
@ -755,7 +755,7 @@ def test_process_operational_exception(default_conf, ticker, markets, mocker) ->
|
|||||||
result = freqtrade._process()
|
result = freqtrade._process()
|
||||||
assert result is False
|
assert result is False
|
||||||
assert freqtrade.state == State.STOPPED
|
assert freqtrade.state == State.STOPPED
|
||||||
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]
|
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]['status']
|
||||||
|
|
||||||
|
|
||||||
def test_process_trade_handling(
|
def test_process_trade_handling(
|
||||||
@ -1375,13 +1375,14 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, moc
|
|||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
last_call = rpc_mock.call_args_list[-1][0][0]['status']
|
||||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling' in last_call
|
||||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
assert '[ETH/BTC]' in last_call
|
||||||
assert 'Profit' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Amount' in last_call
|
||||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Profit' in last_call
|
||||||
assert 'profit: 6.11%, 0.00006126' in rpc_mock.call_args_list[-1][0][0]
|
assert '0.00001172' in last_call
|
||||||
assert '0.919 USD' in rpc_mock.call_args_list[-1][0][0]
|
assert 'profit: 6.11%, 0.00006126' in last_call
|
||||||
|
assert '0.919 USD' in last_call
|
||||||
|
|
||||||
|
|
||||||
def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets, mocker) -> None:
|
def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets, mocker) -> None:
|
||||||
@ -1417,12 +1418,13 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets,
|
|||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
last_call = rpc_mock.call_args_list[-1][0][0]['status']
|
||||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling' in last_call
|
||||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
assert '[ETH/BTC]' in last_call
|
||||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Amount' in last_call
|
||||||
assert 'loss: -5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
assert '0.00001044' in last_call
|
||||||
assert '-0.824 USD' in rpc_mock.call_args_list[-1][0][0]
|
assert 'loss: -5.48%, -0.00005492' in last_call
|
||||||
|
assert '-0.824 USD' in last_call
|
||||||
|
|
||||||
|
|
||||||
def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
|
def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
|
||||||
@ -1459,12 +1461,13 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
|
|||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
last_call = rpc_mock.call_args_list[-1][0][0]['status']
|
||||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling' in last_call
|
||||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
assert '[ETH/BTC]' in last_call
|
||||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Amount' in last_call
|
||||||
assert '(profit: 6.11%, 0.00006126)' in rpc_mock.call_args_list[-1][0][0]
|
assert '0.00001172' in last_call
|
||||||
assert 'USD' not in rpc_mock.call_args_list[-1][0][0]
|
assert '(profit: 6.11%, 0.00006126)' in last_call
|
||||||
|
assert 'USD' not in last_call
|
||||||
|
|
||||||
|
|
||||||
def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
|
def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
|
||||||
@ -1501,10 +1504,11 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
|
|||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
last_call = rpc_mock.call_args_list[-1][0][0]['status']
|
||||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling' in last_call
|
||||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
assert '[ETH/BTC]' in last_call
|
||||||
assert 'loss: -5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
assert '0.00001044' in last_call
|
||||||
|
assert 'loss: -5.48%, -0.00005492' in last_call
|
||||||
|
|
||||||
|
|
||||||
def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
|
def test_sell_profit_only_enable_profit(default_conf, limit_buy_order,
|
||||||
|
Loading…
Reference in New Issue
Block a user