Idea in brief
Brent Penfold traded Elliott waves for twelve years and blew up the trading account twice. The turning point came after a conversation with broker Jeff Morgan. Morgan calmly said that the futures on the Australian SPI index had just made their median move, three closes in a row higher, so Morgan expected a pullback and was looking for a place to sell. The next day the market fell. After that, Penfold started looking for statistics instead of opinions and became a mechanical trader.
Later Penfold measured the length of streaks of closes in one direction on the 30 markets the author trades. According to Penfold's data, one standard deviation of streak length is about 2.4 days, two are about 5 days, and the figure barely changes across markets, sectors and decades. Hence a simple hypothesis: a streak of three higher closes is already longer than typical, and the next day more often goes against it.
The card takes the setup (three higher closes, wait for a pullback) and the streak statistics from the author. The entry, stop, exit and the mirror side are ours.
Why it might work
Penfold explains it this way. If you strip the names off markets and look only at the price series, they are the same: all traders essentially trade volatility, and volatility has a stable rhythm. The author recalls George Taylor, a grain trader of the 1930s–40s. Taylor divided the market into a three-day cycle: a buying day, a selling day and a short-selling day. Sometimes the cycle stretched to a fourth or fifth day. Penfold believes the 2.4-day figure describes the same phenomenon.
A Finetiq caveat. Streak statistics by themselves do not prove a reversal. Suppose up and down days are equally likely and independent of each other. Then half of all streaks are 1 day long, a quarter are 2 days, and another quarter are 3 days or longer. In such a model 75% of streaks are no longer than two days, and about 97% are no longer than five. This is close to the author's numbers if you read them as shares of streaks. Identical figures on different markets may only mean that daily changes resemble coin flips.
There is an edge only if, after three higher closes, a lower close the next day occurs noticeably more often than usual. This can be checked in one evening without any trading system, see "What to test".
Rules
Close streaks
// daily bars
IF Close > Close[1] THEN UpStreak = UpStreak[1] + 1; DnStreak = 0
ELSE IF Close < Close[1] THEN DnStreak = DnStreak[1] + 1; UpStreak = 0
ELSE UpStreak = 0; DnStreak = 0
// Finetiq: a close equal to the previous one breaks both streaks
Entry
Setup = UpStreak == 3 // author: three higher closes in a row, wait for a pullback
// Finetiq: exactly 3, not "3 or more", so that one streak gives one signal
// Variant A: immediate entry
IF Setup AND MarketPosition == 0
SELL SHORT AT NEXT BAR OPEN // Finetiq
// Variant B: entry only if the pullback has started
IF Setup AND MarketPosition == 0
SELL SHORT STOP at Low - 1 tick // Finetiq: break of the third bar's low
// the order lives for the next bar only, then CANCEL
Stop and exit (Finetiq)
StopLoss = Highest(High, 3) + 0.5 * ATR(14) // above the streak high
EXIT STOP at StopLoss
IF UpStreak >= 5 THEN EXIT AT NEXT BAR OPEN // the streak reached the author's two deviations
IF Close < Close[1] THEN EXIT AT NEXT BAR OPEN // the pullback happened: first lower close
IF BarsSinceEntry >= 3 THEN EXIT AT NEXT BAR OPEN // per the three-day cycle from the author's story
Mirror side (Finetiq)
// the author only talks about selling after a rise. Buying after a decline is our symmetry
IF DnStreak == 3 AND MarketPosition == 0
BUY AT NEXT BAR OPEN
// stop below the streak low, exits mirrored
Recalculating the streak statistics (Finetiq)
// when a streak ends, record its length
IF UpStreak[1] > 0 AND UpStreak == 0 THEN Add(UpLengths, UpStreak[1])
IF DnStreak[1] > 0 AND DnStreak == 0 THEN Add(DnLengths, DnStreak[1])
MeanLen = Average(UpLengths)
StdLen = StdDev(UpLengths)
Share2 = share of streaks 1–2 days long
Share5 = share of streaks 1–5 days long
// the question the whole idea depends on
P_all = share of days where Close < Close[1]
P_after3 = share of days where Close < Close[1], among days with UpStreak[1] == 3
// control: the same daily changes in random order, 100 permutations
// for each permutation recalculate StdLen, Share2, Share5 and P_after3
Parameters
| Parameter | Value | Source |
|---|---|---|
| Timeframe | daily bars | author |
| Streak length for the signal | 3 higher closes in a row | author |
| Direction | sell after a rise | author |
| Buy after three lower closes | mirrored | Finetiq |
| Equal close | breaks the streak | Finetiq |
| Entry | next bar's open or a stop below the third bar's low | Finetiq |
| Stop | high of three bars + 0.5 × ATR(14) | Finetiq |
| Streak length exit | 5 higher closes in a row | Finetiq (author's number: two deviations) |
| Pullback exit | first close below the previous one | Finetiq |
| Time exit | 3 bars | Finetiq |
What to test
- Recalculate the author's statistics on your own data. Using the block above, collect the lengths of all streaks, the mean, the standard deviation, and the shares of streaks up to 2 and up to 5 days. Then shuffle the order of daily changes (do not touch the changes themselves) and calculate the same 100 times. If the real figures lie within the range of the shuffled ones, streaks on your market behave like random ones, and 2.4 days says nothing about a reversal.
- Conditional probability without trading. Compare
P_after3withP_alland with the same value on shuffled series. Repeat for streaks of 2, 4 and 5. If a decline after three higher closes is no more frequent than usual, entry and exit rules will not create an edge. - Streak length neighborhood. Run the entry after 2, 3, 4 and 5 closes. The author singles out 3. If the result exists only at 3, it looks like sampling luck.
- Immediate entry or on a break of the low. Variant A versus variant B. The second skips trades where the pullback never started, but enters lower and pays with missed moves.
- Sides and regime separately. Count sells after rises and buys after declines separately, and separately above and below SMA(200). Stock indices have a long upward drift, and a short against it can lose even when the short-term pullback is real.
- Costs. With random days, a streak of three or more higher closes occurs about 15 times a year per market, and as many downward. A trade lasts 1–3 days. Add spread, commission and CFD swap, and see whether the average trade stays positive.
- Market uniformity. The author claims that markets are the same. Run the same rules without tuning on indices, rates, currencies and commodities. Look at the median by sector, not at the best market.
Platform notes
TradingView (Pine Script)
- The streak is tracked with a counter:
var int up = 0andup := close > close[1] ? up + 1 : 0. On instruments with a large tick size equal closes are common, so check that the reset matches your definition. - Variant A matches the default execution: signal on the close, entry at the next bar's open (
process_orders_on_close = false). The entry price includes the overnight gap. - The variant B stop order via
strategy.entry(..., stop = low)stays active until canceled. By the rule it lives for one bar, sostrategy.cancelis needed on the next bar. - There are many short trades. Set
commission_valueandslippageinstrategy(), otherwise the test will show a result without costs.
MultiCharts and TradeStation (EasyLanguage)
- For futures in TradeStation, the close of a daily bar is the settlement, while a 1440-minute bar closes on the last trade. Close streaks on the two kinds of bar come out different, and the signals diverge. Test and trade on the same kind of bar.
Sell Short next bar at Low stoplives exactly one bar. This matches variant B without a separate cancel.- Set the stop as a price:
Buy to Cover next bar at StopLoss stop.SetStopLossis set in money and can produce a different level. - Time exit:
If BarsSinceEntry >= 3 then Buy to Cover next bar at market.
MetaTrader 5 (MQL5)
- The daily bar is built on the broker's server time. Servers not on GMT+2/+3 may have short Sunday bars. They add extra closes and shift the streak count. Compare the broker's daily closes with the exchange closes.
- The price of an index CFD differs from the futures close. Streaks on a CFD may not match the streaks in the author's data.
- Calculate the signal on the closed bar (index 1), once per new daily bar.
- Holding a CFD position overnight incurs swap. With a holding period of 1–3 days it noticeably cuts into a small average trade.
Where the idea can break
- The author has no test of these rules. There is one SPI episode and the streak length statistics. The trading rules are entirely our formalization.
- The same 2.4 days on all markets may be a property of a random series rather than of reversals. Test 1 will show this.
- The author talks about the median move, the standard deviation and 68% of streaks as if they were the same thing. The interview does not say how the author calculated them. Your figures may differ from the author's even on the same markets.
- Shorting after a rise on stock indices goes against a multi-year drift. A combined result for both sides can hide that only one side works.
- The average trade is short and small. Slippage at the open, spread and CFD swap eat it faster than in trend systems.
- The author's data: 30 futures markets since 1980. On a short CFD history, streak shares and conditional probabilities are unstable.