Builtins: candles and the trade tape
The tape builtins read the trades that printed inside the current bar. They split into two families, and the difference matters because only one of them is available everywhere.
Bar totals, available on every bar
| Signature | Returns |
|---|---|
| tape.available() -> bool | Whether this bar carries totals or prints |
| tape.volume() -> float | Buy plus sell volume |
| tape.buy_volume() -> float | Volume that lifted the offer |
| tape.sell_volume() -> float | Volume that hit the bid |
| tape.delta() -> float | Buy volume minus sell volume |
Individual prints
| Signature | Returns |
|---|---|
| tape.prints_available() -> bool | Whether this bar carries individual prints |
| tape.count() -> int | How many prints this bar carries |
| tape.price(index: int) -> float | Price of print index, nan when out of range |
| tape.size(index: int) -> float | Size of print index, nan when out of range |
| tape.side(index: int) -> side | BUY when it lifted the offer, SELL when it hit the bid, UNDEFINED when out of range |
| tape.time(index: int) -> float | Epoch milliseconds, nan when absent |
| tape.vwap() -> float | Size weighted price of the prints on this bar |
| tape.high() -> float | Highest print price on this bar |
| tape.low() -> float | Lowest print price on this bar |
Finding the big prints in one call
These walk the prints for you with your rule as the argument, and are faster than a loop over tape.price and tape.size. Your own big trade rule is a size threshold, a side and a radius that follows size.
| Signature | Returns |
|---|---|
| tape.largest_index() -> int | Index of the largest print on the bar, or -1 |
| tape.largest_size() -> float | Size of that print, nan when there is none |
| tape.largest_price() -> float | Price of that print |
| tape.largest_side() -> side | Side of that print |
| tape.nth_largest_index(rank: int) -> int | Index of the print at that size rank, 0 being the largest, or -1. Equal sizes keep tape order |
| tape.count_above(min_size: float) -> int | How many prints on the bar are at least min_size |
| tape.volume_above(min_size: float) -> float | Their total volume |
| tape.buy_volume_above(min_size: float) -> float | The part of it that lifted the offer |
| tape.sell_volume_above(min_size: float) -> float | The part that hit the bid |
- Print indexes start at 0 and run to tape.count() minus 1, in the order the trades printed.
- tape.largest_index and tape.nth_largest_index answer -1 when there is no print, and tape.price, tape.size, tape.side and tape.time answer nan or UNDEFINED for -1, so the pair needs no guard.
- A whole bar answer is one call. Reach for tape.price and tape.size only when you want one specific print.
- Calling any print accessor tells the chart your indicator wants the per print tape for the window, which is a heavier load than totals alone. Use the totals when they answer the question.
- Bars built from the tape carry prints for the whole loaded window. Time based history is served as completed candles, so on a time chart tape.prints_available() is commonly false on older bars while the totals still answer. Guard print work with tape.prints_available().
let has_prints: bool = tape.prints_available()
let mean_size: float = tape.volume() / math.max(tape.count(), 1)
let first_side: side = tape.side(0)
let sweep: bool = has_prints && tape.size(0) > 100 && first_side == "BUY"
let biggest: int = tape.largest_index()
let biggest_price: float = tape.price(biggest)