From fc256749af4a29ee30353a2ae4edc17f9b3a4021 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 22 Feb 2021 06:54:33 +0100 Subject: [PATCH] Add test for backtesting _enter_trade --- freqtrade/optimize/backtesting.py | 7 +++-- tests/data/test_btanalysis.py | 1 - tests/optimize/test_backtesting.py | 41 +++++++++++++++++++++++++++++- tests/test_persistence.py | 3 +-- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index aeafaffd3..9a4a3787a 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -22,8 +22,7 @@ from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.mixins import LoggingMixin from freqtrade.optimize.optimize_reports import (generate_backtest_stats, show_backtest_results, store_backtest_stats) -from freqtrade.persistence import PairLocks, Trade -from freqtrade.persistence.models import LocalTrade +from freqtrade.persistence import LocalTrade, PairLocks, Trade from freqtrade.plugins.pairlistmanager import PairListManager from freqtrade.plugins.protectionmanager import ProtectionManager from freqtrade.resolvers import ExchangeResolver, StrategyResolver @@ -267,13 +266,13 @@ class Backtesting: return None - def _enter_trade(self, pair: str, row, max_open_trades: int, + def _enter_trade(self, pair: str, row: List, max_open_trades: int, open_trade_count: int) -> Optional[LocalTrade]: try: stake_amount = self.wallets.get_trade_stake_amount( pair, max_open_trades - open_trade_count, None) except DependencyException: - stake_amount = 0 + return None min_stake_amount = self.exchange.get_min_pair_stake_amount(pair, row[OPEN_IDX], -0.05) if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount): # print(f"{pair}, {stake_amount}") diff --git a/tests/data/test_btanalysis.py b/tests/data/test_btanalysis.py index 538c89a90..e42c13e18 100644 --- a/tests/data/test_btanalysis.py +++ b/tests/data/test_btanalysis.py @@ -301,7 +301,6 @@ def test_calculate_csum(testdatadir): assert csum_min1 == csum_min + 5 assert csum_max1 == csum_max + 5 - with pytest.raises(ValueError, match='Trade dataframe empty.'): csum_min, csum_max = calculate_csum(DataFrame()) diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index eda8aac9d..354b3f6b0 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -17,8 +17,9 @@ from freqtrade.data.btanalysis import BT_DATA_COLUMNS, evaluate_result_multi from freqtrade.data.converter import clean_ohlcv_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.data.history import get_timerange -from freqtrade.exceptions import OperationalException +from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.optimize.backtesting import Backtesting +from freqtrade.persistence import LocalTrade from freqtrade.resolvers import StrategyResolver from freqtrade.state import RunMode from freqtrade.strategy.interface import SellType @@ -447,6 +448,44 @@ def test_backtesting_pairlist_list(default_conf, mocker, caplog, testdatadir, ti Backtesting(default_conf) +def test_backtest__enter_trade(default_conf, fee, mocker, testdatadir) -> None: + default_conf['ask_strategy']['use_sell_signal'] = False + mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) + mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) + patch_exchange(mocker) + default_conf['stake_amount'] = 'unlimited' + backtesting = Backtesting(default_conf) + pair = 'UNITTEST/BTC' + row = [ + pd.Timestamp(year=2020, month=1, day=1, hour=5, minute=0), + 1, # Sell + 0.001, # Open + 0.0011, # Close + 0, # Sell + 0.00099, # Low + 0.0012, # High + ] + trade = backtesting._enter_trade(pair, row=row, max_open_trades=2, open_trade_count=0) + assert isinstance(trade, LocalTrade) + assert trade.stake_amount == 495 + + trade = backtesting._enter_trade(pair, row=row, max_open_trades=2, open_trade_count=2) + assert trade is None + + # Stake-amount too high! + mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=600.0) + + trade = backtesting._enter_trade(pair, row=row, max_open_trades=2, open_trade_count=0) + assert trade is None + + # Stake-amount too high! + mocker.patch("freqtrade.wallets.Wallets.get_trade_stake_amount", + side_effect=DependencyException) + + trade = backtesting._enter_trade(pair, row=row, max_open_trades=2, open_trade_count=0) + assert trade is None + + def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None: default_conf['ask_strategy']['use_sell_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 18a377ca3..1a8124b00 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -1,12 +1,11 @@ # pragma pylint: disable=missing-docstring, C0103 -from types import FunctionType import logging +from types import FunctionType from unittest.mock import MagicMock import arrow import pytest from sqlalchemy import create_engine -from sqlalchemy.sql.schema import Column from freqtrade import constants from freqtrade.exceptions import DependencyException, OperationalException