Freqtrade Strategy Development
Build profitable trading strategies with disciplined iteration, tight risk management, and data-driven entry/exit rules. Assumes Freqtrade is running via Docker (docker-compose).
Strategy Anatomy
Every Freqtrade strategy requires three methods:
populate_indicators(dataframe, metadata) — Add technical indicators (RSI, MACD, Bollinger Bands, etc.) to the dataframe
populate_entry_trend(dataframe, metadata) — Define buy signal logic; set enter_long = 1 when conditions met
populate_exit_trend(dataframe, metadata) — Define sell signal logic; set exit_long = 1 when conditions met (optional if using ROI/stop-loss)
Key Config Parameters
stoploss = -0.03 # 3% max loss per trade
trailing_stop = True
trailing_stop_positive = 0.01
trailing_stop_positive_offset = 0.02
minimal_roi = {
"0": 0.04, # 4% profit target immediately
"30": 0.02, # 2% after 30 candles
"60": 0.01, # 1% after 60 candles
}
timeframe = "5m" # or "15m", "1h", etc.
stake_currency = "USDT"
dry_run = True # Always backtest/dry-run first
Proven Entry Pattern
stoploss = -0.03
trailing_stop = True
trailing_stop_positive = 0.01
trailing_stop_positive_offset = 0.02
minimal_roi = {"0": 0.04, "30": 0.02, "60": 0.01}
# In populate_indicators: calculate RSI, CCI, Bollinger Bands, EMA, Volume SMA
# In populate_entry_trend: only buy when ALL conditions met
conditions = [
(dataframe['rsi'] < 30), # Oversold
(dataframe['cci'] < -100), # Momentum confirmation
(dataframe['close'] < dataframe['bb_lowerband']), # Price near lower band
(dataframe['volume'] > dataframe['volume_sma']), # Volume confirms
(dataframe['bullish_candle']), # Pattern confirmation
]
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'enter_long'] = 1
Key Lessons Learned
- Tight stops save accounts — 3% max loss beats 5%, 7%, or 8% every time
- Quality over quantity — 25 selective trades outperform 308 mediocre ones
- Win rate alone is meaningless — 63% win rate unprofitable if avg loss is 5x avg gain
- Selectivity is survival — RSI(30) + CCI(-100) dual filters dramatically reduce noise
- Test in bear markets — If strategy survives a crash, it works everywhere
- Volume confirms conviction — Entries without above-average volume fail more often
Useful Indicators
- RSI (14) — Momentum; < 30 = oversold, > 70 = overbought
- CCI — Commodity Channel Index; momentum confirmation; < -100 = deep oversold
- MACD — Trend following; watch for crossovers
- Bollinger Bands — Volatility; price near lower band = potential reversal
- EMA — Trend filter; price above EMA = uptrend
- MFI — Money Flow Index; volume-weighted momentum
Iteration Workflow
- Write baseline strategy with core entry/exit logic
- Backtest on 90–120 days of historical data
- Analyze exit reasons: are you exiting winners or losers too fast?
- Tighten ONE parameter at a time (e.g., RSI threshold)
- Backtest same period, compare vs. baseline
- If better → keep; if worse → revert
- Test different market conditions (Bull, bear, sideways)
- Dry-run on live feeds before deploying to live trading
Version Control
Keep all versions: name files MyStrategy_v1.py, MyStrategy_v2.py, etc. Add comments above each change explaining what improved and why. This preserves your iteration history and makes reverting safe.
References
references/indicators-guide.md — Technical indicator formulas and interpretation
references/iteration-workflow.md — Step-by-step walkthrough of strategy optimization
1---2name: freqtrade-strategy-dev3description: Develop, iterate, and improve Freqtrade cryptocurrency trading strategies. Use when writing a new strategy, improving an existing one, analyzing why a strategy is losing, or understanding which indicators to use. Covers strategy anatomy, key configuration parameters, proven entry/exit patterns, and the iteration workflow. Trigger phrases: write freqtrade strategy, improve strategy, why is my strategy losing, freqtrade indicators, strategy not profitable, freqtrade entry conditions.4---56# Freqtrade Strategy Development78Build profitable trading strategies with disciplined iteration, tight risk management, and data-driven entry/exit rules. Assumes Freqtrade is running via Docker (`docker-compose`).910## Strategy Anatomy1112Every Freqtrade strategy requires three methods:1314- **`populate_indicators(dataframe, metadata)`** — Add technical indicators (RSI, MACD, Bollinger Bands, etc.) to the dataframe15- **`populate_entry_trend(dataframe, metadata)`** — Define buy signal logic; set `enter_long = 1` when conditions met16- **`populate_exit_trend(dataframe, metadata)`** — Define sell signal logic; set `exit_long = 1` when conditions met (optional if using ROI/stop-loss)1718## Key Config Parameters1920```python21stoploss = -0.03 # 3% max loss per trade22trailing_stop = True23trailing_stop_positive = 0.0124trailing_stop_positive_offset = 0.022526minimal_roi = {27 "0": 0.04, # 4% profit target immediately28 "30": 0.02, # 2% after 30 candles29 "60": 0.01, # 1% after 60 candles30}3132timeframe = "5m" # or "15m", "1h", etc.33stake_currency = "USDT"34dry_run = True # Always backtest/dry-run first35```3637## Proven Entry Pattern3839```python40stoploss = -0.0341trailing_stop = True42trailing_stop_positive = 0.0143trailing_stop_positive_offset = 0.0244minimal_roi = {"0": 0.04, "30": 0.02, "60": 0.01}4546# In populate_indicators: calculate RSI, CCI, Bollinger Bands, EMA, Volume SMA4748# In populate_entry_trend: only buy when ALL conditions met49conditions = [50 (dataframe['rsi'] < 30), # Oversold51 (dataframe['cci'] < -100), # Momentum confirmation52 (dataframe['close'] < dataframe['bb_lowerband']), # Price near lower band53 (dataframe['volume'] > dataframe['volume_sma']), # Volume confirms54 (dataframe['bullish_candle']), # Pattern confirmation55]56dataframe.loc[reduce(lambda x, y: x & y, conditions), 'enter_long'] = 157```5859## Key Lessons Learned60611. **Tight stops save accounts** — 3% max loss beats 5%, 7%, or 8% every time622. **Quality over quantity** — 25 selective trades outperform 308 mediocre ones633. **Win rate alone is meaningless** — 63% win rate unprofitable if avg loss is 5x avg gain644. **Selectivity is survival** — RSI(30) + CCI(-100) dual filters dramatically reduce noise655. **Test in bear markets** — If strategy survives a crash, it works everywhere666. **Volume confirms conviction** — Entries without above-average volume fail more often6768## Useful Indicators6970- **RSI (14)** — Momentum; < 30 = oversold, > 70 = overbought71- **CCI** — Commodity Channel Index; momentum confirmation; < -100 = deep oversold72- **MACD** — Trend following; watch for crossovers73- **Bollinger Bands** — Volatility; price near lower band = potential reversal74- **EMA** — Trend filter; price above EMA = uptrend75- **MFI** — Money Flow Index; volume-weighted momentum7677## Iteration Workflow78791. Write baseline strategy with core entry/exit logic802. Backtest on 90–120 days of historical data813. Analyze exit reasons: are you exiting winners or losers too fast?824. Tighten ONE parameter at a time (e.g., RSI threshold)835. Backtest same period, compare vs. baseline846. If better → keep; if worse → revert857. Test different market conditions (Bull, bear, sideways)868. Dry-run on live feeds before deploying to live trading8788## Version Control8990Keep all versions: name files `MyStrategy_v1.py`, `MyStrategy_v2.py`, etc. Add comments above each change explaining what improved and why. This preserves your iteration history and makes reverting safe.9192## References9394- **`references/indicators-guide.md`** — Technical indicator formulas and interpretation95- **`references/iteration-workflow.md`** — Step-by-step walkthrough of strategy optimization