store periodic breakdown in backtest results

This will enable the webserver to use this data.
This commit is contained in:
Matthias
2023-04-24 10:36:30 +02:00
parent 3948890c3b
commit e99af87b6d
2 changed files with 25 additions and 7 deletions

View File

@@ -379,7 +379,8 @@ class Hyperopt:
strat_stats = generate_strategy_stats(
self.pairlist, self.backtesting.strategy.get_strategy_name(),
backtesting_results, min_date, max_date, market_change=self.market_change
backtesting_results, min_date, max_date, market_change=self.market_change,
is_hyperopt=True,
)
results_explanation = HyperoptTools.format_results_explanation_string(
strat_stats, self.config['stake_currency'])

View File

@@ -7,8 +7,8 @@ from typing import Any, Dict, List, Union
from pandas import DataFrame, to_datetime
from tabulate import tabulate
from freqtrade.constants import (DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN, UNLIMITED_STAKE_AMOUNT,
Config, IntOrInf)
from freqtrade.constants import (BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT, LAST_BT_RESULT_FN,
UNLIMITED_STAKE_AMOUNT, Config, IntOrInf)
from freqtrade.data.metrics import (calculate_cagr, calculate_calmar, calculate_csum,
calculate_expectancy, calculate_market_change,
calculate_max_drawdown, calculate_sharpe, calculate_sortino)
@@ -296,6 +296,7 @@ def generate_periodic_breakdown_stats(trade_list: List, period: str) -> List[Dic
stats.append(
{
'date': name.strftime('%d/%m/%Y'),
'date_ts': int(name.to_pydatetime().timestamp() * 1000),
'profit_abs': profit_abs,
'wins': wins,
'draws': draws,
@@ -305,6 +306,13 @@ def generate_periodic_breakdown_stats(trade_list: List, period: str) -> List[Dic
return stats
def generate_all_periodic_breakdown_stats(trade_list: List) -> Dict[str, List]:
result = {}
for period in BACKTEST_BREAKDOWNS:
result[period] = generate_periodic_breakdown_stats(trade_list, period)
return result
def generate_trading_stats(results: DataFrame) -> Dict[str, Any]:
""" Generate overall trade statistics """
if len(results) == 0:
@@ -381,7 +389,8 @@ def generate_strategy_stats(pairlist: List[str],
strategy: str,
content: Dict[str, Any],
min_date: datetime, max_date: datetime,
market_change: float
market_change: float,
is_hyperopt: bool = False,
) -> Dict[str, Any]:
"""
:param pairlist: List of pairs to backtest
@@ -416,6 +425,11 @@ def generate_strategy_stats(pairlist: List[str],
daily_stats = generate_daily_stats(results)
trade_stats = generate_trading_stats(results)
periodic_breakdown = {}
if not is_hyperopt:
periodic_breakdown = {'periodic_breakdown': generate_all_periodic_breakdown_stats(results)}
best_pair = max([pair for pair in pair_results if pair['key'] != 'TOTAL'],
key=lambda x: x['profit_sum']) if len(pair_results) > 1 else None
worst_pair = min([pair for pair in pair_results if pair['key'] != 'TOTAL'],
@@ -434,7 +448,6 @@ def generate_strategy_stats(pairlist: List[str],
'results_per_enter_tag': enter_tag_results,
'exit_reason_summary': exit_reason_stats,
'left_open_trades': left_open_results,
# 'days_breakdown_stats': days_breakdown_stats,
'total_trades': len(results),
'trade_count_long': len(results.loc[~results['is_short']]),
@@ -499,6 +512,7 @@ def generate_strategy_stats(pairlist: List[str],
'exit_profit_only': config['exit_profit_only'],
'exit_profit_offset': config['exit_profit_offset'],
'ignore_roi_if_entry_signal': config['ignore_roi_if_entry_signal'],
**periodic_breakdown,
**daily_stats,
**trade_stats
}
@@ -891,8 +905,11 @@ def show_backtest_result(strategy: str, results: Dict[str, Any], stake_currency:
print(table)
for period in backtest_breakdown:
days_breakdown_stats = generate_periodic_breakdown_stats(
trade_list=results['trades'], period=period)
if period in results.get('periodic_breakdown', {}):
days_breakdown_stats = results['periodic_breakdown'][period]
else:
days_breakdown_stats = generate_periodic_breakdown_stats(
trade_list=results['trades'], period=period)
table = text_table_periodic_breakdown(days_breakdown_stats=days_breakdown_stats,
stake_currency=stake_currency, period=period)
if isinstance(table, str) and len(table) > 0: