Skip to content
All library documents

A Five-Minute MACD and Bollinger Band Long Strategy

Code Freqtrade

Summary

This Freqtrade strategy defines long entries on a five-minute chart using MACD, RSI, and Bollinger Bands. It requires MACD to be above zero and its signal line, the upper Bollinger Band to be rising, and RSI to exceed 70. Long exits are triggered when RSI exceeds 80. The code also sets a 1% minimal return-on-investment threshold and a 25% stop loss, though configuration settings can override these values.

The strategy calculates RSI with a seven-period setting and Bollinger Bands over a twelve-bar window at two standard deviations. The source labels the RSI entry filter as optional and in need of investigation, and offers no backtest results, market-specific validation, or rationale for the threshold choices. The exit rule is separate from the entry logic, so the document describes implementation rules rather than demonstrating that the system is profitable or robust across assets and market regimes.

Key ideas

  • Long entries require positive MACD above its signal line and a rising upper Bollinger Band.
  • The entry also requires RSI above 70, while an RSI reading above 80 triggers an exit.
  • The strategy uses a five-minute timeframe with a 1% return threshold and a 25% stop loss by default.
  • The RSI entry filter is identified as needing investigation, and no backtest evidence is supplied.

Tags

Full text
# Simple.py


```py
# --- Do not remove these libs ---
from freqtrade.strategy import IStrategy
from typing import Dict, List
from functools import reduce
from pandas import DataFrame
# --------------------------------

import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib


class Simple(IStrategy):
    """

    author@: Gert Wohlgemuth

    idea:
        this strategy is based on the book, 'The Simple Strategy' and can be found in detail here:

        https://www.amazon.com/Simple-Strategy-Powerful-Trading-Futures-ebook/dp/B00E66QPCG/ref=sr_1_1?ie=UTF8&qid=1525202675&sr=8-1&keywords=the+simple+strategy
    """

    INTERFACE_VERSION: int = 3
    # Minimal ROI designed for the strategy.
    # adjust based on market conditions. We would recommend to keep it low for quick turn arounds
    # This attribute will be overridden if the config file contains "minimal_roi"
    minimal_roi = {
        "0": 0.01
    }

    # Optimal stoploss designed for the strategy
    # This attribute will be overridden if the config file contains "stoploss"
    stoploss = -0.25

    # Optimal timeframe for the strategy
    timeframe = '5m'

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # MACD
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']

        # RSI
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=7)

        # required for graphing
        bollinger = qtpylib.bollinger_bands(dataframe['close'], window=12, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_upperband'] = bollinger['upper']
        dataframe['bb_middleband'] = bollinger['mid']

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (
                        (dataframe['macd'] > 0)  # over 0
                        & (dataframe['macd'] > dataframe['macdsignal'])  # over signal
                        & (dataframe['bb_upperband'] > dataframe['bb_upperband'].shift(1))  # pointed up
                        & (dataframe['rsi'] > 70)  # optional filter, need to investigate
                )
            ),
            'enter_long'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # different strategy used for sell points, due to be able to duplicate it to 100%
        dataframe.loc[
            (
                (dataframe['rsi'] > 80)
            ),
            'exit_long'] = 1
        return dataframe

```

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.