diff --git a/freqtrade/commands/pairlist_commands.py b/freqtrade/commands/pairlist_commands.py index a815cd5f3..b1df7e98b 100644 --- a/freqtrade/commands/pairlist_commands.py +++ b/freqtrade/commands/pairlist_commands.py @@ -15,6 +15,7 @@ def start_test_pairlist(args: Dict[str, Any]) -> None: """ Test Pairlist configuration """ + from freqtrade.persistence import FtNoDBContext from freqtrade.plugins.pairlistmanager import PairListManager config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) @@ -24,11 +25,12 @@ def start_test_pairlist(args: Dict[str, Any]) -> None: if not quote_currencies: quote_currencies = [config.get('stake_currency')] results = {} - for curr in quote_currencies: - config['stake_currency'] = curr - pairlists = PairListManager(exchange, config) - pairlists.refresh_pairlist() - results[curr] = pairlists.whitelist + with FtNoDBContext(): + for curr in quote_currencies: + config['stake_currency'] = curr + pairlists = PairListManager(exchange, config) + pairlists.refresh_pairlist() + results[curr] = pairlists.whitelist for curr, pairlist in results.items(): if not args.get('print_one_column', False) and not args.get('list_pairs_print_json', False): diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index ce37a0dcc..137e51de5 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -33,7 +33,8 @@ from freqtrade.optimize.optimize_reports import (generate_backtest_stats, genera show_backtest_results, store_backtest_analysis_results, store_backtest_stats) -from freqtrade.persistence import LocalTrade, Order, PairLocks, Trade +from freqtrade.persistence import (LocalTrade, Order, PairLocks, Trade, disable_database_use, + enable_database_use) from freqtrade.plugins.pairlistmanager import PairListManager from freqtrade.plugins.protectionmanager import ProtectionManager from freqtrade.resolvers import ExchangeResolver, StrategyResolver @@ -177,8 +178,7 @@ class Backtesting: @staticmethod def cleanup(): LoggingMixin.show_output = True - PairLocks.use_db = True - Trade.use_db = True + enable_database_use() def init_backtest_detail(self) -> None: # Load detail timeframe if specified @@ -325,9 +325,7 @@ class Backtesting: self.futures_data = {} def disable_database_use(self): - PairLocks.use_db = False - PairLocks.timeframe = self.timeframe - Trade.use_db = False + disable_database_use(self.timeframe) def prepare_backtest(self, enable_protections): """ diff --git a/freqtrade/persistence/__init__.py b/freqtrade/persistence/__init__.py index 4cf7aa455..6205174a7 100644 --- a/freqtrade/persistence/__init__.py +++ b/freqtrade/persistence/__init__.py @@ -4,3 +4,5 @@ from freqtrade.persistence.key_value_store import KeyStoreKeys, KeyValueStore from freqtrade.persistence.models import init_db from freqtrade.persistence.pairlock_middleware import PairLocks from freqtrade.persistence.trade_model import LocalTrade, Order, Trade +from freqtrade.persistence.usedb_context import (FtNoDBContext, disable_database_use, + enable_database_use) diff --git a/freqtrade/persistence/usedb_context.py b/freqtrade/persistence/usedb_context.py new file mode 100644 index 000000000..6fffd2fb5 --- /dev/null +++ b/freqtrade/persistence/usedb_context.py @@ -0,0 +1,33 @@ + +from freqtrade.persistence.pairlock_middleware import PairLocks +from freqtrade.persistence.trade_model import Trade + + +def disable_database_use(timeframe: str) -> None: + """ + Disable database usage for PairLocks and Trade models. + Used for backtesting, and some other utility commands. + """ + PairLocks.use_db = False + PairLocks.timeframe = timeframe + Trade.use_db = False + + +def enable_database_use() -> None: + """ + Cleanup function to restore database usage. + """ + PairLocks.use_db = True + PairLocks.timeframe = '' + Trade.use_db = True + + +class FtNoDBContext: + def __init__(self, timeframe: str = ''): + self.timeframe = timeframe + + def __enter__(self): + disable_database_use(self.timeframe) + + def __exit__(self, exc_type, exc_val, exc_tb): + enable_database_use() diff --git a/freqtrade/rpc/api_server/api_background_tasks.py b/freqtrade/rpc/api_server/api_background_tasks.py index c13fa31e4..04e98c609 100644 --- a/freqtrade/rpc/api_server/api_background_tasks.py +++ b/freqtrade/rpc/api_server/api_background_tasks.py @@ -7,6 +7,7 @@ from fastapi.exceptions import HTTPException from freqtrade.constants import Config from freqtrade.enums import CandleType from freqtrade.exceptions import OperationalException +from freqtrade.persistence import FtNoDBContext from freqtrade.rpc.api_server.api_schemas import (BackgroundTaskStatus, BgJobStarted, ExchangeModePayloadMixin, PairListsPayload, PairListsResponse, WhitelistEvaluateResponse) @@ -57,16 +58,16 @@ def __run_pairlist(job_id: str, config_loc: Config): ApiBG.jobs[job_id]['is_running'] = True from freqtrade.plugins.pairlistmanager import PairListManager - - exchange = get_exchange(config_loc) - pairlists = PairListManager(exchange, config_loc) - pairlists.refresh_pairlist() - ApiBG.jobs[job_id]['result'] = { - 'method': pairlists.name_list, - 'length': len(pairlists.whitelist), - 'whitelist': pairlists.whitelist - } - ApiBG.jobs[job_id]['status'] = 'success' + with FtNoDBContext(): + exchange = get_exchange(config_loc) + pairlists = PairListManager(exchange, config_loc) + pairlists.refresh_pairlist() + ApiBG.jobs[job_id]['result'] = { + 'method': pairlists.name_list, + 'length': len(pairlists.whitelist), + 'whitelist': pairlists.whitelist + } + ApiBG.jobs[job_id]['status'] = 'success' except (OperationalException, Exception) as e: logger.exception(e) ApiBG.jobs[job_id]['error'] = str(e) diff --git a/tests/persistence/test_db_context.py b/tests/persistence/test_db_context.py new file mode 100644 index 000000000..690006219 --- /dev/null +++ b/tests/persistence/test_db_context.py @@ -0,0 +1,24 @@ +import pytest + +from freqtrade.persistence import FtNoDBContext, PairLocks, Trade + + +@pytest.mark.parametrize('timeframe', ['', '5m', '1d']) +def test_FtNoDBContext(timeframe): + PairLocks.timeframe = '' + assert Trade.use_db is True + assert PairLocks.use_db is True + assert PairLocks.timeframe == '' + + with FtNoDBContext(timeframe): + assert Trade.use_db is False + assert PairLocks.use_db is False + assert PairLocks.timeframe == timeframe + + with FtNoDBContext(): + assert Trade.use_db is False + assert PairLocks.use_db is False + assert PairLocks.timeframe == '' + + assert Trade.use_db is True + assert PairLocks.use_db is True