From a217a7c75d6af0aa47f898ad3ee59d5e1e705f4c Mon Sep 17 00:00:00 2001 From: caglarylmz Date: Thu, 12 May 2022 19:51:33 +0300 Subject: [PATCH 1/2] Add some strategies for binance futures --- .../strategies/futures/f_adx_sma_strategy.py | 130 +++++++++ .../strategies/futures/f_ott_strategy.py | 187 +++++++++++++ .../futures/f_reinforced_average.py | 144 ++++++++++ .../strategies/futures/f_sampleStrategy.py | 162 ++++++++++++ .../futures/f_supertrend_strategy.py | 249 ++++++++++++++++++ 5 files changed, 872 insertions(+) create mode 100644 user_data/strategies/futures/f_adx_sma_strategy.py create mode 100644 user_data/strategies/futures/f_ott_strategy.py create mode 100644 user_data/strategies/futures/f_reinforced_average.py create mode 100644 user_data/strategies/futures/f_sampleStrategy.py create mode 100644 user_data/strategies/futures/f_supertrend_strategy.py diff --git a/user_data/strategies/futures/f_adx_sma_strategy.py b/user_data/strategies/futures/f_adx_sma_strategy.py new file mode 100644 index 0000000..2dbc83a --- /dev/null +++ b/user_data/strategies/futures/f_adx_sma_strategy.py @@ -0,0 +1,130 @@ +# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement +# flake8: noqa: F401 +# isort: skip_file +# --- Do not remove these libs --- +from functools import reduce +import numpy as np # noqa +import pandas as pd # noqa +from pandas import DataFrame + +from freqtrade.strategy import ( + BooleanParameter, + CategoricalParameter, + DecimalParameter, + IStrategy, + IntParameter, +) + +# -------------------------------- +# Add your lib to import here +import talib.abstract as ta +import freqtrade.vendor.qtpylib.indicators as qtpylib + + +# This class is a sample. Feel free to customize it. +class FAdxSmaStrategy(IStrategy): + + INTERFACE_VERSION = 3 + timeframe = "1h" + # Minimal ROI designed for the strategy. + # This attribute will be overridden if the config file contains "minimal_roi". + minimal_roi = {"60": 0.075, "30": 0.1, "0": 0.05} + # minimal_roi = {"0": 1} + + stoploss = -0.05 + can_short = True + + # Trailing stoploss + trailing_stop = False + # trailing_only_offset_is_reached = False + # trailing_stop_positive = 0.01 + # trailing_stop_positive_offset = 0.0 # Disabled / not configured + + # Run "populate_indicators()" only for new candle. + process_only_new_candles = False + + # Number of candles the strategy requires before producing valid signals + startup_candle_count: int = 14 + + # Hyperoptable parameters + + # Define the guards spaces + pos_entry_adx = DecimalParameter(15, 40, decimals=1, default=30.0, space="buy") + pos_exit_adx = DecimalParameter(15, 40, decimals=1, default=30.0, space="sell") + + # Define the parameter spaces + adx_period = IntParameter(4, 24, default=14) + sma_short_period = IntParameter(4, 24, default=12) + sma_long_period = IntParameter(12, 175, default=48) + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + # Calculate all adx values + for val in self.adx_period.range: + dataframe[f"adx_{val}"] = ta.ADX(dataframe, timeperiod=val) + + # Calculate all sma_short values + for val in self.sma_short_period.range: + dataframe[f"sma_short_{val}"] = ta.SMA(dataframe, timeperiod=val) + + # Calculate all sma_long values + for val in self.sma_long_period.range: + dataframe[f"sma_long_{val}"] = ta.SMA(dataframe, timeperiod=val) + + return dataframe + + def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + conditions_long = [] + conditions_short = [] + + # GUARDS AND TRIGGERS + conditions_long.append( + dataframe[f"adx_{self.adx_period.value}"] > self.pos_entry_adx.value + ) + conditions_short.append( + dataframe[f"adx_{self.adx_period.value}"] > self.pos_entry_adx.value + ) + + conditions_long.append( + qtpylib.crossed_above( + dataframe[f"sma_short_{self.sma_short_period.value}"], + dataframe[f"sma_long_{self.sma_long_period.value}"], + ) + ) + conditions_short.append( + qtpylib.crossed_below( + dataframe[f"sma_short_{self.sma_short_period.value}"], + dataframe[f"sma_long_{self.sma_long_period.value}"], + ) + ) + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_long), + "enter_long", + ] = 1 + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_short), + "enter_short", + ] = 1 + + return dataframe + + def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + conditions_close = [] + conditions_close.append( + dataframe[f"adx_{self.adx_period.value}"] < self.pos_entry_adx.value + ) + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_close), + "exit_long", + ] = 1 + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_close), + "exit_short", + ] = 1 + + return dataframe diff --git a/user_data/strategies/futures/f_ott_strategy.py b/user_data/strategies/futures/f_ott_strategy.py new file mode 100644 index 0000000..02398ef --- /dev/null +++ b/user_data/strategies/futures/f_ott_strategy.py @@ -0,0 +1,187 @@ +import logging +from numpy.lib import math +from freqtrade.strategy.interface import IStrategy +from freqtrade.strategy.hyper import IntParameter +from pandas import DataFrame +import talib.abstract as ta +import numpy as np +import freqtrade.vendor.qtpylib.indicators as qtpylib + + + +class FOttStrategy(IStrategy): + # Buy params, Sell params, ROI, Stoploss and Trailing Stop are values generated by 'freqtrade hyperopt --strategy Supertrend --hyperopt-loss ShortTradeDurHyperOptLoss --timerange=20210101- --timeframe=1h --spaces all' + # It's encourage you find the values that better suites your needs and risk management strategies + + # ROI table: + minimal_roi = {"0": 0.1, "30": 0.75, "60": 0.05, "120": 0.025} + # minimal_roi = {"0": 1} + + # Stoploss: + stoploss = -0.265 + + # Trailing stop: + trailing_stop = True + trailing_stop_positive = 0.05 + trailing_stop_positive_offset = 0.1 + trailing_only_offset_is_reached = False + + timeframe = "1h" + + startup_candle_count = 18 + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe["ott"] = self.ott(dataframe)["OTT"] + dataframe["var"] = self.ott(dataframe)["VAR"] + dataframe["adx"] = ta.ADX(dataframe, timeperiod=14) + + return dataframe + + def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe.loc[ + (qtpylib.crossed_above(dataframe["var"], dataframe["ott"])), + "enter_long", + ] = 1 + + dataframe.loc[ + (qtpylib.crossed_below(dataframe["var"], dataframe["ott"])), + "enter_short", + ] = 1 + + return dataframe + + def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + dataframe.loc[ + ( + dataframe["adx"]>60 + ), + "exit_long", + ] = 1 + + dataframe.loc[ + ( + dataframe["adx"]>60 + ), + "exit_short", + ] = 1 + + return dataframe + + """ + Supertrend Indicator; adapted for freqtrade + from: https://github.com/freqtrade/freqtrade-strategies/issues/30 + """ + + def ott(self, dataframe: DataFrame): + df = dataframe.copy() + + pds = 2 + percent = 1.4 + alpha = 2 / (pds + 1) + + df["ud1"] = np.where( + df["close"] > df["close"].shift(1), (df["close"] - df["close"].shift()), 0 + ) + df["dd1"] = np.where( + df["close"] < df["close"].shift(1), (df["close"].shift() - df["close"]), 0 + ) + df["UD"] = df["ud1"].rolling(9).sum() + df["DD"] = df["dd1"].rolling(9).sum() + df["CMO"] = ((df["UD"] - df["DD"]) / (df["UD"] + df["DD"])).fillna(0).abs() + + # df['Var'] = talib.EMA(df['close'], timeperiod=5) + df["Var"] = 0.0 + for i in range(pds, len(df)): + df["Var"].iat[i] = (alpha * df["CMO"].iat[i] * df["close"].iat[i]) + ( + 1 - alpha * df["CMO"].iat[i] + ) * df["Var"].iat[i - 1] + + df["fark"] = df["Var"] * percent * 0.01 + df["newlongstop"] = df["Var"] - df["fark"] + df["newshortstop"] = df["Var"] + df["fark"] + df["longstop"] = 0.0 + df["shortstop"] = 999999999999999999 + # df['dir'] = 1 + for i in df["UD"]: + + def maxlongstop(): + df.loc[(df["newlongstop"] > df["longstop"].shift(1)), "longstop"] = df[ + "newlongstop" + ] + df.loc[(df["longstop"].shift(1) > df["newlongstop"]), "longstop"] = df[ + "longstop" + ].shift(1) + + return df["longstop"] + + def minshortstop(): + df.loc[ + (df["newshortstop"] < df["shortstop"].shift(1)), "shortstop" + ] = df["newshortstop"] + df.loc[ + (df["shortstop"].shift(1) < df["newshortstop"]), "shortstop" + ] = df["shortstop"].shift(1) + + return df["shortstop"] + + df["longstop"] = np.where( + ((df["Var"] > df["longstop"].shift(1))), + maxlongstop(), + df["newlongstop"], + ) + + df["shortstop"] = np.where( + ((df["Var"] < df["shortstop"].shift(1))), + minshortstop(), + df["newshortstop"], + ) + + # get xover + + df["xlongstop"] = np.where( + ( + (df["Var"].shift(1) > df["longstop"].shift(1)) + & (df["Var"] < df["longstop"].shift(1)) + ), + 1, + 0, + ) + + df["xshortstop"] = np.where( + ( + (df["Var"].shift(1) < df["shortstop"].shift(1)) + & (df["Var"] > df["shortstop"].shift(1)) + ), + 1, + 0, + ) + + df["trend"] = 0 + df["dir"] = 0 + for i in df["UD"]: + df["trend"] = np.where( + ((df["xshortstop"] == 1)), + 1, + (np.where((df["xlongstop"] == 1), -1, df["trend"].shift(1))), + ) + + df["dir"] = np.where( + ((df["xshortstop"] == 1)), + 1, + (np.where((df["xlongstop"] == 1), -1, df["dir"].shift(1).fillna(1))), + ) + + # get OTT + + df["MT"] = np.where(df["dir"] == 1, df["longstop"], df["shortstop"]) + df["OTT"] = np.where( + df["Var"] > df["MT"], + (df["MT"] * (200 + percent) / 200), + (df["MT"] * (200 - percent) / 200), + ) + df["OTT"] = df["OTT"].shift(2) + + return DataFrame(index=df.index, data={"OTT": df["OTT"], "VAR": df["Var"]}) + diff --git a/user_data/strategies/futures/f_reinforced_average.py b/user_data/strategies/futures/f_reinforced_average.py new file mode 100644 index 0000000..ede5d50 --- /dev/null +++ b/user_data/strategies/futures/f_reinforced_average.py @@ -0,0 +1,144 @@ +# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement +# flake8: noqa: F401 +# isort: skip_file +# --- Do not remove these libs --- +from functools import reduce +import numpy as np # noqa +import pandas as pd # noqa +from pandas import DataFrame + +from freqtrade.strategy import ( + BooleanParameter, + CategoricalParameter, + DecimalParameter, + IStrategy, + IntParameter, +) + +# -------------------------------- +# Add your lib to import here +import talib.abstract as ta +import freqtrade.vendor.qtpylib.indicators as qtpylib +from freqtrade.exchange import timeframe_to_minutes +from technical.util import resample_to_interval, resampled_merge + + +# This class is a sample. Feel free to customize it. +class FReinforcedStrategy(IStrategy): + + INTERFACE_VERSION = 3 + timeframe = "5m" + # Minimal ROI designed for the strategy. + # This attribute will be overridden if the config file contains "minimal_roi". + minimal_roi = {"60": 0.075, "30": 0.1, "0": 0.05} + # minimal_roi = {"0": 1} + + stoploss = -0.05 + can_short = True + + # Trailing stoploss + trailing_stop = False + # trailing_only_offset_is_reached = False + # trailing_stop_positive = 0.01 + # trailing_stop_positive_offset = 0.0 # Disabled / not configured + + # Run "populate_indicators()" only for new candle. + process_only_new_candles = False + + # Number of candles the strategy requires before producing valid signals + startup_candle_count: int = 14 + + # Hyperoptable parameters + + # Define the guards spaces + pos_entry_adx = DecimalParameter(15, 40, decimals=1, default=30.0, space="buy") + pos_exit_adx = DecimalParameter(15, 40, decimals=1, default=30.0, space="sell") + + # Define the parameter spaces + adx_period = IntParameter(4, 24, default=14) + ema_short_period = IntParameter(4, 24, default=8) + ema_long_period = IntParameter(12, 175, default=21) + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + # Calculate all adx values + for val in self.adx_period.range: + dataframe[f"adx_{val}"] = ta.ADX(dataframe, timeperiod=val) + + # Calculate all ema_short values + for val in self.ema_short_period.range: + dataframe[f"ema_short_{val}"] = ta.EMA(dataframe, timeperiod=val) + + # Calculate all ema_long values + for val in self.ema_long_period.range: + dataframe[f"ema_long_{val}"] = ta.EMA(dataframe, timeperiod=val) + + # required for graphing + bollinger = qtpylib.bollinger_bands(dataframe["close"], window=20, stds=2) + dataframe["bb_lowerband"] = bollinger["lower"] + dataframe["bb_upperband"] = bollinger["upper"] + dataframe["bb_middleband"] = bollinger["mid"] + + self.resample_interval = timeframe_to_minutes(self.timeframe) * 12 + dataframe_long = resample_to_interval(dataframe, self.resample_interval) + dataframe_long["sma"] = ta.SMA(dataframe_long, timeperiod=50, price="close") + dataframe = resampled_merge(dataframe, dataframe_long, fill_na=True) + + return dataframe + + def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + conditions_long = [] + conditions_short = [] + + # GUARDS AND TRIGGERS + conditions_long.append( + dataframe["close"] > dataframe[f"resample_{self.resample_interval}_sma"] + ) + + conditions_short.append( + dataframe["close"] < dataframe[f"resample_{self.resample_interval}_sma"] + ) + + conditions_long.append( + qtpylib.crossed_above( + dataframe[f"ema_short_{self.ema_short_period.value}"], + dataframe[f"ema_long_{self.ema_long_period.value}"], + ) + ) + conditions_short.append( + qtpylib.crossed_below( + dataframe[f"ema_short_{self.ema_short_period.value}"], + dataframe[f"ema_long_{self.ema_long_period.value}"], + ) + ) + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_long), + "enter_long", + ] = 1 + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_short), + "enter_short", + ] = 1 + + return dataframe + + def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + conditions_close = [] + conditions_close.append( + dataframe[f"adx_{self.adx_period.value}"] < self.pos_entry_adx.value + ) + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_close), + "exit_long", + ] = 1 + + dataframe.loc[ + reduce(lambda x, y: x & y, conditions_close), + "exit_short", + ] = 1 + + return dataframe diff --git a/user_data/strategies/futures/f_sampleStrategy.py b/user_data/strategies/futures/f_sampleStrategy.py new file mode 100644 index 0000000..fc2db48 --- /dev/null +++ b/user_data/strategies/futures/f_sampleStrategy.py @@ -0,0 +1,162 @@ +# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement +# flake8: noqa: F401 +# isort: skip_file +# --- Do not remove these libs --- +import numpy as np # noqa +import pandas as pd # noqa +from pandas import DataFrame + +from freqtrade.strategy import ( + BooleanParameter, + CategoricalParameter, + DecimalParameter, + IStrategy, + IntParameter, +) + +# -------------------------------- +# Add your lib to import here +import talib.abstract as ta +import freqtrade.vendor.qtpylib.indicators as qtpylib + + +# This class is a sample. Feel free to customize it. +class FSampleStrategy(IStrategy): + + INTERFACE_VERSION = 3 + timeframe = "1h" + # Minimal ROI designed for the strategy. + # This attribute will be overridden if the config file contains "minimal_roi". + # minimal_roi = {"60": 0.1, "30": 0.2, "0": 0.2} + minimal_roi = {"0": 1} + + stoploss = -0.05 + can_short = True + + # Trailing stoploss + trailing_stop = False + # trailing_only_offset_is_reached = False + # trailing_stop_positive = 0.01 + # trailing_stop_positive_offset = 0.0 # Disabled / not configured + + # Run "populate_indicators()" only for new candle. + process_only_new_candles = False + + # Number of candles the strategy requires before producing valid signals + startup_candle_count: int = 30 + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe["adx"] = ta.ADX(dataframe) + # RSI + dataframe["rsi"] = ta.RSI(dataframe) + + # Stochastic Fast + stoch_fast = ta.STOCHF(dataframe) + dataframe["fastd"] = stoch_fast["fastd"] + dataframe["fastk"] = stoch_fast["fastk"] + + # MACD + macd = ta.MACD(dataframe) + dataframe["macd"] = macd["macd"] + dataframe["macdsignal"] = macd["macdsignal"] + dataframe["macdhist"] = macd["macdhist"] + + # MFI + dataframe["mfi"] = ta.MFI(dataframe) + + # 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"] + dataframe["bb_percent"] = (dataframe["close"] - dataframe["bb_lowerband"]) / ( + dataframe["bb_upperband"] - dataframe["bb_lowerband"] + ) + dataframe["bb_width"] = ( + dataframe["bb_upperband"] - dataframe["bb_lowerband"] + ) / dataframe["bb_middleband"] + + # Parabolic SAR + dataframe["sar"] = ta.SAR(dataframe) + + # TEMA - Triple Exponential Moving Average + dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9) + + # Cycle Indicator + # ------------------------------------ + # Hilbert Transform Indicator - SineWave + hilbert = ta.HT_SINE(dataframe) + dataframe["htsine"] = hilbert["sine"] + dataframe["htleadsine"] = hilbert["leadsine"] + + return dataframe + + def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe.loc[ + ( + # Signal: RSI crosses above 30 + (qtpylib.crossed_above(dataframe["rsi"], 30)) + & (dataframe["tema"] <= dataframe["bb_middleband"]) + & ( # Guard: tema below BB middle + dataframe["tema"] > dataframe["tema"].shift(1) + ) + & ( # Guard: tema is raising + dataframe["volume"] > 0 + ) # Make sure Volume is not 0 + ), + "enter_long", + ] = 1 + + dataframe.loc[ + ( + # Signal: RSI crosses above 70 + (qtpylib.crossed_above(dataframe["rsi"], 70)) + & (dataframe["tema"] > dataframe["bb_middleband"]) + & ( # Guard: tema above BB middle + dataframe["tema"] < dataframe["tema"].shift(1) + ) + & ( # Guard: tema is falling + dataframe["volume"] > 0 + ) # Make sure Volume is not 0 + ), + "enter_short", + ] = 1 + + return dataframe + + def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + dataframe.loc[ + ( + # Signal: RSI crosses above 70 + (qtpylib.crossed_above(dataframe["rsi"], 70)) + & (dataframe["tema"] > dataframe["bb_middleband"]) + & ( # Guard: tema above BB middle + dataframe["tema"] < dataframe["tema"].shift(1) + ) + & ( # Guard: tema is falling + dataframe["volume"] > 0 + ) # Make sure Volume is not 0 + ), + "exit_long", + ] = 1 + + dataframe.loc[ + ( + # Signal: RSI crosses above 30 + (qtpylib.crossed_above(dataframe["rsi"], 30)) + & + # Guard: tema below BB middle + (dataframe["tema"] <= dataframe["bb_middleband"]) + & (dataframe["tema"] > dataframe["tema"].shift(1)) + & ( # Guard: tema is raising + dataframe["volume"] > 0 + ) # Make sure Volume is not 0 + ), + "exit_short", + ] = 1 + + return dataframe diff --git a/user_data/strategies/futures/f_supertrend_strategy.py b/user_data/strategies/futures/f_supertrend_strategy.py new file mode 100644 index 0000000..f4e2f3c --- /dev/null +++ b/user_data/strategies/futures/f_supertrend_strategy.py @@ -0,0 +1,249 @@ +""" +Supertrend strategy: +* Description: Generate a 3 supertrend indicators for 'buy' strategies & 3 supertrend indicators for 'sell' strategies + Buys if the 3 'buy' indicators are 'up' + Sells if the 3 'sell' indicators are 'down' +* Author: @juankysoriano (Juan Carlos Soriano) +* github: https://github.com/juankysoriano/ +*** NOTE: This Supertrend strategy is just one of many possible strategies using `Supertrend` as indicator. It should on any case used at your own risk. + It comes with at least a couple of caveats: + 1. The implementation for the `supertrend` indicator is based on the following discussion: https://github.com/freqtrade/freqtrade-strategies/issues/30 . Concretelly https://github.com/freqtrade/freqtrade-strategies/issues/30#issuecomment-853042401 + 2. The implementation for `supertrend` on this strategy is not validated; meaning this that is not proven to match the results by the paper where it was originally introduced or any other trusted academic resources +""" + +import logging +from numpy.lib import math +from freqtrade.strategy.interface import IStrategy +from freqtrade.strategy.hyper import IntParameter +from pandas import DataFrame +import talib.abstract as ta +import numpy as np + + +class FSupertrendStrategy(IStrategy): + # Buy params, Sell params, ROI, Stoploss and Trailing Stop are values generated by 'freqtrade hyperopt --strategy Supertrend --hyperopt-loss ShortTradeDurHyperOptLoss --timerange=20210101- --timeframe=1h --spaces all' + # It's encourage you find the values that better suites your needs and risk management strategies + + # Buy hyperspace params: + buy_params = { + "buy_m1": 4, + "buy_m2": 7, + "buy_m3": 1, + "buy_p1": 8, + "buy_p2": 9, + "buy_p3": 8, + } + + # Sell hyperspace params: + sell_params = { + "sell_m1": 1, + "sell_m2": 3, + "sell_m3": 6, + "sell_p1": 16, + "sell_p2": 18, + "sell_p3": 18, + } + + # ROI table: + minimal_roi = {"0": 0.1, "30": 0.75, "60": 0.05, "120": 0.025} + # minimal_roi = {"0": 1} + + # Stoploss: + stoploss = -0.265 + + # Trailing stop: + trailing_stop = True + trailing_stop_positive = 0.05 + trailing_stop_positive_offset = 0.1 + trailing_only_offset_is_reached = False + + timeframe = "1h" + + startup_candle_count = 18 + + buy_m1 = IntParameter(1, 7, default=1) + buy_m2 = IntParameter(1, 7, default=3) + buy_m3 = IntParameter(1, 7, default=4) + buy_p1 = IntParameter(7, 21, default=14) + buy_p2 = IntParameter(7, 21, default=10) + buy_p3 = IntParameter(7, 21, default=10) + + sell_m1 = IntParameter(1, 7, default=1) + sell_m2 = IntParameter(1, 7, default=3) + sell_m3 = IntParameter(1, 7, default=4) + sell_p1 = IntParameter(7, 21, default=14) + sell_p2 = IntParameter(7, 21, default=10) + sell_p3 = IntParameter(7, 21, default=10) + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + for multiplier in self.buy_m1.range: + for period in self.buy_p1.range: + dataframe[f"supertrend_1_buy_{multiplier}_{period}"] = self.supertrend( + dataframe, multiplier, period + )["STX"] + + for multiplier in self.buy_m2.range: + for period in self.buy_p2.range: + dataframe[f"supertrend_2_buy_{multiplier}_{period}"] = self.supertrend( + dataframe, multiplier, period + )["STX"] + + for multiplier in self.buy_m3.range: + for period in self.buy_p3.range: + dataframe[f"supertrend_3_buy_{multiplier}_{period}"] = self.supertrend( + dataframe, multiplier, period + )["STX"] + + for multiplier in self.sell_m1.range: + for period in self.sell_p1.range: + dataframe[f"supertrend_1_sell_{multiplier}_{period}"] = self.supertrend( + dataframe, multiplier, period + )["STX"] + + for multiplier in self.sell_m2.range: + for period in self.sell_p2.range: + dataframe[f"supertrend_2_sell_{multiplier}_{period}"] = self.supertrend( + dataframe, multiplier, period + )["STX"] + + for multiplier in self.sell_m3.range: + for period in self.sell_p3.range: + dataframe[f"supertrend_3_sell_{multiplier}_{period}"] = self.supertrend( + dataframe, multiplier, period + )["STX"] + + return dataframe + + def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + + dataframe.loc[ + ( + dataframe[f"supertrend_1_buy_{self.buy_m1.value}_{self.buy_p1.value}"] + == "up" + ) + & ( + dataframe[f"supertrend_2_buy_{self.buy_m2.value}_{self.buy_p2.value}"] + == "up" + ) + & ( + dataframe[f"supertrend_3_buy_{self.buy_m3.value}_{self.buy_p3.value}"] + == "up" + ) + & ( # The three indicators are 'up' for the current candle + dataframe["volume"] > 0 + ), + "enter_long", + ] = 1 + + dataframe.loc[ + ( + dataframe[ + f"supertrend_1_sell_{self.sell_m1.value}_{self.sell_p1.value}" + ] + == "down" + ) + & ( + dataframe[ + f"supertrend_2_sell_{self.sell_m2.value}_{self.sell_p2.value}" + ] + == "down" + ) + & ( + dataframe[ + f"supertrend_3_sell_{self.sell_m3.value}_{self.sell_p3.value}" + ] + == "down" + ) + & ( # The three indicators are 'down' for the current candle + dataframe["volume"] > 0 + ), + "enter_short", + ] = 1 + + return dataframe + + def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + dataframe.loc[ + ( + dataframe[ + f"supertrend_2_sell_{self.sell_m2.value}_{self.sell_p2.value}" + ] + == "down" + ), + "exit_long", + ] = 1 + + dataframe.loc[ + ( + dataframe[f"supertrend_2_buy_{self.buy_m2.value}_{self.buy_p2.value}"] + == "up" + ), + "exit_short", + ] = 1 + + return dataframe + + """ + Supertrend Indicator; adapted for freqtrade + from: https://github.com/freqtrade/freqtrade-strategies/issues/30 + """ + + def supertrend(self, dataframe: DataFrame, multiplier, period): + df = dataframe.copy() + + df["TR"] = ta.TRANGE(df) + df["ATR"] = ta.SMA(df["TR"], period) + + st = "ST_" + str(period) + "_" + str(multiplier) + stx = "STX_" + str(period) + "_" + str(multiplier) + + # Compute basic upper and lower bands + df["basic_ub"] = (df["high"] + df["low"]) / 2 + multiplier * df["ATR"] + df["basic_lb"] = (df["high"] + df["low"]) / 2 - multiplier * df["ATR"] + + # Compute final upper and lower bands + df["final_ub"] = 0.00 + df["final_lb"] = 0.00 + for i in range(period, len(df)): + df["final_ub"].iat[i] = ( + df["basic_ub"].iat[i] + if df["basic_ub"].iat[i] < df["final_ub"].iat[i - 1] + or df["close"].iat[i - 1] > df["final_ub"].iat[i - 1] + else df["final_ub"].iat[i - 1] + ) + df["final_lb"].iat[i] = ( + df["basic_lb"].iat[i] + if df["basic_lb"].iat[i] > df["final_lb"].iat[i - 1] + or df["close"].iat[i - 1] < df["final_lb"].iat[i - 1] + else df["final_lb"].iat[i - 1] + ) + + # Set the Supertrend value + df[st] = 0.00 + for i in range(period, len(df)): + df[st].iat[i] = ( + df["final_ub"].iat[i] + if df[st].iat[i - 1] == df["final_ub"].iat[i - 1] + and df["close"].iat[i] <= df["final_ub"].iat[i] + else df["final_lb"].iat[i] + if df[st].iat[i - 1] == df["final_ub"].iat[i - 1] + and df["close"].iat[i] > df["final_ub"].iat[i] + else df["final_lb"].iat[i] + if df[st].iat[i - 1] == df["final_lb"].iat[i - 1] + and df["close"].iat[i] >= df["final_lb"].iat[i] + else df["final_ub"].iat[i] + if df[st].iat[i - 1] == df["final_lb"].iat[i - 1] + and df["close"].iat[i] < df["final_lb"].iat[i] + else 0.00 + ) + # Mark the trend direction up/down + df[stx] = np.where( + (df[st] > 0.00), np.where((df["close"] < df[st]), "down", "up"), np.NaN + ) + + # Remove basic and final bands from the columns + df.drop(["basic_ub", "basic_lb", "final_ub", "final_lb"], inplace=True, axis=1) + + df.fillna(0, inplace=True) + + return DataFrame(index=df.index, data={"ST": df[st], "STX": df[stx]}) From 02a00323952ccefc930ccefd113cd9aeeb845518 Mon Sep 17 00:00:00 2001 From: caglarylmz Date: Thu, 12 May 2022 19:51:46 +0300 Subject: [PATCH 2/2] . --- user_data/strategies/futures/Readme.md | 188 ++++++++++++++++++ ...sampleStrategy.py => f_sample_strategy.py} | 0 2 files changed, 188 insertions(+) create mode 100644 user_data/strategies/futures/Readme.md rename user_data/strategies/futures/{f_sampleStrategy.py => f_sample_strategy.py} (100%) diff --git a/user_data/strategies/futures/Readme.md b/user_data/strategies/futures/Readme.md new file mode 100644 index 0000000..71978c9 --- /dev/null +++ b/user_data/strategies/futures/Readme.md @@ -0,0 +1,188 @@ +# all strategies are tested against this config. Tests only done on binance futures + +``` + +{ + "max_open_trades": -1, + "stake_currency": "USDT", + "stake_amount": 100, + "tradable_balance_ratio": 0.99, + "fiat_display_currency": "USD", + "dry_run": true, + "cancel_open_orders_on_exit": false, + "trading_mode": "futures", + "margin_mode": "isolated", + "unfilledtimeout": { + "entry": 10, + "exit": 10, + "exit_timeout_count": 0, + "unit": "minutes" + }, + "entry_pricing": { + "price_side": "same", + "use_order_book": true, + "order_book_top": 1, + "price_last_balance": 0.0, + "check_depth_of_market": { + "enabled": false, + "bids_to_ask_delta": 1 + } + }, + "exit_pricing": { + "price_side": "same", + "use_order_book": true, + "order_book_top": 1 + }, + "exchange": { + "name": "binance", + "key": "", + "secret": "", + "ccxt_config": {}, + "ccxt_async_config": {}, + "pair_whitelist": [ + "AUDIO/USDT", + "AAVE/USDT", + "ALICE/USDT", + "ARPA/USDT", + "AVAX/USDT", + "ATOM/USDT", + "ANKR/USDT", + "AXS/USDT", + "ADA/USDT", + "ALGO/USDT", + "BTS/USDT", + "BAND/USDT", + "BEL/USDT", + "BNB/USDT", + "BTC/USDT", + "BLZ/USDT", + "BAT/USDT", + "CHR/USDT", + "C98/USDT", + "COTI/USDT", + "CHZ/USDT", + "COMP/USDT", + "CRV/USDT", + "CELO/USDT", + "DUSK/USDT", + "DOGE/USDT", + "DENT/USDT", + "DASH/USDT", + "DOT/USDT", + "DYDX/USDT", + "ENJ/USDT", + "EOS/USDT", + "ETH/USDT", + "ETC/USDT", + "ENS/USDT", + "EGLD/USDT", + "FIL/USDT", + "FTM/USDT", + "FLM/USDT", + "GRT/USDT", + "GALA/USDT", + "HBAR/USDT", + "HOT/USDT", + "IOTX/USDT", + "ICX/USDT", + "ICP/USDT", + "IOTA/USDT", + "IOST/USDT", + "KLAY/USDT", + "KAVA/USDT", + "KNC/USDT", + "KSM/USDT", + "LUNA/USDT", + "LRC/USDT", + "LINA/USDT", + "LTC/USDT", + "LINK/USDT", + "MATIC/USDT", + "NEAR/USDT", + "MANA/USDT", + "MTL/USDT", + "NEO/USDT", + "ONT/USDT", + "OMG/USDT", + "OCEAN/USDT", + "OGN/USDT", + "ONE/USDT", + "PEOPLE/USDT", + "RLC/USDT", + "RUNE/USDT", + "RVN/USDT", + "RSR/USDT", + "REEF/USDT", + "ROSE/USDT", + "SNX/USDT", + "SAND/USDT", + "SOL/USDT", + "SUSHI/USDT", + "SRM/USDT", + "SKL/USDT", + "SXP/USDT", + "STORJ/USDT", + "TRX/USDT", + "TOMO/USDT", + "TRB/USDT", + "TLM/USDT", + "THETA/USDT", + "UNI/USDT", + "UNFI/USDT", + "VET/USDT", + "YFI/USDT", + "ZIL/USDT", + "ZEN/USDT", + "ZRX/USDT", + "ZEC/USDT", + "WAVES/USDT", + "XRP/USDT", + "XLM/USDT", + "XTZ/USDT", + "XMR/USDT", + "XEM/USDT", + "QTUM/USDT", + "1INCH/USDT" + ], + "pair_blacklist": ["BNB/.*"] + }, + "pairlists": [{ "method": "StaticPairList" }], + "edge": { + "enabled": false, + "process_throttle_secs": 3600, + "calculate_since_number_of_days": 7, + "allowed_risk": 0.01, + "stoploss_range_min": -0.01, + "stoploss_range_max": -0.1, + "stoploss_range_step": -0.01, + "minimum_winrate": 0.6, + "minimum_expectancy": 0.2, + "min_trade_number": 10, + "max_trade_duration_minute": 1440, + "remove_pumps": false + }, + "telegram": { + "enabled": true, + "token": "", + "chat_id": "" + }, + "api_server": { + "enabled": true, + "listen_ip_address": "0.0.0.0", + "listen_port": 8080, + "verbosity": "error", + "enable_openapi": false, + "jwt_secret_key": "556ebba5770ae3a07e80eda0f0f2b55df102896f8a5b86459c3433c1314345c4", + "CORS_origins": [], + "username": "", + "password": "" + }, + "bot_name": "", + "initial_state": "running", + "force_entry_enable": false, + "internals": { + "process_throttle_secs": 5 + } +} + +``` diff --git a/user_data/strategies/futures/f_sampleStrategy.py b/user_data/strategies/futures/f_sample_strategy.py similarity index 100% rename from user_data/strategies/futures/f_sampleStrategy.py rename to user_data/strategies/futures/f_sample_strategy.py