Freqtrade Strategy

MACDStrategy

5m candlesMomentumSpot, long only

Tested 1 Jun 2023 – 30 May 2025
Rank 9 of 27 by return

MACDStrategy turned $1,000 into $1,229 (+22.9%) over 729 days, while holding Bitcoin returned +288.1% and an equal mix of the ten coins +194.8%. Its worst drawdown was 39.2%, a substantial dip to sit through. It won 97% of trades with small targets; a profit factor of 1.11 shows how thin that edge is.

MACDStrategy account balance compared with holding Bitcoin$0$1,000$2,000$3,000$4,000JulOctJan 2024AprJulOctJan 2025AprMACDStrategy $1,229BTC hold $3,880
Account balance from $1,000 (closed trades, daily). Dashed line: $1,000 held in BTC over the same days.
Total return+22.9%$1,229 final balance
Max drawdown39.2%24 Jan 2025 to 7 Apr 2025
Win rate96.6%1,101 wins / 39 losses
Profit factor1.11Gross wins ÷ gross losses
Trades1,1401.6 per day
Average trade+0.10%after fees
Average hold2d 21hwinners 2d 1h, losers 26d 2h
Annualised (CAGR)+10.9%Sharpe 0.56 · Sortino 0.44

How MACDStrategy trades

MACDStrategy buys when the MACD line is above its signal line while CCI is at or below -48, catching a momentum turn from a weak reading. It sells when MACD falls below the signal line with CCI above 687.

The sell threshold of 687 is so high that the exit signal almost never fires. In practice trades close through the stepped take-profit (5% falling to 1%) or the 30% stoploss.

Rules at a glance

Indicators
MACD, CCI
Take-profit (minimal ROI)
5% from entry; 4% after 20m; 3% after 30m; 1% after 1h 0m
Stoploss
−30%
Trailing stop
Off
Exit signal
Used

Results by month

Profit or loss in USDT for trades closed in each month.

JFMAMJJASOND2023-26+22-104+0+68+156+1452024-24+84+186-130+19-141+57-171+36+0+342+682025+72-252-97-102+21

Results by coin

PairTradesWin rateProfit (USDT)Avg. hold
BNB/USDT11398.2%+104.653d 11h
ADA/USDT12497.6%+90.961d 19h
AVAX/USDT12796.9%+66.111d 22h
LINK/USDT11196.4%+40.272d 13h
DOGE/USDT10996.3%+32.002d 3h
BTC/USDT7996.2%+25.986d 20h
XRP/USDT12796.1%+6.662d 17h
ETH/USDT7295.8%−41.567d 4h
SOL/USDT15596.1%−44.971d 15h
DOT/USDT12395.9%−50.902d 3h

Why trades closed

Exit reasonTradesWin rateProfit (USDT)
Take-profit (ROI)1101100.0%+2,379.48
Still open at end of test50.0%−99.07
Stoploss340.0%−2,051.22

The code

MACDStrategy comes from the community freqtrade-strategies repository (GPL-3.0). These are the parts that decide when it trades; the full file is 103 lines.

Entry rules
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    dataframe.loc[
        (
            (dataframe['macd'] > dataframe['macdsignal']) &
            (dataframe['cci'] <= self.buy_cci.value) &
            (dataframe['volume'] > 0)  # Make sure Volume is not 0
        ),
        'enter_long'] = 1

    return dataframe
Exit rules
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    dataframe.loc[
        (
            (dataframe['macd'] < dataframe['macdsignal']) &
            (dataframe['cci'] >= self.sell_cci.value) &
            (dataframe['volume'] > 0)  # Make sure Volume is not 0
        ),
        'exit_long'] = 1

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

    macd = ta.MACD(dataframe)
    dataframe['macd'] = macd['macd']
    dataframe['macdsignal'] = macd['macdsignal']
    dataframe['macdhist'] = macd['macdhist']
    dataframe['cci'] = ta.CCI(dataframe)

    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 MACDStrategy --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.