from freqtrade.strategy.interface import IStrategy from typing import Dict, List from functools import reduce from pandas import DataFrame, Series, DatetimeIndex, merge from datetime import datetime, timedelta import talib.abstract as ta import numpy as np import pandas_ta as pta from freqtrade.strategy import merge_informative_pair, CategoricalParameter, DecimalParameter, IntParameter, stoploss_from_open import freqtrade.vendor.qtpylib.indicators as qtpylib class KC_BB(IStrategy): """ author @jilv220 KC_BB Stra """ minimal_roi = { "0": 20.5 } stoploss = -0.99 use_custom_stoploss = True timeframe = '5m' def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: sl_new = 1 if (current_profit > 0.2): sl_new = 0.05 elif (current_profit > 0.1): sl_new = 0.03 elif (current_profit > 0.06): sl_new = 0.02 elif (current_profit > 0.03): sl_new = 0.015 return sl_new def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['trange'] = ta.TRANGE(dataframe) dataframe['sma_20'] = ta.SMA(dataframe, timeperiod=20) dataframe['sma_28'] = ta.SMA(dataframe, timeperiod=28) dataframe['range_ma_20'] = ta.SMA(dataframe['trange'], 20) dataframe['kc_upperband_20_2'] = dataframe['sma_20'] + dataframe['range_ma_20'] * 2 dataframe['kc_lowerband_20_2'] = dataframe['sma_20'] - dataframe['range_ma_20'] * 2 dataframe['range_ma_28'] = ta.SMA(dataframe['trange'], 28) dataframe['kc_upperband_28_1'] = dataframe['sma_28'] + dataframe['range_ma_28'] dataframe['kc_lowerband_28_1'] = dataframe['sma_28'] - dataframe['range_ma_28'] bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) dataframe['bb_lowerband2'] = bollinger2['lower'] dataframe['bb_middleband2'] = bollinger2['mid'] dataframe['bb_upperband2'] = bollinger2['upper'] dataframe['kc_bb_delta'] = ( dataframe['kc_lowerband_20_2'] - dataframe['bb_lowerband2'] ) / dataframe['bb_lowerband2'] * 100 heikinashi = qtpylib.heikinashi(dataframe) dataframe['ha_open'] = heikinashi['open'] dataframe['ha_close'] = heikinashi['close'] dataframe['ha_high'] = heikinashi['high'] dataframe['ha_low'] = heikinashi['low'] dataframe['ha_closedelta'] = (dataframe['ha_close'] - dataframe['ha_close'].shift()).abs() rsi = ta.RSI(dataframe) dataframe["rsi"] = rsi rsi = 0.1 * (rsi - 50) dataframe["fisher"] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1) dataframe['ema_fast'] = ta.EMA(dataframe['ha_close'], timeperiod=3) dataframe['r_14'] = williams_r(dataframe, period=14) return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ (dataframe['kc_lowerband_28_1'] < dataframe['bb_upperband2']) & (dataframe['kc_lowerband_28_1'] > dataframe['bb_lowerband2']) & (dataframe['kc_bb_delta'] < 1.5) & (dataframe['kc_bb_delta'] > 0.928) & (dataframe['r_14'] < -80) & (dataframe['r_14'] > -90) & (dataframe['ha_closedelta'] > dataframe['ha_close'] * 0.008) ,'buy'] = 1 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ (dataframe['fisher'] > 0.39075) & (dataframe['ha_high'].le(dataframe['ha_high'].shift(1))) & (dataframe['ha_high'].shift(1).le(dataframe['ha_high'].shift(2))) & (dataframe['ha_close'].le(dataframe['ha_close'].shift(1))) & (dataframe['ema_fast'] > dataframe['ha_close']) & (dataframe['ha_close'] * 0.99754 > dataframe['bb_middleband2']) & (dataframe['volume'] > 0) ,'sell'] = 1 return dataframe def williams_r(dataframe: DataFrame, period: int = 14) -> Series: """Williams %R, or just %R, is a technical analysis oscillator showing the current closing price in relation to the high and low of the past N days (for a given N). It was developed by a publisher and promoter of trading materials, Larry Williams. Its purpose is to tell whether a stock or commodity market is trading near the high or the low, or somewhere in between, of its recent trading range. The oscillator is on a negative scale, from −100 (lowest) up to 0 (highest). """ highest_high = dataframe["high"].rolling(center=False, window=period).max() lowest_low = dataframe["low"].rolling(center=False, window=period).min() WR = Series( (highest_high - dataframe["close"]) / (highest_high - lowest_low), name=f"{period} Williams %R", ) return WR * -100