Idea in brief
Andrea Unger, a four-time winner of the World Cup Trading Championship, builds strategies for each futures market separately. The starting point is almost always the same. Buy on a breakout of the prior session high, exit at the end of the day, with a mandatory stop. If this skeleton gives a rising but still untradable equity curve on a market, Unger looks for conditions under which the breakout works better.
Unger calls one of the filters almost universal: the daily ADX with a period of 5. When ADX is below 35, the breakout works noticeably better than when ADX is high. A high ADX, as Unger explains it, means the market has already run a lot and is exhausted.
Variant B from Toby Crabel adds no entry rules. It gives rare figures: the share of continuations after a run above yesterday's high has fallen from 56% to 52 or 51%. This is a reason to measure the decay of the basic breakout by year before adding filters to it.
Why it might work
Unger compares the market to a runner chasing a bus. After a strong directional move it is hard for the market to keep running right away, and a breakout of another high fades more often. When ADX is low, the market has rested, and a move above yesterday's high more often turns into a move for the whole day. Unger names the horizon this applies to: intraday or three to four days.
Unger does not use indicators as a setup, only as a filter of conditions. The method is described directly. The same entry is run separately with the condition and without it. If the outcome changes statistically, the condition is checked for common sense: does it have an explanation, or is it a coincidence.
Crabel explains why such breakouts are weakening. Markets trade around the clock, and instead of the open and yesterday's extremes there are now 10-20 reference points. The prior day's close has become more important than before. Around one- and two-day highs and lows there are many options-related orders, markets stall there, and there is more mean reversion. A shift in probability of a few percent, according to Crabel, changes the trading result a lot.
Unger gives no figures for the ADX filter. It is an assessment based on experience with the markets Unger trades.
Rules
Filter (author)
// daily series: Unger uses 1440-minute bars so that the close is the last trade of the day, not the settlement
DailyADX = ADX(5) on yesterday's closed daily bar // author: period 5
// Finetiq: Wilder smoothing, as in the standard ADX
TradeAllowed = DailyADX < 35 // author: "below 40 or 35"
Entry (author)
// 15-minute chart, liquid CME and EUREX futures
PrevHigh = high of the prior session
PrevLow = low of the prior session
IF TradeAllowed AND TradesToday = 0
BUY STOP at PrevHigh + 1 tick // author: breakout of the prior session high; Finetiq: 1 tick offset
// Finetiq: mirrored short on a breakout of PrevLow. Unger describes the long, test the short separately
// Finetiq: one trade per day
Exit (author, sizes by Finetiq)
StopLoss = EntryPrice - 0.5 * DailyATR(20) // author: a stop is always mandatory; Finetiq: size
EXIT at SessionClose - 15 min // author: exit at the end of the day; Finetiq: time
// the author's other skeleton exits: after two days or at a take-profit, sizes not named
How Unger tests the filter (author)
Run A: same entry and exit, only days with DailyADX < 35
Run B: same entry and exit, only days with DailyADX >= 35
// compare the average trade, profit factor and the shape of the equity curve
// the condition goes into the system if the difference is noticeable and has an explanation
// cost screen: test on 1 contract without commissions,
// but the average trade must cover commission and slippage with a margin
Variant B. Testing the decay per Toby Crabel
// event: during the day price exceeded the prior session high
Event = High > PrevHigh
// continuation: Crabel did not name a definition, the rest is Finetiq
Continued = Close > PrevHigh // the day closed above the broken level
// variant: Close > PrevHigh + 0.25 * DailyATR(20)
ContinuationRate[year] = number of days (Event AND Continued) / number of Event days
// Crabel: about 56% before, now 52%, 51% or less
// calculate by year, separately for days with DailyADX < 35 and >= 35
// mirrored for a run below yesterday's low
Parameters
| Parameter | Value | Source |
|---|---|---|
| Markets | liquid CME and EUREX futures | author |
| Entry timeframe | 15 minutes | author (Unger's main timeframe) |
| Entry level | prior session high | author |
| Offset | 1 tick | Finetiq |
| Filter | daily ADX(5) < 35 | author |
| Second threshold | 40 | author |
| Daily bar | 1440-minute, close without settlement | author |
| Stop | mandatory, 0.5 × daily ATR(20) | author (presence), Finetiq (size) |
| Exit | end of day | author |
| Alternative exits | after 2 days, take-profit | author, sizes not named |
| Short | mirrored at the low | Finetiq |
| Trades per day | 1 | Finetiq |
| Continuation in variant B | close above the broken high | Finetiq |
What to test
- The filter by the author's method. Two runs of the same entry and exit: ADX(5) below 35 and not below 35. Unger says the difference is huge. If there is none on your market, the filter is not needed.
- Filter neighborhood. ADX period 4, 5, 7 and 10, threshold 25, 30, 35 and 40. A robust filter gives similar results at neighboring values. Unger names two thresholds, 35 and 40.
- Decay by year. Calculate the continuation rate from variant B for each year, separately for days with and without the filter. Check Crabel's figures on your markets and whether ADX keeps the rate above 52%.
- Which daily bar. ADX on daily bars with settlement versus 1440-minute bars. Unger switched to 1440 minutes precisely because of settlement.
- Which session. The main session high versus the 24-hour session high. For futures these are different levels, and Crabel says around-the-clock trading has changed the reference points themselves.
- Average trade versus costs. The author's main screen. If the average trade per contract is close to $80 on mini NASDAQ or lower, Unger does not trade such a system. Add commission and 1-2 ticks of slippage on the stop entry order and on the exit.
- Gaps and long versus short. Look separately at days when the market opened above yesterday's high and the stop order filled immediately. On indices, compare the long with the mirrored short: the author describes only the long.
Platform notes
TradingView (Pine Script)
- Daily ADX on a 15-minute chart without lookahead:
request.security(syminfo.tickerid, "D", adx[1], lookahead = barmerge.lookahead_on), whereadxcomes fromta.dmi(5, 5). Without[1]the backtest will see today's unfinished ADX. ta.dmicalculates ADX with Wilder smoothing, like the standard indicator in EasyLanguage.- Take yesterday's high via
request.securitywith the[1]offset too. A CME futures daily bar starts at 18:00 ET, so this high includes overnight trading. Calculate the main session high yourself over a time window. - Stop order:
strategy.entry("L", strategy.long, stop = prevHigh + syminfo.mintick). If the day opened above the level, the order fills at the first available price, not at the level.
MultiCharts and TradeStation (EasyLanguage)
- Kevin Davey (The Algorithmic Advantage, #036) describes the same pitfall as Unger. In TradeStation, the close of a futures daily bar is the settlement, while for a 1440-minute bar it is the last trade. ADX and signals differ between the two bar types. Backtest and trade on the same type.
- Add the daily series as a second data stream (
Data2) and useADX(5) of Data2on the closed daily bar. Buy next bar at PrevHigh + MinMove / PriceScale stoplives for one bar. Send it on every 15-minute bar while there has been no entry that day.- End-of-day exit:
If Time >= 1545 then Sell next bar at marketwith the session closing at 16:00 (the bar is labeled with its close time).SetExitOnClosedoes not fire in live trading.
MetaTrader 5 (MQL5)
- MT5 has two ADX indicators:
iADXwith different smoothing andiADXWilder. To match Pine and EasyLanguage, useiADXWilder(_Symbol, PERIOD_D1, 5), with the value from the closed bar (shift 1). - The daily bar is built on the broker's server time. Brokers whose server is not on GMT+2/+3 may show short Sunday bars. With a period of 5, one such bar is a fifth of the ADX window.
- Yesterday's high
iHigh(_Symbol, PERIOD_D1, 1)on a CFD is the high of the server day, not the high of the exchange's main session. The author chose the ADX threshold of 35 on futures, so it has to be retested on CFD daily bars. - Place a pending
BuyStopviaCTradewith expiration at the end of the day, so an unfilled order does not carry over to tomorrow.
Where the idea can break
- There are no figures for the ADX filter. "Much better" is Unger's assessment for the markets Unger trades and for strategy versions that are further tuned to each market.
- Unger says that the skeleton "breakout of yesterday's high, exit at the end of the day" is usually untradable: the average trade does not cover costs. The filter reduces the number of trades, and costs remain the main risk.
- Crabel's figures come without a market, period or definition of continuation. If the shift from 56% to 51% is real, the basic breakout is close to a coin flip, and all the edge has to come from the filter.
- Crabel links stalls at one- and two-day extremes to options orders and to a rise in mean reversion. This is an argument against a breakout of yesterday's high rather than for it.
- The author did not name the stop and take-profit sizes. The stop changes the result more than the ADX threshold does, and it is easy to overfit.
- The "prior session" high for around-the-clock futures, cash indices and CFDs is three different levels. The test result depends on this choice more than it seems.