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
What we found
What the 27 backtests show
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.
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.
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.
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.
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
- 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.
- 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.
- 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.
- Skip the signal if the candle has already closed at or beyond P, because price is already at the target.
- 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.
- 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.
- 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.
- 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
.
Free account. No credit card needed.
See every strategy we tested Browse strategies shared by tradersBacktest 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.