Extract btstorage methods
This commit is contained in:
@@ -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 = {}
|
||||||
|
|||||||
@@ -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()}}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user