Aggressive Scalper - PROFIT MAXIMIZATION FOCUS - Fast entries/exits - Multiple confirmation (but relaxed) - High trading frequency
Timeframe
5m
Direction
Long Only
Stoploss
-2.0%
Trailing Stop
Yes
ROI
0m: 1.0%, 10m: 0.8%, 30m: 0.5%, 60m: 0.0%
Interface Version
3
Startup Candles
50
Indicators
7
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
from freqtrade.strategy import IStrategy, merge_informative_pair
from pandas import DataFrame
import numpy as np
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
class AggressiveScalper(IStrategy):
"""
Aggressive Scalper - PROFIT MAXIMIZATION FOCUS
- Fast entries/exits
- Multiple confirmation (but relaxed)
- High trading frequency
"""
INTERFACE_VERSION = 3
timeframe = '5m'
startup_candle_count = 50
# Quick profit targets
minimal_roi = {
"0": 0.01, # 1% immediate
"10": 0.008, # 0.8% after 10 min
"30": 0.005, # 0.5% after 30 min
"60": 0 # Break even
}
stoploss = -0.02
trailing_stop = True
trailing_stop_positive = 0.005
trailing_stop_positive_offset = 0.01
trailing_only_offset_is_reached = True
def informative_pairs(self):
whitelist = []
if self.dp:
whitelist = self.dp.current_whitelist()
if not whitelist:
whitelist = self.config.get('exchange', {}).get('pair_whitelist', [])
return [(pair, '1h') for pair in whitelist]
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# === RSI ===
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=7)
# === EMA ===
dataframe['ema_9'] = ta.EMA(dataframe, timeperiod=9)
dataframe['ema_21'] = ta.EMA(dataframe, timeperiod=21)
dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50)
# === MACD ===
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
# === Bollinger Bands ===
bollinger = ta.BBANDS(dataframe, timeperiod=20, nbdevup=2.0, nbdevdn=2.0)
dataframe['bb_lower'] = bollinger['lowerband']
dataframe['bb_middle'] = bollinger['middleband']
dataframe['bb_upper'] = bollinger['upperband']
# === Stochastic ===
stoch = ta.STOCH(dataframe)
dataframe['stoch_k'] = stoch['slowk']
dataframe['stoch_d'] = stoch['slowd']
# === Volume ===
dataframe['volume'] = dataframe['volume'].astype(float)
dataframe['volume_mean'] = dataframe['volume'].rolling(window=20).mean()
dataframe['volume_ratio'] = dataframe['volume'] / dataframe['volume_mean']
# === ADX (Trend Strength) ===
dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
# === ATR (Volatility) ===
dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
# === 1h Trend Confirmation ===
if self.dp:
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h')
informative['ema_21'] = ta.EMA(informative, timeperiod=21)
dataframe = merge_informative_pair(dataframe, informative, '5m', '1h', ffill=True)
if 'ema_21_1h' not in dataframe:
dataframe['ema_21_1h'] = dataframe['ema_21']
dataframe['ema_21_1h'] = dataframe['ema_21_1h'].fillna(dataframe['ema_21'])
# === Trend Signals ===
dataframe['trend_up_5m'] = dataframe['ema_9'] > dataframe['ema_21']
dataframe['trend_up_1h'] = dataframe['close'] > dataframe['ema_21_1h']
dataframe['rsi_oversold'] = dataframe['rsi'] < 45
dataframe['rsi_overbought'] = dataframe['rsi'] > 55
dataframe['macd_bullish'] = dataframe['macd'] > dataframe['macdsignal']
dataframe['stoch_bullish'] = dataframe['stoch_k'] > dataframe['stoch_d']
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# === ENTRY CONDITIONS (Relaxed for more trades) ===
# Main entry: Multiple bullish signals
entry_1 = (
dataframe['trend_up_5m'] & # 5m uptrend
dataframe['rsi_oversold'] & # RSI not overbought
dataframe['macd_bullish'] & # MACD bullish
dataframe['stoch_bullish'] & # Stochastic bullish
dataframe['volume_ratio'] > 0.5 # Minimal volume
)
# RSI reversal entry
entry_2 = (
(dataframe['rsi'] < 50) &
(dataframe['rsi_fast'] > dataframe['rsi']) &
(dataframe['close'] > dataframe['bb_lower']) &
dataframe['trend_up_5m']
)
# MACD cross entry
entry_3 = (
qtpylib.crossed_above(dataframe['macd'], dataframe['macdsignal']) &
(dataframe['macdhist'] > -0.5) &
dataframe['trend_up_5m']
)
# Stochastic reversal entry
entry_4 = (
qtpylib.crossed_above(dataframe['stoch_k'], dataframe['stoch_d']) &
(dataframe['stoch_k'] < 70) &
(dataframe['volume_ratio'] > 0.3)
)
# Combined
dataframe.loc[(entry_1 | entry_2 | entry_3 | entry_4), 'enter_long'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# === EXIT CONDITIONS ===
# RSI overbought
exit_1 = (dataframe['rsi'] > 70) | (dataframe['rsi_fast'] < dataframe['rsi'])
# MACD bearish cross
exit_2 = qtpylib.crossed_below(dataframe['macd'], dataframe['macdsignal'])
# Trend reversal
exit_3 = ~dataframe['trend_up_5m']
# Take profit at BB upper
exit_4 = dataframe['close'] > dataframe['bb_middle']
# Stochastic overbought reversal
exit_5 = qtpylib.crossed_below(dataframe['stoch_k'], dataframe['stoch_d']) & (dataframe['stoch_k'] > 60)
dataframe.loc[(exit_1 | exit_2 | exit_3 | exit_4 | exit_5) & (dataframe['volume'] > 0), 'exit_long'] = 1
return dataframe