From 92241baadee5b41651d087d2d659c9e1e688ecd5 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 14 Jan 2018 13:09:39 +0200 Subject: [PATCH 01/12] log the loss value --- freqtrade/optimize/hyperopt.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 71ddd33c6..19c48371c 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -133,10 +133,11 @@ def log_results(results): if results['loss'] < CURRENT_BEST_LOSS: CURRENT_BEST_LOSS = results['loss'] - logger.info('{:5d}/{}: {}'.format( + logger.info('{:5d}/{}: {}. Loss {:.5f}'.format( results['current_tries'], results['total_tries'], - results['result'])) + results['result'], + results['loss'])) else: print('.', end='') sys.stdout.flush() From f1e176d35c77d3772732532978007409d2d2adb3 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 14 Jan 2018 13:10:25 +0200 Subject: [PATCH 02/12] log total profit in percentages also --- freqtrade/optimize/hyperopt.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 19c48371c..97c6a82f5 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -191,12 +191,13 @@ def optimizer(params): def format_results(results: DataFrame): return ('{:6d} trades. Avg profit {: 5.2f}%. ' - 'Total profit {: 11.8f} BTC. Avg duration {:5.1f} mins.').format( + 'Total profit {: 11.8f} BTC ({:.4f}Σ%). Avg duration {:5.1f} mins.').format( len(results.index), results.profit_percent.mean() * 100.0, results.profit_BTC.sum(), + results.profit_percent.sum(), results.duration.mean() * 5, - ) + ) def buy_strategy_generator(params): From ec7bfba8dfcc85fe47282b76d39dc994ddcf47f3 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Sun, 14 Jan 2018 13:11:19 +0200 Subject: [PATCH 03/12] add comment about checking the new total profit logging --- freqtrade/optimize/hyperopt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 97c6a82f5..3235a10e6 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -41,6 +41,7 @@ MAX_ACCEPTED_TRADE_DURATION = 240 # this is expexted avg profit * expected trade count # for example 3.5%, 1100 trades, EXPECTED_MAX_PROFIT = 3.85 +# check that the reported Σ% values do not exceed this! EXPECTED_MAX_PROFIT = 3.85 # Configuration and data used by hyperopt From 38fe7ec7cdae4703cb96588067ea419e10f7acfa Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 16:35:48 +0200 Subject: [PATCH 04/12] adjust default target values for hyperopt --- freqtrade/optimize/hyperopt.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 3235a10e6..02a64fa74 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -30,19 +30,19 @@ logging.getLogger('hyperopt.tpe').setLevel(logging.WARNING) logger = logging.getLogger(__name__) # set TARGET_TRADES to suit your number concurrent trades so its realistic to 20days of data -TARGET_TRADES = 1100 +TARGET_TRADES = 600 TOTAL_TRIES = 0 _CURRENT_TRIES = 0 CURRENT_BEST_LOSS = 100 # max average trade duration in minutes # if eval ends with higher value, we consider it a failed eval -MAX_ACCEPTED_TRADE_DURATION = 240 +MAX_ACCEPTED_TRADE_DURATION = 300 # this is expexted avg profit * expected trade count # for example 3.5%, 1100 trades, EXPECTED_MAX_PROFIT = 3.85 # check that the reported Σ% values do not exceed this! -EXPECTED_MAX_PROFIT = 3.85 +EXPECTED_MAX_PROFIT = 3.0 # Configuration and data used by hyperopt PROCESSED = None # optimize.preprocess(optimize.load_data()) From 501be8a3bc2df259765bedf6ad6f3fd6f66cd4a8 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 16:36:50 +0200 Subject: [PATCH 05/12] adjust the hyperopt objective function to emphasize profit and allow more variation in trade counts --- freqtrade/optimize/hyperopt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 02a64fa74..f8a494a0a 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -146,9 +146,9 @@ def log_results(results): def calculate_loss(total_profit: float, trade_count: int, trade_duration: float): """ objective function, returns smaller number for more optimal results """ - trade_loss = 1 - 0.35 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.2) + trade_loss = 1 - 0.25 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.8) profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT) - duration_loss = min(trade_duration / MAX_ACCEPTED_TRADE_DURATION, 1) + duration_loss = 0.7 + 0.3 * min(trade_duration / MAX_ACCEPTED_TRADE_DURATION, 1) return trade_loss + profit_loss + duration_loss From 3e1a70bbb2510b2aec9aa8b0ac54976a1d29d9cb Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 10:47:34 +0200 Subject: [PATCH 06/12] enable correct bollinger bands --- freqtrade/analyze.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index f85c46248..ac8279603 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -114,11 +114,11 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: dataframe['blower'] = ta.BBANDS(dataframe, nbdevup=2, nbdevdn=2)['lowerband'] """ # Bollinger bands + """ bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) dataframe['bb_lowerband'] = bollinger['lower'] dataframe['bb_middleband'] = bollinger['mid'] dataframe['bb_upperband'] = bollinger['upper'] - """ # EMA - Exponential Moving Average dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5) From 99260735ae9202918579e58b8d54193aa7a41a21 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 10:48:42 +0200 Subject: [PATCH 07/12] remove broken bbands trigger from hyperopt. add two working bbands triggers --- freqtrade/optimize/hyperopt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index f8a494a0a..9afea7f79 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -96,6 +96,7 @@ SPACE = { ]), 'trigger': hp.choice('trigger', [ {'type': 'lower_bb'}, + {'type': 'lower_bb_tema'}, {'type': 'faststoch10'}, {'type': 'ao_cross_zero'}, {'type': 'ema5_cross_ema10'}, @@ -227,7 +228,8 @@ def buy_strategy_generator(params): # TRIGGERS triggers = { - 'lower_bb': dataframe['tema'] <= dataframe['blower'], + 'lower_bb': (dataframe['close'] < dataframe['bb_lowerband']), + 'lower_bb_tema': (dataframe['tema'] < dataframe['bb_lowerband']), 'faststoch10': (crossed_above(dataframe['fastd'], 10.0)), 'ao_cross_zero': (crossed_above(dataframe['ao'], 0.0)), 'ema5_cross_ema10': (crossed_above(dataframe['ema5'], dataframe['ema10'])), From fadac5fe4abe89442b80e3cd73b502e9808c6377 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 11:13:12 +0200 Subject: [PATCH 08/12] remove too aggressive trigger --- freqtrade/optimize/hyperopt.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 9afea7f79..a21549922 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -102,7 +102,6 @@ SPACE = { {'type': 'ema5_cross_ema10'}, {'type': 'macd_cross_signal'}, {'type': 'sar_reversal'}, - {'type': 'stochf_cross'}, {'type': 'ht_sine'}, ]), 'stoploss': hp.uniform('stoploss', -0.5, -0.02), @@ -235,7 +234,6 @@ def buy_strategy_generator(params): 'ema5_cross_ema10': (crossed_above(dataframe['ema5'], dataframe['ema10'])), 'macd_cross_signal': (crossed_above(dataframe['macd'], dataframe['macdsignal'])), 'sar_reversal': (crossed_above(dataframe['close'], dataframe['sar'])), - 'stochf_cross': (crossed_above(dataframe['fastk'], dataframe['fastd'])), 'ht_sine': (crossed_above(dataframe['htleadsine'], dataframe['htsine'])), } conditions.append(triggers.get(params['trigger']['type'])) From dc01807b3ca608139e40259fbe1cc0f3b867f75c Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 11:16:08 +0200 Subject: [PATCH 09/12] switch ema5 trigger to ema3 cross trigger --- freqtrade/analyze.py | 1 + freqtrade/optimize/hyperopt.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index ac8279603..ecb0b2b57 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -121,6 +121,7 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: dataframe['bb_upperband'] = bollinger['upper'] # EMA - Exponential Moving Average + dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3) dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5) dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10) dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index a21549922..9b71900c5 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -99,7 +99,7 @@ SPACE = { {'type': 'lower_bb_tema'}, {'type': 'faststoch10'}, {'type': 'ao_cross_zero'}, - {'type': 'ema5_cross_ema10'}, + {'type': 'ema3_cross_ema10'}, {'type': 'macd_cross_signal'}, {'type': 'sar_reversal'}, {'type': 'ht_sine'}, @@ -231,7 +231,7 @@ def buy_strategy_generator(params): 'lower_bb_tema': (dataframe['tema'] < dataframe['bb_lowerband']), 'faststoch10': (crossed_above(dataframe['fastd'], 10.0)), 'ao_cross_zero': (crossed_above(dataframe['ao'], 0.0)), - 'ema5_cross_ema10': (crossed_above(dataframe['ema5'], dataframe['ema10'])), + 'ema3_cross_ema10': (crossed_above(dataframe['ema3'], dataframe['ema10'])), 'macd_cross_signal': (crossed_above(dataframe['macd'], dataframe['macdsignal'])), 'sar_reversal': (crossed_above(dataframe['close'], dataframe['sar'])), 'ht_sine': (crossed_above(dataframe['htleadsine'], dataframe['htsine'])), From ce963aae5822c9c6ad5b2a222657a9468956205c Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 13:31:45 +0200 Subject: [PATCH 10/12] add macd < 0 guard to hyperopt --- freqtrade/optimize/hyperopt.py | 6 ++++++ freqtrade/tests/optimize/test_hyperopt.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 9b71900c5..0fdd2fc01 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -58,6 +58,10 @@ main._CONF = OPTIMIZE_CONFIG SPACE = { + 'macd_below_zero': hp.choice('macd_below_zero', [ + {'enabled': False}, + {'enabled': True} + ]), 'mfi': hp.choice('mfi', [ {'enabled': False}, {'enabled': True, 'value': hp.quniform('mfi-value', 5, 25, 1)} @@ -207,6 +211,8 @@ def buy_strategy_generator(params): # GUARDS AND TRENDS if params['uptrend_long_ema']['enabled']: conditions.append(dataframe['ema50'] > dataframe['ema100']) + if params['macd_below_zero']['enabled']: + conditions.append(dataframe['macd'] < 0) if params['uptrend_short_ema']['enabled']: conditions.append(dataframe['ema5'] > dataframe['ema10']) if params['mfi']['enabled']: diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index 3e03d26c0..4bb5c8c0b 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -107,6 +107,7 @@ def test_no_log_if_loss_does_not_improve(mocker): def test_fmin_best_results(mocker, caplog): fmin_result = { + "macd_below_zero": 0, "adx": 1, "adx-value": 15.0, "fastd": 1, @@ -136,7 +137,7 @@ def test_fmin_best_results(mocker, caplog): '"adx": {\n "enabled": true,\n "value": 15.0\n },', '"green_candle": {\n "enabled": true\n },', '"mfi": {\n "enabled": false\n },', - '"trigger": {\n "type": "ao_cross_zero"\n },', + '"trigger": {\n "type": "faststoch10"\n },', '"stoploss": -0.1', ] From 8896b39231e43886f20f0d5f34cbf85a6481c4a9 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 13:53:30 +0200 Subject: [PATCH 11/12] add heikenashi reversal bullish trigger to hyperopt --- freqtrade/analyze.py | 2 -- freqtrade/optimize/hyperopt.py | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index ecb0b2b57..3d3f9b5cc 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -211,14 +211,12 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: # Chart type # ------------------------------------ - """ # Heikinashi stategy heikinashi = qtpylib.heikinashi(dataframe) dataframe['ha_open'] = heikinashi['open'] dataframe['ha_close'] = heikinashi['close'] dataframe['ha_high'] = heikinashi['high'] dataframe['ha_low'] = heikinashi['low'] - """ return dataframe diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 0fdd2fc01..cb681cf36 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -107,6 +107,7 @@ SPACE = { {'type': 'macd_cross_signal'}, {'type': 'sar_reversal'}, {'type': 'ht_sine'}, + {'type': 'heiken_reversal_bull'}, ]), 'stoploss': hp.uniform('stoploss', -0.5, -0.02), } @@ -241,6 +242,8 @@ def buy_strategy_generator(params): 'macd_cross_signal': (crossed_above(dataframe['macd'], dataframe['macdsignal'])), 'sar_reversal': (crossed_above(dataframe['close'], dataframe['sar'])), 'ht_sine': (crossed_above(dataframe['htleadsine'], dataframe['htsine'])), + 'heiken_reversal_bull': (crossed_above(dataframe['ha_close'], dataframe['ha_open'])) & + (dataframe['ha_low'] == dataframe['ha_open']), } conditions.append(triggers.get(params['trigger']['type'])) From c670ccfd376b23c798a01cf26b0250eccaaeb8d5 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 16 Jan 2018 18:51:22 +0200 Subject: [PATCH 12/12] add trigger +DI crossed above -DI --- freqtrade/analyze.py | 2 ++ freqtrade/optimize/hyperopt.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index 3d3f9b5cc..0d01576df 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -74,6 +74,8 @@ def populate_indicators(dataframe: DataFrame) -> DataFrame: # Plus Directional Indicator / Movement dataframe['plus_dm'] = ta.PLUS_DM(dataframe) dataframe['plus_di'] = ta.PLUS_DI(dataframe) + dataframe['minus_di'] = ta.MINUS_DI(dataframe) + """ # ROC dataframe['roc'] = ta.ROC(dataframe) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index cb681cf36..959e64206 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -108,6 +108,7 @@ SPACE = { {'type': 'sar_reversal'}, {'type': 'ht_sine'}, {'type': 'heiken_reversal_bull'}, + {'type': 'di_cross'}, ]), 'stoploss': hp.uniform('stoploss', -0.5, -0.02), } @@ -244,6 +245,7 @@ def buy_strategy_generator(params): 'ht_sine': (crossed_above(dataframe['htleadsine'], dataframe['htsine'])), 'heiken_reversal_bull': (crossed_above(dataframe['ha_close'], dataframe['ha_open'])) & (dataframe['ha_low'] == dataframe['ha_open']), + 'di_cross': (crossed_above(dataframe['plus_di'], dataframe['minus_di'])), } conditions.append(triggers.get(params['trigger']['type']))