Save backtest-stats

This commit is contained in:
Matthias 2020-06-26 07:46:59 +02:00
parent 81c8e8677d
commit 415853583b
3 changed files with 38 additions and 8 deletions

View File

@ -3,7 +3,7 @@ Helpers when analyzing backtest data
""" """
import logging import logging
from pathlib import Path from pathlib import Path
from typing import Dict, Union, Tuple from typing import Dict, Union, Tuple, Any
import numpy as np import numpy as np
import pandas as pd import pandas as pd
@ -20,6 +20,23 @@ BT_DATA_COLUMNS = ["pair", "profit_percent", "open_time", "close_time", "index",
"open_rate", "close_rate", "open_at_end", "sell_reason"] "open_rate", "close_rate", "open_at_end", "sell_reason"]
def load_backtest_stats(filename: Union[Path, str]) -> Dict[str, Any]:
"""
Load backtest statistics file.
:param filename: pathlib.Path object, or string pointing to the file.
:return: a dictionary containing the resulting file.
"""
if isinstance(filename, str):
filename = Path(filename)
if not filename.is_file():
raise ValueError(f"File {filename} does not exist.")
with filename.open() as file:
data = json_load(file)
return data
def load_backtest_data(filename: Union[Path, str]) -> pd.DataFrame: def load_backtest_data(filename: Union[Path, str]) -> pd.DataFrame:
""" """
Load backtest data file. Load backtest data file.

View File

@ -11,9 +11,9 @@ from typing import Any, Dict, List, NamedTuple, Optional, Tuple
import arrow import arrow
from pandas import DataFrame from pandas import DataFrame
from freqtrade.constants import DATETIME_PRINT_FORMAT
from freqtrade.configuration import (TimeRange, remove_credentials, from freqtrade.configuration import (TimeRange, remove_credentials,
validate_config_consistency) validate_config_consistency)
from freqtrade.constants import DATETIME_PRINT_FORMAT
from freqtrade.data import history from freqtrade.data import history
from freqtrade.data.converter import trim_dataframe from freqtrade.data.converter import trim_dataframe
from freqtrade.data.dataprovider import DataProvider from freqtrade.data.dataprovider import DataProvider
@ -21,7 +21,8 @@ from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.optimize.optimize_reports import (generate_backtest_stats, from freqtrade.optimize.optimize_reports import (generate_backtest_stats,
show_backtest_results, show_backtest_results,
store_backtest_result) store_backtest_result,
store_backtest_stats)
from freqtrade.pairlist.pairlistmanager import PairListManager from freqtrade.pairlist.pairlistmanager import PairListManager
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.resolvers import ExchangeResolver, StrategyResolver from freqtrade.resolvers import ExchangeResolver, StrategyResolver
@ -420,3 +421,4 @@ class Backtesting:
stats = generate_backtest_stats(self.config, data, all_results, stats = generate_backtest_stats(self.config, data, all_results,
min_date=min_date, max_date=max_date) min_date=min_date, max_date=max_date)
show_backtest_results(self.config, stats) show_backtest_results(self.config, stats)
store_backtest_stats(self.config['exportfilename'], stats)

View File

@ -14,6 +14,18 @@ from freqtrade.misc import file_dump_json
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def store_backtest_stats(recordfilename: Path, stats: Dict[str, DataFrame]) -> None:
filename = Path.joinpath(recordfilename.parent,
f'{recordfilename.stem}-{datetime.now().isoformat()}'
).with_suffix(recordfilename.suffix)
file_dump_json(filename, stats)
latest_filename = Path.joinpath(recordfilename.parent,
'.last_result.json')
file_dump_json(latest_filename, {'latest_backtest': str(filename.name)})
def store_backtest_result(recordfilename: Path, all_results: Dict[str, DataFrame]) -> None: def store_backtest_result(recordfilename: Path, all_results: Dict[str, DataFrame]) -> None:
""" """
Stores backtest results to file (one file per strategy) Stores backtest results to file (one file per strategy)
@ -224,7 +236,7 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame],
backtest_days = (max_date - min_date).days backtest_days = (max_date - min_date).days
strat_stats = { strat_stats = {
'trades': backtest_result_to_list(results), 'trades': results.to_dict(orient='records'),
'results_per_pair': pair_results, 'results_per_pair': pair_results,
'sell_reason_summary': sell_reason_stats, 'sell_reason_summary': sell_reason_stats,
'left_open_trades': left_open_results, 'left_open_trades': left_open_results,
@ -338,12 +350,11 @@ def text_table_strategy(strategy_results, stake_currency: str) -> str:
def text_table_add_metrics(strategy_results: Dict) -> str: def text_table_add_metrics(strategy_results: Dict) -> str:
if len(strategy_results['trades']) > 0: if len(strategy_results['trades']) > 0:
min_trade = min(strategy_results['trades'], key=lambda x: x[2]) min_trade = min(strategy_results['trades'], key=lambda x: x['open_time'])
metrics = [ metrics = [
('Total trades', strategy_results['total_trades']), ('Total trades', strategy_results['total_trades']),
('First trade', datetime.fromtimestamp(min_trade[2], ('First trade', min_trade['open_time'].strftime(DATETIME_PRINT_FORMAT)),
tz=timezone.utc).strftime(DATETIME_PRINT_FORMAT)), ('First trade Pair', min_trade['pair']),
('First trade Pair', min_trade[0]),
('Backtesting from', strategy_results['backtest_start'].strftime(DATETIME_PRINT_FORMAT)), ('Backtesting from', strategy_results['backtest_start'].strftime(DATETIME_PRINT_FORMAT)),
('Backtesting to', strategy_results['backtest_end'].strftime(DATETIME_PRINT_FORMAT)), ('Backtesting to', strategy_results['backtest_end'].strftime(DATETIME_PRINT_FORMAT)),
('Trades per day', strategy_results['trades_per_day']), ('Trades per day', strategy_results['trades_per_day']),