From aaac23a96a0b7ef5964b2d3943b694685f504bf8 Mon Sep 17 00:00:00 2001 From: OtenMoten <32872932+OtenMoten@users.noreply.github.com> Date: Mon, 22 Feb 2021 12:17:46 +0100 Subject: [PATCH 1/5] Added Hyper-Optimization "Swing-High-To-Sky" I like to share my newest hyperopt with you. I though about how cool it would be to know what's the perfect timeperiod for CCI indicator. In a strategy you do something like this: dataframe['cci'] = ta.CCI(timeperiod=14) You would do this by hand for each timeperiod which is very annoying. Therefore, I created this hyperopt to looking for the perfect timeperiod for the CCI indicator. Please review this pull request very critical and share your minds. Since the last two months (from 1st Jan 2021 until now) this strategy in BTC/USDT 30m chart had worked very very well. After two months I now optimize this strategy again. --- user_data/hyperopts/HO-SwingHighToSky.py | 124 +++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 user_data/hyperopts/HO-SwingHighToSky.py diff --git a/user_data/hyperopts/HO-SwingHighToSky.py b/user_data/hyperopts/HO-SwingHighToSky.py new file mode 100644 index 0000000..3807ac9 --- /dev/null +++ b/user_data/hyperopts/HO-SwingHighToSky.py @@ -0,0 +1,124 @@ +# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement + +import talib.abstract as ta +from pandas import DataFrame +from typing import Dict, Any, Callable, List +from functools import reduce + +import numpy as np +from skopt.space import Categorical, Dimension, Integer, Real +import freqtrade.vendor.qtpylib.indicators as qtpylib +from freqtrade.optimize.hyperopt_interface import IHyperOpt + +__author__ = "Kevin Ossenbrück" +__copyright__ = "Free For Use" +__credits__ = ["Bloom Trading, Mohsen Hassan"] +__license__ = "MIT" +__version__ = "1.0" +__maintainer__ = "Kevin Ossenbrück" +__email__ = "kevin.ossenbrueck@pm.de" +__status__ = "Live" + +cciTimeMin = 10 +cciTimeMax = 100 +cciValueMin = -400 +cciValueMax = 400 +cciTimeRange = range(cciTimeMin, cciTimeMax) + +class_name = 'HOSwingHighToSky' +class HOSwingHighToSky(IHyperOpt): + + @staticmethod + def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame: + + macd = ta.MACD(dataframe) + dataframe['macd'] = macd['macd'] + dataframe['macdsignal'] = macd['macdsignal'] + + for cciTime in cciTimeRange: + + cciName = "cci-" + str(cciTime) + dataframe[cciName] = ta.CCI(dataframe, timeperiod = cciTime) + + return dataframe + + @staticmethod + def buy_strategy_generator(params: Dict[str, Any]) -> Callable: + + def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: + + conditions = [] + + # TRIGGERS & GUARDS + if 'trigger' in params: + + for cciTime in cciTimeRange: + + cciName = "cci-" + str(cciTime) + + if params['trigger'] == cciName: + conditions.append(dataframe[cciName] < params["buy-cci-value"]) + conditions.append(dataframe['macd'] > dataframe['macdsignal']) + conditions.append(dataframe['volume'] > 0) + + if conditions: + dataframe.loc[reduce(lambda x, y: x & y, conditions), 'buy'] = 1 + + return dataframe + + return populate_buy_trend + + @staticmethod + def indicator_space() -> List[Dimension]: + + buyTriggerList = [] + + for cciTime in cciTimeRange: + + cciName = "cci-" + str(cciTime) + buyTriggerList.append(cciName) + + return [ + Integer(cciValueMin, cciValueMax, name='buy-cci-value'), + Categorical(buyTriggerList, name='trigger') + ] + + @staticmethod + def sell_strategy_generator(params: Dict[str, Any]) -> Callable: + + def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: + + conditions = [] + + # TRIGGERS & GUARDS + if 'sell-trigger' in params: + + for cciTime in cciTimeRange: + + cciName = "cci-" + str(cciTime) + + if params['sell-trigger'] == cciName: + conditions.append(dataframe[cciName] > params["sell-cci-value"]) + conditions.append(dataframe['macd'] < dataframe['macdsignal']) + + if conditions: + dataframe.loc[reduce(lambda x, y: x & y, conditions), 'sell'] = 1 + + return dataframe + + return populate_sell_trend + + @staticmethod + def sell_indicator_space() -> List[Dimension]: + + sellTriggerList = [] + + for cciTime in cciTimeRange: + + cciName = "cci-" + str(cciTime) + sellTriggerList.append(cciName) + + return [ + Integer(cciValueMin, cciValueMax, name='sell-cci-value'), + Categorical(sellTriggerList, name='sell-trigger') + ] \ No newline at end of file From 40353219aed4967d6c0da18875d0e52a327ca813 Mon Sep 17 00:00:00 2001 From: OtenMoten <32872932+OtenMoten@users.noreply.github.com> Date: Mon, 22 Feb 2021 12:21:35 +0100 Subject: [PATCH 2/5] Added strategy "Swing-High-To-Sky" ## Hello dear community, I like to share my newest hyperopt with you. I though about how cool it would be to know what's the perfect timeperiod for CCI indicator. In a strategy you do something like this: `dataframe['cci'] = ta.CCI(timeperiod=14)` You would do this by hand for each timeperiod which is very annoying. Therefore, I created this hyperopt to looking for the perfect timeperiod for the CCI indicator. Please review this pull request very critical and share your minds. Since the last two months (from 1st Jan 2021 until now) this strategy in BTC/USDT 30m chart had worked **very very** well. After two months I now optimize this strategy again. I provided both, strategy and hyperopt file, in the attachements. ## Summary The goal of this hyper-optimization is to find the perfect timeframe of the CCI indicator (from 10 to 100) within a range from -400 to +400. The MACD indicator here is just a favorite of myself, replace with your favorit indicator if you like. --- user_data/strategies/Swing-High-To-Sky.py | 71 +++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 user_data/strategies/Swing-High-To-Sky.py diff --git a/user_data/strategies/Swing-High-To-Sky.py b/user_data/strategies/Swing-High-To-Sky.py new file mode 100644 index 0000000..0d7ab06 --- /dev/null +++ b/user_data/strategies/Swing-High-To-Sky.py @@ -0,0 +1,71 @@ +# --- Do not remove these libs --- +from freqtrade.strategy.interface import IStrategy +from typing import Dict, List +from functools import reduce +from pandas import DataFrame +# -------------------------------- + +import talib.abstract as ta +import freqtrade.vendor.qtpylib.indicators as qtpylib +import numpy # noqa + +__author__ = "Kevin Ossenbrück" +__copyright__ = "Free For Use" +__credits__ = ["Bloom Trading, Mohsen Hassan"] +__license__ = "MIT" +__version__ = "1.0" +__maintainer__ = "Kevin Ossenbrück" +__email__ = "kevin.ossenbrueck@pm.de" +__status__ = "Live" + +class_name = 'SwingHighToSky' +class SwingHighToSky(IStrategy): + + # Disable ROI + minimal_roi = { + "0": 100 + } + + stoploss = -0.30 + trailing_stop = True + trailing_stop_positive = 0.08 + trailing_stop_positive_offset = 0.10 + trailing_only_offset_is_reached = True + + ticker_interval = '30m' + + def informative_pairs(self): + return [] + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + macd = ta.MACD(dataframe) + dataframe['macd'] = macd['macd'] + dataframe['macdsignal'] = macd['macdsignal'] + dataframe['macdhist'] = macd['macdhist'] + + dataframe['cci'] = ta.CCI(dataframe) + + return dataframe + + def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe.loc[ + ( + (dataframe['macd'] > dataframe['macdsignal']) & + (dataframe['cci'] <= -100.0) + ), + 'buy'] = 1 + + return dataframe + + def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe.loc[ + ( + (dataframe['macd'] < dataframe['macdsignal']) & + (dataframe['cci'] >= 200.0) + ), + 'sell'] = 1 + + return dataframe \ No newline at end of file From 05933f9e263580aef8d89d3e2fa6a8b9c905409b Mon Sep 17 00:00:00 2001 From: OtenMoten <32872932+OtenMoten@users.noreply.github.com> Date: Tue, 23 Feb 2021 20:32:06 +0100 Subject: [PATCH 3/5] Update user_data/strategies/Swing-High-To-Sky.py Jep, very good. Co-authored-by: Matthias --- user_data/strategies/Swing-High-To-Sky.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/user_data/strategies/Swing-High-To-Sky.py b/user_data/strategies/Swing-High-To-Sky.py index 0d7ab06..a9491c5 100644 --- a/user_data/strategies/Swing-High-To-Sky.py +++ b/user_data/strategies/Swing-High-To-Sky.py @@ -44,7 +44,8 @@ class SwingHighToSky(IStrategy): dataframe['macdsignal'] = macd['macdsignal'] dataframe['macdhist'] = macd['macdhist'] - dataframe['cci'] = ta.CCI(dataframe) + dataframe['cci-buy'] = ta.CCI(dataframe, timeperiod=xx) + dataframe['cci-sell'] = ta.CCI(dataframe, timeperiod=xx-sell) return dataframe @@ -68,4 +69,4 @@ class SwingHighToSky(IStrategy): ), 'sell'] = 1 - return dataframe \ No newline at end of file + return dataframe From e567422b0d3fe0f91eaf2af98af4836c86774526 Mon Sep 17 00:00:00 2001 From: OtenMoten <32872932+OtenMoten@users.noreply.github.com> Date: Tue, 23 Feb 2021 20:38:34 +0100 Subject: [PATCH 4/5] Changed syntax and added comments --- user_data/strategies/Swing-High-To-Sky.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/user_data/strategies/Swing-High-To-Sky.py b/user_data/strategies/Swing-High-To-Sky.py index a9491c5..652decd 100644 --- a/user_data/strategies/Swing-High-To-Sky.py +++ b/user_data/strategies/Swing-High-To-Sky.py @@ -22,11 +22,15 @@ class_name = 'SwingHighToSky' class SwingHighToSky(IStrategy): # Disable ROI + # Could be replaced with new ROI from hyperopt. minimal_roi = { "0": 100 } stoploss = -0.30 + + ### Do extra hyperopt for trailing seperat. Use "--spaces default" and then "--spaces trailing". + ### See here for more information: https://www.freqtrade.io/en/latest/hyperopt trailing_stop = True trailing_stop_positive = 0.08 trailing_stop_positive_offset = 0.10 @@ -42,10 +46,10 @@ class SwingHighToSky(IStrategy): macd = ta.MACD(dataframe) dataframe['macd'] = macd['macd'] dataframe['macdsignal'] = macd['macdsignal'] - dataframe['macdhist'] = macd['macdhist'] + ### Add timeperiod from hyperopt (replace xx with value) dataframe['cci-buy'] = ta.CCI(dataframe, timeperiod=xx) - dataframe['cci-sell'] = ta.CCI(dataframe, timeperiod=xx-sell) + dataframe['cci-sell'] = ta.CCI(dataframe, timeperiod=xx) return dataframe @@ -54,7 +58,7 @@ class SwingHighToSky(IStrategy): dataframe.loc[ ( (dataframe['macd'] > dataframe['macdsignal']) & - (dataframe['cci'] <= -100.0) + (dataframe['cci-buy'] <= -100.0) # Replace with value from hyperopt. ), 'buy'] = 1 @@ -65,7 +69,7 @@ class SwingHighToSky(IStrategy): dataframe.loc[ ( (dataframe['macd'] < dataframe['macdsignal']) & - (dataframe['cci'] >= 200.0) + (dataframe['cci-sell'] >= 200.0) # Replace with value from hyperopt. ), 'sell'] = 1 From f670aac23b9584c18f1f1ddf7acf38a54f77854d Mon Sep 17 00:00:00 2001 From: OtenMoten <32872932+OtenMoten@users.noreply.github.com> Date: Thu, 25 Feb 2021 12:54:17 +0100 Subject: [PATCH 5/5] Update Swing-High-To-Sky.py Added comment --- user_data/strategies/Swing-High-To-Sky.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/user_data/strategies/Swing-High-To-Sky.py b/user_data/strategies/Swing-High-To-Sky.py index 652decd..ea83bf9 100644 --- a/user_data/strategies/Swing-High-To-Sky.py +++ b/user_data/strategies/Swing-High-To-Sky.py @@ -47,7 +47,9 @@ class SwingHighToSky(IStrategy): dataframe['macd'] = macd['macd'] dataframe['macdsignal'] = macd['macdsignal'] - ### Add timeperiod from hyperopt (replace xx with value) + ### Add timeperiod from hyperopt (replace xx with value): + ### "xx" must be replaced even before the first hyperopt is run, + ### else "xx" would be a syntax error because it must be a Integer value. dataframe['cci-buy'] = ta.CCI(dataframe, timeperiod=xx) dataframe['cci-sell'] = ta.CCI(dataframe, timeperiod=xx)