Don't have public attributes marked as private

This commit is contained in:
Matthias
2023-05-21 09:12:02 +02:00
parent 5316227219
commit 96d74063fc
4 changed files with 50 additions and 50 deletions

View File

@@ -30,9 +30,9 @@ router = APIRouter()
async def api_start_backtest( # noqa: C901 async def api_start_backtest( # noqa: C901
bt_settings: BacktestRequest, background_tasks: BackgroundTasks, bt_settings: BacktestRequest, background_tasks: BackgroundTasks,
config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): config=Depends(get_config), ws_mode=Depends(is_webserver_mode)):
ApiBG._bt['bt_error'] = None ApiBG.bt['bt_error'] = None
"""Start backtesting if not done so already""" """Start backtesting if not done so already"""
if ApiBG._bgtask_running: if ApiBG.bgtask_running:
raise RPCException('Bot Background task already running') raise RPCException('Bot Background task already running')
if ':' in bt_settings.strategy: if ':' in bt_settings.strategy:
@@ -63,30 +63,30 @@ async def api_start_backtest( # noqa: C901
asyncio.set_event_loop(asyncio.new_event_loop()) asyncio.set_event_loop(asyncio.new_event_loop())
try: try:
# Reload strategy # Reload strategy
lastconfig = ApiBG._bt['last_config'] lastconfig = ApiBG.bt['last_config']
strat = StrategyResolver.load_strategy(btconfig) strat = StrategyResolver.load_strategy(btconfig)
validate_config_consistency(btconfig) validate_config_consistency(btconfig)
if ( if (
not ApiBG._bt['bt'] not ApiBG.bt['bt']
or lastconfig.get('timeframe') != strat.timeframe or lastconfig.get('timeframe') != strat.timeframe
or lastconfig.get('timeframe_detail') != btconfig.get('timeframe_detail') or lastconfig.get('timeframe_detail') != btconfig.get('timeframe_detail')
or lastconfig.get('timerange') != btconfig['timerange'] or lastconfig.get('timerange') != btconfig['timerange']
): ):
from freqtrade.optimize.backtesting import Backtesting from freqtrade.optimize.backtesting import Backtesting
ApiBG._bt['bt'] = Backtesting(btconfig) ApiBG.bt['bt'] = Backtesting(btconfig)
ApiBG._bt['bt'].load_bt_data_detail() ApiBG.bt['bt'].load_bt_data_detail()
else: else:
ApiBG._bt['bt'].config = btconfig ApiBG.bt['bt'].config = btconfig
ApiBG._bt['bt'].init_backtest() ApiBG.bt['bt'].init_backtest()
# Only reload data if timeframe changed. # Only reload data if timeframe changed.
if ( if (
not ApiBG._bt['data'] not ApiBG.bt['data']
or not ApiBG._bt['timerange'] or not ApiBG.bt['timerange']
or lastconfig.get('timeframe') != strat.timeframe or lastconfig.get('timeframe') != strat.timeframe
or lastconfig.get('timerange') != btconfig['timerange'] or lastconfig.get('timerange') != btconfig['timerange']
): ):
ApiBG._bt['data'], ApiBG._bt['timerange'] = ApiBG._bt[ ApiBG.bt['data'], ApiBG.bt['timerange'] = ApiBG.bt[
'bt'].load_bt_data() 'bt'].load_bt_data()
lastconfig['timerange'] = btconfig['timerange'] lastconfig['timerange'] = btconfig['timerange']
@@ -95,27 +95,27 @@ async def api_start_backtest( # noqa: C901
lastconfig['enable_protections'] = btconfig.get('enable_protections') lastconfig['enable_protections'] = btconfig.get('enable_protections')
lastconfig['dry_run_wallet'] = btconfig.get('dry_run_wallet') lastconfig['dry_run_wallet'] = btconfig.get('dry_run_wallet')
ApiBG._bt['bt'].enable_protections = btconfig.get('enable_protections', False) ApiBG.bt['bt'].enable_protections = btconfig.get('enable_protections', False)
ApiBG._bt['bt'].strategylist = [strat] ApiBG.bt['bt'].strategylist = [strat]
ApiBG._bt['bt'].results = {} ApiBG.bt['bt'].results = {}
ApiBG._bt['bt'].load_prior_backtest() ApiBG.bt['bt'].load_prior_backtest()
ApiBG._bt['bt'].abort = False ApiBG.bt['bt'].abort = False
if (ApiBG._bt['bt'].results and if (ApiBG.bt['bt'].results and
strat.get_strategy_name() in ApiBG._bt['bt'].results['strategy']): strat.get_strategy_name() in ApiBG.bt['bt'].results['strategy']):
# When previous result hash matches - reuse that result and skip backtesting. # When previous result hash matches - reuse that result and skip backtesting.
logger.info(f'Reusing result of previous backtest for {strat.get_strategy_name()}') logger.info(f'Reusing result of previous backtest for {strat.get_strategy_name()}')
else: else:
min_date, max_date = ApiBG._bt['bt'].backtest_one_strategy( min_date, max_date = ApiBG.bt['bt'].backtest_one_strategy(
strat, ApiBG._bt['data'], ApiBG._bt['timerange']) strat, ApiBG.bt['data'], ApiBG.bt['timerange'])
ApiBG._bt['bt'].results = generate_backtest_stats( ApiBG.bt['bt'].results = generate_backtest_stats(
ApiBG._bt['data'], ApiBG._bt['bt'].all_results, ApiBG.bt['data'], ApiBG.bt['bt'].all_results,
min_date=min_date, max_date=max_date) min_date=min_date, max_date=max_date)
if btconfig.get('export', 'none') == 'trades': if btconfig.get('export', 'none') == 'trades':
store_backtest_stats( store_backtest_stats(
btconfig['exportfilename'], ApiBG._bt['bt'].results, btconfig['exportfilename'], ApiBG.bt['bt'].results,
datetime.now().strftime("%Y-%m-%d_%H-%M-%S") datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
) )
@@ -123,13 +123,13 @@ async def api_start_backtest( # noqa: C901
except (Exception, OperationalException, DependencyException) as e: except (Exception, OperationalException, DependencyException) as e:
logger.exception(f"Backtesting caused an error: {e}") logger.exception(f"Backtesting caused an error: {e}")
ApiBG._bt['bt_error'] = str(e) ApiBG.bt['bt_error'] = str(e)
pass pass
finally: finally:
ApiBG._bgtask_running = False ApiBG.bgtask_running = False
background_tasks.add_task(run_backtest) background_tasks.add_task(run_backtest)
ApiBG._bgtask_running = True ApiBG.bgtask_running = True
return { return {
"status": "running", "status": "running",
@@ -147,18 +147,18 @@ def api_get_backtest(ws_mode=Depends(is_webserver_mode)):
Returns Result after backtesting has been ran. Returns Result after backtesting has been ran.
""" """
from freqtrade.persistence import LocalTrade from freqtrade.persistence import LocalTrade
if ApiBG._bgtask_running: if ApiBG.bgtask_running:
return { return {
"status": "running", "status": "running",
"running": True, "running": True,
"step": (ApiBG._bt['bt'].progress.action if ApiBG._bt['bt'] "step": (ApiBG.bt['bt'].progress.action if ApiBG.bt['bt']
else str(BacktestState.STARTUP)), else str(BacktestState.STARTUP)),
"progress": ApiBG._bt['bt'].progress.progress if ApiBG._bt['bt'] else 0, "progress": ApiBG.bt['bt'].progress.progress if ApiBG.bt['bt'] else 0,
"trade_count": len(LocalTrade.trades), "trade_count": len(LocalTrade.trades),
"status_msg": "Backtest running", "status_msg": "Backtest running",
} }
if not ApiBG._bt['bt']: if not ApiBG.bt['bt']:
return { return {
"status": "not_started", "status": "not_started",
"running": False, "running": False,
@@ -166,13 +166,13 @@ def api_get_backtest(ws_mode=Depends(is_webserver_mode)):
"progress": 0, "progress": 0,
"status_msg": "Backtest not yet executed" "status_msg": "Backtest not yet executed"
} }
if ApiBG._bt['bt_error']: if ApiBG.bt['bt_error']:
return { return {
"status": "error", "status": "error",
"running": False, "running": False,
"step": "", "step": "",
"progress": 0, "progress": 0,
"status_msg": f"Backtest failed with {ApiBG._bt['bt_error']}" "status_msg": f"Backtest failed with {ApiBG.bt['bt_error']}"
} }
return { return {
@@ -181,14 +181,14 @@ def api_get_backtest(ws_mode=Depends(is_webserver_mode)):
"status_msg": "Backtest ended", "status_msg": "Backtest ended",
"step": "finished", "step": "finished",
"progress": 1, "progress": 1,
"backtest_result": ApiBG._bt['bt'].results, "backtest_result": ApiBG.bt['bt'].results,
} }
@router.delete('/backtest', response_model=BacktestResponse, tags=['webserver', 'backtest']) @router.delete('/backtest', response_model=BacktestResponse, tags=['webserver', 'backtest'])
def api_delete_backtest(ws_mode=Depends(is_webserver_mode)): def api_delete_backtest(ws_mode=Depends(is_webserver_mode)):
"""Reset backtesting""" """Reset backtesting"""
if ApiBG._bgtask_running: if ApiBG.bgtask_running:
return { return {
"status": "running", "status": "running",
"running": True, "running": True,
@@ -196,12 +196,12 @@ def api_delete_backtest(ws_mode=Depends(is_webserver_mode)):
"progress": 0, "progress": 0,
"status_msg": "Backtest running", "status_msg": "Backtest running",
} }
if ApiBG._bt['bt']: if ApiBG.bt['bt']:
ApiBG._bt['bt'].cleanup() ApiBG.bt['bt'].cleanup()
del ApiBG._bt['bt'] del ApiBG.bt['bt']
ApiBG._bt['bt'] = None ApiBG.bt['bt'] = None
del ApiBG._bt['data'] del ApiBG.bt['data']
ApiBG._bt['data'] = None ApiBG.bt['data'] = None
logger.info("Backtesting reset") logger.info("Backtesting reset")
return { return {
"status": "reset", "status": "reset",
@@ -214,7 +214,7 @@ def api_delete_backtest(ws_mode=Depends(is_webserver_mode)):
@router.get('/backtest/abort', response_model=BacktestResponse, tags=['webserver', 'backtest']) @router.get('/backtest/abort', response_model=BacktestResponse, tags=['webserver', 'backtest'])
def api_backtest_abort(ws_mode=Depends(is_webserver_mode)): def api_backtest_abort(ws_mode=Depends(is_webserver_mode)):
if not ApiBG._bgtask_running: if not ApiBG.bgtask_running:
return { return {
"status": "not_running", "status": "not_running",
"running": False, "running": False,
@@ -222,7 +222,7 @@ def api_backtest_abort(ws_mode=Depends(is_webserver_mode)):
"progress": 0, "progress": 0,
"status_msg": "Backtest ended", "status_msg": "Backtest ended",
} }
ApiBG._bt['bt'].abort = True ApiBG.bt['bt'].abort = True
return { return {
"status": "stopping", "status": "stopping",
"running": False, "running": False,

View File

@@ -44,11 +44,11 @@ def get_api_config() -> Dict[str, Any]:
def get_exchange(config=Depends(get_config)): def get_exchange(config=Depends(get_config)):
if not ApiBG._exchange: if not ApiBG.exchange:
from freqtrade.resolvers import ExchangeResolver from freqtrade.resolvers import ExchangeResolver
ApiBG._exchange = ExchangeResolver.load_exchange( ApiBG.exchange = ExchangeResolver.load_exchange(
config, load_leverage_tiers=False) config, load_leverage_tiers=False)
return ApiBG._exchange return ApiBG.exchange
def get_message_stream(): def get_message_stream():

View File

@@ -4,13 +4,13 @@ from typing import Any, Dict
class ApiBG(): class ApiBG():
# Backtesting type: Backtesting # Backtesting type: Backtesting
_bt: Dict[str, Any] = { bt: Dict[str, Any] = {
'bt': None, 'bt': None,
'data': None, 'data': None,
'timerange': None, 'timerange': None,
'last_config': {}, 'last_config': {},
'bt_error': None, 'bt_error': None,
} }
_bgtask_running: bool = False bgtask_running: bool = False
# Exchange - only available in webserver mode. # Exchange - only available in webserver mode.
_exchange = None exchange = None

View File

@@ -1734,7 +1734,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
assert result['status_msg'] == 'Backtest ended' assert result['status_msg'] == 'Backtest ended'
# Simulate running backtest # Simulate running backtest
ApiBG._bgtask_running = True ApiBG.bgtask_running = True
rc = client_get(client, f"{BASE_URI}/backtest/abort") rc = client_get(client, f"{BASE_URI}/backtest/abort")
assert_response(rc) assert_response(rc)
result = rc.json() result = rc.json()
@@ -1763,7 +1763,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
result = rc.json() result = rc.json()
assert 'Bot Background task already running' in result['error'] assert 'Bot Background task already running' in result['error']
ApiBG._bgtask_running = False ApiBG.bgtask_running = False
# Rerun backtest (should get previous result) # Rerun backtest (should get previous result)
rc = client_post(client, f"{BASE_URI}/backtest", data=data) rc = client_post(client, f"{BASE_URI}/backtest", data=data)