EMA and Bollinger Band Rules for Avoiding Pump Conditions
Summary
This five-minute long-only strategy is presented as an attempt to avoid pump-and-dump conditions. It calculates short, medium, and long exponential moving averages, 20-period Bollinger Bands, and rolling price extremes. An entry is signaled when the close is below the short and medium averages, equals the medium-period low, and is at or below the lower band, while volume remains below a threshold based on the prior 30-bar average. The exit requires the close to exceed the short and medium averages, reach the medium-period high, and be at or above the upper band.
The configuration sets a 5% stop loss and a minimum return-on-investment threshold of 10% before selling, unless the exit conditions occur first. The long EMA is calculated but does not appear in the displayed entry or exit rules. The code supplies no backtest results, market universe, or evidence that the filters identify pump activity reliably. Its rules are a testable example, not demonstrated performance guidance.
Key ideas
- The strategy uses a five-minute timeframe and evaluates long entries using EMAs, Bollinger Bands, rolling lows, and volume.
- Entry requires price weakness relative to short and medium EMAs and a close at the medium-period low near or below the lower band.
- Exit requires strength relative to the short and medium EMAs, the medium-period high, and the upper Bollinger Band.
- The configuration specifies a 5% stop loss and a 10% minimum ROI threshold unless exit conditions occur sooner.
- The code provides no backtest evidence that its rules avoid pump-and-dump conditions.
Tags
Full text
# EMASkipPump.py
```py
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
import numpy # noqa
class EMASkipPump(IStrategy):
"""
basic strategy, which trys to avoid pump and dump market conditions. Shared from the tradingview
slack
"""
INTERFACE_VERSION: int = 3
EMA_SHORT_TERM = 5
EMA_MEDIUM_TERM = 12
EMA_LONG_TERM = 21
# Minimal ROI designed for the strategy.
# we only sell after 100%, unless our sell points are found before
minimal_roi = {
"0": 0.1
}
# Optimal stoploss designed for the strategy
# This attribute will be overridden if the config file contains "stoploss"
# should be converted to a trailing stop loss
stoploss = -0.05
# Optimal timeframe for the strategy
timeframe = '5m'
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
""" Adds several different TA indicators to the given DataFrame
"""
dataframe['ema_{}'.format(self.EMA_SHORT_TERM)] = ta.EMA(
dataframe, timeperiod=self.EMA_SHORT_TERM
)
dataframe['ema_{}'.format(self.EMA_MEDIUM_TERM)] = ta.EMA(
dataframe, timeperiod=self.EMA_MEDIUM_TERM
)
dataframe['ema_{}'.format(self.EMA_LONG_TERM)] = ta.EMA(
dataframe, timeperiod=self.EMA_LONG_TERM
)
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['min'] = ta.MIN(dataframe, timeperiod=self.EMA_MEDIUM_TERM)
dataframe['max'] = ta.MAX(dataframe, timeperiod=self.EMA_MEDIUM_TERM)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(dataframe['volume'] < (dataframe['volume'].rolling(window=30).mean().shift(1) * 20)) &
(dataframe['close'] < dataframe['ema_{}'.format(self.EMA_SHORT_TERM)]) &
(dataframe['close'] < dataframe['ema_{}'.format(self.EMA_MEDIUM_TERM)]) &
(dataframe['close'] == dataframe['min']) &
(dataframe['close'] <= dataframe['bb_lowerband']),
'enter_long'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(dataframe['close'] > dataframe['ema_{}'.format(self.EMA_SHORT_TERM)]) &
(dataframe['close'] > dataframe['ema_{}'.format(self.EMA_MEDIUM_TERM)]) &
(dataframe['close'] >= dataframe['max']) &
(dataframe['close'] >= dataframe['bb_upperband']),
'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.