Skip to content
All library documents

EMA Crossover Entries and Exits in a Freqtrade Strategy

Code Freqtrade

Summary

The document presents a basic long-only strategy that enters when a shorter exponential moving average crosses above a longer one and exits when the longer average crosses above the shorter. It calculates multiple EMA periods so the short and long lookbacks can be selected from parameter ranges. The strategy checks that volume is positive before setting either signal and uses a four-hour timeframe.

The configuration also specifies a minimum return-on-investment threshold and a stop-loss, though the document does not show how those settings were selected or evaluated. Its own description calls the strategy a proof of concept and says its performance is weak. No backtest results, assets, comparison strategy, or risk-adjusted metrics are supplied, so the crossover logic should not be taken as evidence of a profitable approach.

Key ideas

  • A long entry is signaled when the selected short EMA crosses above the selected long EMA.
  • A long exit is signaled when the selected long EMA crosses above the short EMA.
  • Both signals require positive volume, and the configured timeframe is four hours.
  • The EMA lookbacks are parameterized within defined short and long ranges.
  • The document labels the strategy a proof of concept and reports no supporting backtest results.

Tags

Full text
# AverageStrategy.py


```py
# --- Do not remove these libs ---
from functools import reduce
from freqtrade.strategy import IStrategy
from freqtrade.strategy import CategoricalParameter, DecimalParameter, IntParameter
from pandas import DataFrame
# --------------------------------

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


class AverageStrategy(IStrategy):
    """

    author@: Gert Wohlgemuth

    idea:
        buys and sells on crossovers - doesn't really perfom that well and its just a proof of concept
    """

    INTERFACE_VERSION: int = 3
    # Minimal ROI designed for the strategy.
    # This attribute will be overridden if the config file contains "minimal_roi"
    minimal_roi = {
        "0": 0.5
    }

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

    # Optimal timeframe for the strategy
    timeframe = '4h'

    buy_range_short = IntParameter(5, 20, default=8)
    buy_range_long = IntParameter(20, 120, default=21)

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        # Combine all ranges ... to avoid duplicate calculation
        for val in list(set(list(self.buy_range_short.range) + list(self.buy_range_long.range))):
            dataframe[f'ema{val}'] = ta.EMA(dataframe, timeperiod=val)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the buy signal for the given dataframe
        :param dataframe: DataFrame
        :return: DataFrame with buy column
        """
        dataframe.loc[
            (
                qtpylib.crossed_above(
                    dataframe[f'ema{self.buy_range_short.value}'],
                    dataframe[f'ema{self.buy_range_long.value}']
                ) &
                (dataframe['volume'] > 0)
            ),
            'enter_long'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the sell signal for the given dataframe
        :param dataframe: DataFrame
        :return: DataFrame with buy column
        """
        dataframe.loc[
            (
                qtpylib.crossed_above(
                    dataframe[f'ema{self.buy_range_long.value}'],
                    dataframe[f'ema{self.buy_range_short.value}']
                    ) &
                (dataframe['volume'] > 0)
            ),
            '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.