From 9880524f058b41d926fa504164b33912fe8d38cd Mon Sep 17 00:00:00 2001 From: Masoud Azizi Date: Sun, 27 Jun 2021 03:12:18 +0000 Subject: [PATCH 1/4] heracles in New API, Bugs fixed --- user_data/hyperopts/HeraclesHo.py | 118 ------------------- user_data/strategies/Heracles.py | 184 +++++++++++++++++++----------- 2 files changed, 115 insertions(+), 187 deletions(-) delete mode 100644 user_data/hyperopts/HeraclesHo.py diff --git a/user_data/hyperopts/HeraclesHo.py b/user_data/hyperopts/HeraclesHo.py deleted file mode 100644 index aa174ee..0000000 --- a/user_data/hyperopts/HeraclesHo.py +++ /dev/null @@ -1,118 +0,0 @@ -# Heracles Strategy Hyperopt -# Author: @Mablue (Masoud Azizi) -# github: https://github.com/mablue/ -# IMPORTANT: INSTALL TA BEFOUR RUN: -# :~$ pip install ta -# freqtrade hyperopt --hyperopt GodStraHo --hyperopt-loss SharpeHyperOptLossDaily --gene all --strategy GodStra --config config.json -e 100 - -# --- Do not remove these libs --- -from functools import reduce -from typing import Any, Callable, Dict, List - -import numpy as np # noqa -import pandas as pd # noqa -from pandas import DataFrame -from skopt.space import Categorical, Dimension, Integer, Real # noqa - -from freqtrade.optimize.hyperopt_interface import IHyperOpt - -# -------------------------------- -# Add your lib to import here -# import talib.abstract as ta # noqa -from ta import add_all_ta_features -from ta.utils import dropna -import freqtrade.vendor.qtpylib.indicators as qtpylib -# this is your trading strategy DNA Size -# you can change it and see the results... - - -class HeraclesHo(IHyperOpt): - - @staticmethod - def indicator_space() -> List[Dimension]: - """ - Define your Hyperopt space for searching buy strategy parameters. - """ - - return [ - Real(-0.1, 1.1, name='buy-div'), - Integer(0, 5, name='DFINDShift'), - Integer(0, 5, name='DFCRSShift'), - ] - - @staticmethod - def buy_strategy_generator(params: Dict[str, Any]) -> Callable: - """ - Define the buy strategy parameters to be used by Hyperopt. - """ - def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: - """ - Buy strategy Hyperopt will build and use. - """ - conditions = [] - - IND = 'volatility_dcp' - CRS = 'volatility_kcw' - DFIND = dataframe[IND] - DFCRS = dataframe[CRS] - - conditions.append( - DFIND.shift(params['DFINDShift']).div( - DFCRS.shift(params['DFCRSShift']) - ) <= params['buy-div'] - ) - - if conditions: - dataframe.loc[ - reduce(lambda x, y: x & y, conditions), - 'buy'] = 1 - - return dataframe - - return populate_buy_trend - - @ staticmethod - def sell_indicator_space() -> List[Dimension]: - """ - Define your Hyperopt space for searching sell strategy parameters. - """ - return [ - Real(1.e-10, 1.e-0, name='sell-rtol'), - Real(1.e-16, 1.e-0, name='sell-atol'), - Integer(0, 5, name='DFINDShift'), - Integer(0, 5, name='DFCRSShift'), - ] - - @ staticmethod - def sell_strategy_generator(params: Dict[str, Any]) -> Callable: - """ - Define the sell strategy parameters to be used by Hyperopt. - """ - def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: - """ - Sell strategy Hyperopt will build and use. - """ - conditions = [] - - IND = 'trend_ema_fast' - CRS = 'trend_macd_signal' - DFIND = dataframe[IND] - DFCRS = dataframe[CRS] - - conditions.append( - np.isclose( - DFIND.shift(params['DFINDShift']), - DFCRS.shift(params['DFCRSShift']), - rtol=params['sell-rtol'], - atol=params['sell-atol'] - ) - ) - - if conditions: - dataframe.loc[ - reduce(lambda x, y: x & y, conditions), - 'sell']=1 - - return dataframe - - return populate_sell_trend diff --git a/user_data/strategies/Heracles.py b/user_data/strategies/Heracles.py index 48967f4..8ecc27e 100644 --- a/user_data/strategies/Heracles.py +++ b/user_data/strategies/Heracles.py @@ -8,19 +8,14 @@ # "min_days_listed": 100 # }, # IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta) +# +# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy sell --strategy Heracles # ###################################################################### -# Optimal config settings: -# "max_open_trades": 100, -# "stake_amount": "unlimited", - # --- Do not remove these libs --- -import logging - -from numpy.lib import math +from freqtrade.strategy.hyper import IntParameter, DecimalParameter from freqtrade.strategy.interface import IStrategy from pandas import DataFrame # -------------------------------- - # Add your lib to import here # import talib.abstract as ta import pandas as pd @@ -31,103 +26,154 @@ from functools import reduce import numpy as np +def normalize(df): + # To enable normalization outcomment below line: + df = (df-df.min())/(df.max()-df.min()) + return df + class Heracles(IStrategy): - # 65/600: 2275 trades. 1438/7/830 W/D/L. - # Avg profit 3.10%. Median profit 3.06%. - # Total profit 113171 USDT ( 7062 Σ%). - # Avg duration 345 min. Objective: -23.0 + ########################################## RESULT PASTE PLACE ########################################## + # 35/50: 129 trades. 96/15/18 Wins/Draws/Losses. Avg profit 3.57%. Median profit 4.30%. Total profit 2302.93351920 USDT ( 46.06Σ%). Avg duration 2 days, 19:04:00 min. Objective: -21.29091 + # Buy hyperspace params: buy_params = { - 'buy-cross-0': 'volatility_kcw', - 'buy-indicator-0': 'volatility_dcp', - 'buy-oper-0': '<', + "buy_crossed_indicator_shift": -5, + "buy_div": 4.7968, + "buy_indicator_shift": 5, } # Sell hyperspace params: sell_params = { - 'sell-cross-0': 'trend_macd_signal', - 'sell-indicator-0': 'trend_ema_fast', - 'sell-oper-0': '=', + "sell_atol": 0.21256, + "sell_crossed_indicator_shift": 0, + "sell_indicator_shift": -1, + "sell_rtol": 0.11195, } # ROI table: minimal_roi = { - "0": 0.32836, - "1629": 0.17896, - "6302": 0.05372, - "10744": 0 + "0": 0.43, + "994": 0.076, + "2864": 0.043, + "6947": 0 } - + # Stoploss: - stoploss = -0.04655 + stoploss = -0.312 + + ########################################## END RESULT PASTE PLACE ###################################### - # Trailing stop: - trailing_stop = True - trailing_stop_positive = 0.02444 - trailing_stop_positive_offset = 0.04406 - trailing_only_offset_is_reached = True - # Buy hypers - timeframe = '12h' + # buy params + buy_div = DecimalParameter(-5, 5, default=0.51844, decimals=4, space='buy') + buy_indicator_shift = IntParameter(-5, 5, default=4, space='buy') + buy_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='buy') + # sell params + sell_rtol = DecimalParameter(1.e-10, 1.e-0, default=0.05468, decimals=10, space='sell') + sell_atol = DecimalParameter(1.e-16, 1.e-0, default=0.00019, decimals=10, space='sell') + sell_indicator_shift = IntParameter(-5, 5, default=4, space='sell') + sell_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='sell') + + + # Optimal timeframe use it in your config + timeframe = '4h' + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - # Add all ta features dataframe = dropna(dataframe) - dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband( - dataframe['high'], - dataframe['low'], - dataframe['close'], - window=20, - window_atr=10, - fillna=False, - original_version=True - ) - dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband( - dataframe['high'], - dataframe['low'], - dataframe['close'], - window=10, - offset=0, - fillna=False - ) - dataframe['trend_macd_signal'] = ta.trend.macd_signal( - dataframe['close'], - window_slow=26, - window_fast=12, - window_sign=9, - fillna=False - ) + dataframe['volatility_kcw'] = normalize(ta.volatility.keltner_channel_wband( + dataframe['high'], + dataframe['low'], + dataframe['close'], + window=20, + window_atr=10, + fillna=False, + original_version=True + )) + + dataframe['volatility_dcp'] =normalize(ta.volatility.donchian_channel_pband( + dataframe['high'], + dataframe['low'], + dataframe['close'], + window=10, + offset=0, + fillna=False + )) + + dataframe['trend_macd_signal'] =normalize(ta.trend.macd_signal( + dataframe['close'], + window_slow=26, + window_fast=12, + window_sign=9, + fillna=False + )) + - dataframe['trend_ema_fast'] = ta.trend.EMAIndicator( - close=dataframe['close'], window=12, fillna=False - ).ema_indicator() + dataframe['trend_ema_fast'] =normalize(ta.trend.EMAIndicator( + close=dataframe['close'], window=12, fillna=False + ).ema_indicator()) + + + # for checking crossovers! + # but we dont need to crossovers we just calculate dividation + + # import matplotlib.pyplot as plt + # dataframe.iloc[:,6:].plot(subplots=False) + # plt.tight_layout() + # plt.show() return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + """ + Buy strategy Hyperopt will build and use. + """ + conditions = [] - IND = self.buy_params['buy-indicator-0'] - CRS = self.buy_params['buy-cross-0'] + IND = 'volatility_dcp' + CRS = 'volatility_kcw' DFIND = dataframe[IND] DFCRS = dataframe[CRS] - dataframe.loc[ - (DFIND < DFCRS), - 'buy'] = 1 + conditions.append( + DFIND.shift(self.buy_indicator_shift.value).div( + DFCRS.shift(self.buy_crossed_indicator_shift.value) + ) <= self.buy_div.value + ) + + if conditions: + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'buy'] = 1 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - IND = self.sell_params['sell-indicator-0'] - CRS = self.sell_params['sell-cross-0'] + """ + Sell strategy Hyperopt will build and use. + """ + conditions = [] + IND = 'trend_ema_fast' + CRS = 'trend_macd_signal' DFIND = dataframe[IND] DFCRS = dataframe[CRS] - dataframe.loc[ - (qtpylib.crossed_below(DFIND, DFCRS)), - 'sell'] = 1 + conditions.append( + np.isclose( + DFIND.shift(self.sell_indicator_shift.value), + DFCRS.shift(self.sell_crossed_indicator_shift.value), + rtol=self.sell_rtol.value, + atol=self.sell_rtol.value + ) + ) + + if conditions: + dataframe.loc[ + reduce(lambda x, y: x & y, conditions), + 'sell']=1 return dataframe From 11256af1b60da845cf2a46ebfe57fdaca370c7ec Mon Sep 17 00:00:00 2001 From: Masoud Azizi Date: Sun, 27 Jun 2021 16:09:51 +0430 Subject: [PATCH 2/4] decrease decimals --- user_data/strategies/Heracles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_data/strategies/Heracles.py b/user_data/strategies/Heracles.py index 8ecc27e..bed3619 100644 --- a/user_data/strategies/Heracles.py +++ b/user_data/strategies/Heracles.py @@ -71,8 +71,8 @@ class Heracles(IStrategy): buy_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='buy') # sell params - sell_rtol = DecimalParameter(1.e-10, 1.e-0, default=0.05468, decimals=10, space='sell') - sell_atol = DecimalParameter(1.e-16, 1.e-0, default=0.00019, decimals=10, space='sell') + sell_rtol = DecimalParameter(1.e-10, 1.e-0, default=0.05468, decimals=4, space='sell') + sell_atol = DecimalParameter(1.e-16, 1.e-0, default=0.00019, decimals=4, space='sell') sell_indicator_shift = IntParameter(-5, 5, default=4, space='sell') sell_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='sell') From 6253be7e6c3d35713b79cd922737cb207b92052a Mon Sep 17 00:00:00 2001 From: Masoud Azizi Date: Thu, 15 Jul 2021 23:31:26 +0000 Subject: [PATCH 3/4] normalization removed --- user_data/strategies/Heracles.py | 102 ++++++++++++++----------------- 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/user_data/strategies/Heracles.py b/user_data/strategies/Heracles.py index bed3619..3eaed3d 100644 --- a/user_data/strategies/Heracles.py +++ b/user_data/strategies/Heracles.py @@ -8,7 +8,7 @@ # "min_days_listed": 100 # }, # IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta) -# +# # freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy sell --strategy Heracles # ###################################################################### # --- Do not remove these libs --- @@ -26,44 +26,36 @@ from functools import reduce import numpy as np -def normalize(df): - # To enable normalization outcomment below line: - df = (df-df.min())/(df.max()-df.min()) - return df - class Heracles(IStrategy): ########################################## RESULT PASTE PLACE ########################################## - # 35/50: 129 trades. 96/15/18 Wins/Draws/Losses. Avg profit 3.57%. Median profit 4.30%. Total profit 2302.93351920 USDT ( 46.06Σ%). Avg duration 2 days, 19:04:00 min. Objective: -21.29091 - + # 18/100: 111 trades. 77/23/11 Wins/Draws/Losses. Avg profit 3.81%. Median profit 4.40%. Total profit 2114.06222218 USDT ( 42.28Σ%). Avg duration 3 days, 3:04:00 min. Objective: -16.78579 # Buy hyperspace params: buy_params = { - "buy_crossed_indicator_shift": -5, - "buy_div": 4.7968, - "buy_indicator_shift": 5, + "buy_crossed_indicator_shift": 5, + "buy_div": 3.61, + "buy_indicator_shift": 1, } # Sell hyperspace params: sell_params = { - "sell_atol": 0.21256, - "sell_crossed_indicator_shift": 0, - "sell_indicator_shift": -1, - "sell_rtol": 0.11195, + "sell_atol": 0.30989, + "sell_crossed_indicator_shift": 2, + "sell_indicator_shift": 5, + "sell_rtol": 0.19449, } # ROI table: minimal_roi = { - "0": 0.43, - "994": 0.076, - "2864": 0.043, - "6947": 0 + "0": 0.725, + "889": 0.171, + "2776": 0.044, + "5299": 0 } - # Stoploss: stoploss = -0.312 - - ########################################## END RESULT PASTE PLACE ###################################### + ########################################## END RESULT PASTE PLACE ###################################### # buy params buy_div = DecimalParameter(-5, 5, default=0.51844, decimals=4, space='buy') @@ -71,51 +63,47 @@ class Heracles(IStrategy): buy_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='buy') # sell params - sell_rtol = DecimalParameter(1.e-10, 1.e-0, default=0.05468, decimals=4, space='sell') - sell_atol = DecimalParameter(1.e-16, 1.e-0, default=0.00019, decimals=4, space='sell') + sell_rtol = DecimalParameter(1.e-10, 1.e-0, default=0.05468, decimals=10, space='sell') + sell_atol = DecimalParameter(1.e-16, 1.e-0, default=0.00019, decimals=10, space='sell') sell_indicator_shift = IntParameter(-5, 5, default=4, space='sell') sell_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='sell') - # Optimal timeframe use it in your config timeframe = '4h' - def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe = dropna(dataframe) - dataframe['volatility_kcw'] = normalize(ta.volatility.keltner_channel_wband( - dataframe['high'], - dataframe['low'], - dataframe['close'], - window=20, - window_atr=10, - fillna=False, - original_version=True - )) - - dataframe['volatility_dcp'] =normalize(ta.volatility.donchian_channel_pband( - dataframe['high'], - dataframe['low'], - dataframe['close'], - window=10, - offset=0, - fillna=False - )) - - dataframe['trend_macd_signal'] =normalize(ta.trend.macd_signal( - dataframe['close'], - window_slow=26, - window_fast=12, - window_sign=9, - fillna=False - )) - + dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband( + dataframe['high'], + dataframe['low'], + dataframe['close'], + window=20, + window_atr=10, + fillna=False, + original_version=True + ) - dataframe['trend_ema_fast'] =normalize(ta.trend.EMAIndicator( - close=dataframe['close'], window=12, fillna=False - ).ema_indicator()) - + dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband( + dataframe['high'], + dataframe['low'], + dataframe['close'], + window=10, + offset=0, + fillna=False + ) + + dataframe['trend_macd_signal'] = ta.trend.macd_signal( + dataframe['close'], + window_slow=26, + window_fast=12, + window_sign=9, + fillna=False + ) + + dataframe['trend_ema_fast'] = ta.trend.EMAIndicator( + close=dataframe['close'], window=12, fillna=False + ).ema_indicator() # for checking crossovers! # but we dont need to crossovers we just calculate dividation From e0acc18d2cbda8b79f1651d5bdf4699a03d91e5c Mon Sep 17 00:00:00 2001 From: Masoud Azizi Date: Mon, 26 Jul 2021 00:59:46 +0000 Subject: [PATCH 4/4] space decimals increased,sell spaces removed --- user_data/strategies/Heracles.py | 96 +++++++++----------------------- 1 file changed, 25 insertions(+), 71 deletions(-) diff --git a/user_data/strategies/Heracles.py b/user_data/strategies/Heracles.py index 3eaed3d..1cdb3d4 100644 --- a/user_data/strategies/Heracles.py +++ b/user_data/strategies/Heracles.py @@ -9,7 +9,7 @@ # }, # IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta) # -# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy sell --strategy Heracles +# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy --strategy Heracles # ###################################################################### # --- Do not remove these libs --- from freqtrade.strategy.hyper import IntParameter, DecimalParameter @@ -28,48 +28,41 @@ import numpy as np class Heracles(IStrategy): ########################################## RESULT PASTE PLACE ########################################## - # 18/100: 111 trades. 77/23/11 Wins/Draws/Losses. Avg profit 3.81%. Median profit 4.40%. Total profit 2114.06222218 USDT ( 42.28Σ%). Avg duration 3 days, 3:04:00 min. Objective: -16.78579 + # 10/100: 25 trades. 18/4/3 Wins/Draws/Losses. Avg profit 5.92%. Median profit 6.33%. Total profit 0.04888306 BTC ( 48.88Σ%). Avg duration 4 days, 6:24:00 min. Objective: -11.42103 # Buy hyperspace params: buy_params = { - "buy_crossed_indicator_shift": 5, - "buy_div": 3.61, - "buy_indicator_shift": 1, + "buy_crossed_indicator_shift": 9, + "buy_div_max": 0.75, + "buy_div_min": 0.16, + "buy_indicator_shift": 15, } # Sell hyperspace params: sell_params = { - "sell_atol": 0.30989, - "sell_crossed_indicator_shift": 2, - "sell_indicator_shift": 5, - "sell_rtol": 0.19449, } # ROI table: minimal_roi = { - "0": 0.725, - "889": 0.171, - "2776": 0.044, - "5299": 0 + "0": 0.598, + "644": 0.166, + "3269": 0.115, + "7289": 0 } + # Stoploss: - stoploss = -0.312 + stoploss = -0.256 + + # Optimal timeframe use it in your config + timeframe = '4h' ########################################## END RESULT PASTE PLACE ###################################### # buy params - buy_div = DecimalParameter(-5, 5, default=0.51844, decimals=4, space='buy') - buy_indicator_shift = IntParameter(-5, 5, default=4, space='buy') - buy_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='buy') - - # sell params - sell_rtol = DecimalParameter(1.e-10, 1.e-0, default=0.05468, decimals=10, space='sell') - sell_atol = DecimalParameter(1.e-16, 1.e-0, default=0.00019, decimals=10, space='sell') - sell_indicator_shift = IntParameter(-5, 5, default=4, space='sell') - sell_crossed_indicator_shift = IntParameter(-5, 5, default=1, space='sell') - - # Optimal timeframe use it in your config - timeframe = '4h' + buy_div_min = DecimalParameter(0, 1, default=0.16, decimals=2, space='buy') + buy_div_max = DecimalParameter(0, 1, default=0.75, decimals=2, space='buy') + buy_indicator_shift = IntParameter(0, 20, default=16, space='buy') + buy_crossed_indicator_shift = IntParameter(0, 20, default=9, space='buy') def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe = dropna(dataframe) @@ -93,26 +86,6 @@ class Heracles(IStrategy): fillna=False ) - dataframe['trend_macd_signal'] = ta.trend.macd_signal( - dataframe['close'], - window_slow=26, - window_fast=12, - window_sign=9, - fillna=False - ) - - dataframe['trend_ema_fast'] = ta.trend.EMAIndicator( - close=dataframe['close'], window=12, fillna=False - ).ema_indicator() - - # for checking crossovers! - # but we dont need to crossovers we just calculate dividation - - # import matplotlib.pyplot as plt - # dataframe.iloc[:,6:].plot(subplots=False) - # plt.tight_layout() - # plt.show() - return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: @@ -126,16 +99,17 @@ class Heracles(IStrategy): DFIND = dataframe[IND] DFCRS = dataframe[CRS] + d = DFIND.shift(self.buy_indicator_shift.value).div( + DFCRS.shift(self.buy_crossed_indicator_shift.value)) + + # print(d.min(), "\t", d.max()) conditions.append( - DFIND.shift(self.buy_indicator_shift.value).div( - DFCRS.shift(self.buy_crossed_indicator_shift.value) - ) <= self.buy_div.value - ) + d.between(self.buy_div_min.value, self.buy_div_max.value)) if conditions: dataframe.loc[ reduce(lambda x, y: x & y, conditions), - 'buy'] = 1 + 'buy']=1 return dataframe @@ -143,25 +117,5 @@ class Heracles(IStrategy): """ Sell strategy Hyperopt will build and use. """ - conditions = [] - - IND = 'trend_ema_fast' - CRS = 'trend_macd_signal' - DFIND = dataframe[IND] - DFCRS = dataframe[CRS] - - conditions.append( - np.isclose( - DFIND.shift(self.sell_indicator_shift.value), - DFCRS.shift(self.sell_crossed_indicator_shift.value), - rtol=self.sell_rtol.value, - atol=self.sell_rtol.value - ) - ) - - if conditions: - dataframe.loc[ - reduce(lambda x, y: x & y, conditions), - 'sell']=1 return dataframe