merged upstream
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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': [],
|
||||
|
||||
@@ -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': [],
|
||||
|
||||
@@ -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
|
||||
):
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
2
tests/testdata/backtest-result_new.json
vendored
2
tests/testdata/backtest-result_new.json
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user