Strategies we backtested pivot point bounce

Tested by BacktestingMax

Pivot point bounce strategy backtest on forex, gold and indices

Does the pivot point bounce strategy make money?

Mostly no. In our backtest, it lost money in 24 of 27 tests, after trading costs. Pivot points are daily price lines calculated from the previous day's high, low and close. The middle line is the pivot point (P). S1 is the first line below P, and R1 the first line above P. With our standard rules, the strategy buys when price falls to S1 and a candle closes back above S1. It sells short (sells first, to profit if price falls) when price rises to R1 and a candle closes back below R1. It takes profit at P, with the stop-loss 1 ATR (one average candle) beyond the line. We tested 4 currency pairs, gold, silver, the S&P 500, the Nasdaq 100 and the DAX from 2020 to 2025, on 5-minute, 15-minute and 1-hour charts. Only the Nasdaq 100 made money, on all three charts and in both 2020–2023 and 2024–2025. Fake lines, moved every day by a random amount, did about as well as the real lines before costs on 8 of the 9 markets. So on most markets, the pivot lines gave no clear edge. None of our four changes, such as trading only the first touch, made money on most tests.

27 backtests 2020–2025 Trading costs included Tested 26 October 2026

Where it worked 27 backtests
Made money
3
of 27 tests, with the standard rules
Made money in both periods
3
2020–2023 and again 2024–2025
Best backtest
+257%
Nasdaq 100, 5-minute chart: account growth 2020–2025
First touch of each line only
2
tests made money in both periods, compared with 3 with the standard rules

Made money in both periods

  • Nasdaq 100, 5-minute
  • Nasdaq 100, 15-minute
  • Nasdaq 100, 1-hour

The results

Results on every market

Each box shows one backtest of the pivot point bounce with the standard rules, 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 5-minute 15-minute 1-hour
EUR/USD −86% Lost money −71% Lost money −45% Lost money
GBP/USD −93% Lost money. Account down 90% by Aug 2025 −84% Lost money −51% Lost money
USD/JPY −93% Lost money. Account down 90% by Sept 2022 −79% Lost money −50% Lost money
AUD/USD −98% Lost money. Account down 90% by Apr 2022 −82% Lost money −32% Lost money
Gold −92% Lost money. Account down 90% by Jan 2025 −56% Lost money −41% Lost money
Silver −99% Lost money. Account down 90% by Jul 2021 −96% Lost money. Account down 90% by Sept 2023 −72% Lost money
S&P 500 −92% Lost money. Account down 90% by Jan 2024 −38% Lost money −45% Lost money
Nasdaq 100 +257% Made money in both periods +85% Made money in both periods +48% Passed all four checks
DAX −49% Lost money −32% Lost money −17% 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 5-minute 1,858 25.6% 0.86 −86.1% −89.2% −68.1% −56.4% −92.8% $8,736
EUR/USD 15-minute 1,363 33% 0.85 −70.6% −75.8% −59.6% −27.2% −82.1% $4,794
EUR/USD 1-hour 903 45.7% 0.86 −44.6% −51.7% −37.9% −10.8% −58.0% $2,321
GBP/USD 5-minute 1,940 25% 0.80 −93.1% −93.5% −85.5% −52.3% −96.0% $6,932
GBP/USD 15-minute 1,396 32.9% 0.78 −83.7% −84.5% −72.4% −41.0% −88.7% $4,332
GBP/USD 1-hour 928 44.6% 0.85 −50.8% −53.1% −32.7% −26.8% −61.8% $2,902
USD/JPY 5-minute 1,865 23.5% 0.73 −93.4% −94.8% −92.5% −12.2% −96.3% $5,969
USD/JPY 15-minute 1,303 30.5% 0.81 −79.4% −82.1% −73.4% −22.6% −85.9% $4,824
USD/JPY 1-hour 863 44.1% 0.81 −50.1% −58.0% −52.9% +6.0% −60.6% $2,050
AUD/USD 5-minute 2,088 23.3% 0.71 −98.4% −98.5% −96.6% −51.2% −99.0% $6,521
AUD/USD 15-minute 1,495 32.2% 0.83 −82.4% −84.3% −72.4% −36.3% −88.4% $6,883
AUD/USD 1-hour 991 45.9% 0.92 −31.6% −38.7% −33.1% +2.3% −52.8% $4,196
Gold 5-minute 1,806 26.1% 0.82 −92.3% −93.9% −75.4% −68.6% −95.5% $8,507
Gold 15-minute 1,335 35.8% 0.90 −55.7% −66.0% −31.6% −35.3% −73.7% $6,753
Gold 1-hour 888 47.1% 0.87 −41.0% −45.8% −14.9% −30.7% −54.1% $2,584
Silver 5-minute 1,120 22.7% 0.43 −98.5% −98.5% −98.0% −24.9% −98.8% $6,543
Silver 15-minute 1,203 31.1% 0.60 −95.5% −95.8% −90.1% −54.5% −96.2% $6,860
Silver 1-hour 906 43.8% 0.67 −71.9% −73.2% −56.8% −34.9% −75.4% $4,336
S&P 500 5-minute 1,763 23.8% 0.83 −92.4% −94.7% −89.3% −28.9% −95.8% $6,154
S&P 500 15-minute 1,230 33.1% 0.94 −38.1% −54.1% −44.0% +10.6% −69.3% $4,728
S&P 500 1-hour 794 44.6% 0.85 −45.2% −49.8% −30.6% −21.1% −57.4% $1,541
Nasdaq 100 5-minute 1,688 28.5% 1.07 +257.4% −43.6% +169.0% +32.9% −65.8% $31,487
Nasdaq 100 15-minute 1,203 36.4% 1.07 +85.4% −37.8% +28.5% +44.3% −50.6% $7,634
Nasdaq 100 1-hour 775 48.8% 1.12 +48.1% −19.6% +15.7% +28.1% −29.4% $1,880
DAX 5-minute 1,944 25.5% 0.97 −49.2% −67.5% +38.4% −63.3% −83.4% $9,880
DAX 15-minute 1,405 34.7% 0.97 −31.6% −54.2% +42.8% −52.1% −67.2% $4,401
DAX 1-hour 976 47.4% 0.96 −17.1% −24.6% +3.7% −20.0% −45.2% $1,291

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 Nasdaq 100, 5-minute chart +257.4% from 2020 to 2025
Middle test (median): half of the 27 did better, half did worse Gold, 15-minute chart −55.7% from 2020 to 2025

What we found

What the 27 backtests show

  1. With the standard rules, 24 of the 27 tests lost money from 2020 to 2025, after trading costs. Of the 36,029 trades, 21.9% reached the take-profit at P, 61.4% hit the stop-loss, and 16.7% were still open at 15:00 New York time and closed then. We measure trades in R. R is 1% of the account at the time of the trade (not the R1 line): the amount each trade was sized to risk. Before trading costs, the average trade made almost nothing: +0.007R. After costs, it lost 0.083R. The cost is the spread, the gap between the buy and the sell price, and it weighed most on 5-minute charts, where the stop-loss is closest: the average trade lost 0.105R there after costs, against 0.052R on 1-hour charts.

  2. To see whether the pivot lines themselves matter, we ran the same rules on fake lines. Every day, we moved P, S1 and R1 up or down together by a random amount. The amount was between 15% and 50% of the previous day's range: the distance from its high to its low. The lines stayed the same distance apart, so the trades had the same kind of take-profits and stop-losses. Only the place of the lines changed. On about 6 days in 7, the fake S1 and R1 were not near any real pivot line. That means they were more than 5% of the day's range away from P, S1, R1, S2 and R2. Before costs, the average trade at the fake lines lost 0.011R, and at the real lines it made +0.007R. On 8 of the 9 markets, the real and the fake lines were less than 0.05R per trade apart (see the table below). That is about half of what the spread cost the average trade: 0.09R. After costs, the fake lines lost money in all 27 tests. They made more trades, 45,748, because a line that is moved closer to the price gets reached more often.

  3. The Nasdaq 100 was the one market where the standard rules made money. From 2020 to 2025, it made +257.4% on the 5-minute chart, +85.4% on the 15-minute chart and +48.1% on the 1-hour chart. All three made money in both 2020–2023 and 2024–2025. The 1-hour test also passed all four of our checks (see 'How a test passes'). The 5-minute and 15-minute tests failed two of them: the profit factor in 2024–2025 and the Monte Carlo drawdown. Both the buys and the sells made money: +125.2R and +173.7R on the three charts together. Before costs, the Nasdaq 100 trades at the real lines made +0.133R each, and at the fake lines they lost 0.012R. But be careful with this result. It is 1 market of 9, and its three charts trade the same daily lines, so they are not three separate results. And at S2 and R2, the next lines further from P, the same rules lost money on the Nasdaq 100 on all three charts.

  4. Waiting for a candle to close back above S1 (or back below R1) did better than a limit order at the line. A limit order is an order that waits at a set price. With limit orders at S1 and R1, every touch of a line opened a trade: 61,719 trades instead of 36,029. Before costs, these trades lost 0.022R each on average, while the trades that waited for the close made +0.007R. Our test filled the limit orders exactly at the line and charged them no spread on the way in. Even so, after costs, they lost 0.079R per trade, about the same as the 0.083R of the standard rules. With far more trades, they lost more in total, and they made money in 2 of 27 tests, compared with 3.

  5. Trading only each market's busiest hours made the results worse, not better. In this version, the currency pairs, gold and silver traded from 08:00 London time to 15:00 New York time. The US indices traded from 09:30 to 15:00 New York time, and the DAX from 09:00 to 17:30 Frankfurt time. Before costs, its trades lost 0.021R each on average, compared with a gain of 0.007R with the standard rules, and only 1 of the 27 tests made money after costs. On the Nasdaq 100, with the standard rules, the trades that opened from 06:00 to 09:30 New York time made +244.9R on the three charts together. That is most of the whole profit of +298.9R. The busiest-hours version starts at 09:30, so it left those trades out, and it lost money on the Nasdaq 100's 5-minute and 1-hour charts.

Do the lines matter?

On 8 of the 9 markets, fake lines did about as well as the real pivot lines before costs

Each row puts together the 5-minute, 15-minute and 1-hour charts of one market, from 2020 to 2025, with the standard rules. The real lines are the pivot lines (P, S1 and R1). The fake lines are the same lines moved up or down together every day, by a random amount between 15% and 50% of the previous day's range. Results are in R: R is 1% of the account at the time of the trade (not the R1 line). 'Before costs' adds back the spread that each trade paid.

Market Average trade before costs, real lines Average trade before costs, fake lines Average trade after costs, real lines Average trade after costs, fake lines
EUR/USD +0.007R +0.032R −0.078R −0.068R
GBP/USD −0.012R −0.028R −0.108R −0.139R
USD/JPY −0.027R −0.019R −0.110R −0.108R
AUD/USD +0.002R +0.018R −0.122R −0.123R
Gold −0.001R 0.000R −0.084R −0.102R
Silver −0.041R −0.070R −0.254R −0.299R
S&P 500 −0.019R −0.027R −0.081R −0.096R
Nasdaq 100 +0.133R −0.012R +0.082R −0.069R
DAX +0.021R −0.020R −0.014R −0.060R
All 9 markets +0.007R −0.011R −0.083R −0.110R

With the real lines, the 9 markets made 36,029 trades. With the fake lines, they made 45,748, because a line that is moved closer to the price gets reached more often. Before costs, the real lines did better on 5 of the 9 markets and the fake lines on 4. Only on the Nasdaq 100 was the gap bigger than 0.05R per trade. For scale: with the real lines, the spread cost the average trade about 0.09R.

The four changes, trade by trade

Before costs, every version came close to break-even

Each row adds up all 27 tests of one version (9 markets, each on 5-minute, 15-minute and 1-hour charts) from 2020 to 2025. The versions are explained under 'Can the pivot point bounce be improved?' further down. Results are in R: R is 1% of the account at the time of the trade (not the R1 line). 'Before costs' adds back the spread that each trade paid.

Version Trades Trades that made money Average trade before costs Average trade after costs Tests that made money
Standard rules 36,029 32.3% +0.007R −0.083R 3 of 27
Limit orders at S1 and R1 61,719 23.4% −0.022R −0.079R 2 of 27
Busiest hours only 25,846 34.4% −0.021R −0.109R 1 of 27
First touch of each line only 17,321 33.2% +0.007R −0.078R 4 of 27
S2 and R2 instead of S1 and R1 12,664 39.1% +0.003R −0.077R 3 of 27
Fake lines (a check, not a version) 45,748 28.8% −0.011R −0.110R 0 of 27

'Trades that made money' also counts the trades that closed at 15:00 with a profit, so it is higher than the share of trades that reached the take-profit. The limit orders paid no spread on the way in, so they paid less in trading costs per trade than the other versions. The first-touch and the S2 and R2 versions made far fewer trades, so they lost less in total, but each trade lost about as much as with the standard rules.

The strategy

What the pivot point bounce is

Pivot points are price lines that many day traders put on their charts. They come from the previous day's high, low and close, so every day has new lines. The main line is the pivot point (P), the average of those three prices. Above it are the resistance lines R1 and R2, where traders expect rising prices to stop and turn down. Below it are the support lines S1 and S2, where they expect falling prices to stop and turn up. These are the classic pivot points, also called floor pivots: traders on the floor of the exchange used them before charting software. The pivot point bounce trades those turns. A common way to trade it: buy when price falls to S1 and turns back up. Sell short (sell first, to profit if price falls) when price rises to R1 and turns back down. Take profit at P. The lines depend on when each day starts. Our test starts the day at 17:00 New York time, for every market. That is when the forex market's day ends and the next one begins, so many forex brokers start their daily candles, and their pivot lines, at that time. Gold, silver and the 3 stock indices also take a daily break in our price data around then, between 16:15 and 18:00 New York time. So for them, each day runs from one daily break to the next. A day that starts at midnight, in London or New York time, would make a short extra day on Sunday evenings. Monday's lines would then come from those few hours of prices.

Pivot lines
Classic (floor) pivot points from the previous trading day's high (H), low (L) and close (C). P = (H + L + C) ÷ 3, R1 = 2 × P − L and S1 = 2 × P − H. For the S2 and R2 version: R2 = P + (H − L) and S2 = P − (H − L).
Trading day
17:00 to 17:00 New York time, for every market (the text above explains why). For the S&P 500 and the Nasdaq 100, this is the US index futures day: in our data, from 18:00 to 16:15 New York time. For the DAX, it runs from about midnight to the late evening in Frankfurt. So the index lines come from the whole day, not only from the stock market hours. Some index traders draw their lines from the stock market hours only (09:30 to 16:00 New York time for the US indices). We did not test that.
Entry
At the next candle's open, after a candle reaches the line and closes back above S1 (for a buy) or back below R1 (for a sell)
Stop-loss
1 ATR(14) beyond the line. ATR (average true range) is how far price moves in an average candle, measured over the last 14 candles of the chart. So the stop-loss is closer on a 5-minute chart than on a 1-hour chart.
Take-profit
P, the pivot point. On a typical trade (the median), P was 4.2 times as far from the entry as the stop-loss on 5-minute charts. It was 2.6 times as far on 15-minute charts, and 1.3 times on 1-hour charts.
Trading hours
New trades from 18:00 in the evening to 15:00 the next afternoon, New York time. A trade still open at 15:00 closes then. On US market holidays, gold, silver and the US indices closed early in our data, at about 13:00 New York time. A trade still open then closed at the first candle after the market opened again. This happened to 61 out of 36,029 trades.
Risk per trade
1% of the account, which started at $10,000
Smallest trade size
When risking 1% needed a trade smaller than the smallest size a market allows, the test skipped the trade. This happened 2,597 times, almost all on the silver and gold 5-minute and 15-minute charts, and all except 36 times after the account had lost 90% of its starting balance. Two more trades were refused because the account did not have enough margin (the money a broker holds while a trade is open). The smallest sizes are 1,000 units of a currency pair, 1 ounce of gold, 50 ounces of silver and 0.1 of an index contract. Gold trades in whole ounces and silver in steps of 50 ounces, so many of their trades were rounded down. In total, 1,350 out of 7,258 gold and silver trades risked less than 0.9% of the account. A very close stop-loss can also need a bigger trade than the account may open: 30 times the account balance on currency pairs, and 20 times on the other markets. Then the trade used the biggest size allowed and risked less than 1%. This happened to 282 trades, 277 of them on 5-minute charts.
Fills
A fill is the price at which an order opens or closes a trade. Entries, and the 15:00 close, fill at a candle's open. The stop-loss fills at its price, or at a candle's open if price opens past it. The take-profit fills at its exact price. When price reaches both in the same candle, the test looks at the 1-minute candles inside it to see which came first. If both are in the same 1-minute candle, the test counts the stop-loss as hit first.
Trading costs
Each market's usual spread (the gap between the buy and the sell price). Currency pairs: 0.8 pips on EUR/USD, 1.2 on GBP/USD, 0.9 on USD/JPY and 1.0 on AUD/USD (a pip is 0.0001, or 0.01 on USD/JPY). Metals: $0.30 on gold and $0.020 on silver. Stock indices: 0.4 points on the S&P 500, 1.5 on the Nasdaq 100 and 1.0 on the DAX. For silver, the Nasdaq 100 and the DAX, these are wider than our backtest engine's own spreads, to match a typical retail broker. Our test treats chart prices as the middle between the buy and the sell price. So a trade pays half the spread when it opens at a candle's open, and half when it closes at the stop-loss or at 15:00. The take-profit is a limit order (an order that waits at a set price), so it pays no spread: our test fills it as soon as price touches P. With a real broker, a limit order at P fills only when the chart price goes half a spread past P. In 95.5% of the take-profit exits, price did that before the stop-loss or 15:00, so a real order would have filled too, though not always in the same candle. The other 357 trades made +757.5R in our test. With a real broker, 200 of them would have hit the stop-loss instead, and 157 would have closed at 15:00, so the real results would have been worse. On the Nasdaq 100, 34 trades were like this, with +48.5R of its +298.9R. In the limit-order version, the entries are limit orders too, and they pay no spread in our test. No commission.
Overnight fees
None. Every trade closes by 15:00 New York time, before the daily rollover at 17:00, when brokers charge overnight fees (swaps). The 61 trades held over a market holiday are the only exception.
Price data
CFD prices: the prices a broker quotes for a CFD (contract for difference), the product most brokers outside the US offer for trading these markets.

The rules we tested

  1. Each trading day runs from 17:00 to 17:00 New York time. At the start of the day, calculate the lines from the previous day's high (H), low (L) and close (C). P = (H + L + C) ÷ 3, S1 = 2 × P − H and R1 = 2 × P − L.
  2. Buy when a candle's low reaches S1 or goes below it, and the candle closes back above S1. The candle before it must have closed above S1, so price came down to S1 from above. The trade opens at the next candle's open.
  3. Sell short when a candle's high reaches R1 or goes above it, the candle closes back below R1, and the candle before it closed below R1.
  4. Skip the signal if the candle has already closed at or beyond P, because price is already at the target.
  5. Take profit at P. ATR (average true range) is an indicator of how far price moves in an average candle, measured over the last 14 candles of the chart. Put the stop-loss 1 ATR beyond the line: 1 ATR below S1 for a buy, and 1 ATR above R1 for a sell.
  6. Open new trades only from 18:00 in the evening to 15:00 the next afternoon, New York time. There are no new trades from 17:00 to 18:00: that hour is the forex day's rollover, when trading is thin, and gold, silver and the indices are closed. If a trade is still open at 15:00, close it then, before any of these markets closes for the day.
  7. Only one trade is open at a time, but a day can have several trades. Size every trade so that a loss at the stop-loss costs 1% of the account.
  8. Don't trade on 25 December and 1 January. These days, and the few minutes of prices that some markets have after the Friday close, are left out of the lines too.

The method

How we tested it

The test

Markets
EUR/USD, GBP/USD, USD/JPY, AUD/USD, Gold, Silver, S&P 500, Nasdaq 100 and DAX
Charts
5-minute, 15-minute and 1-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 pivot point bounce be improved?

We tested four changes that pivot traders often make, one at a time, on the same 27 tests. They are listed in the table below: limit orders at the lines, the busiest hours only, the first touch only, and the outer lines S2 and R2. We picked the best change using 2020–2023 only: the one that made money in the most tests. Then we checked it on 2024–2025, the years we did not use to pick it. A change that is picked and judged on the same years almost always looks better than it really is.

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
Standard rules The rules under 'The rules we tested'. Wait for a candle to close back above S1 (for a buy) or back below R1 (for a sell), then enter at the next candle's open. 6 of 27middle test −52.9% 6 of 27middle test −27.2% 3 1
Limit orders at S1 and R1 No candle close needed. While price is above S1, a buy limit order (an order that waits at a set price) waits at S1. While price is below R1, a sell limit order waits at R1. The trade opens as soon as price reaches the line. The stop-loss (1 ATR beyond the line) and the take-profit (P) are the same as in the standard rules. Our test filled these orders exactly at the line, with no spread. 4 of 27middle test −76.1% 3 of 27middle test −45.1% 1 0
Busiest hours only Only take signals from candles that open in each market's busiest hours. For the currency pairs, gold and silver, that is from 08:00 London time to 15:00 New York time. For the S&P 500 and the Nasdaq 100, it is from 09:30 to 15:00 New York time, when the US stock market is open. For the DAX, it is from 09:00 to 17:30 Frankfurt time, when the Frankfurt stock exchange is open. 2 of 27middle test −44.3% 6 of 27middle test −23.2% 0 0
First touch of each line onlyBest on 2020–2023 Only the first candle of the day that reaches S1 can give a buy, and only the first candle that reaches R1 can give a sell. If that candle does not close back above S1 (or back below R1), there is no trade at that line that day. Many traders say a line holds best the first time price reaches it. 5 of 27middle test −39.6% 5 of 27middle test −18.9% 2 1
S2 and R2 instead of S1 and R1 The same rules at the outer lines: buy the bounce at S2 with the take-profit at S1, and sell short the turn at R2 with the take-profit at R1. The stop-loss is 1 ATR beyond S2 or R2. Many traders expect the outer lines to hold better. 4 of 27middle test −21.1% 7 of 27middle test −10.0% 3 1

None of the four changes made money in most tests. In 2020–2023, the years we used to pick, trading only the first touch of each line did best of the four changes: 5 of 27 tests made money. That is 1 fewer than the standard rules (6 of 27). In 2024–2025, the years we kept for the check, it made money in 5 of 27, compared with 6. It made fewer trades, 17,321 instead of 36,029, so it lost less: in 2024–2025, its middle test lost 18.9%, compared with 27.2%. S2 and R2 lost the least: in 2024–2025, 7 of 27 tests made money, and the middle test lost 10.0%. All 3 of its tests that made money in both periods were on the DAX, where the standard rules lost money on all three charts. Limit orders and the busiest hours did worse than the standard rules in 2020–2023.

Passed all four checks with first touch of each line only

  • Nasdaq 100, 1-hour

Questions

Questions traders ask

Do pivot points work?

Not as a bounce strategy on most markets, in our backtest. Buying the bounce off S1 and selling the turn at R1, with the take-profit at the pivot point, lost money in 24 of 27 tests after trading costs. We tested 9 markets from 2020 to 2025: 4 currency pairs, gold, silver, the S&P 500, the Nasdaq 100 and the DAX. Each ran on 5-minute, 15-minute and 1-hour charts. Only the Nasdaq 100 made money. Before costs, the average trade came close to break-even: +0.007R, where R is 1% of the account. Fake lines, moved up or down every day by a random amount, did about as well before costs on 8 of the 9 markets. So on most markets, the real pivot lines gave these trades no clear advantage over lines at other prices.

Which pivot point level is the strongest: S1 and R1, or S2 and R2?

Trades at S2 and R2 won more often in our test, but they did not make more money. With the same rules at S2 and R2, 39.1% of the trades made money, compared with 32.3% at S1 and R1. This version buys at S2 and sells short at R2, with the take-profit at S1 or R1. After costs, its average trade lost 0.077R, about the same as the 0.083R at S1 and R1, where R is 1% of the account. Price reached S2 and R2 less often, so it made 12,664 trades instead of 36,029. With both pairs of lines, 3 of 27 tests made money, but in different markets: the DAX at S2 and R2, and the Nasdaq 100 at S1 and R1. Each of them lost money at the other pair of lines, so we would not rely on either.

Should you place a limit order at the pivot level or wait for a candle to close?

Waiting for the close did better in our test, but neither way made money on most markets. With a limit order at S1 or R1 (an order that waits at the line), every touch of the line opened a trade: 61,719 trades instead of 36,029. Before costs, those trades lost 0.022R each on average (R is 1% of the account). The trades that waited for a candle to close back above S1 or back below R1 made +0.007R. Our test filled the limit orders at the line with no spread, and after costs they still lost 0.079R per trade. They made money in 2 of 27 tests, compared with 3 when waiting for the close.

What time zone should you use for pivot points?

We can't say which is best, because we tested only one start time. Our trading day ran from 17:00 to 17:00 New York time, for every market, because that is when the forex day ends and a new one begins. Many forex brokers start their daily candles, and so their pivot lines, at that time. Gold, silver and the 3 stock indices also take a daily break in our price data around then. A day from midnight to midnight, in London or New York time, makes a short extra day on Sunday evenings. Then Monday's lines come from a few hours of prices, unless your platform leaves that short day out.

Keep exploring

Related strategies we tested

Support & resistance Support and resistance breakout strategy backtest Made money in 10 of 30 tests, 5 of them in both periods. Best: GBP/JPY, 4-hour, +93%
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 PivotPointsBounce(Strategy):
    """The daily pivot points bounce: buy a bounce off S1, sell short a rejection at R1, and
    take profit at the pivot point (P).
    The trading day runs from 17:00 to 17:00 New York time. That is when the forex day ends,
    and every market in the test (currency pairs, gold, silver, stock indices) has its daily
    break in our data between 16:15 and 18:00 New York time, so each day runs from one break
    to the next. Classic floor pivots come from the previous trading day's high (H), low (L)
    and close (C):
        P = (H + L + C) / 3    R1 = 2P - L    S1 = 2P - H    R2 = P + (H - L)    S2 = P - (H - L)
    A day that falls on a Saturday or a Sunday (a few minutes of prices after the Friday
    close), 25 December and 1 January are not traded and do not give pivots: the next day
    uses the last full day before them. A day needs at least 4 hours of candles to give pivots.
    Standard (all switches off): buy when a candle's low reaches S1 or goes below it, the
    candle closes back above S1, and the candle before it closed above S1 (price came down to
    S1 and bounced). Sell short when a candle's high reaches R1 or goes above it, the candle
    closes back below R1, and the candle before it closed below R1. The trade opens at the
    next candle's open. Skip the signal if the candle already closed at or beyond P. The
    take-profit is P. The stop-loss is 1 ATR(14) beyond the line: S1 - ATR for a buy, R1 + ATR
    for a sell. New trades only from 18:00 to 15:00 New York time; a trade still open at 15:00
    New York closes then, before any of these markets closes for the day (the DAX closes at
    16:00 New York on most Fridays). One trade at a time. Size every trade so the stop-loss
    costs 1% of the account.
    The changes, one at a time:
      limit_entry = 1   no candle close needed: while price is above S1, a buy limit order waits
                        at S1; while price is below R1, a sell limit order waits at R1. The orders
                        are placed again at every candle close with that candle's ATR, and the
                        first one that fills cancels the other. Same stop-loss and take-profit.
      session     = 1   only signals from candles that open in the market's busiest hours:
                        08:00 London to 15:00 New York for the currency pairs, gold and silver;
                        09:30 to 15:00 New York for the US indices (the US stock market, until
                        the daily exit); 09:00 to 17:30 Frankfurt for the DAX.
      first_touch = 1   only the first candle of the day that reaches the line can give a trade
      level       = 2   trade the bounce at S2 and R2 instead, with the take-profit at S1 and R1
      fake_lines  = 1   a check, not a way to trade: every day, move P, S1, R1, S2 and R2 up or
                        down together, by 15% to 50% of the previous day's range (the amount and
                        the direction change from day to day, from the date only). The distances
                        between the lines stay the same, so only the place of the lines changes.
    """
    params = {"level": Param(type=int, default=1, min=1, max=2),
              "atr_mult": Param(type=float, default=1.0, min=0.1, max=5.0),
              "limit_entry": Param(type=int, default=0, min=0, max=1),
              "session": Param(type=int, default=0, min=0, max=1),
              "first_touch": Param(type=int, default=0, min=0, max=1),
              "fake_lines": Param(type=int, default=0, min=0, max=1)}
    lookback = 3
    day_start = "17:00"      # the trading day starts at 17:00 New York time
    first_trade = 60         # new trades from 18:00 New York (minutes after the day starts)
    day_end = 1320           # open trades close at 15:00 New York (minutes after the day starts)
    min_day_minutes = 240    # a day needs 4 hours of candles to give pivots
    us_indices = ("USA500IDXUSD", "USATECHIDXUSD", "USA30IDXUSD")
    def init(self, ctx):
        self.ny = ctx.clock("America/New_York")
        self.lon = ctx.clock("Europe/London")
        self.fra = ctx.clock("Europe/Berlin")
        self.atr = ctx.atr(period=14)
        self.day = None            # today: [high, low, close, minutes of candles, trade today?]
        self.lines = None          # (P, S1, R1, S2, R2) from the last full trading day
        self.low_touched = False   # a candle has reached today's buy line
        self.high_touched = False  # a candle has reached today's sell line
        self.orders = []           # resting limit orders (limit_entry = 1)
        self.trades_before = 0     # closed trades when those orders were placed
    def on_bar(self, ctx):
        p = ctx.params
        m = self.ny.minute_of_day                  # this candle's open, New York time
        if self.ny.new_day(at=self.day_start) or self.day is None:
            self.start_day(ctx, m)
        d = self.day
        hi, lo, cl = ctx.high[0], ctx.low[0], ctx.close[0]
        d[0] = hi if d[0] is None else max(d[0], hi)
        d[1] = lo if d[1] is None else min(d[1], lo)
        d[2] = cl
        d[3] += ctx.timeframe_minutes
        # A limit order filled (limit_entry = 1): cancel the other one.
        if self.orders and (ctx.position is not None or len(ctx.closed_trades) > self.trades_before):
            self.cancel_orders(ctx)
        if self.lines is None:
            return
        pivot, s1, r1, s2, r2 = self.lines
        if p.level == 2:
            buy_line, sell_line, buy_target, sell_target = s2, r2, s1, r1
        else:
            buy_line, sell_line, buy_target, sell_target = s1, r1, pivot, pivot
        first_low = lo <= buy_line and not self.low_touched
        first_high = hi >= sell_line and not self.high_touched
        self.low_touched = self.low_touched or lo <= buy_line
        self.high_touched = self.high_touched or hi >= sell_line
        start = (m - 1020) % 1440                  # this candle's open, minutes after 17:00 New York
        end = start + ctx.timeframe_minutes        # this candle's close
        if ctx.position is not None:
            if end >= self.day_end:
                ctx.close_position()               # 15:00 New York: fills at the next candle's open
            return
        if self.orders:
            self.cancel_orders(ctx)                # placed again below, with this candle's ATR
        a = self.atr.value
        if a is None:
            return
        if not ctx.gate("trading_day", d[4]):
            return
        if not ctx.gate("trading_hours", start >= self.first_trade and end < self.day_end):
            return
        if p.session == 1 and not ctx.gate("busy_hours", self.busy_hours(ctx, m)):
            return
        gap = p.atr_mult * a
        if p.limit_entry == 1:
            self.place_limits(ctx, cl, buy_line, sell_line, buy_target, sell_target, gap)
            return
        c1 = ctx.close[1]
        buy = c1 > buy_line and lo <= buy_line < cl
        sell = c1 < sell_line and hi >= sell_line > cl
        if not ctx.gate("bounce_off_line", buy or sell):
            return
        if p.first_touch == 1 and not ctx.gate("first_touch_today", first_low if buy else first_high):
            return
        if buy:
            if not ctx.gate("room_to_target", cl < buy_target):
                return
            stop = buy_line - gap
            size = ctx.size_by_risk_pct(0.01, stop=stop, entry=cl)
            if ctx.gate("size_fits_1pct_risk", size > 0):
                ctx.buy(size=size, sl=stop, tp=buy_target, tag="pivot_long")
        else:
            if not ctx.gate("room_to_target", cl > sell_target):
                return
            stop = sell_line + gap
            size = ctx.size_by_risk_pct(0.01, stop=stop, entry=cl)
            if ctx.gate("size_fits_1pct_risk", size > 0):
                ctx.sell(size=size, sl=stop, tp=sell_target, tag="pivot_short")
    def start_day(self, ctx, m):
        """A new trading day: pivots from the day that just ended, if it was a full one."""
        d = self.day
        if d is not None and d[4] and d[0] is not None and d[0] > d[1] and d[3] >= self.min_day_minutes:
            self.lines = self.make_lines(ctx, d[0], d[1], d[2])
        weekday = self.ny.weekday
        date = self.ny.date[5:]
        if m >= 1020:                              # from 17:00 on, the trading day is tomorrow
            weekday = (weekday + 1) % 7
            date = {"12-24": "12-25", "12-31": "01-01"}.get(date, "")
        self.day = [None, None, None, 0, weekday < 5 and date not in ("12-25", "01-01")]
        self.low_touched = self.high_touched = False
        if self.orders:
            self.cancel_orders(ctx)
        if ctx.position is not None:
            ctx.close_position()                   # the market closed early: close at the next candle
    def make_lines(self, ctx, h, l, c):
        pivot = (h + l + c) / 3
        rng = h - l
        lines = [pivot, 2 * pivot - h, 2 * pivot - l, pivot - rng, pivot + rng]
        if ctx.params.fake_lines == 1:
            day = ctx.bar_time // 86_400_000
            u = ((day * 2654435761) % 4294967296) / 4294967296
            move = (0.15 + 0.35 * ((u * 2) % 1)) * rng * (1 if u < 0.5 else -1)
            lines = [x + move for x in lines]
        return tuple(lines)
    def busy_hours(self, ctx, m):
        sym = ctx.symbol.upper()
        if sym in self.us_indices:
            return 570 <= m < 900                      # 09:30 to 15:00 New York
        if sym == "DEUIDXEUR":
            return self.fra.between("09:00", "17:30")  # the Frankfurt stock exchange
        if sym == "GBRIDXGBP":
            return self.lon.between("08:00", "16:30")  # the London stock exchange
        return m < 900 and self.lon.minute_of_day >= 480   # 08:00 London to 15:00 New York
    def place_limits(self, ctx, close, buy_line, sell_line, buy_target, sell_target, gap):
        if close > buy_line:
            stop = buy_line - gap
            size = ctx.size_by_risk_pct(0.01, stop=stop, entry=buy_line)
            if ctx.gate("size_fits_1pct_risk", size > 0):
                order = ctx.buy(size=size, limit=buy_line, sl=stop, tp=buy_target, tag="pivot_limit_long")
                if order is not None:
                    self.orders.append(order)
        if close < sell_line:
            stop = sell_line + gap
            size = ctx.size_by_risk_pct(0.01, stop=stop, entry=sell_line)
            if ctx.gate("size_fits_1pct_risk", size > 0):
                order = ctx.sell(size=size, limit=sell_line, sl=stop, tp=sell_target, tag="pivot_limit_short")
                if order is not None:
                    self.orders.append(order)
        self.trades_before = len(ctx.closed_trades)
    def cancel_orders(self, ctx):
        for order in self.orders:
            ctx.cancel_order(order.order_id)
        self.orders = []

Your turn

Test the pivot point bounce yourself

Change the settings, the market or the stop-loss and see the result in seconds. Ask the BacktestingMax AI: Backtest a pivot point bounce on the Nasdaq 100, 15-minute chart: daily classic pivots from 17:00 New York time, buy when a candle closes back above S1, sell short when a candle closes back below R1, take profit at the pivot point, stop-loss 1 ATR beyond the line, close open trades at 15:00 New York time.

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