This commit is contained in:
Stephen 2018-03-06 07:51:27 +00:00 committed by GitHub
commit 96d742de99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 282 additions and 314 deletions

View File

@ -19,8 +19,8 @@ your strategy file located into [user_data/strategies/](https://github.com/gcarq
### 1. Configure your Guards and Triggers
There are two places you need to change in your strategy file to add a
new buy strategy for testing:
- Inside [populate_buy_trend()](https://github.com/gcarq/freqtrade/blob/develop/user_data/strategies/test_strategy.py#L278-L294).
- Inside [hyperopt_space()](https://github.com/gcarq/freqtrade/blob/develop/user_data/strategies/test_strategy.py#L244-L297) known as `SPACE`.
- Inside [populate_buy_trend()](https://github.com/gcarq/freqtrade/blob/develop/user_data/strategies/test_strategy.py#L273-L294).
- Inside [indicator_space()](https://github.com/gcarq/freqtrade/blob/develop/user_data/strategies/test_strategy.py#L251-L67).
There you have two different type of indicators: 1. `guards` and 2.
`triggers`.
@ -55,10 +55,14 @@ Your hyperopt file must contain `guards` to find the right value for
`(dataframe['adx'] > 65)` & and `(dataframe['plus_di'] > 0.5)`. That
means you will need to enable/disable triggers.
In our case the `SPACE` and `populate_buy_trend` in your strategy file
In our case the `indicator_space` and `populate_buy_trend` in your strategy file
will look like:
```python
space = {
def indicator_space(self) -> Dict[str, Any]:
"""
Define your Hyperopt space for searching strategy parameters
"""
return {
'rsi': hp.choice('rsi', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('rsi-value', 20, 40, 1)}
@ -77,7 +81,7 @@ space = {
{'type': 'stochf_cross'},
{'type': 'ht_sine'},
]),
}
}
...
@ -100,7 +104,13 @@ def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
'stochf_cross': (crossed_above(dataframe['fastk'], dataframe['fastd'])),
'ht_sine': (crossed_above(dataframe['htleadsine'], dataframe['htsine'])),
}
...
conditions.append(triggers.get(params['trigger']['type']))
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy'] = 1
return dataframe
```
@ -116,7 +126,7 @@ The Hyperopt configuration is located in
## Advanced notions
### Understand the Guards and Triggers
When you need to add the new guards and triggers to be hyperopt
parameters, you do this by adding them into the [hyperopt_space()](https://github.com/gcarq/freqtrade/blob/develop/user_data/strategies/test_strategy.py#L244-L297).
parameters, you do this by adding them into the [indicator_space()](https://github.com/gcarq/freqtrade/blob/develop/user_data/strategies/test_strategy.py#L251-L267).
If it's a trigger, you add one line to the 'trigger' choice group and that's it.

View File

@ -7,18 +7,14 @@ import os
import pickle
import signal
import sys
from functools import reduce
from math import exp
from operator import itemgetter
from typing import Dict, Any, Callable
from typing import Dict, Any
import numpy
import talib.abstract as ta
from hyperopt import STATUS_FAIL, STATUS_OK, Trials, fmin, hp, space_eval, tpe
from hyperopt import STATUS_FAIL, STATUS_OK, Trials, fmin, space_eval, tpe
from hyperopt.mongoexp import MongoTrials
from pandas import DataFrame
import freqtrade.vendor.qtpylib.indicators as qtpylib
# Monkey patch config
from freqtrade import main # noqa; noqa
from freqtrade import exchange, misc, optimize
@ -61,126 +57,6 @@ TRIALS = Trials()
main._CONF = OPTIMIZE_CONFIG
def populate_indicators(dataframe: DataFrame) -> DataFrame:
"""
Adds several different TA indicators to the given DataFrame
"""
dataframe['adx'] = ta.ADX(dataframe)
dataframe['ao'] = qtpylib.awesome_oscillator(dataframe)
dataframe['cci'] = ta.CCI(dataframe)
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
dataframe['mfi'] = ta.MFI(dataframe)
dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
dataframe['roc'] = ta.ROC(dataframe)
dataframe['rsi'] = ta.RSI(dataframe)
# Inverse Fisher transform on RSI, values [-1.0, 1.0] (https://goo.gl/2JGGoy)
rsi = 0.1 * (dataframe['rsi'] - 50)
dataframe['fisher_rsi'] = (numpy.exp(2 * rsi) - 1) / (numpy.exp(2 * rsi) + 1)
# Inverse Fisher transform on RSI normalized, value [0.0, 100.0] (https://goo.gl/2JGGoy)
dataframe['fisher_rsi_norma'] = 50 * (dataframe['fisher_rsi'] + 1)
# Stoch
stoch = ta.STOCH(dataframe)
dataframe['slowd'] = stoch['slowd']
dataframe['slowk'] = stoch['slowk']
# Stoch fast
stoch_fast = ta.STOCHF(dataframe)
dataframe['fastd'] = stoch_fast['fastd']
dataframe['fastk'] = stoch_fast['fastk']
# Stoch RSI
stoch_rsi = ta.STOCHRSI(dataframe)
dataframe['fastd_rsi'] = stoch_rsi['fastd']
dataframe['fastk_rsi'] = stoch_rsi['fastk']
# 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['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)
dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
# SAR Parabolic
dataframe['sar'] = ta.SAR(dataframe)
# SMA - Simple Moving Average
dataframe['sma'] = ta.SMA(dataframe, timeperiod=40)
# TEMA - Triple Exponential Moving Average
dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9)
# Hilbert Transform Indicator - SineWave
hilbert = ta.HT_SINE(dataframe)
dataframe['htsine'] = hilbert['sine']
dataframe['htleadsine'] = hilbert['leadsine']
# Pattern Recognition - Bullish candlestick patterns
# ------------------------------------
"""
# Hammer: values [0, 100]
dataframe['CDLHAMMER'] = ta.CDLHAMMER(dataframe)
# Inverted Hammer: values [0, 100]
dataframe['CDLINVERTEDHAMMER'] = ta.CDLINVERTEDHAMMER(dataframe)
# Dragonfly Doji: values [0, 100]
dataframe['CDLDRAGONFLYDOJI'] = ta.CDLDRAGONFLYDOJI(dataframe)
# Piercing Line: values [0, 100]
dataframe['CDLPIERCING'] = ta.CDLPIERCING(dataframe) # values [0, 100]
# Morningstar: values [0, 100]
dataframe['CDLMORNINGSTAR'] = ta.CDLMORNINGSTAR(dataframe) # values [0, 100]
# Three White Soldiers: values [0, 100]
dataframe['CDL3WHITESOLDIERS'] = ta.CDL3WHITESOLDIERS(dataframe) # values [0, 100]
"""
# Pattern Recognition - Bearish candlestick patterns
# ------------------------------------
"""
# Hanging Man: values [0, 100]
dataframe['CDLHANGINGMAN'] = ta.CDLHANGINGMAN(dataframe)
# Shooting Star: values [0, 100]
dataframe['CDLSHOOTINGSTAR'] = ta.CDLSHOOTINGSTAR(dataframe)
# Gravestone Doji: values [0, 100]
dataframe['CDLGRAVESTONEDOJI'] = ta.CDLGRAVESTONEDOJI(dataframe)
# Dark Cloud Cover: values [0, 100]
dataframe['CDLDARKCLOUDCOVER'] = ta.CDLDARKCLOUDCOVER(dataframe)
# Evening Doji Star: values [0, 100]
dataframe['CDLEVENINGDOJISTAR'] = ta.CDLEVENINGDOJISTAR(dataframe)
# Evening Star: values [0, 100]
dataframe['CDLEVENINGSTAR'] = ta.CDLEVENINGSTAR(dataframe)
"""
# Pattern Recognition - Bullish/Bearish candlestick patterns
# ------------------------------------
"""
# Three Line Strike: values [0, -100, 100]
dataframe['CDL3LINESTRIKE'] = ta.CDL3LINESTRIKE(dataframe)
# Spinning Top: values [0, -100, 100]
dataframe['CDLSPINNINGTOP'] = ta.CDLSPINNINGTOP(dataframe) # values [0, -100, 100]
# Engulfing: values [0, -100, 100]
dataframe['CDLENGULFING'] = ta.CDLENGULFING(dataframe) # values [0, -100, 100]
# Harami: values [0, -100, 100]
dataframe['CDLHARAMI'] = ta.CDLHARAMI(dataframe) # values [0, -100, 100]
# Three Outside Up/Down: values [0, -100, 100]
dataframe['CDL3OUTSIDE'] = ta.CDL3OUTSIDE(dataframe) # values [0, -100, 100]
# Three Inside Up/Down: values [0, -100, 100]
dataframe['CDL3INSIDE'] = ta.CDL3INSIDE(dataframe) # values [0, -100, 100]
"""
# 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
def save_trials(trials, trials_path=TRIALS_FILE):
"""Save hyperopt trials to file"""
logger.info('Saving Trials to \'{}\''.format(trials_path))
@ -235,188 +111,35 @@ def generate_roi_table(params) -> Dict[int, float]:
return roi_table
def roi_space() -> Dict[str, Any]:
return {
'roi_t1': hp.quniform('roi_t1', 10, 120, 20),
'roi_t2': hp.quniform('roi_t2', 10, 60, 15),
'roi_t3': hp.quniform('roi_t3', 10, 40, 10),
'roi_p1': hp.quniform('roi_p1', 0.01, 0.04, 0.01),
'roi_p2': hp.quniform('roi_p2', 0.01, 0.07, 0.01),
'roi_p3': hp.quniform('roi_p3', 0.01, 0.20, 0.01),
}
def stoploss_space() -> Dict[str, Any]:
return {
'stoploss': hp.quniform('stoploss', -0.5, -0.02, 0.02),
}
def indicator_space() -> Dict[str, Any]:
"""
Define your Hyperopt space for searching strategy parameters
"""
return {
'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', 10, 25, 5)}
]),
'fastd': hp.choice('fastd', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('fastd-value', 15, 45, 5)}
]),
'adx': hp.choice('adx', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('adx-value', 20, 50, 5)}
]),
'rsi': hp.choice('rsi', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('rsi-value', 20, 40, 5)}
]),
'uptrend_long_ema': hp.choice('uptrend_long_ema', [
{'enabled': False},
{'enabled': True}
]),
'uptrend_short_ema': hp.choice('uptrend_short_ema', [
{'enabled': False},
{'enabled': True}
]),
'over_sar': hp.choice('over_sar', [
{'enabled': False},
{'enabled': True}
]),
'green_candle': hp.choice('green_candle', [
{'enabled': False},
{'enabled': True}
]),
'uptrend_sma': hp.choice('uptrend_sma', [
{'enabled': False},
{'enabled': True}
]),
'trigger': hp.choice('trigger', [
{'type': 'lower_bb'},
{'type': 'lower_bb_tema'},
{'type': 'faststoch10'},
{'type': 'ao_cross_zero'},
{'type': 'ema3_cross_ema10'},
{'type': 'macd_cross_signal'},
{'type': 'sar_reversal'},
{'type': 'ht_sine'},
{'type': 'heiken_reversal_bull'},
{'type': 'di_cross'},
]),
}
def has_space(spaces, space):
if space in spaces or 'all' in spaces:
return True
return False
def hyperopt_space(selected_spaces: str) -> Dict[str, Any]:
def hyperopt_space(selected_spaces: str, strategy) -> Dict[str, Any]:
spaces = {}
if has_space(selected_spaces, 'buy'):
spaces = {**spaces, **indicator_space()}
spaces = {**spaces, **strategy.indicator_space()}
if has_space(selected_spaces, 'roi'):
spaces = {**spaces, **roi_space()}
spaces = {**spaces, **strategy.roi_space()}
if has_space(selected_spaces, 'stoploss'):
spaces = {**spaces, **stoploss_space()}
spaces = {**spaces, **strategy.stoploss_space()}
return spaces
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) -> DataFrame:
conditions = []
# GUARDS AND TRENDS
if 'uptrend_long_ema' in params and params['uptrend_long_ema']['enabled']:
conditions.append(dataframe['ema50'] > dataframe['ema100'])
if 'macd_below_zero' in params and params['macd_below_zero']['enabled']:
conditions.append(dataframe['macd'] < 0)
if 'uptrend_short_ema' in params and params['uptrend_short_ema']['enabled']:
conditions.append(dataframe['ema5'] > dataframe['ema10'])
if 'mfi' in params and params['mfi']['enabled']:
conditions.append(dataframe['mfi'] < params['mfi']['value'])
if 'fastd' in params and params['fastd']['enabled']:
conditions.append(dataframe['fastd'] < params['fastd']['value'])
if 'adx' in params and params['adx']['enabled']:
conditions.append(dataframe['adx'] > params['adx']['value'])
if 'rsi' in params and params['rsi']['enabled']:
conditions.append(dataframe['rsi'] < params['rsi']['value'])
if 'over_sar' in params and params['over_sar']['enabled']:
conditions.append(dataframe['close'] > dataframe['sar'])
if 'green_candle' in params and params['green_candle']['enabled']:
conditions.append(dataframe['close'] > dataframe['open'])
if 'uptrend_sma' in params and params['uptrend_sma']['enabled']:
prevsma = dataframe['sma'].shift(1)
conditions.append(dataframe['sma'] > prevsma)
# TRIGGERS
triggers = {
'lower_bb': (
dataframe['close'] < dataframe['bb_lowerband']
),
'lower_bb_tema': (
dataframe['tema'] < dataframe['bb_lowerband']
),
'faststoch10': (qtpylib.crossed_above(
dataframe['fastd'], 10.0
)),
'ao_cross_zero': (qtpylib.crossed_above(
dataframe['ao'], 0.0
)),
'ema3_cross_ema10': (qtpylib.crossed_above(
dataframe['ema3'], dataframe['ema10']
)),
'macd_cross_signal': (qtpylib.crossed_above(
dataframe['macd'], dataframe['macdsignal']
)),
'sar_reversal': (qtpylib.crossed_above(
dataframe['close'], dataframe['sar']
)),
'ht_sine': (qtpylib.crossed_above(
dataframe['htleadsine'], dataframe['htsine']
)),
'heiken_reversal_bull': (
(qtpylib.crossed_above(dataframe['ha_close'], dataframe['ha_open'])) &
(dataframe['ha_low'] == dataframe['ha_open'])
),
'di_cross': (qtpylib.crossed_above(
dataframe['plus_di'], dataframe['minus_di']
)),
}
conditions.append(triggers.get(params['trigger']['type']))
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy'] = 1
return dataframe
return populate_buy_trend
def generate_optimizer(args):
def generate_optimizer(args, strategy):
def optimizer(params):
global _CURRENT_TRIES
strategy = Strategy()
if has_space(args.spaces, 'roi'):
strategy.minimal_roi = generate_roi_table(params)
if has_space(args.spaces, 'buy'):
backtesting.populate_buy_trend = buy_strategy_generator(params)
backtesting.populate_buy_trend = strategy.buy_strategy_generator(params)
if has_space(args.spaces, 'stoploss'):
strategy.stoploss = params['stoploss']
results = backtest({'stake_amount': OPTIMIZE_CONFIG['stake_amount'],
'processed': PROCESSED,
'realistic': args.realistic_simulation,
@ -497,7 +220,7 @@ def start(args):
ticker_interval=strategy.ticker_interval,
timerange=timerange)
if has_space(args.spaces, 'buy'):
optimize.populate_indicators = populate_indicators
optimize.populate_indicators = strategy.populate_indicators
PROCESSED = optimize.tickerdata_to_dataframe(data)
if args.mongodb:
@ -521,8 +244,8 @@ def start(args):
try:
best_parameters = fmin(
fn=generate_optimizer(args),
space=hyperopt_space(args.spaces),
fn=generate_optimizer(args, strategy),
space=hyperopt_space(args.spaces, strategy),
algo=tpe.suggest,
max_evals=TOTAL_TRIES,
trials=TRIALS
@ -539,7 +262,7 @@ def start(args):
# Improve best parameter logging display
if best_parameters:
best_parameters = space_eval(
hyperopt_space(args.spaces),
hyperopt_space(args.spaces, strategy),
best_parameters
)

View File

@ -2,7 +2,10 @@
import talib.abstract as ta
from pandas import DataFrame
from typing import Dict, Any, Callable
import freqtrade.vendor.qtpylib.indicators as qtpylib
from hyperopt import hp
from functools import reduce
from freqtrade.strategy.interface import IStrategy
from freqtrade.indicator_helpers import fishers_inverse
@ -239,3 +242,150 @@ class DefaultStrategy(IStrategy):
),
'sell'] = 1
return dataframe
def indicator_space(self) -> Dict[str, Any]:
"""
Define your Hyperopt space for searching strategy parameters
"""
return {
'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', 10, 25, 5)}
]),
'fastd': hp.choice('fastd', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('fastd-value', 15, 45, 5)}
]),
'adx': hp.choice('adx', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('adx-value', 20, 50, 5)}
]),
'rsi': hp.choice('rsi', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('rsi-value', 20, 40, 5)}
]),
'uptrend_long_ema': hp.choice('uptrend_long_ema', [
{'enabled': False},
{'enabled': True}
]),
'uptrend_short_ema': hp.choice('uptrend_short_ema', [
{'enabled': False},
{'enabled': True}
]),
'over_sar': hp.choice('over_sar', [
{'enabled': False},
{'enabled': True}
]),
'green_candle': hp.choice('green_candle', [
{'enabled': False},
{'enabled': True}
]),
'uptrend_sma': hp.choice('uptrend_sma', [
{'enabled': False},
{'enabled': True}
]),
'trigger': hp.choice('trigger', [
{'type': 'lower_bb'},
{'type': 'lower_bb_tema'},
{'type': 'faststoch10'},
{'type': 'ao_cross_zero'},
{'type': 'ema3_cross_ema10'},
{'type': 'macd_cross_signal'},
{'type': 'sar_reversal'},
{'type': 'ht_sine'},
{'type': 'heiken_reversal_bull'},
{'type': 'di_cross'},
]),
}
def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable:
"""
Define the buy strategy parameters to be used by hyperopt
"""
def populate_buy_trend(dataframe: DataFrame) -> DataFrame:
conditions = []
# GUARDS AND TRENDS
if 'uptrend_long_ema' in params and params['uptrend_long_ema']['enabled']:
conditions.append(dataframe['ema50'] > dataframe['ema100'])
if 'macd_below_zero' in params and params['macd_below_zero']['enabled']:
conditions.append(dataframe['macd'] < 0)
if 'uptrend_short_ema' in params and params['uptrend_short_ema']['enabled']:
conditions.append(dataframe['ema5'] > dataframe['ema10'])
if 'mfi' in params and params['mfi']['enabled']:
conditions.append(dataframe['mfi'] < params['mfi']['value'])
if 'fastd' in params and params['fastd']['enabled']:
conditions.append(dataframe['fastd'] < params['fastd']['value'])
if 'adx' in params and params['adx']['enabled']:
conditions.append(dataframe['adx'] > params['adx']['value'])
if 'rsi' in params and params['rsi']['enabled']:
conditions.append(dataframe['rsi'] < params['rsi']['value'])
if 'over_sar' in params and params['over_sar']['enabled']:
conditions.append(dataframe['close'] > dataframe['sar'])
if 'green_candle' in params and params['green_candle']['enabled']:
conditions.append(dataframe['close'] > dataframe['open'])
if 'uptrend_sma' in params and params['uptrend_sma']['enabled']:
prevsma = dataframe['sma'].shift(1)
conditions.append(dataframe['sma'] > prevsma)
# TRIGGERS
triggers = {
'lower_bb': (
dataframe['close'] < dataframe['bb_lowerband']
),
'lower_bb_tema': (
dataframe['tema'] < dataframe['bb_lowerband']
),
'faststoch10': (qtpylib.crossed_above(
dataframe['fastd'], 10.0
)),
'ao_cross_zero': (qtpylib.crossed_above(
dataframe['ao'], 0.0
)),
'ema3_cross_ema10': (qtpylib.crossed_above(
dataframe['ema3'], dataframe['ema10']
)),
'macd_cross_signal': (qtpylib.crossed_above(
dataframe['macd'], dataframe['macdsignal']
)),
'sar_reversal': (qtpylib.crossed_above(
dataframe['close'], dataframe['sar']
)),
'ht_sine': (qtpylib.crossed_above(
dataframe['htleadsine'], dataframe['htsine']
)),
'heiken_reversal_bull': (
(qtpylib.crossed_above(dataframe['ha_close'], dataframe['ha_open'])) &
(dataframe['ha_low'] == dataframe['ha_open'])
),
'di_cross': (qtpylib.crossed_above(
dataframe['plus_di'], dataframe['minus_di']
)),
}
conditions.append(triggers.get(params['trigger']['type']))
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy'] = 1
return dataframe
return populate_buy_trend
def roi_space(self) -> Dict[str, Any]:
return {
'roi_t1': hp.quniform('roi_t1', 10, 120, 20),
'roi_t2': hp.quniform('roi_t2', 10, 60, 15),
'roi_t3': hp.quniform('roi_t3', 10, 40, 10),
'roi_p1': hp.quniform('roi_p1', 0.01, 0.04, 0.01),
'roi_p2': hp.quniform('roi_p2', 0.01, 0.07, 0.01),
'roi_p3': hp.quniform('roi_p3', 0.01, 0.20, 0.01),
}
def stoploss_space(self) -> Dict[str, Any]:
return {
'stoploss': hp.quniform('stoploss', -0.5, -0.02, 0.02),
}

View File

@ -8,6 +8,7 @@ import sys
import logging
import importlib
from collections import OrderedDict
from typing import Dict, Any, Callable
from pandas import DataFrame
from freqtrade.strategy.interface import IStrategy
@ -178,3 +179,21 @@ class Strategy(object):
:return: DataFrame with buy column
"""
return self.custom_strategy.populate_sell_trend(dataframe)
def indicator_space(self) -> Dict[str, Any]:
"""
Define your Hyperopt space for searching strategy parameters
"""
return self.custom_strategy.indicator_space()
def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable:
"""
Define the buy strategy parameters to be used by hyperopt
"""
return self.custom_strategy.buy_strategy_generator(params)
def roi_space(self) -> Dict[str, Any]:
return self.custom_strategy.roi_space()
def stoploss_space(self) -> Dict[str, Any]:
return self.custom_strategy.stoploss_space()

View File

@ -2,6 +2,9 @@
# --- Do not remove these libs ---
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
from typing import Dict, Any, Callable
from hyperopt import STATUS_FAIL, STATUS_OK, Trials, fmin, hp, space_eval, tpe
from functools import reduce
# --------------------------------
# Add your lib to import here
@ -244,3 +247,66 @@ class TestStrategy(IStrategy):
),
'sell'] = 1
return dataframe
def indicator_space(self) -> Dict[str, Any]:
"""
Define your Hyperopt space for searching strategy parameters
"""
return {
'adx': hp.choice('adx', [
{'enabled': False},
{'enabled': True, 'value': hp.quniform('adx-value', 50, 80, 5)}
]),
'uptrend_tema': hp.choice('uptrend_tema', [
{'enabled': False},
{'enabled': True}
]),
'trigger': hp.choice('trigger', [
{'type': 'middle_bb_tema'},
]),
}
def buy_strategy_generator(self, params: Dict[str, Any]) -> Callable:
"""
Define the buy strategy parameters to be used by hyperopt
"""
def populate_buy_trend(dataframe: DataFrame) -> DataFrame:
conditions = []
# GUARDS AND TRENDS
if 'adx' in params and params['adx']['enabled']:
conditions.append(dataframe['adx'] > params['adx']['value'])
if 'uptrend_tema' in params and params['uptrend_tema']['enabled']:
prevtema = dataframe['tema'].shift(1)
conditions.append(dataframe['tema'] > prevtema)
# TRIGGERS
triggers = {
'middle_bb_tema': (
dataframe['tema'] > dataframe['bb_middleband']
),
}
conditions.append(triggers.get(params['trigger']['type']))
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy'] = 1
return dataframe
return populate_buy_trend
def roi_space(self) -> Dict[str, Any]:
return {
'roi_t1': hp.quniform('roi_t1', 10, 120, 20),
'roi_t2': hp.quniform('roi_t2', 10, 60, 15),
'roi_t3': hp.quniform('roi_t3', 10, 40, 10),
'roi_p1': hp.quniform('roi_p1', 0.01, 0.04, 0.01),
'roi_p2': hp.quniform('roi_p2', 0.01, 0.07, 0.01),
'roi_p3': hp.quniform('roi_p3', 0.01, 0.20, 0.01),
}
def stoploss_space(self) -> Dict[str, Any]:
return {
'stoploss': hp.quniform('stoploss', -0.5, -0.02, 0.02),
}