Extract btstorage methods

This commit is contained in:
Matthias
2023-06-25 17:42:58 +02:00
parent 65e8359908
commit 72504e62ad
4 changed files with 78 additions and 68 deletions
@@ -7,10 +7,11 @@ from freqtrade.optimize.optimize_reports.bt_output import (show_backtest_result,
text_table_exit_reason, text_table_exit_reason,
text_table_periodic_breakdown, text_table_periodic_breakdown,
text_table_strategy, text_table_tags) text_table_strategy, text_table_tags)
from freqtrade.optimize.optimize_reports.bt_storage import (store_backtest_analysis_results,
store_backtest_stats)
from freqtrade.optimize.optimize_reports.optimize_reports import ( from freqtrade.optimize.optimize_reports.optimize_reports import (
generate_all_periodic_breakdown_stats, generate_backtest_stats, generate_daily_stats, generate_all_periodic_breakdown_stats, generate_backtest_stats, generate_daily_stats,
generate_edge_table, generate_exit_reason_stats, generate_pair_metrics, generate_edge_table, generate_exit_reason_stats, generate_pair_metrics,
generate_periodic_breakdown_stats, generate_rejected_signals, generate_strategy_comparison, generate_periodic_breakdown_stats, generate_rejected_signals, generate_strategy_comparison,
generate_strategy_stats, generate_tag_metrics, generate_trade_signal_candles, generate_strategy_stats, generate_tag_metrics, generate_trade_signal_candles,
generate_trading_stats, generate_wins_draws_losses, store_backtest_analysis_results, generate_trading_stats, generate_wins_draws_losses)
store_backtest_stats)
@@ -0,0 +1,71 @@
import logging
from pathlib import Path
from typing import Dict
from pandas import DataFrame
from freqtrade.constants import LAST_BT_RESULT_FN
from freqtrade.misc import file_dump_joblib, file_dump_json
from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename
logger = logging.getLogger(__name__)
def store_backtest_stats(
recordfilename: Path, stats: Dict[str, DataFrame], dtappendix: str) -> None:
"""
Stores backtest results
:param recordfilename: Path object, which can either be a filename or a directory.
Filenames will be appended with a timestamp right before the suffix
while for directories, <directory>/backtest-result-<datetime>.json will be used as filename
:param stats: Dataframe containing the backtesting statistics
:param dtappendix: Datetime to use for the filename
"""
if recordfilename.is_dir():
filename = (recordfilename / f'backtest-result-{dtappendix}.json')
else:
filename = Path.joinpath(
recordfilename.parent, f'{recordfilename.stem}-{dtappendix}'
).with_suffix(recordfilename.suffix)
# Store metadata separately.
file_dump_json(get_backtest_metadata_filename(filename), stats['metadata'])
del stats['metadata']
file_dump_json(filename, stats)
latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN)
file_dump_json(latest_filename, {'latest_backtest': str(filename.name)})
def _store_backtest_analysis_data(
recordfilename: Path, data: Dict[str, Dict],
dtappendix: str, name: str) -> Path:
"""
Stores backtest trade candles for analysis
:param recordfilename: Path object, which can either be a filename or a directory.
Filenames will be appended with a timestamp right before the suffix
while for directories, <directory>/backtest-result-<datetime>_<name>.pkl will be used
as filename
:param candles: Dict containing the backtesting data for analysis
:param dtappendix: Datetime to use for the filename
:param name: Name to use for the file, e.g. signals, rejected
"""
if recordfilename.is_dir():
filename = (recordfilename / f'backtest-result-{dtappendix}_{name}.pkl')
else:
filename = Path.joinpath(
recordfilename.parent, f'{recordfilename.stem}-{dtappendix}_{name}.pkl'
)
file_dump_joblib(filename, data)
return filename
def store_backtest_analysis_results(
recordfilename: Path, candles: Dict[str, Dict], trades: Dict[str, Dict],
dtappendix: str) -> None:
_store_backtest_analysis_data(recordfilename, candles, dtappendix, "signals")
_store_backtest_analysis_data(recordfilename, trades, dtappendix, "rejected")
@@ -1,83 +1,21 @@
import logging import logging
from copy import deepcopy from copy import deepcopy
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any, Dict, List, Union from typing import Any, Dict, List, Union
from pandas import DataFrame, concat, to_datetime from pandas import DataFrame, concat, to_datetime
from tabulate import tabulate from tabulate import tabulate
from freqtrade.constants import (BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, from freqtrade.constants import BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT, IntOrInf
IntOrInf)
from freqtrade.data.metrics import (calculate_cagr, calculate_calmar, calculate_csum, from freqtrade.data.metrics import (calculate_cagr, calculate_calmar, calculate_csum,
calculate_expectancy, calculate_market_change, calculate_expectancy, calculate_market_change,
calculate_max_drawdown, calculate_sharpe, calculate_sortino) calculate_max_drawdown, calculate_sharpe, calculate_sortino)
from freqtrade.misc import decimals_per_coin, file_dump_joblib, file_dump_json, round_coin_value from freqtrade.misc import decimals_per_coin, round_coin_value
from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def store_backtest_stats(
recordfilename: Path, stats: Dict[str, DataFrame], dtappendix: str) -> None:
"""
Stores backtest results
:param recordfilename: Path object, which can either be a filename or a directory.
Filenames will be appended with a timestamp right before the suffix
while for directories, <directory>/backtest-result-<datetime>.json will be used as filename
:param stats: Dataframe containing the backtesting statistics
:param dtappendix: Datetime to use for the filename
"""
if recordfilename.is_dir():
filename = (recordfilename / f'backtest-result-{dtappendix}.json')
else:
filename = Path.joinpath(
recordfilename.parent, f'{recordfilename.stem}-{dtappendix}'
).with_suffix(recordfilename.suffix)
# Store metadata separately.
file_dump_json(get_backtest_metadata_filename(filename), stats['metadata'])
del stats['metadata']
file_dump_json(filename, stats)
latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN)
file_dump_json(latest_filename, {'latest_backtest': str(filename.name)})
def _store_backtest_analysis_data(
recordfilename: Path, data: Dict[str, Dict],
dtappendix: str, name: str) -> Path:
"""
Stores backtest trade candles for analysis
:param recordfilename: Path object, which can either be a filename or a directory.
Filenames will be appended with a timestamp right before the suffix
while for directories, <directory>/backtest-result-<datetime>_<name>.pkl will be used
as filename
:param candles: Dict containing the backtesting data for analysis
:param dtappendix: Datetime to use for the filename
:param name: Name to use for the file, e.g. signals, rejected
"""
if recordfilename.is_dir():
filename = (recordfilename / f'backtest-result-{dtappendix}_{name}.pkl')
else:
filename = Path.joinpath(
recordfilename.parent, f'{recordfilename.stem}-{dtappendix}_{name}.pkl'
)
file_dump_joblib(filename, data)
return filename
def store_backtest_analysis_results(
recordfilename: Path, candles: Dict[str, Dict], trades: Dict[str, Dict],
dtappendix: str) -> None:
_store_backtest_analysis_data(recordfilename, candles, dtappendix, "signals")
_store_backtest_analysis_data(recordfilename, trades, dtappendix, "rejected")
def generate_trade_signal_candles(preprocessed_df: Dict[str, DataFrame], def generate_trade_signal_candles(preprocessed_df: Dict[str, DataFrame],
bt_results: Dict[str, Any]) -> DataFrame: bt_results: Dict[str, Any]) -> DataFrame:
signal_candles_only = {} signal_candles_only = {}
+2 -2
View File
@@ -210,7 +210,7 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir):
def test_store_backtest_stats(testdatadir, mocker): def test_store_backtest_stats(testdatadir, mocker):
dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.optimize_reports.file_dump_json') dump_mock = mocker.patch('freqtrade.optimize.optimize_reports.bt_storage.file_dump_json')
store_backtest_stats(testdatadir, {'metadata': {}}, '2022_01_01_15_05_13') store_backtest_stats(testdatadir, {'metadata': {}}, '2022_01_01_15_05_13')
@@ -230,7 +230,7 @@ def test_store_backtest_stats(testdatadir, mocker):
def test_store_backtest_candles(testdatadir, mocker): def test_store_backtest_candles(testdatadir, mocker):
dump_mock = mocker.patch( dump_mock = mocker.patch(
'freqtrade.optimize.optimize_reports.optimize_reports.file_dump_joblib') 'freqtrade.optimize.optimize_reports.bt_storage.file_dump_joblib')
candle_dict = {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}} candle_dict = {'DefStrat': {'UNITTEST/BTC': pd.DataFrame()}}