Merge pull request #5885 from ethanopp/develop
Include more details in _FILL telegram notifications
This commit is contained in:
commit
33f00d23b9
@ -219,26 +219,28 @@ class Telegram(RPCHandler):
|
|||||||
msg['stake_amount'], msg['stake_currency'], msg['fiat_currency'])
|
msg['stake_amount'], msg['stake_currency'], msg['fiat_currency'])
|
||||||
else:
|
else:
|
||||||
msg['stake_amount_fiat'] = 0
|
msg['stake_amount_fiat'] = 0
|
||||||
|
is_fill = msg['type'] == RPCMessageType.BUY_FILL
|
||||||
|
emoji = '\N{CHECK MARK}' if is_fill else '\N{LARGE BLUE CIRCLE}'
|
||||||
|
|
||||||
content = []
|
message = (
|
||||||
content.append(
|
f"{emoji} *{msg['exchange']}:* {'Bought' if is_fill else 'Buying'} {msg['pair']}"
|
||||||
f"\N{LARGE BLUE CIRCLE} *{msg['exchange']}:* Buying {msg['pair']}"
|
|
||||||
f" (#{msg['trade_id']})\n"
|
f" (#{msg['trade_id']})\n"
|
||||||
)
|
)
|
||||||
if msg.get('buy_tag', None):
|
message += f"*Buy Tag:* `{msg['buy_tag']}`\n" if msg.get('buy_tag', None) else ""
|
||||||
content.append(f"*Buy Tag:* `{msg['buy_tag']}`\n")
|
message += f"*Amount:* `{msg['amount']:.8f}`\n"
|
||||||
content.append(f"*Amount:* `{msg['amount']:.8f}`\n")
|
|
||||||
content.append(f"*Open Rate:* `{msg['limit']:.8f}`\n")
|
if msg['type'] == RPCMessageType.BUY_FILL:
|
||||||
content.append(f"*Current Rate:* `{msg['current_rate']:.8f}`\n")
|
message += f"*Open Rate:* `{msg['open_rate']:.8f}`\n"
|
||||||
content.append(
|
|
||||||
f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}"
|
elif msg['type'] == RPCMessageType.BUY:
|
||||||
)
|
message += f"*Open Rate:* `{msg['limit']:.8f}`\n"\
|
||||||
if msg.get('fiat_currency', None):
|
f"*Current Rate:* `{msg['current_rate']:.8f}`\n"
|
||||||
content.append(
|
|
||||||
f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}"
|
message += 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'])}"
|
||||||
|
|
||||||
message = ''.join(content)
|
|
||||||
message += ")`"
|
message += ")`"
|
||||||
return message
|
return message
|
||||||
|
|
||||||
@ -258,54 +260,57 @@ class Telegram(RPCHandler):
|
|||||||
and self._rpc._fiat_converter):
|
and self._rpc._fiat_converter):
|
||||||
msg['profit_fiat'] = self._rpc._fiat_converter.convert_amount(
|
msg['profit_fiat'] = self._rpc._fiat_converter.convert_amount(
|
||||||
msg['profit_amount'], msg['stake_currency'], msg['fiat_currency'])
|
msg['profit_amount'], msg['stake_currency'], msg['fiat_currency'])
|
||||||
msg['profit_extra'] = (' ({gain}: {profit_amount:.8f} {stake_currency}'
|
msg['profit_extra'] = (
|
||||||
' / {profit_fiat:.3f} {fiat_currency})').format(**msg)
|
f" ({msg['gain']}: {msg['profit_amount']:.8f} {msg['stake_currency']}"
|
||||||
|
f" / {msg['profit_fiat']:.3f} {msg['fiat_currency']})")
|
||||||
else:
|
else:
|
||||||
msg['profit_extra'] = ''
|
msg['profit_extra'] = ''
|
||||||
|
is_fill = msg['type'] == RPCMessageType.SELL_FILL
|
||||||
|
message = (
|
||||||
|
f"{msg['emoji']} *{msg['exchange']}:* "
|
||||||
|
f"{'Sold' if is_fill else 'Selling'} {msg['pair']} (#{msg['trade_id']})\n"
|
||||||
|
f"*{'Profit' if is_fill else 'Unrealized Profit'}:* "
|
||||||
|
f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n"
|
||||||
|
f"*Buy Tag:* `{msg['buy_tag']}`\n"
|
||||||
|
f"*Sell Reason:* `{msg['sell_reason']}`\n"
|
||||||
|
f"*Duration:* `{msg['duration']} ({msg['duration_min']:.1f} min)`\n"
|
||||||
|
f"*Amount:* `{msg['amount']:.8f}`\n")
|
||||||
|
|
||||||
message = ("{emoji} *{exchange}:* Selling {pair} (#{trade_id})\n"
|
if msg['type'] == RPCMessageType.SELL:
|
||||||
"*Profit:* `{profit_ratio:.2%}{profit_extra}`\n"
|
message += (f"*Open Rate:* `{msg['open_rate']:.8f}`\n"
|
||||||
"*Buy Tag:* `{buy_tag}`\n"
|
f"*Current Rate:* `{msg['current_rate']:.8f}`\n"
|
||||||
"*Sell Reason:* `{sell_reason}`\n"
|
f"*Close Rate:* `{msg['limit']:.8f}`")
|
||||||
"*Duration:* `{duration} ({duration_min:.1f} min)`\n"
|
|
||||||
"*Amount:* `{amount:.8f}`\n"
|
elif msg['type'] == RPCMessageType.SELL_FILL:
|
||||||
"*Open Rate:* `{open_rate:.8f}`\n"
|
message += f"*Close Rate:* `{msg['close_rate']:.8f}`"
|
||||||
"*Current Rate:* `{current_rate:.8f}`\n"
|
|
||||||
"*Close Rate:* `{limit:.8f}`").format(**msg)
|
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def compose_message(self, msg: Dict[str, Any], msg_type: RPCMessageType) -> str:
|
def compose_message(self, msg: Dict[str, Any], msg_type: RPCMessageType) -> str:
|
||||||
|
if msg_type in [RPCMessageType.BUY, RPCMessageType.BUY_FILL]:
|
||||||
if msg_type == RPCMessageType.BUY:
|
|
||||||
message = self._format_buy_msg(msg)
|
message = self._format_buy_msg(msg)
|
||||||
|
|
||||||
|
elif msg_type in [RPCMessageType.SELL, RPCMessageType.SELL_FILL]:
|
||||||
|
message = self._format_sell_msg(msg)
|
||||||
|
|
||||||
elif msg_type in (RPCMessageType.BUY_CANCEL, RPCMessageType.SELL_CANCEL):
|
elif msg_type in (RPCMessageType.BUY_CANCEL, RPCMessageType.SELL_CANCEL):
|
||||||
msg['message_side'] = 'buy' if msg_type == RPCMessageType.BUY_CANCEL else 'sell'
|
msg['message_side'] = 'buy' if msg_type == RPCMessageType.BUY_CANCEL else 'sell'
|
||||||
message = ("\N{WARNING SIGN} *{exchange}:* "
|
message = ("\N{WARNING SIGN} *{exchange}:* "
|
||||||
"Cancelling open {message_side} Order for {pair} (#{trade_id}). "
|
"Cancelling open {message_side} Order for {pair} (#{trade_id}). "
|
||||||
"Reason: {reason}.".format(**msg))
|
"Reason: {reason}.".format(**msg))
|
||||||
|
|
||||||
elif msg_type == RPCMessageType.BUY_FILL:
|
|
||||||
message = ("\N{LARGE CIRCLE} *{exchange}:* "
|
|
||||||
"Buy order for {pair} (#{trade_id}) filled "
|
|
||||||
"for {open_rate}.".format(**msg))
|
|
||||||
elif msg_type == RPCMessageType.SELL_FILL:
|
|
||||||
message = ("\N{LARGE CIRCLE} *{exchange}:* "
|
|
||||||
"Sell order for {pair} (#{trade_id}) filled "
|
|
||||||
"for {close_rate}.".format(**msg))
|
|
||||||
elif msg_type == RPCMessageType.SELL:
|
|
||||||
message = self._format_sell_msg(msg)
|
|
||||||
elif msg_type == RPCMessageType.PROTECTION_TRIGGER:
|
elif msg_type == RPCMessageType.PROTECTION_TRIGGER:
|
||||||
message = (
|
message = (
|
||||||
"*Protection* triggered due to {reason}. "
|
"*Protection* triggered due to {reason}. "
|
||||||
"`{pair}` will be locked until `{lock_end_time}`."
|
"`{pair}` will be locked until `{lock_end_time}`."
|
||||||
).format(**msg)
|
).format(**msg)
|
||||||
|
|
||||||
elif msg_type == RPCMessageType.PROTECTION_TRIGGER_GLOBAL:
|
elif msg_type == RPCMessageType.PROTECTION_TRIGGER_GLOBAL:
|
||||||
message = (
|
message = (
|
||||||
"*Protection* triggered due to {reason}. "
|
"*Protection* triggered due to {reason}. "
|
||||||
"*All pairs* will be locked until `{lock_end_time}`."
|
"*All pairs* will be locked until `{lock_end_time}`."
|
||||||
).format(**msg)
|
).format(**msg)
|
||||||
|
|
||||||
elif msg_type == RPCMessageType.STATUS:
|
elif msg_type == RPCMessageType.STATUS:
|
||||||
message = '*Status:* `{status}`'.format(**msg)
|
message = '*Status:* `{status}`'.format(**msg)
|
||||||
|
|
||||||
@ -357,7 +362,7 @@ class Telegram(RPCHandler):
|
|||||||
elif float(msg['profit_percent']) >= 0.0:
|
elif float(msg['profit_percent']) >= 0.0:
|
||||||
return "\N{EIGHT SPOKED ASTERISK}"
|
return "\N{EIGHT SPOKED ASTERISK}"
|
||||||
elif msg['sell_reason'] == "stop_loss":
|
elif msg['sell_reason'] == "stop_loss":
|
||||||
return"\N{WARNING SIGN}"
|
return "\N{WARNING SIGN}"
|
||||||
else:
|
else:
|
||||||
return "\N{CROSS MARK}"
|
return "\N{CROSS MARK}"
|
||||||
|
|
||||||
|
@ -1686,17 +1686,25 @@ def test_send_msg_buy_fill_notification(default_conf, mocker) -> None:
|
|||||||
|
|
||||||
telegram.send_msg({
|
telegram.send_msg({
|
||||||
'type': RPCMessageType.BUY_FILL,
|
'type': RPCMessageType.BUY_FILL,
|
||||||
'buy_tag': 'buy_signal_01',
|
|
||||||
'trade_id': 1,
|
'trade_id': 1,
|
||||||
|
'buy_tag': 'buy_signal_01',
|
||||||
'exchange': 'Binance',
|
'exchange': 'Binance',
|
||||||
'pair': 'ETH/USDT',
|
'pair': 'ETH/BTC',
|
||||||
'open_rate': 200,
|
'stake_amount': 0.001,
|
||||||
'stake_amount': 100,
|
# 'stake_amount_fiat': 0.0,
|
||||||
'amount': 0.5,
|
'stake_currency': 'BTC',
|
||||||
'open_date': arrow.utcnow().datetime
|
'fiat_currency': 'USD',
|
||||||
|
'open_rate': 1.099e-05,
|
||||||
|
'amount': 1333.3333333333335,
|
||||||
|
'open_date': arrow.utcnow().shift(hours=-1)
|
||||||
})
|
})
|
||||||
assert (msg_mock.call_args[0][0] == '\N{LARGE CIRCLE} *Binance:* '
|
|
||||||
'Buy order for ETH/USDT (#1) filled for 200.')
|
assert msg_mock.call_args[0][0] \
|
||||||
|
== '\N{CHECK MARK} *Binance:* Bought ETH/BTC (#1)\n' \
|
||||||
|
'*Buy Tag:* `buy_signal_01`\n' \
|
||||||
|
'*Amount:* `1333.33333333`\n' \
|
||||||
|
'*Open Rate:* `0.00001099`\n' \
|
||||||
|
'*Total:* `(0.00100000 BTC, 12.345 USD)`'
|
||||||
|
|
||||||
|
|
||||||
def test_send_msg_sell_notification(default_conf, mocker) -> None:
|
def test_send_msg_sell_notification(default_conf, mocker) -> None:
|
||||||
@ -1727,7 +1735,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
|
|||||||
})
|
})
|
||||||
assert msg_mock.call_args[0][0] \
|
assert msg_mock.call_args[0][0] \
|
||||||
== ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH (#1)\n'
|
== ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH (#1)\n'
|
||||||
'*Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n'
|
'*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n'
|
||||||
'*Buy Tag:* `buy_signal1`\n'
|
'*Buy Tag:* `buy_signal1`\n'
|
||||||
'*Sell Reason:* `stop_loss`\n'
|
'*Sell Reason:* `stop_loss`\n'
|
||||||
'*Duration:* `1:00:00 (60.0 min)`\n'
|
'*Duration:* `1:00:00 (60.0 min)`\n'
|
||||||
@ -1759,7 +1767,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
|
|||||||
})
|
})
|
||||||
assert msg_mock.call_args[0][0] \
|
assert msg_mock.call_args[0][0] \
|
||||||
== ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH (#1)\n'
|
== ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH (#1)\n'
|
||||||
'*Profit:* `-57.41%`\n'
|
'*Unrealized Profit:* `-57.41%`\n'
|
||||||
'*Buy Tag:* `buy_signal1`\n'
|
'*Buy Tag:* `buy_signal1`\n'
|
||||||
'*Sell Reason:* `stop_loss`\n'
|
'*Sell Reason:* `stop_loss`\n'
|
||||||
'*Duration:* `1 day, 2:30:00 (1590.0 min)`\n'
|
'*Duration:* `1 day, 2:30:00 (1590.0 min)`\n'
|
||||||
@ -1813,25 +1821,30 @@ def test_send_msg_sell_fill_notification(default_conf, mocker) -> None:
|
|||||||
'type': RPCMessageType.SELL_FILL,
|
'type': RPCMessageType.SELL_FILL,
|
||||||
'trade_id': 1,
|
'trade_id': 1,
|
||||||
'exchange': 'Binance',
|
'exchange': 'Binance',
|
||||||
'pair': 'ETH/USDT',
|
'pair': 'KEY/ETH',
|
||||||
'gain': 'loss',
|
'gain': 'loss',
|
||||||
'limit': 3.201e-05,
|
'limit': 3.201e-05,
|
||||||
'amount': 0.1,
|
'amount': 1333.3333333333335,
|
||||||
'order_type': 'market',
|
'order_type': 'market',
|
||||||
'open_rate': 500,
|
'open_rate': 7.5e-05,
|
||||||
'close_rate': 550,
|
'close_rate': 3.201e-05,
|
||||||
'current_rate': 3.201e-05,
|
|
||||||
'profit_amount': -0.05746268,
|
'profit_amount': -0.05746268,
|
||||||
'profit_ratio': -0.57405275,
|
'profit_ratio': -0.57405275,
|
||||||
'stake_currency': 'ETH',
|
'stake_currency': 'ETH',
|
||||||
'fiat_currency': 'USD',
|
|
||||||
'buy_tag': 'buy_signal1',
|
'buy_tag': 'buy_signal1',
|
||||||
'sell_reason': SellType.STOP_LOSS.value,
|
'sell_reason': SellType.STOP_LOSS.value,
|
||||||
'open_date': arrow.utcnow().shift(hours=-1),
|
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||||
'close_date': arrow.utcnow(),
|
'close_date': arrow.utcnow(),
|
||||||
})
|
})
|
||||||
assert msg_mock.call_args[0][0] \
|
assert msg_mock.call_args[0][0] \
|
||||||
== ('\N{LARGE CIRCLE} *Binance:* Sell order for ETH/USDT (#1) filled for 550.')
|
== ('\N{WARNING SIGN} *Binance:* Sold KEY/ETH (#1)\n'
|
||||||
|
'*Profit:* `-57.41%`\n'
|
||||||
|
'*Buy Tag:* `buy_signal1`\n'
|
||||||
|
'*Sell Reason:* `stop_loss`\n'
|
||||||
|
'*Duration:* `1 day, 2:30:00 (1590.0 min)`\n'
|
||||||
|
'*Amount:* `1333.33333333`\n'
|
||||||
|
'*Close Rate:* `0.00003201`'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_send_msg_status_notification(default_conf, mocker) -> None:
|
def test_send_msg_status_notification(default_conf, mocker) -> None:
|
||||||
@ -1923,7 +1936,7 @@ def test_send_msg_sell_notification_no_fiat(default_conf, mocker) -> None:
|
|||||||
'close_date': arrow.utcnow(),
|
'close_date': arrow.utcnow(),
|
||||||
})
|
})
|
||||||
assert msg_mock.call_args[0][0] == ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH (#1)\n'
|
assert msg_mock.call_args[0][0] == ('\N{WARNING SIGN} *Binance:* Selling KEY/ETH (#1)\n'
|
||||||
'*Profit:* `-57.41%`\n'
|
'*Unrealized Profit:* `-57.41%`\n'
|
||||||
'*Buy Tag:* `buy_signal1`\n'
|
'*Buy Tag:* `buy_signal1`\n'
|
||||||
'*Sell Reason:* `stop_loss`\n'
|
'*Sell Reason:* `stop_loss`\n'
|
||||||
'*Duration:* `2:35:03 (155.1 min)`\n'
|
'*Duration:* `2:35:03 (155.1 min)`\n'
|
||||||
|
Loading…
Reference in New Issue
Block a user