diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 8a5356b3e..acfe124a8 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -67,6 +67,8 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool, trade.close(open_rate * (2 - profit_rate if is_short else profit_rate)) trade.exit_reason = exit_reason + Trade.query.session.add(trade) + Trade.commit() return trade @@ -125,33 +127,33 @@ def test_stoploss_guard(mocker, default_conf, fee, caplog, is_short): assert not log_has_re(message, caplog) caplog.clear() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=200, min_ago_close=30, is_short=is_short, - )) + ) assert not freqtrade.protections.global_stop() assert not log_has_re(message, caplog) caplog.clear() # This trade does not count, as it's closed too long ago - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'BCH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=250, min_ago_close=100, is_short=is_short, - )) + ) - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=240, min_ago_close=30, is_short=is_short, - )) + ) # 3 Trades closed - but the 2nd has been closed too long ago. assert not freqtrade.protections.global_stop() assert not log_has_re(message, caplog) caplog.clear() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'LTC/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=180, min_ago_close=30, is_short=is_short, - )) + ) assert freqtrade.protections.global_stop() assert log_has_re(message, caplog) @@ -186,25 +188,25 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair assert not log_has_re(message, caplog) caplog.clear() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=200, min_ago_close=30, profit_rate=0.9, is_short=is_short - )) + ) assert not freqtrade.protections.stop_per_pair(pair) assert not freqtrade.protections.global_stop() assert not log_has_re(message, caplog) caplog.clear() # This trade does not count, as it's closed too long ago - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=250, min_ago_close=100, profit_rate=0.9, is_short=is_short - )) + ) # Trade does not count for per pair stop as it's the wrong pair. - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=240, min_ago_close=30, profit_rate=0.9, is_short=is_short - )) + ) # 3 Trades closed - but the 2nd has been closed too long ago. assert not freqtrade.protections.stop_per_pair(pair) assert freqtrade.protections.global_stop() != only_per_pair @@ -216,10 +218,10 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair caplog.clear() # Trade does not count potentially, as it's in the wrong direction - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=150, min_ago_close=25, profit_rate=0.9, is_short=not is_short - )) + ) freqtrade.protections.stop_per_pair(pair) assert freqtrade.protections.global_stop() != only_per_pair assert PairLocks.is_pair_locked(pair, side=check_side) != (only_per_side and only_per_pair) @@ -231,10 +233,10 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair caplog.clear() # 2nd Trade that counts with correct pair - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=180, min_ago_close=30, profit_rate=0.9, is_short=is_short - )) + ) freqtrade.protections.stop_per_pair(pair) assert freqtrade.protections.global_stop() != only_per_pair @@ -259,20 +261,20 @@ def test_CooldownPeriod(mocker, default_conf, fee, caplog): assert not log_has_re(message, caplog) caplog.clear() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=200, min_ago_close=30, - )) + ) assert not freqtrade.protections.global_stop() assert freqtrade.protections.stop_per_pair('XRP/BTC') assert PairLocks.is_pair_locked('XRP/BTC') assert not PairLocks.is_global_lock() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=205, min_ago_close=35, - )) + ) assert not freqtrade.protections.global_stop() assert not PairLocks.is_pair_locked('ETH/BTC') @@ -300,10 +302,10 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog, only_per_side): assert not log_has_re(message, caplog) caplog.clear() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=800, min_ago_close=450, profit_rate=0.9, - )) + ) Trade.commit() # Not locked with 1 trade @@ -312,10 +314,10 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog, only_per_side): assert not PairLocks.is_pair_locked('XRP/BTC') assert not PairLocks.is_global_lock() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=200, min_ago_close=120, profit_rate=0.9, - )) + ) Trade.commit() # Not locked with 1 trade (first trade is outside of lookback_period) @@ -325,19 +327,19 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog, only_per_side): assert not PairLocks.is_global_lock() # Add positive trade - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=20, min_ago_close=10, profit_rate=1.15, is_short=True - )) + ) Trade.commit() assert freqtrade.protections.stop_per_pair('XRP/BTC') != only_per_side assert not PairLocks.is_pair_locked('XRP/BTC', side='*') assert PairLocks.is_pair_locked('XRP/BTC', side='long') == only_per_side - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=110, min_ago_close=21, profit_rate=0.8, - )) + ) Trade.commit() # Locks due to 2nd trade @@ -365,36 +367,38 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): assert not freqtrade.protections.stop_per_pair('XRP/BTC') caplog.clear() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, - )) - Trade.query.session.add(generate_mock_trade( + ) + generate_mock_trade( 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, - )) - Trade.query.session.add(generate_mock_trade( + ) + generate_mock_trade( 'NEO/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, - )) + ) + Trade.commit() # No losing trade yet ... so max_drawdown will raise exception assert not freqtrade.protections.global_stop() assert not freqtrade.protections.stop_per_pair('XRP/BTC') - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=500, min_ago_close=400, profit_rate=0.9, - )) + ) # Not locked with one trade assert not freqtrade.protections.global_stop() assert not freqtrade.protections.stop_per_pair('XRP/BTC') assert not PairLocks.is_pair_locked('XRP/BTC') assert not PairLocks.is_global_lock() - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1200, min_ago_close=1100, profit_rate=0.5, - )) + ) + Trade.commit() # Not locked with 1 trade (2nd trade is outside of lookback_period) assert not freqtrade.protections.global_stop() @@ -404,20 +408,22 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): assert not log_has_re(message, caplog) # Winning trade ... (should not lock, does not change drawdown!) - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=320, min_ago_close=410, profit_rate=1.5, - )) + ) + Trade.commit() assert not freqtrade.protections.global_stop() assert not PairLocks.is_global_lock() caplog.clear() # Add additional negative trade, causing a loss of > 15% - Trade.query.session.add(generate_mock_trade( + generate_mock_trade( 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=20, min_ago_close=10, profit_rate=0.8, - )) + ) + Trade.commit() assert not freqtrade.protections.stop_per_pair('XRP/BTC') # local lock not supported assert not PairLocks.is_pair_locked('XRP/BTC') diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index ace77a3b6..a1a16c039 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -677,6 +677,7 @@ def test_process_trade_no_whitelist_pair(default_conf_usdt, ticker_usdt, limit_b open_rate=0.001, exchange='binance', )) + Trade.commit() assert pair not in freqtrade.active_pair_whitelist freqtrade.process() @@ -2414,6 +2415,7 @@ def test_manage_open_orders_entry_usercustom( open_trade.orders[0].side = 'sell' if is_short else 'buy' open_trade.orders[0].ft_order_side = 'sell' if is_short else 'buy' Trade.query.session.add(open_trade) + Trade.commit() # Ensure default is to return empty (so not mocked yet) freqtrade.manage_open_orders() @@ -2472,6 +2474,7 @@ def test_manage_open_orders_entry( open_trade.is_short = is_short Trade.query.session.add(open_trade) + Trade.commit() freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False) freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234) @@ -2509,6 +2512,7 @@ def test_adjust_entry_cancel( open_trade.is_short = is_short Trade.query.session.add(open_trade) + Trade.commit() # Timeout to not interfere freqtrade.strategy.ft_check_timed_out = MagicMock(return_value=False) @@ -2549,6 +2553,7 @@ def test_adjust_entry_maintain_replace( open_trade.is_short = is_short Trade.query.session.add(open_trade) + Trade.commit() # Timeout to not interfere freqtrade.strategy.ft_check_timed_out = MagicMock(return_value=False) @@ -2601,6 +2606,7 @@ def test_check_handle_cancelled_buy( open_trade.orders = [] open_trade.is_short = is_short Trade.query.session.add(open_trade) + Trade.commit() # check it does cancel buy orders over the time limit freqtrade.manage_open_orders() @@ -2631,6 +2637,7 @@ def test_manage_open_orders_buy_exception( open_trade.is_short = is_short Trade.query.session.add(open_trade) + Trade.commit() # check it does cancel buy orders over the time limit freqtrade.manage_open_orders() @@ -2672,6 +2679,7 @@ def test_manage_open_orders_exit_usercustom( open_trade_usdt.is_open = False Trade.query.session.add(open_trade_usdt) + Trade.commit() # Ensure default is false freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 @@ -2754,6 +2762,7 @@ def test_manage_open_orders_exit( open_trade_usdt.is_short = is_short Trade.query.session.add(open_trade_usdt) + Trade.commit() freqtrade.strategy.check_exit_timeout = MagicMock(return_value=False) freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False) @@ -2794,6 +2803,7 @@ def test_check_handle_cancelled_exit( open_trade_usdt.is_short = is_short Trade.query.session.add(open_trade_usdt) + Trade.commit() # check it does cancel sell orders over the time limit freqtrade.manage_open_orders() @@ -2830,6 +2840,7 @@ def test_manage_open_orders_partial( freqtrade = FreqtradeBot(default_conf_usdt) prior_stake = open_trade.stake_amount Trade.query.session.add(open_trade) + Trade.commit() # check it does cancel buy orders over the time limit # note this is for a partially-complete buy order @@ -2874,6 +2885,7 @@ def test_manage_open_orders_partial_fee( open_trade.fee_open = fee() open_trade.fee_close = fee() Trade.query.session.add(open_trade) + Trade.commit() # cancelling a half-filled order should update the amount to the bought amount # and apply fees if necessary. freqtrade.manage_open_orders() @@ -2923,6 +2935,7 @@ def test_manage_open_orders_partial_except( open_trade.fee_open = fee() open_trade.fee_close = fee() Trade.query.session.add(open_trade) + Trade.commit() # cancelling a half-filled order should update the amount to the bought amount # and apply fees if necessary. freqtrade.manage_open_orders() @@ -2961,6 +2974,7 @@ def test_manage_open_orders_exception(default_conf_usdt, ticker_usdt, open_trade freqtrade = FreqtradeBot(default_conf_usdt) Trade.query.session.add(open_trade_usdt) + Trade.commit() caplog.clear() freqtrade.manage_open_orders() diff --git a/tests/test_persistence.py b/tests/test_persistence.py index bfba58706..50d0788ca 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -1886,6 +1886,7 @@ def test_stoploss_reinitialization(default_conf, fee): assert trade.initial_stop_loss == 0.95 assert trade.initial_stop_loss_pct == -0.05 Trade.query.session.add(trade) + Trade.commit() # Lower stoploss Trade.stoploss_reinitialization(0.06) @@ -1947,6 +1948,7 @@ def test_stoploss_reinitialization_leverage(default_conf, fee): assert trade.initial_stop_loss == 0.98 assert trade.initial_stop_loss_pct == -0.1 Trade.query.session.add(trade) + Trade.commit() # Lower stoploss Trade.stoploss_reinitialization(0.15) @@ -2008,6 +2010,7 @@ def test_stoploss_reinitialization_short(default_conf, fee): assert trade.initial_stop_loss == 1.02 assert trade.initial_stop_loss_pct == -0.1 Trade.query.session.add(trade) + Trade.commit() # Lower stoploss Trade.stoploss_reinitialization(-0.15) trades = Trade.get_open_trades()