Files
freqtrade-strategies/user_data/hyperopts/HO-Strategy005.py
T
2021-03-29 06:59:35 +02:00

169 lines
5.9 KiB
Python

# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
import talib.abstract as ta
import numpy as np
import freqtrade.vendor.qtpylib.indicators as qtpylib
from pandas import DataFrame
from typing import Dict, Any, Callable, List
from functools import reduce
from skopt.space import Categorical, Dimension, Integer, Real
from freqtrade.optimize.hyperopt_interface import IHyperOpt
__author__ = "Kevin Ossenbrueck"
__github__ = "github.com/OtenMoten"
__linkedin__ = "linkedin.com/in/kevin-ossenbrueck/?locale=en_US"
__twitter__ = "twitter.com/ossenbrueck"
__instagram__ = "instagram.com/kevin_ossenbrueck"
__facebook__ = "facebook.com/kevin.ossenbrueck"
__creator__ = ["github.com/xmatthias", "github.com/mishaker"]
__credits__ = ["MontrealTradingGroup", "Udemy", "Mohsen Hassan", "Ilyass Tabiai"]
__version__ = "3.0"
__copyright__ = "GNU GPL"
__status__ = "Live"
"""
I was inspired by: https://github.com/freqtrade/freqtrade-strategies/blob/master/user_data/strategies/Strategy005.py
Therefore, I wrote this hyperopt to make it more better. Thank you xmatthias and mishaker!
"""
# Rolling volume range
volumeAvgValueMin = 50
volumeAvgValueMax = 300
# RSI range
rsiValueMin = 1
rsiValueMax = 100
# STOCH FAST range
fastdValueMin = 1
fastdValueMax = 100
# MINUS DI range
minusdiValueMin = 1
minusdiValueMax = 100
fishRsiNormaValueMin = 1
fishRsiNormaValueMax = 100
class HODobby(IHyperOpt):
"""
Hyperopt file for Strategy005
"""
############### THIS STRATEGY IS DESIGNED FOR 5m TIMEFRAME ###############
@staticmethod
def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame:
# MACD
# tadoc.org/indicator/MACD.htm
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd']
# MINUS DI
# tadoc.org/indicator/MINUS_DI.htm
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
# RSI
# tadoc.org/indicator/RSI.htm
# tradingview.com/scripts/fishertransform/
# goo.gl/2JGGoy
dataframe['rsi'] = ta.RSI(dataframe)
rsi = 0.1 * (dataframe['rsi'] - 50)
dataframe['fisher_rsi'] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1) # Inverse Fisher transform on RSI, values [-1.0, 1.0]
dataframe['fisher_rsi_norma'] = 50 * (dataframe['fisher_rsi'] + 1) # Inverse Fisher transform on RSI normalized, value [0.0, 100.0]
# STOCH FAST
# tadoc.org/indicator/STOCHF.htm
stoch_fast = ta.STOCHF(dataframe)
dataframe['fastd'] = stoch_fast['fastd']
dataframe['fastk'] = stoch_fast['fastk']
# SAR
dataframe['sar'] = ta.SAR(dataframe)
# SMA
dataframe['sma'] = ta.SMA(dataframe, timeperiod=50)
return dataframe
@staticmethod
def buy_strategy_generator(params: Dict[str, Any]) -> Callable:
def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
# TRIGGER and GUARD
if 'buy-trigger' in params:
conditions.append(dataframe['close'] > 0.00000200)
conditions.append(dataframe['volume'] > dataframe['volume'].rolling(params['volumeAVG-buy-value']).mean())
conditions.append(dataframe['close'] < dataframe['sma'])
conditions.append(dataframe['rsi'] > params['rsi-buy-value'])
conditions.append(dataframe['fastd'] > dataframe['fastk'])
conditions.append(dataframe['fastd'] > params['fastd-buy-value'])
conditions.append(dataframe['fisher_rsi_norma'] < params['fishRsiNorma-buy-value'])
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 = ["True"]
return [
Integer(volumeAvgValueMin, volumeAvgValueMax, name='volumeAVG-buy-value'),
Integer(rsiValueMin, rsiValueMax, name='rsi-buy-value'),
Integer(fastdValueMin, fastdValueMax, name='fastd-buy-value'),
Integer(fishRsiNormaValueMin, fishRsiNormaValueMax, name='fishRsiNorma-buy-value'),
Categorical(buyTriggerList, name='buy-trigger')
]
@staticmethod
def sell_strategy_generator(params: Dict[str, Any]) -> Callable:
def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
# TRIGGERS and GUARDS
# Solving a mistery: Which sell trigger is better?
# The winner of both will be displayed in the output of the hyperopt.
conditions = []
if 'sell-trigger' in params:
if params['sell-trigger'] == 'rsi-macd-minusdi':
conditions.append(qtpylib.crossed_above(dataframe['rsi'], params['rsi-sell-value']))
conditions.append(dataframe['macd'] < 0)
conditions.append(dataframe['minus_di'] > params['minusdi-sell-value'])
if 'sell-trigger' in params:
if params['sell-trigger'] == 'sar-fisherRsi':
conditions.append(dataframe['sar'] > dataframe['close'])
conditions.append(dataframe['fisher_rsi'] > params['fishRsiNorma-sell-value'])
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 = ["rsi-macd-minusdi", "sar-fisherRsi"]
return [
Integer(rsiValueMin, rsiValueMax, name='rsi-sell-value'),
Integer(minusdiValueMin, minusdiValueMax, name='minusdi-sell-value'),
Integer(fishRsiNormaValueMin, fishRsiNormaValueMax, name='fishRsiNorma-sell-value'),
Categorical(sellTriggerList, name='sell-trigger')
]