Merge branch 'develop' into feat_readjust_entry
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
MaxDrawDownRelativeHyperOptLoss
|
||||
|
||||
This module defines the alternative HyperOptLoss class which can be used for
|
||||
Hyperoptimization.
|
||||
"""
|
||||
from typing import Dict
|
||||
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.data.metrics import calculate_underwater
|
||||
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
||||
|
||||
|
||||
class MaxDrawDownRelativeHyperOptLoss(IHyperOptLoss):
|
||||
|
||||
"""
|
||||
Defines the loss function for hyperopt.
|
||||
|
||||
This implementation optimizes for max draw down and profit
|
||||
Less max drawdown more profit -> Lower return value
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def hyperopt_loss_function(results: DataFrame, config: Dict,
|
||||
*args, **kwargs) -> float:
|
||||
|
||||
"""
|
||||
Objective function.
|
||||
|
||||
Uses profit ratio weighted max_drawdown when drawdown is available.
|
||||
Otherwise directly optimizes profit ratio.
|
||||
"""
|
||||
total_profit = results['profit_abs'].sum()
|
||||
try:
|
||||
drawdown_df = calculate_underwater(
|
||||
results,
|
||||
value_col='profit_abs',
|
||||
starting_balance=config['dry_run_wallet']
|
||||
)
|
||||
max_drawdown = abs(min(drawdown_df['drawdown']))
|
||||
relative_drawdown = max(drawdown_df['drawdown_relative'])
|
||||
if max_drawdown == 0:
|
||||
return -total_profit
|
||||
return -total_profit / max_drawdown / relative_drawdown
|
||||
except (Exception, ValueError):
|
||||
return -total_profit
|
@@ -19,11 +19,11 @@ class IHyperOptLoss(ABC):
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def hyperopt_loss_function(results: DataFrame, trade_count: int,
|
||||
def hyperopt_loss_function(*, results: DataFrame, trade_count: int,
|
||||
min_date: datetime, max_date: datetime,
|
||||
config: Dict, processed: Dict[str, DataFrame],
|
||||
backtest_stats: Dict[str, Any],
|
||||
*args, **kwargs) -> float:
|
||||
**kwargs) -> float:
|
||||
"""
|
||||
Objective function, returns smaller number for better results
|
||||
"""
|
||||
|
@@ -498,9 +498,12 @@ def generate_strategy_stats(pairlist: List[str],
|
||||
(drawdown_abs, drawdown_start, drawdown_end, high_val, low_val,
|
||||
max_drawdown) = calculate_max_drawdown(
|
||||
results, value_col='profit_abs', starting_balance=start_balance)
|
||||
(_, _, _, _, _, max_relative_drawdown) = calculate_max_drawdown(
|
||||
results, value_col='profit_abs', starting_balance=start_balance, relative=True)
|
||||
strat_stats.update({
|
||||
'max_drawdown': max_drawdown_legacy, # Deprecated - do not use
|
||||
'max_drawdown_account': max_drawdown,
|
||||
'max_relative_drawdown': max_relative_drawdown,
|
||||
'max_drawdown_abs': drawdown_abs,
|
||||
'drawdown_start': drawdown_start.strftime(DATETIME_PRINT_FORMAT),
|
||||
'drawdown_start_ts': drawdown_start.timestamp() * 1000,
|
||||
@@ -521,6 +524,7 @@ def generate_strategy_stats(pairlist: List[str],
|
||||
strat_stats.update({
|
||||
'max_drawdown': 0.0,
|
||||
'max_drawdown_account': 0.0,
|
||||
'max_relative_drawdown': 0.0,
|
||||
'max_drawdown_abs': 0.0,
|
||||
'max_drawdown_low': 0.0,
|
||||
'max_drawdown_high': 0.0,
|
||||
@@ -729,6 +733,26 @@ def text_table_add_metrics(strat_results: Dict) -> str:
|
||||
strat_results['stake_currency'])),
|
||||
] if strat_results.get('trade_count_short', 0) > 0 else []
|
||||
|
||||
drawdown_metrics = []
|
||||
if 'max_relative_drawdown' in strat_results:
|
||||
# Compatibility to show old hyperopt results
|
||||
drawdown_metrics.append(
|
||||
('Max % of account underwater', f"{strat_results['max_relative_drawdown']:.2%}")
|
||||
)
|
||||
drawdown_metrics.extend([
|
||||
('Absolute Drawdown (Account)', f"{strat_results['max_drawdown_account']:.2%}")
|
||||
if 'max_drawdown_account' in strat_results else (
|
||||
'Drawdown', f"{strat_results['max_drawdown']:.2%}"),
|
||||
('Absolute Drawdown', round_coin_value(strat_results['max_drawdown_abs'],
|
||||
strat_results['stake_currency'])),
|
||||
('Drawdown high', round_coin_value(strat_results['max_drawdown_high'],
|
||||
strat_results['stake_currency'])),
|
||||
('Drawdown low', round_coin_value(strat_results['max_drawdown_low'],
|
||||
strat_results['stake_currency'])),
|
||||
('Drawdown Start', strat_results['drawdown_start']),
|
||||
('Drawdown End', strat_results['drawdown_end']),
|
||||
])
|
||||
|
||||
# Newly added fields should be ignored if they are missing in strat_results. hyperopt-show
|
||||
# command stores these results and newer version of freqtrade must be able to handle old
|
||||
# results with missing new fields.
|
||||
@@ -784,18 +808,7 @@ def text_table_add_metrics(strat_results: Dict) -> str:
|
||||
('Max balance', round_coin_value(strat_results['csum_max'],
|
||||
strat_results['stake_currency'])),
|
||||
|
||||
# Compatibility to show old hyperopt results
|
||||
('Drawdown (Account)', f"{strat_results['max_drawdown_account']:.2%}")
|
||||
if 'max_drawdown_account' in strat_results else (
|
||||
'Drawdown', f"{strat_results['max_drawdown']:.2%}"),
|
||||
('Drawdown', round_coin_value(strat_results['max_drawdown_abs'],
|
||||
strat_results['stake_currency'])),
|
||||
('Drawdown high', round_coin_value(strat_results['max_drawdown_high'],
|
||||
strat_results['stake_currency'])),
|
||||
('Drawdown low', round_coin_value(strat_results['max_drawdown_low'],
|
||||
strat_results['stake_currency'])),
|
||||
('Drawdown Start', strat_results['drawdown_start']),
|
||||
('Drawdown End', strat_results['drawdown_end']),
|
||||
*drawdown_metrics,
|
||||
('Market change', f"{strat_results['market_change']:.2%}"),
|
||||
]
|
||||
|
||||
|
Reference in New Issue
Block a user