merged upstream

This commit is contained in:
மனோஜ்குமார் பழனிச்சாமி
2022-04-05 15:52:48 +05:30
34 changed files with 358 additions and 307 deletions

View File

@@ -95,8 +95,8 @@ tc1 = BTContainer(data=[
[6, 5000, 5025, 4975, 4987, 6172, 0, 0], # should sell
],
stop_loss=-0.99, roi={"0": float('inf')}, profit_perc=0.00,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=2),
BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=4, close_tick=6)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=2),
BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=4, close_tick=6)]
)
# 3) Entered, sl 1%, candle drops 8% => Trade closed, 1% loss
@@ -391,7 +391,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc
'trade_duration': '',
'open_rate': 17,
'close_rate': 17,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
@@ -402,7 +402,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc
'trade_duration': '',
'open_rate': 20,
'close_rate': 20,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
@@ -413,7 +413,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc
'trade_duration': '',
'open_rate': 26,
'close_rate': 34,
'exit_type': 'sell_signal'}
'exit_type': 'exit_signal'}
]
trades_df = DataFrame(trades)

View File

@@ -23,7 +23,7 @@ tc0 = BTContainer(data=[
[4, 5010, 5011, 4977, 4995, 6172, 0, 0],
[5, 4995, 4995, 4950, 4950, 6172, 0, 0]],
stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_exit_signal=True,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)]
)
# Test 1: Stop-Loss Triggered 1% loss
@@ -424,7 +424,7 @@ tc26 = BTContainer(data=[
[4, 5010, 5010, 4855, 4995, 6172, 0, 0], # Triggers stoploss + sellsignal acted on
[5, 4995, 4995, 4950, 4950, 6172, 0, 0]],
stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_exit_signal=True,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)]
)
# Test 27: (copy of test26 with leverage)
@@ -441,7 +441,7 @@ tc27 = BTContainer(data=[
[5, 4995, 4995, 4950, 4950, 6172, 0, 0]],
stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_exit_signal=True,
leverage=5.0,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)]
)
# Test 28: (copy of test26 with leverage and as short)
@@ -458,7 +458,7 @@ tc28 = BTContainer(data=[
[5, 4995, 4995, 4950, 4950, 6172, 0, 0, 0, 0]],
stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_exit_signal=True,
leverage=5.0,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4, is_short=True)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4, is_short=True)]
)
# Test 29: Sell with signal sell in candle 3 (ROI at signal candle)
# Stoploss at 10% (irrelevant), ROI at 5% (will trigger)
@@ -486,7 +486,7 @@ tc30 = BTContainer(data=[
[4, 5010, 5251, 4855, 4995, 6172, 0, 0], # Triggers ROI, sell-signal acted on
[5, 4995, 4995, 4950, 4950, 6172, 0, 0]],
stop_loss=-0.10, roi={"0": 0.05}, profit_perc=0.002, use_exit_signal=True,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)]
)
# Test 31: trailing_stop should raise so candle 3 causes a stoploss
@@ -708,7 +708,7 @@ tc44 = BTContainer(data=[
stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.01,
use_exit_signal=True,
custom_exit_price=4552,
trades=[BTrade(exit_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=3)]
trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=3)]
)
# Test 45: Custom exit price above all candles
@@ -723,7 +723,7 @@ tc45 = BTContainer(data=[
stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.0,
use_exit_signal=True,
custom_exit_price=6052,
trades=[BTrade(exit_reason=ExitType.FORCE_SELL, open_tick=1, close_tick=4)]
trades=[BTrade(exit_reason=ExitType.FORCE_EXIT, open_tick=1, close_tick=4)]
)
# Test 46: (Short of tc45) Custom short exit price above below candles
@@ -738,7 +738,7 @@ tc46 = BTContainer(data=[
stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.0,
use_exit_signal=True,
custom_exit_price=4700,
trades=[BTrade(exit_reason=ExitType.FORCE_SELL, open_tick=1, close_tick=4, is_short=True)]
trades=[BTrade(exit_reason=ExitType.FORCE_EXIT, open_tick=1, close_tick=4, is_short=True)]
)
# Test 47: Colliding long and short signal

View File

@@ -358,7 +358,7 @@ def test_hyperopt_format_results(hyperopt):
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01],
"exit_reason": [ExitType.ROI, ExitType.STOP_LOSS,
ExitType.ROI, ExitType.FORCE_SELL]
ExitType.ROI, ExitType.FORCE_EXIT]
}),
'config': hyperopt.config,
'locks': [],
@@ -429,7 +429,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01],
"exit_reason": [ExitType.ROI, ExitType.STOP_LOSS,
ExitType.ROI, ExitType.FORCE_SELL]
ExitType.ROI, ExitType.FORCE_EXIT]
}),
'config': hyperopt_conf,
'locks': [],

View File

@@ -77,7 +77,7 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01],
"exit_reason": [ExitType.ROI, ExitType.STOP_LOSS,
ExitType.ROI, ExitType.FORCE_SELL]
ExitType.ROI, ExitType.FORCE_EXIT]
}),
'config': default_conf,
'locks': [],
@@ -129,7 +129,7 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
"is_short": [False, False, False, False],
"stake_amount": [0.01, 0.01, 0.01, 0.01],
"exit_reason": [ExitType.ROI, ExitType.ROI,
ExitType.STOP_LOSS, ExitType.FORCE_SELL]
ExitType.STOP_LOSS, ExitType.FORCE_EXIT]
}),
'config': default_conf,
'locks': [],

View File

@@ -11,7 +11,7 @@ from tests.conftest import get_patched_freqtradebot, log_has_re
def generate_mock_trade(pair: str, fee: float, is_open: bool,
sell_reason: str = ExitType.SELL_SIGNAL,
sell_reason: str = ExitType.EXIT_SIGNAL,
min_ago_open: int = None, min_ago_close: int = None,
profit_rate: float = 0.9
):

View File

@@ -1052,7 +1052,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
assert msg_mock.call_count == 4
last_msg = msg_mock.call_args_list[-2][0][0]
assert {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/BTC',
@@ -1071,8 +1071,8 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
'fiat_currency': 'USD',
'buy_tag': ANY,
'enter_tag': ANY,
'sell_reason': ExitType.FORCE_SELL.value,
'exit_reason': ExitType.FORCE_SELL.value,
'sell_reason': ExitType.FORCE_EXIT.value,
'exit_reason': ExitType.FORCE_EXIT.value,
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
@@ -1123,7 +1123,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
last_msg = msg_mock.call_args_list[-2][0][0]
assert {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/BTC',
@@ -1142,8 +1142,8 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
'fiat_currency': 'USD',
'buy_tag': ANY,
'enter_tag': ANY,
'sell_reason': ExitType.FORCE_SELL.value,
'exit_reason': ExitType.FORCE_SELL.value,
'sell_reason': ExitType.FORCE_EXIT.value,
'exit_reason': ExitType.FORCE_EXIT.value,
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
@@ -1184,7 +1184,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
assert msg_mock.call_count == 8
msg = msg_mock.call_args_list[0][0][0]
assert {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/BTC',
@@ -1203,8 +1203,8 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
'fiat_currency': 'USD',
'buy_tag': ANY,
'enter_tag': ANY,
'sell_reason': ExitType.FORCE_SELL.value,
'exit_reason': ExitType.FORCE_SELL.value,
'sell_reason': ExitType.FORCE_EXIT.value,
'exit_reason': ExitType.FORCE_EXIT.value,
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
@@ -1797,10 +1797,10 @@ def test_show_config_handle(default_conf, update, mocker) -> None:
@pytest.mark.parametrize('message_type,enter,enter_signal,leverage', [
(RPCMessageType.BUY, 'Long', 'long_signal_01', None),
(RPCMessageType.BUY, 'Long', 'long_signal_01', 1.0),
(RPCMessageType.BUY, 'Long', 'long_signal_01', 5.0),
(RPCMessageType.SHORT, 'Short', 'short_signal_01', 2.0)])
(RPCMessageType.ENTRY, 'Long', 'long_signal_01', None),
(RPCMessageType.ENTRY, 'Long', 'long_signal_01', 1.0),
(RPCMessageType.ENTRY, 'Long', 'long_signal_01', 5.0),
(RPCMessageType.ENTRY, 'Short', 'short_signal_01', 2.0)])
def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type,
enter, enter_signal, leverage) -> None:
@@ -1813,6 +1813,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type,
'leverage': leverage,
'limit': 1.099e-05,
'order_type': 'limit',
'direction': enter,
'stake_amount': 0.01465333,
'stake_amount_fiat': 0.0,
'stake_currency': 'BTC',
@@ -1853,8 +1854,8 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type,
@pytest.mark.parametrize('message_type,enter_signal', [
(RPCMessageType.BUY_CANCEL, 'long_signal_01'),
(RPCMessageType.SHORT_CANCEL, 'short_signal_01')])
(RPCMessageType.ENTRY_CANCEL, 'long_signal_01'),
(RPCMessageType.ENTRY_CANCEL, 'short_signal_01')])
def test_send_msg_buy_cancel_notification(default_conf, mocker, message_type, enter_signal) -> None:
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
@@ -1901,14 +1902,14 @@ def test_send_msg_protection_notification(default_conf, mocker, time_machine) ->
@pytest.mark.parametrize('message_type,entered,enter_signal,leverage', [
(RPCMessageType.BUY_FILL, 'Longed', 'long_signal_01', 1.0),
(RPCMessageType.BUY_FILL, 'Longed', 'long_signal_02', 2.0),
(RPCMessageType.SHORT_FILL, 'Shorted', 'short_signal_01', 2.0),
(RPCMessageType.ENTRY_FILL, 'Long', 'long_signal_01', 1.0),
(RPCMessageType.ENTRY_FILL, 'Long', 'long_signal_02', 2.0),
(RPCMessageType.ENTRY_FILL, 'Short', 'short_signal_01', 2.0),
])
def test_send_msg_buy_fill_notification(default_conf, mocker, message_type, entered,
enter_signal, leverage) -> None:
def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, entered,
enter_signal, leverage) -> None:
default_conf['telegram']['notification_settings']['buy_fill'] = 'on'
default_conf['telegram']['notification_settings']['entry_fill'] = 'on'
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
telegram.send_msg({
@@ -1919,6 +1920,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker, message_type, ente
'pair': 'ETH/BTC',
'leverage': leverage,
'stake_amount': 0.01465333,
'direction': entered,
'stake_currency': 'BTC',
'fiat_currency': 'USD',
'open_rate': 1.099e-05,
@@ -1927,7 +1929,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker, message_type, ente
})
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage != 1.0 else ''
assert msg_mock.call_args[0][0] == (
f'\N{CHECK MARK} *Binance:* {entered} ETH/BTC (#1)\n'
f'\N{CHECK MARK} *Binance:* {entered}ed ETH/BTC (#1)\n'
f'*Enter Tag:* `{enter_signal}`\n'
'*Amount:* `1333.33333333`\n'
f"{leverage_text}"
@@ -1969,7 +1971,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
old_convamount = telegram._rpc._fiat_converter.convert_amount
telegram._rpc._fiat_converter.convert_amount = lambda a, b, c: -24.812
telegram.send_msg({
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'KEY/ETH',
@@ -2005,7 +2007,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
msg_mock.reset_mock()
telegram.send_msg({
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'KEY/ETH',
@@ -2085,7 +2087,7 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None:
old_convamount = telegram._rpc._fiat_converter.convert_amount
telegram._rpc._fiat_converter.convert_amount = lambda a, b, c: -24.812
telegram.send_msg({
'type': RPCMessageType.SELL_CANCEL,
'type': RPCMessageType.EXIT_CANCEL,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'KEY/ETH',
@@ -2097,7 +2099,7 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None:
msg_mock.reset_mock()
telegram.send_msg({
'type': RPCMessageType.SELL_CANCEL,
'type': RPCMessageType.EXIT_CANCEL,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'KEY/ETH',
@@ -2117,11 +2119,11 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None:
def test_send_msg_sell_fill_notification(default_conf, mocker, direction,
enter_signal, leverage) -> None:
default_conf['telegram']['notification_settings']['sell_fill'] = 'on'
default_conf['telegram']['notification_settings']['exit_fill'] = 'on'
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
telegram.send_msg({
'type': RPCMessageType.SELL_FILL,
'type': RPCMessageType.EXIT_FILL,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'KEY/ETH',
@@ -2194,9 +2196,9 @@ def test_send_msg_unknown_type(default_conf, mocker) -> None:
@pytest.mark.parametrize('message_type,enter,enter_signal,leverage', [
(RPCMessageType.BUY, 'Long', 'long_signal_01', None),
(RPCMessageType.BUY, 'Long', 'long_signal_01', 2.0),
(RPCMessageType.SHORT, 'Short', 'short_signal_01', 2.0)])
(RPCMessageType.ENTRY, 'Long', 'long_signal_01', None),
(RPCMessageType.ENTRY, 'Long', 'long_signal_01', 2.0),
(RPCMessageType.ENTRY, 'Short', 'short_signal_01', 2.0)])
def test_send_msg_buy_notification_no_fiat(
default_conf, mocker, message_type, enter, enter_signal, leverage) -> None:
del default_conf['fiat_display_currency']
@@ -2211,6 +2213,7 @@ def test_send_msg_buy_notification_no_fiat(
'leverage': leverage,
'limit': 1.099e-05,
'order_type': 'limit',
'direction': enter,
'stake_amount': 0.01465333,
'stake_amount_fiat': 0.0,
'stake_currency': 'BTC',
@@ -2244,7 +2247,7 @@ def test_send_msg_sell_notification_no_fiat(
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
telegram.send_msg({
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'KEY/ETH',

View File

@@ -15,38 +15,38 @@ def get_webhook_dict() -> dict:
return {
"enabled": True,
"url": "https://maker.ifttt.com/trigger/freqtrade_test/with/key/c764udvJ5jfSlswVRukZZ2/",
"webhookbuy": {
"webhookentry": {
"value1": "Buying {pair}",
"value2": "limit {limit:8f}",
"value3": "{stake_amount:8f} {stake_currency}",
"value4": "leverage {leverage:.1f}",
"value5": "direction {direction}"
},
"webhookbuycancel": {
"webhookentrycancel": {
"value1": "Cancelling Open Buy Order for {pair}",
"value2": "limit {limit:8f}",
"value3": "{stake_amount:8f} {stake_currency}",
"value4": "leverage {leverage:.1f}",
"value5": "direction {direction}"
},
"webhookbuyfill": {
"webhookentryfill": {
"value1": "Buy Order for {pair} filled",
"value2": "at {open_rate:8f}",
"value3": "{stake_amount:8f} {stake_currency}",
"value4": "leverage {leverage:.1f}",
"value5": "direction {direction}"
},
"webhooksell": {
"webhookexit": {
"value1": "Selling {pair}",
"value2": "limit {limit:8f}",
"value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})"
},
"webhooksellcancel": {
"webhookexitcancel": {
"value1": "Cancelling Open Sell Order for {pair}",
"value2": "limit {limit:8f}",
"value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})"
},
"webhooksellfill": {
"webhookexitfill": {
"value1": "Sell Order for {pair} filled",
"value2": "at {close_rate:8f}",
"value3": ""
@@ -74,7 +74,7 @@ def test_send_msg_webhook(default_conf, mocker):
msg_mock = MagicMock()
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
msg = {
'type': RPCMessageType.BUY,
'type': RPCMessageType.ENTRY,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': 1.0,
@@ -88,20 +88,20 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhookbuy"]["value1"].format(**msg))
default_conf["webhook"]["webhookentry"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhookbuy"]["value2"].format(**msg))
default_conf["webhook"]["webhookentry"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhookbuy"]["value3"].format(**msg))
default_conf["webhook"]["webhookentry"]["value3"].format(**msg))
assert (msg_mock.call_args[0][0]["value4"] ==
default_conf["webhook"]["webhookbuy"]["value4"].format(**msg))
default_conf["webhook"]["webhookentry"]["value4"].format(**msg))
assert (msg_mock.call_args[0][0]["value5"] ==
default_conf["webhook"]["webhookbuy"]["value5"].format(**msg))
default_conf["webhook"]["webhookentry"]["value5"].format(**msg))
# Test short
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.SHORT,
'type': RPCMessageType.ENTRY,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': 2.0,
@@ -115,20 +115,20 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhookbuy"]["value1"].format(**msg))
default_conf["webhook"]["webhookentry"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhookbuy"]["value2"].format(**msg))
default_conf["webhook"]["webhookentry"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhookbuy"]["value3"].format(**msg))
default_conf["webhook"]["webhookentry"]["value3"].format(**msg))
assert (msg_mock.call_args[0][0]["value4"] ==
default_conf["webhook"]["webhookbuy"]["value4"].format(**msg))
default_conf["webhook"]["webhookentry"]["value4"].format(**msg))
assert (msg_mock.call_args[0][0]["value5"] ==
default_conf["webhook"]["webhookbuy"]["value5"].format(**msg))
default_conf["webhook"]["webhookentry"]["value5"].format(**msg))
# Test buy cancel
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.BUY_CANCEL,
'type': RPCMessageType.ENTRY_CANCEL,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': 1.0,
@@ -142,16 +142,16 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhookbuycancel"]["value1"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhookbuycancel"]["value2"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhookbuycancel"]["value3"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value3"].format(**msg))
# Test short cancel
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.SHORT_CANCEL,
'type': RPCMessageType.ENTRY_CANCEL,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': 2.0,
@@ -165,20 +165,20 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhookbuycancel"]["value1"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhookbuycancel"]["value2"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhookbuycancel"]["value3"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value3"].format(**msg))
assert (msg_mock.call_args[0][0]["value4"] ==
default_conf["webhook"]["webhookbuycancel"]["value4"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg))
assert (msg_mock.call_args[0][0]["value5"] ==
default_conf["webhook"]["webhookbuycancel"]["value5"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg))
# Test buy fill
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.BUY_FILL,
'type': RPCMessageType.ENTRY_FILL,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': 1.0,
@@ -192,20 +192,20 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhookbuyfill"]["value1"].format(**msg))
default_conf["webhook"]["webhookentryfill"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhookbuyfill"]["value2"].format(**msg))
default_conf["webhook"]["webhookentryfill"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhookbuyfill"]["value3"].format(**msg))
default_conf["webhook"]["webhookentryfill"]["value3"].format(**msg))
assert (msg_mock.call_args[0][0]["value4"] ==
default_conf["webhook"]["webhookbuycancel"]["value4"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg))
assert (msg_mock.call_args[0][0]["value5"] ==
default_conf["webhook"]["webhookbuycancel"]["value5"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg))
# Test short fill
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.SHORT_FILL,
'type': RPCMessageType.ENTRY_FILL,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': 2.0,
@@ -219,20 +219,20 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhookbuyfill"]["value1"].format(**msg))
default_conf["webhook"]["webhookentryfill"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhookbuyfill"]["value2"].format(**msg))
default_conf["webhook"]["webhookentryfill"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhookbuyfill"]["value3"].format(**msg))
default_conf["webhook"]["webhookentryfill"]["value3"].format(**msg))
assert (msg_mock.call_args[0][0]["value4"] ==
default_conf["webhook"]["webhookbuycancel"]["value4"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg))
assert (msg_mock.call_args[0][0]["value5"] ==
default_conf["webhook"]["webhookbuycancel"]["value5"].format(**msg))
default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg))
# Test sell
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'gain': "profit",
@@ -249,15 +249,15 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhooksell"]["value1"].format(**msg))
default_conf["webhook"]["webhookexit"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhooksell"]["value2"].format(**msg))
default_conf["webhook"]["webhookexit"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhooksell"]["value3"].format(**msg))
default_conf["webhook"]["webhookexit"]["value3"].format(**msg))
# Test sell cancel
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.SELL_CANCEL,
'type': RPCMessageType.EXIT_CANCEL,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'gain': "profit",
@@ -274,15 +274,15 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhooksellcancel"]["value1"].format(**msg))
default_conf["webhook"]["webhookexitcancel"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhooksellcancel"]["value2"].format(**msg))
default_conf["webhook"]["webhookexitcancel"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhooksellcancel"]["value3"].format(**msg))
default_conf["webhook"]["webhookexitcancel"]["value3"].format(**msg))
# Test Sell fill
msg_mock.reset_mock()
msg = {
'type': RPCMessageType.SELL_FILL,
'type': RPCMessageType.EXIT_FILL,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'gain': "profit",
@@ -299,11 +299,11 @@ def test_send_msg_webhook(default_conf, mocker):
webhook.send_msg(msg=msg)
assert msg_mock.call_count == 1
assert (msg_mock.call_args[0][0]["value1"] ==
default_conf["webhook"]["webhooksellfill"]["value1"].format(**msg))
default_conf["webhook"]["webhookexitfill"]["value1"].format(**msg))
assert (msg_mock.call_args[0][0]["value2"] ==
default_conf["webhook"]["webhooksellfill"]["value2"].format(**msg))
default_conf["webhook"]["webhookexitfill"]["value2"].format(**msg))
assert (msg_mock.call_args[0][0]["value3"] ==
default_conf["webhook"]["webhooksellfill"]["value3"].format(**msg))
default_conf["webhook"]["webhookexitfill"]["value3"].format(**msg))
for msgtype in [RPCMessageType.STATUS,
RPCMessageType.WARNING,
@@ -327,20 +327,20 @@ def test_send_msg_webhook(default_conf, mocker):
def test_exception_send_msg(default_conf, mocker, caplog):
default_conf["webhook"] = get_webhook_dict()
del default_conf["webhook"]["webhookbuy"]
del default_conf["webhook"]["webhookentry"]
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
webhook.send_msg({'type': RPCMessageType.BUY})
assert log_has(f"Message type '{RPCMessageType.BUY}' not configured for webhooks",
webhook.send_msg({'type': RPCMessageType.ENTRY})
assert log_has(f"Message type '{RPCMessageType.ENTRY}' not configured for webhooks",
caplog)
default_conf["webhook"] = get_webhook_dict()
default_conf["webhook"]["webhookbuy"]["value1"] = "{DEADBEEF:8f}"
default_conf["webhook"]["webhookentry"]["value1"] = "{DEADBEEF:8f}"
msg_mock = MagicMock()
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
msg = {
'type': RPCMessageType.BUY,
'type': RPCMessageType.ENTRY,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'limit': 0.005,

View File

@@ -503,15 +503,15 @@ def test_custom_exit(default_conf, fee, caplog) -> None:
enter=False, exit_=False,
low=None, high=None)
assert res.exit_flag is True
assert res.exit_type == ExitType.CUSTOM_SELL
assert res.exit_reason == 'custom_sell'
assert res.exit_type == ExitType.CUSTOM_EXIT
assert res.exit_reason == 'custom_exit'
strategy.custom_exit = MagicMock(return_value='hello world')
res = strategy.should_exit(trade, 1, now,
enter=False, exit_=False,
low=None, high=None)
assert res.exit_type == ExitType.CUSTOM_SELL
assert res.exit_type == ExitType.CUSTOM_EXIT
assert res.exit_flag is True
assert res.exit_reason == 'hello world'
@@ -520,7 +520,7 @@ def test_custom_exit(default_conf, fee, caplog) -> None:
res = strategy.should_exit(trade, 1, now,
enter=False, exit_=False,
low=None, high=None)
assert res.exit_type == ExitType.CUSTOM_SELL
assert res.exit_type == ExitType.CUSTOM_EXIT
assert res.exit_flag is True
assert res.exit_reason == 'h' * 64
assert log_has_re('Custom sell reason returned from custom_exit is too long.*', caplog)

View File

@@ -1212,7 +1212,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
assert freqtrade.handle_stoploss_on_exchange(trade) is False
assert trade.stoploss_order_id is None
assert trade.is_open is False
assert trade.exit_reason == str(ExitType.EMERGENCY_SELL)
assert trade.exit_reason == str(ExitType.EMERGENCY_EXIT)
@pytest.mark.parametrize("is_short", [False, True])
@@ -1295,7 +1295,7 @@ def test_create_stoploss_order_invalid_order(
caplog.clear()
freqtrade.create_stoploss_order(trade, 200)
assert trade.stoploss_order_id is None
assert trade.exit_reason == ExitType.EMERGENCY_SELL.value
assert trade.exit_reason == ExitType.EMERGENCY_EXIT.value
assert log_has("Unable to place a stoploss order on exchange. ", caplog)
assert log_has("Exiting the trade forcefully", caplog)
@@ -1307,7 +1307,7 @@ def test_create_stoploss_order_invalid_order(
# Rpc is sending first buy, then sell
assert rpc_mock.call_count == 2
assert rpc_mock.call_args_list[1][0][0]['sell_reason'] == ExitType.EMERGENCY_SELL.value
assert rpc_mock.call_args_list[1][0][0]['sell_reason'] == ExitType.EMERGENCY_EXIT.value
assert rpc_mock.call_args_list[1][0][0]['order_type'] == 'market'
@@ -2312,7 +2312,7 @@ def test_handle_trade_use_sell_signal(
else:
patch_get_signal(freqtrade, enter_long=False, exit_long=True)
assert freqtrade.handle_trade(trade)
assert log_has("ETH/USDT - Sell signal received. exit_type=ExitType.SELL_SIGNAL",
assert log_has("ETH/USDT - Sell signal received. exit_type=ExitType.EXIT_SIGNAL",
caplog)
@@ -3098,7 +3098,7 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
'trade_id': 1,
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'exchange': 'Binance',
'pair': 'ETH/USDT',
'gain': 'profit',
@@ -3159,7 +3159,7 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd
assert rpc_mock.call_count == 2
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/USDT',
@@ -3232,7 +3232,7 @@ def test_execute_trade_exit_custom_exit_price(
freqtrade.execute_trade_exit(
trade=trade,
limit=ticker_usdt_sell_up()['ask' if is_short else 'bid'],
exit_check=ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL)
exit_check=ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL)
)
# Sell price must be different to default bid price
@@ -3243,7 +3243,7 @@ def test_execute_trade_exit_custom_exit_price(
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
'trade_id': 1,
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'exchange': 'Binance',
'pair': 'ETH/USDT',
'direction': 'Short' if trade.is_short else 'Long',
@@ -3260,8 +3260,8 @@ def test_execute_trade_exit_custom_exit_price(
'profit_ratio': profit_ratio,
'stake_currency': 'USDT',
'fiat_currency': 'USD',
'sell_reason': ExitType.SELL_SIGNAL.value,
'exit_reason': ExitType.SELL_SIGNAL.value,
'sell_reason': ExitType.EXIT_SIGNAL.value,
'exit_reason': ExitType.EXIT_SIGNAL.value,
'open_date': ANY,
'close_date': ANY,
'close_rate': ANY,
@@ -3312,7 +3312,7 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run(
last_msg = rpc_mock.call_args_list[-1][0][0]
assert {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/USDT',
@@ -3502,15 +3502,9 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit(
assert trade.is_open is False
assert trade.exit_reason == ExitType.STOPLOSS_ON_EXCHANGE.value
assert rpc_mock.call_count == 3
if is_short:
assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.SHORT
assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.SHORT_FILL
else:
assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.BUY
assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.BUY_FILL
assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL
assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.ENTRY
assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.ENTRY_FILL
assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.EXIT
@pytest.mark.parametrize(
@@ -3578,7 +3572,7 @@ def test_execute_trade_exit_market_order(
assert rpc_mock.call_count == 3
last_msg = rpc_mock.call_args_list[-2][0][0]
assert {
'type': RPCMessageType.SELL,
'type': RPCMessageType.EXIT,
'trade_id': 1,
'exchange': 'Binance',
'pair': 'ETH/USDT',
@@ -3647,18 +3641,18 @@ def test_execute_trade_exit_insufficient_funds_error(default_conf_usdt, ticker_u
@pytest.mark.parametrize('profit_only,bid,ask,handle_first,handle_second,exit_type,is_short', [
# Enable profit
(True, 2.18, 2.2, False, True, ExitType.SELL_SIGNAL.value, False),
(True, 2.18, 2.2, False, True, ExitType.SELL_SIGNAL.value, True),
(True, 2.18, 2.2, False, True, ExitType.EXIT_SIGNAL.value, False),
(True, 2.18, 2.2, False, True, ExitType.EXIT_SIGNAL.value, True),
# # Disable profit
(False, 3.19, 3.2, True, False, ExitType.SELL_SIGNAL.value, False),
(False, 3.19, 3.2, True, False, ExitType.SELL_SIGNAL.value, True),
(False, 3.19, 3.2, True, False, ExitType.EXIT_SIGNAL.value, False),
(False, 3.19, 3.2, True, False, ExitType.EXIT_SIGNAL.value, True),
# # Enable loss
# # * Shouldn't this be ExitType.STOP_LOSS.value
(True, 0.21, 0.22, False, False, None, False),
(True, 2.41, 2.42, False, False, None, True),
# Disable loss
(False, 0.10, 0.22, True, False, ExitType.SELL_SIGNAL.value, False),
(False, 0.10, 0.22, True, False, ExitType.SELL_SIGNAL.value, True),
(False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, False),
(False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, True),
])
def test_sell_profit_only(
default_conf_usdt, limit_order, limit_order_open, is_short,
@@ -3686,7 +3680,7 @@ def test_sell_profit_only(
})
freqtrade = FreqtradeBot(default_conf_usdt)
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
if exit_type == ExitType.SELL_SIGNAL.value:
if exit_type == ExitType.EXIT_SIGNAL.value:
freqtrade.strategy.min_roi_reached = MagicMock(return_value=False)
else:
freqtrade.strategy.stop_loss_reached = MagicMock(return_value=ExitCheckTuple(

View File

@@ -53,7 +53,7 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee,
# Sell 3rd trade (not called for the first trade)
should_sell_mock = MagicMock(side_effect=[
ExitCheckTuple(exit_type=ExitType.NONE),
ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL)]
ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL)]
)
cancel_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
@@ -123,7 +123,7 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee,
assert trade.is_open
trade = trades[2]
assert trade.exit_reason == ExitType.SELL_SIGNAL.value
assert trade.exit_reason == ExitType.EXIT_SIGNAL.value
assert not trade.is_open
@@ -161,7 +161,7 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, mocker, balance_rati
)
should_sell_mock = MagicMock(side_effect=[
ExitCheckTuple(exit_type=ExitType.NONE),
ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL),
ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL),
ExitCheckTuple(exit_type=ExitType.NONE),
ExitCheckTuple(exit_type=ExitType.NONE),
ExitCheckTuple(exit_type=ExitType.NONE)]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long