2018-07-29 14:09:44 +00:00
|
|
|
# pragma pylint: disable=missing-docstring, C0103, protected-access
|
|
|
|
|
2022-06-11 15:45:37 +00:00
|
|
|
from datetime import datetime, timedelta
|
2018-07-05 19:33:01 +00:00
|
|
|
from unittest.mock import MagicMock
|
2018-07-04 19:42:17 +00:00
|
|
|
|
2018-07-05 19:33:01 +00:00
|
|
|
import pytest
|
|
|
|
from requests import RequestException
|
|
|
|
|
2022-03-25 07:36:03 +00:00
|
|
|
from freqtrade.enums import ExitType, RPCMessageType
|
2021-06-09 17:51:44 +00:00
|
|
|
from freqtrade.rpc import RPC
|
2022-06-11 15:45:37 +00:00
|
|
|
from freqtrade.rpc.discord import Discord
|
2018-07-05 19:33:01 +00:00
|
|
|
from freqtrade.rpc.webhook import Webhook
|
2019-09-08 07:54:15 +00:00
|
|
|
from tests.conftest import get_patched_freqtradebot, log_has
|
2018-07-05 19:33:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_webhook_dict() -> dict:
|
|
|
|
return {
|
2020-02-08 20:02:52 +00:00
|
|
|
"enabled": True,
|
|
|
|
"url": "https://maker.ifttt.com/trigger/freqtrade_test/with/key/c764udvJ5jfSlswVRukZZ2/",
|
2022-04-04 17:32:27 +00:00
|
|
|
"webhookentry": {
|
2020-02-08 20:02:52 +00:00
|
|
|
"value1": "Buying {pair}",
|
|
|
|
"value2": "limit {limit:8f}",
|
2021-12-29 13:24:12 +00:00
|
|
|
"value3": "{stake_amount:8f} {stake_currency}",
|
|
|
|
"value4": "leverage {leverage:.1f}",
|
|
|
|
"value5": "direction {direction}"
|
2020-02-08 20:02:52 +00:00
|
|
|
},
|
2022-04-04 17:32:27 +00:00
|
|
|
"webhookentrycancel": {
|
2020-02-11 14:58:40 +00:00
|
|
|
"value1": "Cancelling Open Buy Order for {pair}",
|
2020-02-08 20:02:52 +00:00
|
|
|
"value2": "limit {limit:8f}",
|
2021-12-29 13:24:12 +00:00
|
|
|
"value3": "{stake_amount:8f} {stake_currency}",
|
|
|
|
"value4": "leverage {leverage:.1f}",
|
|
|
|
"value5": "direction {direction}"
|
2020-02-08 20:02:52 +00:00
|
|
|
},
|
2022-04-04 17:32:27 +00:00
|
|
|
"webhookentryfill": {
|
2021-04-19 17:53:16 +00:00
|
|
|
"value1": "Buy Order for {pair} filled",
|
|
|
|
"value2": "at {open_rate:8f}",
|
2021-12-29 13:24:12 +00:00
|
|
|
"value3": "{stake_amount:8f} {stake_currency}",
|
|
|
|
"value4": "leverage {leverage:.1f}",
|
|
|
|
"value5": "direction {direction}"
|
2021-04-19 17:53:16 +00:00
|
|
|
},
|
2022-04-04 17:05:36 +00:00
|
|
|
"webhookexit": {
|
2020-02-08 20:02:52 +00:00
|
|
|
"value1": "Selling {pair}",
|
|
|
|
"value2": "limit {limit:8f}",
|
2020-03-05 14:44:21 +00:00
|
|
|
"value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})"
|
2020-02-08 20:02:52 +00:00
|
|
|
},
|
2022-04-04 17:05:36 +00:00
|
|
|
"webhookexitcancel": {
|
2020-02-11 14:58:40 +00:00
|
|
|
"value1": "Cancelling Open Sell Order for {pair}",
|
2020-02-08 20:02:52 +00:00
|
|
|
"value2": "limit {limit:8f}",
|
2020-03-05 14:44:21 +00:00
|
|
|
"value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})"
|
2020-02-08 20:02:52 +00:00
|
|
|
},
|
2022-04-04 17:05:36 +00:00
|
|
|
"webhookexitfill": {
|
2021-04-19 17:53:16 +00:00
|
|
|
"value1": "Sell Order for {pair} filled",
|
|
|
|
"value2": "at {close_rate:8f}",
|
2021-04-19 17:58:29 +00:00
|
|
|
"value3": ""
|
2021-04-19 17:53:16 +00:00
|
|
|
},
|
2020-02-08 20:02:52 +00:00
|
|
|
"webhookstatus": {
|
|
|
|
"value1": "Status: {status}",
|
|
|
|
"value2": "",
|
|
|
|
"value3": ""
|
|
|
|
}
|
|
|
|
}
|
2018-07-04 19:42:17 +00:00
|
|
|
|
|
|
|
|
2018-07-05 19:33:01 +00:00
|
|
|
def test__init__(mocker, default_conf):
|
2018-07-14 11:29:50 +00:00
|
|
|
default_conf['webhook'] = {'enabled': True, 'url': "https://DEADBEEF.com"}
|
2020-12-24 08:01:53 +00:00
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
2018-07-05 19:33:01 +00:00
|
|
|
assert webhook._config == default_conf
|
2018-07-04 19:42:17 +00:00
|
|
|
|
2018-07-05 19:33:01 +00:00
|
|
|
|
2021-04-19 17:58:29 +00:00
|
|
|
def test_send_msg_webhook(default_conf, mocker):
|
2018-07-05 19:33:01 +00:00
|
|
|
default_conf["webhook"] = get_webhook_dict()
|
|
|
|
msg_mock = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
2020-12-24 08:01:53 +00:00
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
2020-02-08 23:11:58 +00:00
|
|
|
# Test buy
|
|
|
|
msg_mock = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
2018-07-05 19:33:01 +00:00
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY,
|
2021-04-20 10:54:22 +00:00
|
|
|
'exchange': 'Binance',
|
2018-07-05 19:33:01 +00:00
|
|
|
'pair': 'ETH/BTC',
|
2021-12-29 13:24:12 +00:00
|
|
|
'leverage': 1.0,
|
|
|
|
'direction': 'Long',
|
2018-07-05 19:33:01 +00:00
|
|
|
'limit': 0.005,
|
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value1"].format(**msg))
|
2018-07-05 19:33:01 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value2"].format(**msg))
|
2018-07-05 19:33:01 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value3"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value4"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value4"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value5"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value5"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
# Test short
|
|
|
|
msg_mock.reset_mock()
|
|
|
|
|
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY,
|
2021-12-29 13:24:12 +00:00
|
|
|
'exchange': 'Binance',
|
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'leverage': 2.0,
|
|
|
|
'direction': 'Short',
|
|
|
|
'limit': 0.005,
|
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value1"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value2"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value3"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value4"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value4"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value5"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value5"].format(**msg))
|
2020-02-08 23:11:58 +00:00
|
|
|
# Test buy cancel
|
2021-04-19 17:53:16 +00:00
|
|
|
msg_mock.reset_mock()
|
|
|
|
|
2020-02-08 23:11:58 +00:00
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY_CANCEL,
|
2021-04-20 10:54:22 +00:00
|
|
|
'exchange': 'Binance',
|
2020-02-08 23:11:58 +00:00
|
|
|
'pair': 'ETH/BTC',
|
2021-12-29 13:24:12 +00:00
|
|
|
'leverage': 1.0,
|
|
|
|
'direction': 'Long',
|
|
|
|
'limit': 0.005,
|
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value1"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value2"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value3"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
# Test short cancel
|
|
|
|
msg_mock.reset_mock()
|
|
|
|
|
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY_CANCEL,
|
2021-12-29 13:24:12 +00:00
|
|
|
'exchange': 'Binance',
|
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'leverage': 2.0,
|
|
|
|
'direction': 'Short',
|
2020-02-08 23:11:58 +00:00
|
|
|
'limit': 0.005,
|
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value1"].format(**msg))
|
2020-02-08 23:11:58 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value2"].format(**msg))
|
2020-02-08 23:11:58 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value3"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value4"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value5"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
# Test buy fill
|
|
|
|
msg_mock.reset_mock()
|
|
|
|
|
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY_FILL,
|
2021-04-20 04:41:58 +00:00
|
|
|
'exchange': 'Binance',
|
2021-04-19 17:58:29 +00:00
|
|
|
'pair': 'ETH/BTC',
|
2021-12-29 13:24:12 +00:00
|
|
|
'leverage': 1.0,
|
|
|
|
'direction': 'Long',
|
2021-04-19 17:58:29 +00:00
|
|
|
'open_rate': 0.005,
|
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentryfill"]["value1"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentryfill"]["value2"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentryfill"]["value3"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value4"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value5"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
# Test short fill
|
|
|
|
msg_mock.reset_mock()
|
|
|
|
|
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY_FILL,
|
2021-12-29 13:24:12 +00:00
|
|
|
'exchange': 'Binance',
|
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'leverage': 2.0,
|
|
|
|
'direction': 'Short',
|
|
|
|
'open_rate': 0.005,
|
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentryfill"]["value1"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentryfill"]["value2"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentryfill"]["value3"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value4"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg))
|
2021-12-29 13:24:12 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value5"] ==
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg))
|
2018-07-05 19:33:01 +00:00
|
|
|
# Test sell
|
2021-04-19 17:53:16 +00:00
|
|
|
msg_mock.reset_mock()
|
2021-12-29 13:24:12 +00:00
|
|
|
|
2018-07-05 19:33:01 +00:00
|
|
|
msg = {
|
2022-04-04 17:10:44 +00:00
|
|
|
'type': RPCMessageType.EXIT,
|
2021-04-20 10:54:22 +00:00
|
|
|
'exchange': 'Binance',
|
2018-07-05 19:33:01 +00:00
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'gain': "profit",
|
|
|
|
'limit': 0.005,
|
|
|
|
'amount': 0.8,
|
2019-06-17 04:55:54 +00:00
|
|
|
'order_type': 'limit',
|
2018-07-05 19:33:01 +00:00
|
|
|
'open_rate': 0.004,
|
|
|
|
'current_rate': 0.005,
|
|
|
|
'profit_amount': 0.001,
|
2020-03-05 14:44:21 +00:00
|
|
|
'profit_ratio': 0.20,
|
2018-07-05 19:33:01 +00:00
|
|
|
'stake_currency': 'BTC',
|
2022-03-25 05:55:37 +00:00
|
|
|
'sell_reason': ExitType.STOP_LOSS.value
|
2018-07-05 19:33:01 +00:00
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:05:36 +00:00
|
|
|
default_conf["webhook"]["webhookexit"]["value1"].format(**msg))
|
2018-07-05 19:33:01 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:05:36 +00:00
|
|
|
default_conf["webhook"]["webhookexit"]["value2"].format(**msg))
|
2018-07-05 19:33:01 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:05:36 +00:00
|
|
|
default_conf["webhook"]["webhookexit"]["value3"].format(**msg))
|
2020-02-08 23:11:58 +00:00
|
|
|
# Test sell cancel
|
2021-04-19 17:53:16 +00:00
|
|
|
msg_mock.reset_mock()
|
2020-02-08 23:11:58 +00:00
|
|
|
msg = {
|
2022-04-04 17:07:20 +00:00
|
|
|
'type': RPCMessageType.EXIT_CANCEL,
|
2021-04-20 10:54:22 +00:00
|
|
|
'exchange': 'Binance',
|
2020-02-08 23:11:58 +00:00
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'gain': "profit",
|
|
|
|
'limit': 0.005,
|
|
|
|
'amount': 0.8,
|
|
|
|
'order_type': 'limit',
|
|
|
|
'open_rate': 0.004,
|
|
|
|
'current_rate': 0.005,
|
|
|
|
'profit_amount': 0.001,
|
2020-03-05 14:44:21 +00:00
|
|
|
'profit_ratio': 0.20,
|
2020-02-08 23:11:58 +00:00
|
|
|
'stake_currency': 'BTC',
|
2022-03-25 05:55:37 +00:00
|
|
|
'sell_reason': ExitType.STOP_LOSS.value
|
2020-02-08 23:11:58 +00:00
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:19:54 +00:00
|
|
|
default_conf["webhook"]["webhookexitcancel"]["value1"].format(**msg))
|
2020-02-08 23:11:58 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:19:54 +00:00
|
|
|
default_conf["webhook"]["webhookexitcancel"]["value2"].format(**msg))
|
2020-02-08 23:11:58 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:19:54 +00:00
|
|
|
default_conf["webhook"]["webhookexitcancel"]["value3"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
# Test Sell fill
|
|
|
|
msg_mock.reset_mock()
|
|
|
|
msg = {
|
2022-04-04 17:08:31 +00:00
|
|
|
'type': RPCMessageType.EXIT_FILL,
|
2021-04-20 04:41:58 +00:00
|
|
|
'exchange': 'Binance',
|
2021-04-19 17:58:29 +00:00
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'gain': "profit",
|
|
|
|
'close_rate': 0.005,
|
|
|
|
'amount': 0.8,
|
|
|
|
'order_type': 'limit',
|
|
|
|
'open_rate': 0.004,
|
|
|
|
'current_rate': 0.005,
|
|
|
|
'profit_amount': 0.001,
|
|
|
|
'profit_ratio': 0.20,
|
|
|
|
'stake_currency': 'BTC',
|
2022-03-25 05:55:37 +00:00
|
|
|
'sell_reason': ExitType.STOP_LOSS.value
|
2021-04-19 17:58:29 +00:00
|
|
|
}
|
|
|
|
webhook.send_msg(msg=msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
2022-04-04 17:05:36 +00:00
|
|
|
default_conf["webhook"]["webhookexitfill"]["value1"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
2022-04-04 17:05:36 +00:00
|
|
|
default_conf["webhook"]["webhookexitfill"]["value2"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
2022-04-04 17:05:36 +00:00
|
|
|
default_conf["webhook"]["webhookexitfill"]["value3"].format(**msg))
|
2021-04-19 17:58:29 +00:00
|
|
|
|
2021-04-20 04:41:58 +00:00
|
|
|
for msgtype in [RPCMessageType.STATUS,
|
|
|
|
RPCMessageType.WARNING,
|
|
|
|
RPCMessageType.STARTUP]:
|
2019-08-30 05:05:22 +00:00
|
|
|
# Test notification
|
|
|
|
msg = {
|
|
|
|
'type': msgtype,
|
|
|
|
'status': 'Unfilled sell order for BTC cancelled due to timeout'
|
|
|
|
}
|
|
|
|
msg_mock = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
|
|
|
webhook.send_msg(msg)
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert (msg_mock.call_args[0][0]["value1"] ==
|
|
|
|
default_conf["webhook"]["webhookstatus"]["value1"].format(**msg))
|
|
|
|
assert (msg_mock.call_args[0][0]["value2"] ==
|
|
|
|
default_conf["webhook"]["webhookstatus"]["value2"].format(**msg))
|
|
|
|
assert (msg_mock.call_args[0][0]["value3"] ==
|
|
|
|
default_conf["webhook"]["webhookstatus"]["value3"].format(**msg))
|
2018-07-05 19:33:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_exception_send_msg(default_conf, mocker, caplog):
|
|
|
|
default_conf["webhook"] = get_webhook_dict()
|
2022-04-04 17:32:27 +00:00
|
|
|
del default_conf["webhook"]["webhookentry"]
|
2018-07-05 19:33:01 +00:00
|
|
|
|
2020-12-24 08:01:53 +00:00
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
2022-04-04 17:29:15 +00:00
|
|
|
webhook.send_msg({'type': RPCMessageType.ENTRY})
|
|
|
|
assert log_has(f"Message type '{RPCMessageType.ENTRY}' not configured for webhooks",
|
2019-08-11 18:17:22 +00:00
|
|
|
caplog)
|
2018-07-05 19:33:01 +00:00
|
|
|
|
|
|
|
default_conf["webhook"] = get_webhook_dict()
|
2022-04-04 17:32:27 +00:00
|
|
|
default_conf["webhook"]["webhookentry"]["value1"] = "{DEADBEEF:8f}"
|
2018-07-05 19:33:01 +00:00
|
|
|
msg_mock = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
2020-12-24 08:01:53 +00:00
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
2018-07-05 19:33:01 +00:00
|
|
|
msg = {
|
2022-04-04 17:29:15 +00:00
|
|
|
'type': RPCMessageType.ENTRY,
|
2021-04-20 10:54:22 +00:00
|
|
|
'exchange': 'Binance',
|
2018-07-05 19:33:01 +00:00
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'limit': 0.005,
|
2019-06-17 04:55:30 +00:00
|
|
|
'order_type': 'limit',
|
2018-07-05 19:33:01 +00:00
|
|
|
'stake_amount': 0.8,
|
|
|
|
'stake_amount_fiat': 500,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'fiat_currency': 'EUR'
|
|
|
|
}
|
|
|
|
webhook.send_msg(msg)
|
|
|
|
assert log_has("Problem calling Webhook. Please check your webhook configuration. "
|
2019-08-11 18:17:22 +00:00
|
|
|
"Exception: 'DEADBEEF'", caplog)
|
2018-07-05 19:33:01 +00:00
|
|
|
|
|
|
|
msg_mock = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
|
|
|
msg = {
|
|
|
|
'type': 'DEADBEEF',
|
|
|
|
'status': 'whatever'
|
|
|
|
}
|
|
|
|
with pytest.raises(NotImplementedError):
|
|
|
|
webhook.send_msg(msg)
|
|
|
|
|
|
|
|
|
|
|
|
def test__send_msg(default_conf, mocker, caplog):
|
|
|
|
default_conf["webhook"] = get_webhook_dict()
|
2020-12-24 08:01:53 +00:00
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
2018-07-05 19:33:01 +00:00
|
|
|
msg = {'value1': 'DEADBEEF',
|
|
|
|
'value2': 'ALIVEBEEF',
|
|
|
|
'value3': 'FREQTRADE'}
|
|
|
|
post = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.post", post)
|
|
|
|
webhook._send_msg(msg)
|
|
|
|
|
|
|
|
assert post.call_count == 1
|
|
|
|
assert post.call_args[1] == {'data': msg}
|
|
|
|
assert post.call_args[0] == (default_conf['webhook']['url'], )
|
|
|
|
|
|
|
|
post = MagicMock(side_effect=RequestException)
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.post", post)
|
|
|
|
webhook._send_msg(msg)
|
2019-08-11 18:17:22 +00:00
|
|
|
assert log_has('Could not call webhook url. Exception: ', caplog)
|
2021-02-26 15:12:10 +00:00
|
|
|
|
2021-02-26 18:32:41 +00:00
|
|
|
|
2021-02-26 15:12:10 +00:00
|
|
|
def test__send_msg_with_json_format(default_conf, mocker, caplog):
|
|
|
|
default_conf["webhook"] = get_webhook_dict()
|
|
|
|
default_conf["webhook"]["format"] = "json"
|
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
|
|
|
msg = {'text': 'Hello'}
|
|
|
|
post = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.post", post)
|
|
|
|
webhook._send_msg(msg)
|
|
|
|
|
|
|
|
assert post.call_args[1] == {'json': msg}
|
2021-11-28 00:42:57 +00:00
|
|
|
|
2021-11-29 18:54:54 +00:00
|
|
|
|
2021-11-28 00:42:57 +00:00
|
|
|
def test__send_msg_with_raw_format(default_conf, mocker, caplog):
|
|
|
|
default_conf["webhook"] = get_webhook_dict()
|
|
|
|
default_conf["webhook"]["format"] = "raw"
|
|
|
|
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
|
|
|
msg = {'data': 'Hello'}
|
|
|
|
post = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.post", post)
|
|
|
|
webhook._send_msg(msg)
|
|
|
|
|
|
|
|
assert post.call_args[1] == {'data': msg['data'], 'headers': {'Content-Type': 'text/plain'}}
|
2022-06-11 15:45:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_send_msg_discord(default_conf, mocker):
|
|
|
|
|
|
|
|
default_conf["discord"] = {
|
|
|
|
'enabled': True,
|
|
|
|
'webhook_url': "https://webhookurl..."
|
|
|
|
}
|
|
|
|
msg_mock = MagicMock()
|
|
|
|
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
|
|
|
discord = Discord(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
|
|
|
|
|
|
|
msg = {
|
|
|
|
'type': RPCMessageType.EXIT_FILL,
|
|
|
|
'trade_id': 1,
|
|
|
|
'exchange': 'Binance',
|
|
|
|
'pair': 'ETH/BTC',
|
|
|
|
'direction': 'Long',
|
|
|
|
'gain': "profit",
|
|
|
|
'close_rate': 0.005,
|
|
|
|
'amount': 0.8,
|
|
|
|
'order_type': 'limit',
|
|
|
|
'open_date': datetime.now() - timedelta(days=1),
|
|
|
|
'close_date': datetime.now(),
|
|
|
|
'open_rate': 0.004,
|
|
|
|
'current_rate': 0.005,
|
|
|
|
'profit_amount': 0.001,
|
|
|
|
'profit_ratio': 0.20,
|
|
|
|
'stake_currency': 'BTC',
|
|
|
|
'enter_tag': 'enter_tagggg',
|
|
|
|
'exit_reason': ExitType.STOP_LOSS.value,
|
|
|
|
}
|
|
|
|
discord.send_msg(msg=msg)
|
|
|
|
|
|
|
|
assert msg_mock.call_count == 1
|
|
|
|
assert 'embeds' in msg_mock.call_args_list[0][0][0]
|
|
|
|
assert 'title' in msg_mock.call_args_list[0][0][0]['embeds'][0]
|
|
|
|
assert 'color' in msg_mock.call_args_list[0][0][0]['embeds'][0]
|
|
|
|
assert 'fields' in msg_mock.call_args_list[0][0][0]['embeds'][0]
|