EMASkipPump
Tested 1 Jun 2023 – 30 May 2025
Rank 26 of 27 by return
EMASkipPump turned $1,000 into $199 (−80.1%) over 729 days, while holding Bitcoin returned +288.1% and an equal mix of the ten coins +194.8%. Its worst drawdown was a severe 80.2%, deep enough that most people would have switched it off. With a 48% win rate and a profit factor of 0.42, losses outweighed gains. Once the balance fell below the $200 stake, it could no longer open trades and stopped.
How EMASkipPump trades
EMASkipPump buys when price makes a 12-candle low below both short EMAs and the lower Bollinger Band, but skips candles with a volume spike (a likely pump or dump). It sells on the opposite setup: a 12-candle high above the upper band.
The volume filter is the idea in the name. A 5% stoploss and a 10% take-profit frame each trade.
Rules at a glance
- Indicators
- EMA 5 / 12 / 21, Bollinger Bands, Rolling min / max
- Take-profit (minimal ROI)
- 10% from entry
- Stoploss
- −5%
- Trailing stop
- Off
- Exit signal
- Used
Results by month
Profit or loss in USDT for trades closed in each month.
Results by coin
| Pair | Trades | Win rate | Profit (USDT) | Avg. hold |
|---|---|---|---|---|
| DOGE/USDT | 133 | 59.4% | −44.85 | 2h 51m |
| BTC/USDT | 187 | 40.6% | −50.00 | 3h 11m |
| ETH/USDT | 157 | 45.9% | −52.87 | 3h 4m |
| DOT/USDT | 104 | 48.1% | −56.93 | 3h 1m |
| AVAX/USDT | 116 | 45.7% | −77.17 | 3h 1m |
| XRP/USDT | 210 | 49.5% | −95.15 | 3h 2m |
| BNB/USDT | 181 | 38.1% | −99.19 | 3h 3m |
| LINK/USDT | 140 | 49.3% | −102.04 | 3h 9m |
| ADA/USDT | 152 | 45.4% | −110.37 | 2h 55m |
| SOL/USDT | 182 | 55.5% | −112.36 | 3h 4m |
Why trades closed
| Exit reason | Trades | Win rate | Profit (USDT) |
|---|---|---|---|
| Exit signal | 1506 | 49.3% | −221.03 |
| Stoploss | 56 | 0.0% | −579.90 |
The code
EMASkipPump comes from the community freqtrade-strategies repository (GPL-3.0). These are the parts that decide when it trades; the full file is 86 lines.
Entry rules
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
Exit rules
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
Indicators
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> 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
Reproduce this test
With freqtrade installed (see our Docker guide), download the data and run the same backtest:
freqtrade download-data --exchange binance --pairs ADA/USDT AVAX/USDT BNB/USDT BTC/USDT DOGE/USDT DOT/USDT ETH/USDT LINK/USDT SOL/USDT XRP/USDT --timeframes 5m --timerange 20230501-20250530
freqtrade backtesting --strategy EMASkipPump --timeframe 5m \
--timerange 20230601-20250530 --dry-run-wallet 1000 --stake-amount 200 --max-open-trades 5 --fee 0.001
Results can differ slightly with a different data source or freqtrade version. See how we test.