Skip to content
All library documents

Multi-Supertrend Entries with Directional Exits

Article Strategy library · Author: @juankysoriano (Juan Carlos Soriano)

Summary

This strategy combines three Supertrend direction signals for long entries and a separate set of three for short entries. It opens a long position when all selected buy indicators are up, and opens a short position when all selected sell indicators are down; both conditions also require nonzero volume. The indicator sets use independently tunable multipliers and periods, with separate entry settings for each direction.

Exits use only the second sell-side Supertrend for closing longs and the second buy-side Supertrend for closing shorts. The document also specifies a one-hour timeframe, optimized example parameters, a return-on-investment schedule, a stop loss, and trailing-stop settings. These are configuration examples rather than evidence of trading performance. The author cautions that the Supertrend implementation has not been validated against the original paper or another trusted reference, and the strategy should be independently tested with suitable risk controls.

Key ideas

  • Long entries require all three selected buy Supertrend signals to indicate an up direction, with volume present.
  • Short entries require all three selected sell Supertrend signals to indicate a down direction, with volume present.
  • Long and short exits each rely on a single Supertrend signal from the opposite-side parameter set.
  • The strategy provides example stop, target, and trailing-stop settings, but no performance evidence.
  • The author states that the indicator implementation has not been validated against a trusted reference.

Tags

Full text
# FSupertrendStrategy


# FSupertrendStrategy









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

## Source (GPL-3.0)

```python
"""
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 freqtrade.strategy import IStrategy, IntParameter
from pandas import DataFrame
import pandas as pd
import talib.abstract as ta
import numpy as np

import technical.indicators as ftt


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

    INTERFACE_VERSION: int = 3
    # 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:
        new_cols = []

        for multiplier in self.buy_m1.range:
            for period in self.buy_p1.range:
                new_cols.append(
                    self.supertrend_direction(
                        dataframe,
                        multiplier,
                        period,
                        f"supertrend_1_buy_{multiplier}_{period}",
                    )
                )

        for multiplier in self.buy_m2.range:
            for period in self.buy_p2.range:
                new_cols.append(
                    self.supertrend_direction(
                        dataframe,
                        multiplier,
                        period,
                        f"supertrend_2_buy_{multiplier}_{period}",
                    )
                )

        for multiplier in self.buy_m3.range:
            for period in self.buy_p3.range:
                new_cols.append(
                    self.supertrend_direction(
                        dataframe,
                        multiplier,
                        period,
                        f"supertrend_3_buy_{multiplier}_{period}",
                    )
                )

        for multiplier in self.sell_m1.range:
            for period in self.sell_p1.range:
                new_cols.append(
                    self.supertrend_direction(
                        dataframe,
                        multiplier,
                        period,
                        f"supertrend_1_sell_{multiplier}_{period}",
                    )
                )

        for multiplier in self.sell_m2.range:
            for period in self.sell_p2.range:
                new_cols.append(
                    self.supertrend_direction(
                        dataframe,
                        multiplier,
                        period,
                        f"supertrend_2_sell_{multiplier}_{period}",
                    )
                )

        for multiplier in self.sell_m3.range:
            for period in self.sell_p3.range:
                new_cols.append(
                    self.supertrend_direction(
                        dataframe,
                        multiplier,
                        period,
                        f"supertrend_3_sell_{multiplier}_{period}",
                    )
                )

        if new_cols:
            dataframe = pd.concat([dataframe] + new_cols, axis=1)

        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

    def supertrend_direction(
        self, dataframe: DataFrame, multiplier: int, period: int, name: str
    ) -> pd.Series:
        """
        Supertrend direction ('up' / 'down') as a named series.
        `ftt.supertrend` returns a (value, direction) tuple - only the direction is used here.
        """
        _, stx = ftt.supertrend(dataframe, period=period, multiplier=multiplier)
        # 'stx' is None before the indicator has warmed up - keep the empty string
        return pd.Series(stx, index=dataframe.index, name=name).fillna("")

```

Shown in full with attribution under the source's licence. Licence: GPL-3.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.