# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
from functools import reduce
import numpy as np
import pandas as pd
from datetime import datetime, timedelta, timezone
from pandas import DataFrame
from typing import Dict, Optional, Union, Tuple
from freqtrade.strategy import (
IStrategy,
Trade,
Order,
PairLocks,
informative,
BooleanParameter,
CategoricalParameter,
DecimalParameter,
IntParameter,
RealParameter,
timeframe_to_minutes,
timeframe_to_next_date,
timeframe_to_prev_date,
merge_informative_pair,
stoploss_from_absolute,
stoploss_from_open,
AnnotationType,
)
import talib.abstract as ta
from technical import qtpylib
class TrendRideStrategy(IStrategy):
"""
Trend Following — Enter on EMA crossover in direction of trend,
stay until trend reverses. No RSI exits — let trends run.
"""
INTERFACE_VERSION = 3
timeframe = "5m"
can_short: bool = False
minimal_roi = {}
stoploss = -0.05
trailing_stop = True
trailing_stop_positive = 0.02
trailing_stop_positive_offset = 0.04
trailing_only_offset_is_reached = True
process_only_new_candles = True
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
startup_candle_count: int = 300
# Hyperopt parameters
buy_ema_fast = IntParameter(5, 20, default=8, space="buy", optimize=True)
buy_ema_slow = IntParameter(20, 100, default=50, space="buy", optimize=True)
buy_volume_mult = RealParameter(0.5, 2.0, default=1.0, space="buy", optimize=True)
sell_trail_offset = RealParameter(0.01, 0.06, default=0.03, space="sell", optimize=True)
sell_trail_stop = RealParameter(0.01, 0.04, default=0.02, space="sell", optimize=True)
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['ema8'] = ta.EMA(dataframe, timeperiod=8)
dataframe['ema13'] = ta.EMA(dataframe, timeperiod=13)
dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
dataframe['ema200'] = ta.EMA(dataframe, timeperiod=200)
dataframe['rsi'] = ta.RSI(dataframe)
dataframe['adx'] = ta.ADX(dataframe)
dataframe['volume_mean'] = dataframe['volume'].rolling(20).mean()
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(qtpylib.crossed_above(dataframe['ema8'], dataframe['ema21'])) &
(dataframe['close'] > dataframe['ema200']) &
(dataframe['volume'] > dataframe['volume_mean'] * self.buy_volume_mult.value) &
(dataframe['adx'] > 15) &
(dataframe['volume'] > 0)
),
'enter_long'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(qtpylib.crossed_below(dataframe['ema8'], dataframe['ema21'])) &
(dataframe['volume'] > 0)
),
'exit_long'
] = 1
return dataframe