import logging from freqtrade.strategy import IStrategy, informative from pandas import DataFrame import numpy as np import pandas as pd logger = logging.getLogger(__name__) class LabStrategy_005(IStrategy): """ Auto-generated by Strategy Lab. Combo: bb(20,3)+rsi(30,70)+adx(25)|btc_sma200|balanced """ INTERFACE_VERSION: int = 3 minimal_roi = { '0': 0.05, '360': 0.03, '720': 0.02, '1440': 0.01 } stoploss = -0.05 trailing_stop = True trailing_stop_positive = 0.02 trailing_stop_positive_offset = 0.03 trailing_only_offset_is_reached = True timeframe = '1h' process_only_new_candles = True use_exit_signal = False exit_profit_only = True exit_profit_offset = 0.01 startup_candle_count = 200 @informative('1h', 'BTC/{stake}') def populate_indicators_btc_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['sma200'] = dataframe['close'].rolling(200).mean() return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['rsi'] = _rsi(dataframe['close'], 14) bb_sma = dataframe['close'].rolling(20).mean() bb_std = dataframe['close'].rolling(20).std() dataframe['bb_lower'] = bb_sma - 3 * bb_std dataframe['adx'] = _adx(dataframe, 14) dataframe['btc_gate'] = ((dataframe['btc_usdt_close_1h'] > dataframe['btc_usdt_sma200_1h'])).astype(int) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ ( (dataframe['close'] > dataframe['bb_lower']) & (dataframe['close'].shift(1) <= dataframe['bb_lower'].shift(1)) & (dataframe['rsi'] >= 30) & (dataframe['rsi'] <= 70) & (dataframe['adx'] > 25) & (dataframe['btc_gate'] == 1) & (dataframe['volume'] > 0) ), 'enter_long'] = 1 return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # Exits handled by ROI, stoploss, and trailing stop return dataframe def _rsi(close, period=14): delta = close.diff() gain = delta.clip(lower=0) loss = (-delta).clip(lower=0) avg_gain = gain.ewm(alpha=1/period, min_periods=period).mean() avg_loss = loss.ewm(alpha=1/period, min_periods=period).mean() rs = avg_gain / (avg_loss + 1e-10) return 100 - (100 / (1 + rs)) def _adx(df, period=14): high, low, close = df['high'], df['low'], df['close'] plus_dm = high.diff() minus_dm = -low.diff() plus_dm = plus_dm.where((plus_dm > minus_dm) & (plus_dm > 0), 0.0) minus_dm = minus_dm.where((minus_dm > plus_dm) & (minus_dm > 0), 0.0) tr = pd.concat([high-low, (high-close.shift(1)).abs(), (low-close.shift(1)).abs()], axis=1).max(axis=1) atr = tr.rolling(period).mean() plus_di = 100 * (plus_dm.ewm(alpha=1/period, min_periods=period).mean() / (atr + 1e-10)) minus_di = 100 * (minus_dm.ewm(alpha=1/period, min_periods=period).mean() / (atr + 1e-10)) dx = 100 * (plus_di - minus_di).abs() / (plus_di + minus_di + 1e-10) return dx.ewm(alpha=1/period, min_periods=period).mean()