New Indicators + Tutorial: Previous Day High/Low and Average Daily Range (ADR)
Ask any day trader which levels they mark on the chart before the open, and two answers come up again and again: yesterday’s high and low, and how far the market usually moves in a day. Today we’re adding both as indicators on TAAPI.IO:
- Previous Day/Week High and Low (
prevhl): the previous day’s or week’s high, low, open and close, whether price is above, below or inside that range, and, for US stocks, today’s pre-market high and low. - Average Daily Range (
adr): the average high-to-low range of recent days, and how much of a normal day’s range the market has already covered today.
This post explains both, shows how traders combine them, and walks you through three examples you can copy and run.
Previous Day High and Low (PDH/PDL)
The previous day’s high (PDH) and low (PDL) are some of the most watched levels in trading. Everyone sees the same numbers, so a lot of orders tend to sit around them. Traders use them in a few ways:
- Breakouts. Price pushing above the PDH (or below the PDL) shows that buyers (or sellers) have taken control beyond yesterday’s range.
- Failed breakouts. Price pokes above the PDH and then closes back inside the range. This “sweep” often traps breakout traders and leads to a move the other way.
- Range days. As long as price stays between the PDH and PDL, many traders expect a range and fade the edges instead of chasing moves.
The same logic works on the previous week’s high and low, for swing traders who think in bigger timeframes.
Endpoint: prevhl
Optional inputs:
period(default:day):dayfor the previous day’s levels,weekfor the previous week’s.session(default:regular, US stocks only):regularbuilds the levels from the 09:30–16:00 New York session (13:00 on early-close days);extendeduses 04:00–20:00, including pre-market and after-hours.
The indicator works on intraday timeframes down to 1m. You don’t need to request daily candles yourself: TAAPI.IO fetches a longer candle series behind the scenes, so the previous day or week is always available. For US stocks, use 1m, 5m or 15m, so pre-market and regular trading don’t get mixed into the same candle. US stocks follow the New York calendar (weekends and holidays are skipped); crypto uses UTC days and weeks starting Monday 00:00 UTC.
Your first request
curl -G https://v2.taapi.io/indicator/prevhl \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-urlencode "exchange=stocks" \
--data-urlencode "symbol=AAPL" \
--data-urlencode "timeframe=1m"
This is a real response, requested on Saturday, 7 November, after Friday’s session had closed:
{
"prevHigh": [355.38],
"prevLow": [342.06],
"prevOpen": [353.89],
"prevClose": [344.33],
"prevStart": [1793889000],
"currentHigh": [345.79],
"currentLow": [338.3],
"premarketHigh": [342.8],
"premarketLow": [338],
"position": ["inside"],
"brokeHigh": [false],
"brokeLow": [true],
"timestamp": [1794013140]
}
Here’s how to read it:
prevHigh,prevLow,prevOpenandprevCloseare the previous trading day’s regular-session levels. Friday is the latest session here, so the previous day is Thursday;prevStartis Thursday’s 09:30 New York open.currentHighandcurrentLoware the current day’s running high and low: Friday’s regular session. During the pre-market, before the session opens, they’renull.premarketHighandpremarketLoware that day’s 04:00–09:30 pre-market levels, another set of levels many stock traders watch at the open.positiontells you where the latest close sits against the previous range:above,beloworinside.brokeHighandbrokeLowturntrueas soon as today has traded beyond the previous high or low, even if price has since come back.
Look at this response again: brokeLow is true, but position is inside. On Friday, AAPL traded down to 338.30, below Thursday’s low of 342.06, and then closed back inside Thursday’s range. That’s the failed breakdown described above, the mirror image of a failed breakout, and you can spot it with a single request.
Average Daily Range (ADR)
The Average Daily Range is the average distance between the daily high and low over the last few days. It tells you how much a market normally moves in a day, which is useful for:
- Realistic targets. If a stock usually moves $4 a day and it’s already moved $3.80 today, a target $2 further away is unlikely to be hit today.
- Avoiding late entries. When a market has already covered 100% or more of its usual range, chasing the move is risky. Many day traders skip new entries at that point.
- Stops that fit the market. A stop at a fixed fraction of the ADR adapts automatically to calm and volatile periods.
Endpoint: adr
Optional input:
period(default:14): how many completed candles to average. The current candle is left out, because it’s usually still forming.
Use timeframe=1d for the classic daily ADR. Other timeframes give you the average range per candle instead, for example the average 4-hour range.
Your first request
curl -G https://v2.taapi.io/indicator/adr \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-urlencode "exchange=binance" \
--data-urlencode "symbol=BTCUSDT" \
--data-urlencode "timeframe=1d"
A real response, from early on 7 November:
{
"value": [2324.826428571427],
"valuePercent": [3.0192838469593974],
"currentRange": [384.11999999999534],
"rangeUsedPercent": [16.522523801315852],
"timestamp": [1794009600]
}
valueis the ADR in price: over the last 14 days, BTC moved about 2,325 USDT between its daily high and low.valuePercentis the same as a percentage (ADR%): about 3.02%. Use it to compare volatility between markets with very different prices.currentRangeis today’s range so far: about 384 USDT.rangeUsedPercentis today’s range as a percentage of the ADR: today has covered about 17% of a normal day.
Values come back unrounded, so round them however your application needs.
Example 1: A stock breakout scanner with an ADR filter (Node.js)
This scanner checks a watchlist of US stocks during the session and answers two questions for each one: where is price against yesterday’s range, and how much of its daily range has it used up? It uses a single bulk request, with two constructs per stock: prevhl on 5-minute candles and adr on daily candles.
const API_KEY = 'YOUR_API_KEY';
const SYMBOLS = ['AAPL', 'NVDA', 'TSLA', 'MSFT', 'AMD'];
async function scan() {
const res = await fetch('https://v2.taapi.io/bulk', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify({
constructs: SYMBOLS.flatMap((symbol) => [
{
id: `${symbol}_5m`,
exchange: 'stocks',
symbol,
timeframe: '5m',
indicators: [{ id: 'levels', indicator: 'prevhl', backtrack: 1 }]
},
{
id: `${symbol}_1d`,
exchange: 'stocks',
symbol,
timeframe: '1d',
indicators: [{ id: 'adr', indicator: 'adr' }]
}
])
})
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
for (const symbol of SYMBOLS) {
const levels = data[`${symbol}_5m`]?.levels;
const adr = data[`${symbol}_1d`]?.adr;
if (!levels || !adr) continue;
const position = levels.position[0];
const used = adr.rangeUsedPercent[0];
const extended = used >= 100 ? ` ⚠️ already ${used.toFixed(0)}% of ADR, extended` : ` (${used.toFixed(0)}% of ADR used)`;
if (position === 'above') {
console.log(`🟢 ${symbol}: above yesterday's high ${levels.prevHigh[0]}${extended}`);
} else if (position === 'below') {
console.log(`🔴 ${symbol}: below yesterday's low ${levels.prevLow[0]}${extended}`);
} else if (levels.brokeHigh[0]) {
console.log(`↩️ ${symbol}: failed breakout, traded above ${levels.prevHigh[0]} and fell back inside`);
} else if (levels.brokeLow[0]) {
console.log(`↩️ ${symbol}: failed breakdown, traded below ${levels.prevLow[0]} and came back inside`);
} else {
console.log(` ${symbol}: inside yesterday's range ${levels.prevLow[0]} – ${levels.prevHigh[0]}${extended}`);
}
}
}
scan();
Run it with Node.js 18 or newer (node scan.js), for example every 5 minutes during the session. When we ran it after Friday’s close, the output looked like this:
↩️ AAPL: failed breakdown, traded below 342.06 and came back inside
NVDA: inside yesterday's range 181.462 – 196.25 ⚠️ already 133% of ADR, extended
TSLA: inside yesterday's range 338.15 – 374.3 (98% of ADR used)
🔴 MSFT: below yesterday's low 532.675 (88% of ADR used)
↩️ AMD: failed breakout, traded above 456.2 and fell back inside
Five stocks, five different stories: two failed moves, one clean breakdown, and NVDA, which stayed inside Thursday’s range despite moving a third more than on a normal day.
A few details:
prevhlusesbacktrack: 1, sopositiondescribes the last closed 5-minute candle. A breakout on a forming candle can still disappear before it closes.adrdoesn’t usebacktrack, because you want today’s forming daily candle: that’s whatrangeUsedPercentmeasures.- Construct IDs may only contain letters, numbers and underscores, which is why the IDs are
AAPL_5mandAAPL_1d. - How many constructs fit in one bulk request depends on your plan; see the pricing page.
Example 2: Weekly levels for crypto (Node.js)
Swing traders often care more about last week’s high and low than yesterday’s. Set period: 'week' and the same indicator gives you the previous week’s range (Monday 00:00 UTC to Sunday 23:59 UTC for crypto):
const API_KEY = 'YOUR_API_KEY';
const SYMBOLS = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT'];
async function weeklyLevels() {
const res = await fetch('https://v2.taapi.io/bulk', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${API_KEY}` },
body: JSON.stringify({
constructs: SYMBOLS.map((symbol) => ({
id: symbol,
exchange: 'binance',
symbol,
timeframe: '1h',
indicators: [{ id: 'week', indicator: 'prevhl', period: 'week', backtrack: 1 }]
}))
})
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
for (const symbol of SYMBOLS) {
const w = data[symbol]?.week;
if (!w) continue;
const high = w.prevHigh[0], low = w.prevLow[0];
const range = `${low} – ${high}`;
const broke = [w.brokeHigh[0] && 'high', w.brokeLow[0] && 'low'].filter(Boolean).join(' and ') || 'neither side';
console.log(`${symbol}: last week ${range}, now ${w.position[0]}, this week has broken ${broke}`);
}
}
weeklyLevels();
When we ran it on Saturday, 7 November:
BTCUSDT: last week 76325.98 – 81971, now below, this week has broken low
ETHUSDT: last week 2174.08 – 2391.55, now inside, this week has broken high
SOLUSDT: last week 92.34 – 103.85, now below, this week has broken low
Bitcoin and Solana have broken below last week’s lows and stayed there, while Ethereum poked above last week’s high and fell back inside.
If this week has broken both the previous high and low, the market has expanded in both directions, which is typical of volatile, news-driven weeks. If it has broken neither, the market is coiling inside last week’s range, and a breakout from that range is what many swing traders wait for.
Example 3: Volatility check and ADR-based stops (Python)
ADR% is a quick way to see whether a market is calmer or wilder than usual. This script fetches the last 60 days of ADR for Bitcoin, compares today with the recent average, and turns the ADR into a stop distance and the range left for the rest of the day:
import requests
API_KEY = "YOUR_API_KEY"
resp = requests.get(
"https://v2.taapi.io/indicator/adr",
headers={"Authorization": f"Bearer {API_KEY}"},
params={
"exchange": "binance",
"symbol": "BTCUSDT",
"timeframe": "1d",
"results": 60,
},
)
adr = resp.json()
pct = [p for p in adr["valuePercent"] if p is not None]
avg_pct = sum(pct) / len(pct)
now = adr["value"][-1]
now_pct = adr["valuePercent"][-1]
used = adr["rangeUsedPercent"][-1]
regime = "more volatile than" if now_pct > avg_pct * 1.2 else "calmer than" if now_pct < avg_pct * 0.8 else "about as volatile as"
print(f"ADR(14) is {now:.2f} USDT ({now_pct:.2f}%), {regime} the 60-day average of {avg_pct:.2f}%")
remaining = max(now - adr["currentRange"][-1], 0)
print(f"Today has used {used:.0f}% of a normal day, about {remaining:.2f} USDT of range left")
print(f"Suggested stop distance (25% of ADR): {now * 0.25:.2f} USDT")
When we ran it:
ADR(14) is 2324.83 USDT (3.02%), about as volatile as the 60-day average of 2.72%
Today has used 17% of a normal day, about 1940.71 USDT of range left
Suggested stop distance (25% of ADR): 581.21 USDT
The 25% stop is only an example; pick the fraction that fits your strategy. The point is that the stop grows and shrinks with the market’s actual volatility, instead of being a fixed number that’s too tight in wild markets and too wide in quiet ones.
Each value in the series is calculated only from the candles up to that point and never repaints, so you can use the same data to backtest without lookahead bias.
Tips
- Use closed candles for signals.
currentHigh,currentLow,positionand the break flags include the forming candle. Addbacktrack=1when you act on them, so a signal can’t vanish before the candle closes. - Pick the right session for stocks. The default
session=regularmatches the levels most traders draw on their charts. Usesession=extendedif you trade pre-market and after-hours. - Compare markets with
valuePercent. An ADR of 5 means very different things for a $20 stock and a $500 stock. ADR% puts them on the same scale, which makes it a good filter for picking which stocks to day trade. - Combine the two. A breakout above the previous day’s high with plenty of ADR left is a very different trade from the same breakout when 120% of the daily range is already used up.
- Got a
202response? The data is still being fetched. Retry after a second or two.
As always, test a strategy on historical data before you trade it with real money. These levels show you where the market has been and how far it usually goes. They don’t guarantee where it will go next.
Where to go from here
- Full parameter and field reference: prevhl documentation and ADR documentation
- Combine them with other indicators from the indicators library, such as VWAP, EMA or the new Fair Value Gap
- Trade US stocks? See our US stocks coverage
Both indicators are available now on every plan. Give them a try, and if you build something with them, we’d love to hear about it: get in touch.