Strategies we backtested 9/21 EMA crossover

Tested by BacktestingMax

9/21 EMA crossover backtest: from 5-minute to daily charts

Does the 9/21 EMA crossover make money, and on which chart?

Mostly no. It made money only on some markets, and only on 1-hour, 4-hour and daily charts. The strategy buys when the 9 EMA (a fast average of recent prices) crosses above the 21 EMA (a slower average), and sells when it crosses below. We ran 40 backtests from 2014 to 2025, after trading costs: 8 markets (EUR/USD, GBP/USD, USD/JPY, AUD/USD, gold, the S&P 500, the Nasdaq 100 and the DAX), each on 5 timeframes from 5-minute to daily charts. On 5-minute and 15-minute charts, the crossover lost money on all 8 markets. On 1-hour, 4-hour and daily charts, 10 of 24 tests made money. 5 of them made money in the older years (2014–2021) and again in the newer years (2022–2025): gold on 1-hour and 4-hour charts, USD/JPY on 1-hour charts, the DAX on 4-hour charts and EUR/USD on daily charts.

40 backtests 2014–2025 Trading costs included Tested 12 October 2026

Where it worked 40 backtests
Made money
10
of 40 tests, with the basic rules
Made money in both periods
5
2014–2021 and again 2022–2025
Best backtest
+539%
USD/JPY, 1-hour chart: account growth 2014–2025
With a 200 EMA trend filter
6
tests made money in both periods, compared with 5 with the basic rules

Made money in both periods

  • EUR/USD, daily
  • USD/JPY, 1-hour
  • Gold, 1-hour
  • Gold, 4-hour
  • DAX, 4-hour

Lost money on every market

  • 5-minute charts
  • 15-minute charts

The results

Results on every market

Each box shows one backtest of the 9/21 EMA crossover with the basic rules, from 2014 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 2014–2021 and 2022–2025, or passed all four of our checks (see "How a test passes" further down).

Market 5-minute 15-minute 1-hour 4-hour daily
EUR/USD −100% Lost money. Account down 90% by Apr 2014 −100% Lost money. Account down 90% by Mar 2016 −52% Lost money −8% Lost money +19% Passed all four checks
GBP/USD −100% Lost money. Account down 90% by Mar 2014 −99% Lost money. Account down 90% by Dec 2014 −59% Lost money +10% Made money overall, lost in one period −4% Lost money
USD/JPY −100% Lost money. Account down 90% by Jun 2014 −99% Lost money. Account down 90% by Nov 2018 +539% Made money in both periods +23% Made money overall, lost in one period −3% Lost money
AUD/USD −100% Lost money. Account down 90% by Apr 2014 −100% Lost money. Account down 90% by Sept 2016 −92% Lost money. Account down 90% by Aug 2025 −58% Lost money −8% Lost money
Gold −100% Lost money. Account down 90% by May 2014 −99% Lost money. Account down 90% by Apr 2015 +194% Made money in both periods +99% Made money in both periods +5% Made money overall, lost in one period
S&P 500 −100% Lost money. Account down 90% by Feb 2014 −100% Lost money. Account down 90% by Jul 2014 −88% Lost money −43% Lost money −1% Lost money
Nasdaq 100 −100% Lost money. Account down 90% by Feb 2014 −100% Lost money. Account down 90% by Jun 2014 −47% Lost money +14% Made money overall, lost in one period −0.4% Lost money
DAX −100% Lost money. Account down 90% by May 2014 −99% Lost money. Account down 90% by Oct 2015 +39% Made money overall, lost in one period +17% Made money in both periods −8% Lost money
All the numbers, test by test
Market Chart Trades Win rate Profit factor Result Max drawdown 2014–2021 2022–2025 Monte Carlo drawdown Trading costs
EUR/USD 5-minute 2,691 18.3% 0.60 −99.7% −99.7% −99.7% −5.1% −99.8% $5,302
EUR/USD 15-minute 6,137 22.9% 0.82 −99.6% −99.6% −99.6% −4.1% −99.8% $6,269
EUR/USD 1-hour 3,057 27.2% 0.96 −52.1% −66.8% −17.5% −42.0% −83.6% $7,925
EUR/USD 4-hour 776 29.5% 0.98 −8.3% −34.1% +16.2% −21.1% −50.3% $1,048
EUR/USD daily 131 26.7% 1.31 +19.1% −15.2% +11.6% +6.7% −20.4% $71
GBP/USD 5-minute 2,026 18.9% 0.58 −99.6% −99.7% −99.6% −1.7% −99.7% $5,656
GBP/USD 15-minute 5,690 22.2% 0.74 −99.3% −99.4% −99.2% −6.2% −99.6% $5,705
GBP/USD 1-hour 3,072 27.2% 0.95 −59.2% −77.4% −2.4% −58.2% −85.0% $7,549
GBP/USD 4-hour 782 29.5% 1.02 +10.0% −27.3% −2.5% +12.9% −46.2% $1,272
GBP/USD daily 132 29.5% 0.93 −3.7% −18.6% −10.5% +7.7% −21.9% $64
USD/JPY 5-minute 3,059 22.4% 0.77 −99.7% −99.7% −99.7% 0.0% −99.8% $10,617
USD/JPY 15-minute 7,237 24.3% 0.94 −99.1% −99.6% −99.5% +59.9% −99.6% $21,834
USD/JPY 1-hour 2,995 28.3% 1.16 +538.9% −54.0% +103.6% +213.8% −59.1% $17,863
USD/JPY 4-hour 771 29.3% 1.05 +22.8% −24.1% −0.2% +23.1% −45.7% $1,297
USD/JPY daily 138 30.4% 0.95 −2.6% −19.2% −18.1% +19.0% −21.0% $67
AUD/USD 5-minute 2,461 20.3% 0.68 −99.8% −99.8% −99.8% −2.5% −99.8% $7,269
AUD/USD 15-minute 4,931 25.5% 0.85 −99.5% −99.6% −99.5% −5.3% −99.7% $9,314
AUD/USD 1-hour 3,150 26% 0.87 −92.1% −94.0% −71.6% −72.2% −95.4% $5,025
AUD/USD 4-hour 832 25.7% 0.80 −57.8% −61.4% −32.7% −37.3% −68.8% $1,045
AUD/USD daily 128 29.7% 0.86 −8.2% −14.7% +1.2% −9.3% −23.1% $93
Gold 5-minute 1,992 21.2% 0.65 −99.6% −99.6% −99.6% 0.0% −99.7% $9,589
Gold 15-minute 4,103 21.9% 0.73 −98.9% −98.9% −98.9% 0.0% −99.4% $7,298
Gold 1-hour 2,955 26.7% 1.08 +193.6% −62.1% +50.1% +95.6% −67.7% $19,076
Gold 4-hour 745 29.7% 1.23 +99.3% −27.9% +16.8% +70.7% −36.1% $1,752
Gold daily 127 24.4% 1.09 +4.5% −11.5% −10.3% +16.6% −18.5% $80
S&P 500 5-minute 1,492 18% 0.33 −99.9% −99.9% −99.9% 0.0% −99.9% $4,777
S&P 500 15-minute 2,369 17.7% 0.54 −99.9% −99.9% −99.9% 0.0% −99.9% $4,661
S&P 500 1-hour 2,901 25.9% 0.81 −88.3% −89.2% −87.3% −7.9% −94.4% $3,634
S&P 500 4-hour 783 28.1% 0.84 −42.7% −54.0% −47.3% +8.8% −63.2% $919
S&P 500 daily 121 34.7% 0.98 −1.1% −12.3% −5.9% +5.2% −19.6% $69
Nasdaq 100 5-minute 1,033 15.7% 0.43 −99.9% −99.9% −99.9% 0.0% −99.9% $8,775
Nasdaq 100 15-minute 1,534 14% 0.49 −99.8% −99.8% −99.8% 0.0% −99.9% $5,627
Nasdaq 100 1-hour 2,839 27% 0.95 −46.6% −75.4% −50.9% +8.8% −83.4% $7,634
Nasdaq 100 4-hour 745 29.1% 1.03 +13.5% −31.5% −0.6% +14.1% −45.8% $1,442
Nasdaq 100 daily 127 26.8% 0.99 −0.4% −11.6% −0.9% +0.5% −18.4% $86
DAX 5-minute 2,994 19.1% 0.64 −99.6% −99.6% −99.6% 0.0% −99.8% $6,574
DAX 15-minute 3,088 19.9% 0.83 −98.7% −98.8% −98.6% −9.6% −99.5% $5,391
DAX 1-hour 2,890 27.7% 1.02 +38.8% −57.8% −5.5% +46.9% −73.6% $4,717
DAX 4-hour 811 27% 1.03 +17.2% −32.2% +9.9% +6.6% −47.9% $678
DAX daily 136 28.7% 0.84 −7.7% −9.5% −8.8% +1.2% −20.1% $26

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. 2014–2021 and 2022–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 USD/JPY, 1-hour chart +538.9% from 2014 to 2025
Middle test (median): half of the 40 did better, half did worse EUR/USD, 1-hour chart −52.1% from 2014 to 2025

What we found

What the 40 backtests show

  1. On 5-minute and 15-minute charts, the 9/21 crossover lost money on all 8 markets. On 5-minute charts, all 8 accounts were down 90% by June 2014, in the first 6 months of the test. Trading costs are the main reason: before costs, the 5-minute trades lost 6.5% of the money they risked in total, and after costs they lost 24.3%. To check that the losses were not only a 2014 problem, we also ran the 5-minute and 15-minute charts on 2022–2025 alone. 15 of the 16 tests still lost money; only USD/JPY on 15-minute charts made money.

  2. Gold made money on the most charts: the crossover made money on its 1-hour, 4-hour and daily charts. USD/JPY and the DAX made money on their 1-hour and 4-hour charts. The best backtest was USD/JPY on 1-hour charts: +539% from 2014 to 2025, but at one point the account fell 54% from its highest balance.

  3. On EUR/USD daily charts, one sell trade from July 2014 to April 2015 made 24.9R (24.9 times the money it risked). That one trade made more than the whole test made in 131 trades (21.2R), so without it the test would have lost money. With the basic rules, this is the only test that passed all four of our checks (see 'How a test passes'). Across the 40 tests, only 14% to 35% of trades won.

  4. On the S&P 500, the crossover lost money on every chart, even though the index rose about 271% from 2014 to 2025. Much of the loss came from the sell trades: on 1-hour, 4-hour and daily charts, the S&P 500 sells lost 257.3R and the buys made 37.7R. In all 24 tests on these three charts, the trades in the same direction as the market's overall move from 2014 to 2025 (buys if it ended higher, sells if it ended lower) did better than the others.

  5. We tried 4 changes traders often make: a 200 EMA trend filter, an ADX trend-strength filter, a pullback entry and a 2:1 take-profit. The 200 EMA filter (only buy above the 200 EMA, only sell below it) did best on 2014–2021, the years we used to pick the best change. On 2022–2025, it made only a small difference (see 'Can the 9/21 EMA crossover be improved?' below). It helped most on 4-hour charts: with the filter, 4 of 8 tests made money in both periods, compared with 2 of 8 with the basic rules. No change made the 5-minute or 15-minute charts make money from 2014 to 2025.

Trading costs

Why the 5-minute and 15-minute charts lost

Every trade pays a trading cost: the spread, which is the gap between the buy price and the sell price. Each bar shows that cost as a share of the money a trade risks (what it loses if the stop-loss is hit), for all trades on all 8 markets from 2014 to 2025.

  • 5-minute17,748 trades 17.8%
  • 15-minute35,089 trades 8.1%
  • 1-hour23,859 trades 3.2%
  • 4-hour6,245 trades 1.5%
  • Daily1,040 trades 0.6%

The stop-loss is 2 times the ATR (how far price moves in an average candle), so on 5-minute and 15-minute charts it is close to the entry price, and the same trading cost is a bigger share of each trade. Most of these 5-minute and 15-minute trades are from 2014 to 2016, because most of those accounts were down 90% by then. On 2022–2025 alone, when prices moved more, the cost was 8.1% of the money risked on 5-minute charts and 4.7% on 15-minute charts. The test does not include overnight (swap) fees, which brokers charge for keeping a trade open overnight.

Buys against sells

On stock indices and gold, the buys made money and the sells lost

We added up all the trades on 1-hour, 4-hour and daily charts from 2014 to 2025, in R. 1R is the money risked on one trade: 1% of the account.

3 stock indices: buys
+455.2R
5,700 trades
3 stock indices: sells
−577.1R
5,653 trades
Gold: buys
+329.1R
1,905 trades
Gold: sells
−90.7R
1,922 trades

The 3 stock indices are the S&P 500, the Nasdaq 100 and the DAX. They and gold all rose a lot from 2014 to 2025. On the 4 currency pairs, the buys lost 31.8R and the sells lost 64.4R. We did not test a version that only buys.

Year by year

Without 2020, the 1-hour, 4-hour and daily tests lost money in total

We added up the 24 tests on 1-hour, 4-hour and daily charts by the year each trade opened, in R (1R is the money risked on one trade).

  • 20142,561 trades +62.1R
  • 20152,591 trades +43.4R
  • 20162,660 trades −270.5R
  • 20172,614 trades −72.6R
  • 20182,589 trades −3.9R
  • 20192,615 trades −95.2R
  • 20202,520 trades +310.2R
  • 20212,679 trades −107.8R
  • 20222,578 trades +137.2R
  • 20232,552 trades +26.2R
  • 20242,626 trades −27.1R
  • 20252,559 trades +18.2R

From 2016 to 2019, the 24 tests lost money four years in a row. 2020 alone made 310.2R, more than all 12 years together (about 20R). The 5-minute and 15-minute tests are left out, because most of those accounts were down 90% by 2016.

The strategy

What the 9/21 EMA crossover is

An EMA (exponential moving average) is an indicator that shows the average price of the last few candles, with more weight on the newest candles. The 9 EMA averages about the last 9 candles, so it follows price closely. The 21 EMA averages about the last 21 candles, so it moves more slowly. After price has been rising for a while, the 9 EMA crosses above the 21 EMA. After price has been falling for a while, the 9 EMA crosses below it. The 9/21 crossover strategy trades in the direction of each cross. Many day traders use it on 5-minute and 15-minute charts.

EMAs
9 and 21, on closing prices
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 9 EMA crosses above the 21 EMA. We check for a cross when each candle closes, and the trade opens at the next candle's open.
  2. Sell (go short) when the 9 EMA crosses below the 21 EMA.
  3. When the EMAs cross the other way, close the trade and open a new trade in the new direction. In our test, the new trade opens one candle after the old trade closes. 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, AUD/USD, Gold, S&P 500, Nasdaq 100 and DAX
Charts
5-minute, 15-minute, 1-hour, 4-hour and daily candles
Dates
January 2014 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 2014 to 2021 and again from 2022 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 2022 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 9/21 EMA crossover be improved?

Traders often add one rule to the 9/21 crossover to try to improve it. We tested four common ones, each on the same 40 tests. If we picked the best change and judged it on the same years, it would almost always look good. So we picked the best change using 2014–2021 only, then checked it on 2022–2025, the years we did not use to pick it.

Version Made money 2014–2021years used to pick the best version Made money 2022–2025years not used to pick it Made money in both periods Passed all four checks
The basic rules, no changes The rules under 'The rules we tested', with nothing added. 7 of 40middle test −40.0% 18 of 40middle test 0.0% 5 1
With a 200 EMA trend filterBest on 2014–2021 Only buy when the price is above the 200 EMA, a moving average of the last 200 candles. Only sell when it is below. A cross the other way still closes the open trade, but the new trade opens only if the price is on the right side of the 200 EMA. 11 of 40middle test −27.0% 20 of 40middle test +0.2% 6 1
With a trend-strength filter (ADX above 25) ADX is an indicator that measures how strong a trend is, from 0 to 100, whether price is rising or falling. Only open a trade when ADX(14) is above 25, a common sign of a strong trend, to skip crosses in a market that moves sideways. A cross the other way still closes the open trade, but the new trade opens only if ADX is above 25. 6 of 40middle test −29.6% 16 of 40middle test −0.1% 4 1
With a pullback entry to the 9 EMA Don't buy as soon as the EMAs cross. After the 9 EMA crosses above the 21 EMA, wait for the first candle that dips back to the 9 EMA and closes above it, then buy. For sells, do the opposite. The next cross closes the trade, and the new trade waits for its own pullback. 8 of 40middle test −38.4% 16 of 40middle test 0.0% 4 2
With a 2:1 take-profit Add a take-profit: close the trade when it has made 2 times the money it risked. If the EMAs cross the other way first, that cross still closes the trade. After a take-profit, wait for the next cross. 10 of 40middle test −31.1% 15 of 40middle test 0.0% 5 0

On 2014–2021, the years we used to pick the best change, the 200 EMA trend filter did best: 11 of 40 tests made money with it, compared with 7 with the basic rules. On 2022–2025, the years we kept for the check, the difference was small: 20 of 40 tests made money with the filter, compared with 18 without it. In every version, most 5-minute and 15-minute accounts were already down 90% before 2022, and each trade risks 1% of what is left, so those tests made only small trades, or none, in 2022–2025. The 2022–2025 counts come mainly from the 1-hour, 4-hour and daily charts. On daily charts, the filter left only 58 to 76 trades per test, too few to judge. So the filter helped a little: with it, 6 of 40 tests made money in both periods, compared with 5 with the basic rules.

Passed all four checks with a 200 EMA trend filter

  • Gold, 4-hour

Questions

Questions traders ask

Does the 9/21 EMA crossover strategy work?

Mostly no. In our backtest from 2014 to 2025, with trading costs, the 9/21 crossover with the basic rules made money in 10 of 40 tests (8 markets, each on 5 timeframes). All 10 were on 1-hour, 4-hour or daily charts; on 5-minute and 15-minute charts, it lost money on all 8 markets. 5 tests made money in both 2014–2021 and 2022–2025: gold on 1-hour and 4-hour charts, USD/JPY on 1-hour charts, the DAX on 4-hour charts and EUR/USD on daily charts.

What is the best timeframe for the 9/21 EMA crossover?

In our test, 4-hour charts did best: the crossover made money on 5 of 8 markets. It made money on 3 of 8 markets on 1-hour charts and on 2 of 8 on daily charts. On 5-minute and 15-minute charts, the timeframes many day traders use, it lost money on all 8 markets. Trading costs are the main reason: on 5-minute charts, the cost of a trade was 17.8% of the money it risked, on average. We also ran the 5-minute and 15-minute charts on 2022–2025 alone, and 15 of those 16 tests still lost money.

What is the win rate of the 9/21 EMA crossover?

Low. In our 40 backtests, only 14% to 35% of trades were winners. The crossover makes its money from a few long trends, and those trends pay for many small losses. For example, on EUR/USD daily charts, one sell trade from July 2014 to April 2015 made 24.9 times the money it risked, more than the whole test made in 131 trades.

Does a 200 EMA filter improve the 9/21 EMA crossover?

A little, in our backtest, and mostly on 4-hour charts. A 200 EMA filter means: only buy when the price is above the 200 EMA (a moving average of the last 200 candles), and only sell when it is below. From 2014 to 2025, 15 of the 40 tests made money with the filter, compared with 10 without it. On 4-hour charts, 4 of 8 tests made money in both 2014–2021 and 2022–2025 with the filter, compared with 2 of 8 without it. In 2022–2025 alone, the years we did not use to pick it, the difference was small: 20 of 40 tests made money with the filter, compared with 18 without it. On 5-minute and 15-minute charts, all 16 tests still lost money with the filter.

Keep exploring

Related strategies we tested

MACD MACD crossover strategy backtest Made money in 6 of 21 tests, 4 of them in both periods. Best: DAX, 1-hour, +294%
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 EmaCrossover921(Strategy):
    """The 9/21 EMA crossover as most traders learn it, plus four changes traders often make.
    Standard (all switches off): buy when the 9 EMA crosses above the 21 EMA, sell short when
    it crosses below. The opposite cross closes the trade and opens a new one the other way
    (the exit fills at the next candle's open, the new trade one candle later). A stop-loss
    2 x ATR(14) away caps each trade; size so that the stop costs 1% of the account. After a
    stop-loss (or a take-profit), wait for the next cross.
    The changes, one at a time:
      trend_filter = 1   only buy above the 200 EMA, only sell below it
      adx_filter   = 1   only open a trade when ADX(14) is above 25 (a trending market)
      pullback     = 1   don't buy the cross itself: after the cross, buy the first candle that
                         dips to the 9 EMA and closes back above it (sells mirror this); the
                         opposite cross closes the trade but doesn't open a new one at once
      exit_rr      = 2   add a take-profit at 2 times the risk; the opposite cross still exits
    """
    params = {"fast": Param(type=int, default=9, min=2, max=100),
              "slow": Param(type=int, default=21, min=3, max=200),
              "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),
              "adx_filter": Param(type=int, default=0, min=0, max=1),
              "adx_min": Param(type=float, default=25.0, min=0.0, max=100.0),
              "pullback": 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.fast = ctx.indicator("builtin:ema", period=ctx.params.fast)
        self.slow = ctx.indicator("builtin:ema", period=ctx.params.slow)
        self.atr = ctx.atr(period=14)
        self.ema200 = ctx.ema(source=ctx.close, period=200)
        self.adx = ctx.indicator("builtin:adx", period=14)
        self.reverse_to = None  # "long" / "short": open this once the closing trade is gone
        self.armed = None       # pullback version: the side of the last cross, until it trades
    def on_bar(self, ctx):
        f0, f1 = self.fast.ema[0], self.fast.ema[1]
        s0, s1 = self.slow.ema[0], self.slow.ema[1]
        a = self.atr.value
        if f0 is None or f1 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.ema200.value is None:
            return
        use_adx = ctx.params.adx_filter == 1
        adx = self.adx.adx[0]
        if use_adx and adx is None:
            return
        pullback = ctx.params.pullback == 1
        rr = ctx.params.exit_rr
        cross_up = f1 <= s1 and f0 > s0
        cross_down = f1 >= s1 and f0 < s0
        if pullback:
            if cross_up:
                self.armed = "long"
            elif cross_down:
                self.armed = "short"
        pos = ctx.position
        if pos is not None:
            if pos.is_long and cross_down:
                ctx.close_position()
                self.reverse_to = None if pullback else "short"
            elif pos.is_short and cross_up:
                ctx.close_position()
                self.reverse_to = None if pullback else "long"
            return
        entry = ctx.close[0]
        if pullback:
            # The first candle after the cross that dips to the 9 EMA and closes back beyond it.
            # The cross candle itself doesn't count, and the EMAs must still be in cross order.
            go_long = (self.armed == "long" and not cross_up and f0 > s0
                       and ctx.low[0] <= f0 and entry > f0)
            go_short = (self.armed == "short" and not cross_down and f0 < s0
                        and ctx.high[0] >= f0 and entry < f0)
        else:
            # A reversal waits one candle for the close to fill. Drop it if the EMAs crossed back.
            pending, self.reverse_to = self.reverse_to, None
            go_long = cross_up or (pending == "long" and f0 > s0)
            go_short = cross_down or (pending == "short" and f0 < s0)
        long_ok = not trend or entry > self.ema200.value
        short_ok = not trend or entry < self.ema200.value
        strong = not use_adx or adx > ctx.params.adx_min
        if ctx.gate("ema9_crosses_up", go_long) and ctx.gate("long_trend_filter", long_ok) \
                and ctx.gate("adx_strong", strong):
            stop = entry - ctx.params.atr_mult * a
            tp = entry + rr * (entry - stop) if rr > 0 else None
            if ctx.buy(size=ctx.size_by_risk_pct(0.01, stop=stop, entry=entry), sl=stop, tp=tp,
                       tag="ema_long") is not None:
                self.armed = None
        elif ctx.gate("ema9_crosses_down", go_short) and ctx.gate("short_trend_filter", short_ok) \
                and ctx.gate("adx_strong", strong):
            stop = entry + ctx.params.atr_mult * a
            tp = entry - rr * (stop - entry) if rr > 0 else None
            if ctx.sell(size=ctx.size_by_risk_pct(0.01, stop=stop, entry=entry), sl=stop, tp=tp,
                        tag="ema_short") is not None:
                self.armed = None

Your turn

Test the 9/21 EMA crossover yourself

Change the settings, the market or the stop-loss and see the result in seconds. Ask the BacktestingMax AI: Backtest a 9/21 EMA crossover with a 200 EMA filter on gold, 4-hour chart, from 2014 to 2025.

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 12 October 2026.