Strategies we backtested MACD crossover

Tested by BacktestingMax

MACD crossover strategy backtest

Does the MACD crossover strategy make money?

No, not on most markets. We ran 21 backtests: 7 markets, each on 15-minute, 1-hour and 4-hour charts, after trading costs. With no filter, the crossover lost money in 15 of the 21, including all 7 markets on 15-minute charts. Only 4 tests made money in 2020–2023 and again in 2024–2025, the newer years: the DAX and the Nasdaq 100 on 1-hour charts, and USD/JPY and EUR/USD on 4-hour charts. With a 200 EMA trend filter, 8 tests made money in both periods instead of 4.

21 backtests 2020–2025 Trading costs included Tested 11 October 2026

Where it worked 21 backtests
Made money
6
of 21 tests, with no filter
Made money in both periods
4
2020–2023 and again 2024–2025
Best backtest
+294%
DAX, 1-hour chart: account growth 2020–2025
With a 200 EMA trend filter
8
tests made money in both periods, compared with 4 with no filter

Made money in both periods

  • EUR/USD, 4-hour
  • USD/JPY, 4-hour
  • Nasdaq 100, 1-hour
  • DAX, 1-hour

Lost money on every market

  • 15-minute charts

The results

Results on every market

Each box shows one backtest of the MACD crossover with no filter, from 2020 to 2025, after trading costs: the % result, and a small chart of the account balance. The solid line is the account balance and the dashed line is the starting balance. Green results made money; red results lost money. Under each result: whether it made money in both 2020–2023 and 2024–2025, or passed all four of our checks (see "How a test passes" further down).

Market 15-minute 1-hour 4-hour
EUR/USD −99% Lost money. Account down 90% by May 2021 −62% Lost money +13% Made money in both periods
GBP/USD −99% Lost money. Account down 90% by May 2021 −70% Lost money +0.2% Made money overall, lost in one period
USD/JPY −99% Lost money. Account down 90% by Sept 2021 +124% Made money overall, lost in one period +56% Made money in both periods
Gold −98% Lost money. Account down 90% by May 2021 −31% Lost money −6% Lost money
Nasdaq 100 −82% Lost money +58% Made money in both periods −0.3% Lost money
S&P 500 −94% Lost money. Account down 90% by Feb 2024 −24% Lost money −17% Lost money
DAX −97% Lost money. Account down 90% by May 2022 +294% Made money in both periods −6% Lost money
All the numbers, test by test
Market Chart Trades Win rate Profit factor Result Max drawdown 2020–2023 2024–2025 Monte Carlo drawdown Trading costs
EUR/USD 15-minute 5,653 28.8% 0.81 −99.4% −99.5% −99.3% −22.6% −99.6% $7,814
EUR/USD 1-hour 2,759 32.4% 0.91 −62.3% −63.0% −57.0% −12.3% −79.6% $4,524
EUR/USD 4-hour 684 36.4% 1.04 +12.8% −20.8% +1.6% +11.1% −33.1% $1,052
GBP/USD 15-minute 4,869 28.7% 0.83 −99.3% −99.3% −99.1% −21.7% −99.5% $8,492
GBP/USD 1-hour 2,760 32.3% 0.93 −69.8% −76.3% −37.5% −51.7% −82.3% $7,062
GBP/USD 4-hour 680 35.9% 1.00 +0.2% −25.9% +9.7% −8.7% −37.0% $1,173
USD/JPY 15-minute 10,064 31.2% 0.87 −98.6% −98.8% −96.8% −56.9% −99.3% $13,791
USD/JPY 1-hour 2,619 33.4% 1.10 +124.0% −44.1% −8.1% +143.7% −52.7% $7,835
USD/JPY 4-hour 635 36.2% 1.15 +55.6% −24.0% +54.2% +0.9% −28.2% $1,124
Gold 15-minute 3,897 29.2% 0.79 −97.9% −98.2% −97.8% −4.1% −98.4% $6,925
Gold 1-hour 2,568 32.4% 0.96 −30.9% −49.4% −31.2% +0.5% −68.1% $5,719
Gold 4-hour 680 31.8% 0.97 −6.4% −35.8% −13.1% +7.7% −38.4% $877
Nasdaq 100 15-minute 9,462 31.9% 0.97 −81.7% −86.4% −63.3% −50.3% −95.3% $21,986
Nasdaq 100 1-hour 2,499 34.5% 1.04 +57.9% −32.3% +29.9% +21.5% −57.2% $5,657
Nasdaq 100 4-hour 667 35.7% 1.00 −0.3% −16.4% −5.0% +4.9% −36.5% $454
S&P 500 15-minute 9,614 32% 0.95 −93.5% −94.7% −85.2% −55.7% −97.9% $16,617
S&P 500 1-hour 2,548 33.3% 0.99 −24.1% −61.8% +30.4% −41.8% −69.6% $7,187
S&P 500 4-hour 674 35.9% 0.94 −17.2% −25.6% −3.0% −14.7% −45.3% $591
DAX 15-minute 7,113 30.7% 0.90 −97.3% −98.2% −96.3% −26.2% −98.5% $5,328
DAX 1-hour 2,547 34.7% 1.10 +294.1% −29.6% +130.9% +70.7% −44.6% $7,935
DAX 4-hour 731 32.7% 0.98 −5.7% −28.0% +1.7% −7.2% −39.4% $410

Profit factor is the money won divided by the money lost. Above 1 means the test made money. Max drawdown is the biggest fall from the highest balance. 2020–2023 and 2024–2025 show the result in each period on its own. Monte Carlo drawdown: we shuffled the trades into a random order 1,000 times; in 95% of those runs, the worst drawdown was this number or less. Result is the change in the account, with the risk of each trade set to 1% of the account at that time.

The account balance

The best test and the middle test

Best test DAX, 1-hour chart +294.1% from 2020 to 2025
Middle test (median): half of the 21 did better, half did worse S&P 500, 1-hour chart −24.1% from 2020 to 2025

What we found

What the 21 backtests show

  1. On 15-minute charts, the MACD crossover lost money on all 7 markets. In 6 of those 7 tests, the account lost more than 90% of its starting balance. A 15-minute trade catches only a small price move, so trading costs take a big share of it. On the Nasdaq 100, the 15-minute trades made $13,813 before costs and paid $21,986 in costs.

  2. On 1-hour and 4-hour charts, the crossover with no filter made money in 6 of 14 tests. 4 of them made money in both 2020–2023 and 2024–2025: the DAX and the Nasdaq 100 on 1-hour charts, and USD/JPY and EUR/USD on 4-hour charts. The best backtest result was the DAX on 1-hour charts: +294% from 2020 to 2025.

  3. In all 21 tests, only about 1 trade in 3 was a winner: the win rate was between 29% and 36%. So the strategy needs a few big winning trades to pay for the many losing ones.

  4. We tried 3 common changes to the crossover. The one that helped most in this backtest was a 200 EMA trend filter: only buy when price is above the 200 EMA, and only sell when it is below. With it, 11 of 21 tests made money, compared with 6 with no filter, and 8 tests made money in both periods, compared with 4. But we picked this filter using 2020–2023, and on 2024–2025 alone the difference was small: 9 tests made money, compared with 8. On 15-minute charts the filter did not help: all 7 markets still lost money.

The strategy

What the MACD crossover is

MACD is an indicator that measures momentum: how fast, and in which direction, price is moving. The MACD line is the gap between two moving averages of the price: one over the last 12 candles and one over the last 26. The signal line is the average of the MACD line over its last 9 values, so it moves more smoothly. The crossover strategy opens a trade every time these two lines cross.

MACD
12, 26, 9 (the standard settings)
Stop-loss
2 × ATR(14)
Take-profit
None. The next cross in the other direction closes the trade.
Risk per trade
1% of the account

The rules we tested

  1. Buy when the MACD line crosses above the signal line.
  2. Sell (go short) when the MACD line crosses below the signal line.
  3. When the MACD line crosses back over the signal line, close the open trade and open a new trade in the new direction. After a stop-loss, wait for the next cross.
  4. ATR is an indicator of how far price moves in an average candle, measured over the last 14 candles. Put the stop-loss 2 times the ATR away from the entry price.
  5. Size every trade so that, if the stop-loss is hit, the trade loses 1% of the account.

The method

How we tested it

The test

Markets
EUR/USD, GBP/USD, USD/JPY, Gold, Nasdaq 100, S&P 500 and DAX
Charts
15-minute, 1-hour and 4-hour candles
Dates
January 2020 to December 2025
Account
$10,000, risking 1% of the account on each trade
Trading costs
Included. Every trade pays that market's normal trading cost: the spread, which is the gap between the buy price and the sell price.

How a test passes

We call a test passed only if it meets all four checks. A strategy can make money in one backtest and still fail one of these checks.

  • At least 100 trades. With fewer trades, a good result could be luck.
  • It made money from 2020 to 2023 and again from 2024 to 2025. This shows whether the strategy kept working in the newer years, not only in the older ones.
  • A profit factor (the money won divided by the money lost) of at least 1.2 from 2024 to 2025, after trading costs.
  • In 95% of 1,000 random shuffles of the trades, the account must not fall more than 30% from its highest point.

Improvements

Can the MACD crossover be improved?

We tried three changes traders often make to the MACD crossover, to see if any of them make it better. Each change ran on the same 21 tests. A change picked on the same years it is judged on will almost always look good, so we picked the best one using 2020–2023 only. Then we checked it on 2024–2025, the years we did not use to pick it.

Version Made money 2020–2023years used to pick the best version Made money 2024–2025years not used to pick it Made money in both periods Passed all four checks
Crossover only, no filter The rules under 'The rules we tested', with nothing added. 7 of 21middle test −13.1% 8 of 21middle test −8.7% 4 0
With a 200 EMA trend filterBest on 2020–2023 Only buy when the price is above the 200 EMA, a moving average of the last 200 candles that gives more weight to recent candles. Only sell when it is below. 13 of 21middle test +4.7% 9 of 21middle test −1.2% 8 2
Buy only below zero, sell only above zero The MACD line is below zero when the 12-candle average is below the 26-candle average, which means price has been falling. Only buy when the lines cross below zero. Only sell when they cross above zero. 6 of 21middle test −22.5% 7 of 21middle test −5.2% 2 0
Fixed 2:1 take-profit Close the trade when it has made 2 times what it would lose at the stop-loss. A cross in the other direction no longer closes the trade; the next trade starts at the next cross after this one has closed. 5 of 21middle test −19.0% 9 of 21middle test −6.4% 3 1

On 2020–2023, the years we used to pick the best change, the 200 EMA trend filter did best: 13 of 21 tests made money with it, compared with 7 with no filter. On 2024–2025, the years we kept for the check, the difference was small: 9 of 21 tests made money, compared with 8. In 2024–2025, the middle test (half of the 21 did better, half did worse) was −1.2% with the filter and −8.7% without it. Over both periods, 8 tests made money with the filter, compared with 4. So in this backtest the filter helped, but most tests still lost money in 2024–2025.

Passed all four checks with a 200 EMA trend filter

  • Gold, 4-hour
  • Nasdaq 100, 4-hour

Questions

Questions traders ask

Does the MACD crossover strategy work?

No, not on most markets. In our backtest from 2020 to 2025, with trading costs, the 12, 26, 9 crossover with no filter lost money in 15 of 21 tests (7 markets, each on 15-minute, 1-hour and 4-hour charts). Only 4 tests made money in both 2020–2023 and 2024–2025: the DAX and the Nasdaq 100 on 1-hour charts, and USD/JPY and EUR/USD on 4-hour charts.

What is the best timeframe for a MACD crossover?

In our tests, 1-hour and 4-hour charts did better than 15-minute charts. But even on those charts, the crossover with no filter made money in only 6 of 14 tests. On 15-minute charts it lost money on all 7 markets, with or without the 200 EMA trend filter: trading costs took a big share of each small trade, and on 4 of the 7 markets the trades lost money even before costs. The best single backtest was the DAX on 1-hour charts, +294% from 2020 to 2025.

Does a 200 EMA filter improve the MACD crossover?

In our backtest it helped, but less on the newer years. A 200 EMA filter means: only buy when price is above the 200 EMA (a moving average of the last 200 candles), and only sell when it is below. Over 2020–2025, it raised the number of tests that made money from 6 to 11 of 21. We picked this filter using 2020–2023 only. On 2024–2025, the years we did not use to pick it, 9 of 21 tests made money with the filter, compared with 8 without it.

What are the best MACD settings?

This test can't tell you, because we tested only the standard settings, 12, 26 and 9. They are the default on most charting platforms. Be careful if you choose settings only because they gave the best backtest result. Settings chosen that way fit the past data, so they often do worse in live trading than in the backtest. You can test other settings in BacktestingMax.

Keep exploring

Related strategies we tested

Supertrend Supertrend (10, 3) strategy backtest Made money in 10 of 36 tests, 4 of them in both periods. Best: USD/JPY, 1-hour, +104% Moving averages 9/21 EMA crossover backtest: from 5-minute to daily charts Made money in 10 of 40 tests, 5 of them in both periods. Best: USD/JPY, 1-hour, +539%
The strategy code we ran

This is the exact code from the BacktestingMax strategy engine. Paste it into the strategy editor in the app to run it on any market.

class MacdCrossover(Strategy):
    """The classic MACD crossover, as most traders learn it, plus three common improvements.
    Standard (all switches off): buy when the MACD line (12/26) crosses above its signal
    line (9), sell short when it crosses below. The opposite cross closes the trade and
    opens the opposite one (the exit fills at the next candle's open, the new trade one
    candle later). A protective stop 2 x ATR(14) away caps each trade; size so that stop
    costs 1% of the account.
    The improvements, one at a time:
      trend_filter = 1   only buy above the 200 EMA, only sell below it
      zero_filter  = 1   only buy on a cross below the zero line, only sell on one above it
      exit_rr      = 2   take profit at 2 times the risk; the opposite cross no longer exits
    """
    params = {"fast": Param(type=int, default=12, min=2, max=50),
              "slow": Param(type=int, default=26, min=5, max=100),
              "signal": Param(type=int, default=9, min=2, max=50),
              "atr_mult": Param(type=float, default=2.0, min=0.5, max=5.0),
              "trend_filter": Param(type=int, default=0, min=0, max=1),
              "zero_filter": Param(type=int, default=0, min=0, max=1),
              "exit_rr": Param(type=float, default=0.0, min=0.0, max=10.0)}
    lookback = 220
    def init(self, ctx):
        self.macd = ctx.indicator("builtin:macd", fast=ctx.params.fast, slow=ctx.params.slow,
                                  signal=ctx.params.signal)
        self.atr = ctx.atr(period=14)
        self.ema = ctx.ema(source=ctx.close, period=200)
        self.reverse_to = None  # "long" / "short": open this once the closing trade is gone
    def on_bar(self, ctx):
        m0, m1 = self.macd.macd[0], self.macd.macd[1]
        s0, s1 = self.macd.signal[0], self.macd.signal[1]
        a = self.atr.value
        if m0 is None or m1 is None or s0 is None or s1 is None or a is None:
            return
        trend = ctx.params.trend_filter == 1
        if trend and self.ema.value is None:
            return
        rr = ctx.params.exit_rr
        cross_up = m1 <= s1 and m0 > s0
        cross_down = m1 >= s1 and m0 < s0
        pos = ctx.position
        if pos is not None:
            if rr > 0:
                return  # the fixed target or the stop ends the trade
            if pos.is_long and cross_down:
                ctx.close_position()
                self.reverse_to = "short"
            elif pos.is_short and cross_up:
                ctx.close_position()
                self.reverse_to = "long"
            return
        # A reversal waits one candle for the close to fill. Drop it if MACD crossed back.
        pending, self.reverse_to = self.reverse_to, None
        if pending == "long" and m0 > s0:
            cross_up = True
        if pending == "short" and m0 < s0:
            cross_down = True
        entry = ctx.close[0]
        long_ok = (not trend or entry > self.ema.value) and (ctx.params.zero_filter == 0 or m0 < 0)
        short_ok = (not trend or entry < self.ema.value) and (ctx.params.zero_filter == 0 or m0 > 0)
        if ctx.gate("macd_crosses_up", cross_up) and ctx.gate("long_filters", long_ok):
            stop = entry - ctx.params.atr_mult * a
            tp = entry + rr * (entry - stop) if rr > 0 else None
            ctx.buy(size=ctx.size_by_risk_pct(0.01, stop=stop, entry=entry), sl=stop, tp=tp, tag="macd_long")
        elif ctx.gate("macd_crosses_down", cross_down) and ctx.gate("short_filters", short_ok):
            stop = entry + ctx.params.atr_mult * a
            tp = entry - rr * (stop - entry) if rr > 0 else None
            ctx.sell(size=ctx.size_by_risk_pct(0.01, stop=stop, entry=entry), sl=stop, tp=tp, tag="macd_short")

Your turn

Test the MACD crossover yourself

Change the settings, the market or the stop-loss and see the result in seconds. Ask the BacktestingMax AI: Backtest a MACD crossover with a 200 EMA filter on the Nasdaq 100, 4-hour chart.

Try it free in BacktestingMax

Free account. No credit card needed.

See every strategy we tested Browse strategies shared by traders

Backtest on historical data with trading costs, run by BacktestingMax. Past results do not guarantee future results, and nothing here is financial advice. Updated 11 October 2026.