stable/freqtrade/optimize/hyperopt_loss_sharpe_trades20.py
2021-02-07 23:09:53 +01:00

86 lines
2.9 KiB
Python

"""
SharpeHyperOptLossTrades
This module defines the alternative HyperOptLoss class which can be used for
Hyperoptimization.
The MINIMUM_TRADES and SLIPPAGE_PER_TRADE_RATIO can be altered to whatever you like.
The values that make up the maximum trade_grade can be altered as well.
"""
import math
from datetime import datetime
from pandas import DataFrame, date_range
from freqtrade.optimize.hyperopt import IHyperOptLoss
class SharpeHyperOptLossTrades20(IHyperOptLoss):
"""
Defines the loss function for hyperopt.
This implementation uses the Sharpe Ratio Daily calculation and the Trade Grade calculation.
"""
@staticmethod
def hyperopt_loss_function(results: DataFrame, trade_count: int,
min_date: datetime, max_date: datetime,
*args, **kwargs) -> float:
"""
Objective function, returns smaller number for more optimal results.
Uses the Sharpe Ratio Daily calculation and the Trade Grade calculation.
"""
# CONSTANTS
MINIMUM_TRADES = 20
SLIPPAGE_PER_TRADE_RATIO = 0.001
NUMERATOR_MAX_TRADEGRADE = 80
DENOMINATOR_MAX_TRADEGRADE = 8
RESAMPLE_FREQ = '1D'
DAYS_IN_YEAR = 365
ANNUAL_RISK_FREE_RATE = 0.0
risk_free_rate = ANNUAL_RISK_FREE_RATE / DAYS_IN_YEAR
"""
Sharpe Ratio Calculation
"""
# apply slippage per trade to profit_percent
results.loc[:, 'profit_percent_after_slippage'] = \
results['profit_percent'] - SLIPPAGE_PER_TRADE_RATIO
# create the index within the min_date and end max_date
t_index = date_range(start=min_date, end=max_date, freq=RESAMPLE_FREQ,
normalize=True)
sum_daily = (
results.resample(RESAMPLE_FREQ, on='close_time').agg(
{"profit_percent_after_slippage": sum}).reindex(t_index).fillna(0)
)
total_profit = sum_daily["profit_percent_after_slippage"] - risk_free_rate
expected_returns_mean = total_profit.mean()
up_stdev = total_profit.std()
if up_stdev != 0:
sharp_ratio = expected_returns_mean / up_stdev * math.sqrt(DAYS_IN_YEAR)
else:
# Define high (negative) sharpe ratio to be clear that this is NOT optimal.
sharp_ratio = -30.
"""
Trade Grade Calculation
This function has a maximum grade of 80/DENOMINATOR_MAX_TRADEGRADE.
A minimum of 25 trades.
"""
if trade_count <= (MINIMUM_TRADES + 5):
# Define high (negative) trade grade tp be clear that this is NOT optimal
trade_grade = -30
else:
trade_grade = ((1 / (-0.001 * (trade_count - MINIMUM_TRADES))) +
NUMERATOR_MAX_TRADEGRADE) / DENOMINATOR_MAX_TRADEGRADE
return -(sharp_ratio + trade_grade)