# Market data in WickScript

> How WickScript reads other timeframes and markets without look-ahead, sessions, killzones and time in UTC, orderflow from ticks, the footprint, every single trade with on tick, and the order book.

Updated: 2026-10-25T00:01:52.000Z · https://chartrider.com/docs/wickscript/data/

Besides the candles of your chart, a script can read other timeframes and markets, the time and session of each candle, orderflow from the recorded trades, the footprint and the order book. ChartRider loads this data automatically before the script runs – in the chart, with F5, in replay and in the Strategy Lab.

## Other timeframes: `on`

```text
<expression> on <timeframe>
```

`ema(close, 50) on 4h` calculates the EMA on 4h candles. Each candle of your chart gets the value of the **last 4h candle that has closed** by the close of your candle – never the running 4h candle. The value changes only when a 4h candle closes, so a higher timeframe can't repaint or look ahead, in the chart as in the backtest.

On a 1h chart, `close on 4h` on the 13:00–14:00 candle is the close of the 08:00–12:00 candle; on the 15:00–16:00 candle it becomes the close of the 12:00–16:00 candle, which has closed at 16:00.

- The timeframe is a time span (`15m`, `1h`, `4h`, `1d`, `1w` …) or a timeframe input: `tf = input timeframe 4h "Timeframe"`, then `… on tf`. A variable holding a time span is not allowed.
- **Write the whole calculation inside**: `ema(close, 50) on 4h` is the EMA of 4h closes. `ema(close on 4h, 50)` is something else – a 50-candle EMA on your chart of the stepped 4h close.
- `on` binds to the value directly in front of it. Use brackets for a calculation: `(high - low) on 1d`.
- Inside `on` (and `of`) you can use market data, built-in and your own functions, inputs and constants – but not your script's variables that change per candle, `use` aliases, `position`, orderflow, the footprint or the order book. The checker explains this with a suggestion.

```wickscript
wickscript 1
indicator "Higher timeframe trend" on chart
tf = input timeframe 4h "Timeframe"
len = input 50 "EMA length"
htf = ema(close, len) on tf
dayRange = (high - low) on 1d
show htf as line "HTF EMA" color amber
show close crosses above htf as event "Above HTF EMA"
hud "Range of the last closed day {dayRange}"
```

## Other markets: `of`

```text
<expression> of <MARKET>
```

`close of BTCUSDT` reads another market on the same exchange and in the same category as your chart. On the same timeframe it is the candle with the same close time; combined with `on`, `close of BTCUSDT on 4h` is the close of the last closed BTCUSDT 4h candle. Market names consist of letters and digits and ignore upper and lower case.

```wickscript
wickscript 1
indicator "ETH vs BTC" in pane
ratio = close / close of BTCUSDT
show ratio / sma(ratio, 50) - 1 as line "Ratio vs. average" color cyan
show pct(close, close[20]) - pct(close, close[20]) of BTCUSDT as histogram "20-candle outperformance"
show rsi(close, 14) of BTCUSDT on 1h as line "BTC 1h RSI" color amber
```

## Time

| Value | Meaning |
|---|---|
| `time` | open time of the candle (unit time); `time - time[1]` is a time span |
| `hour` | hour of the candle's open time, UTC, 0 … 23 |
| `minute` | minute of the candle's open time, 0 … 59 |
| `weekday` | weekday in UTC: `Monday` … `Sunday` |
| `date` | date in UTC as text, e.g. `"2026-10-24"` |

These values are always in UTC, whatever time zone the chart displays. Compare weekdays with `weekday is Monday` or `weekday is Saturday or Sunday`, dates with `date == "2026-10-24"`.

History works on these values like on any other: `hour[1]` is the hour of the previous candle, `session[1]` its session.

```wickscript
wickscript 1
indicator "Time filters" in pane
h = hour
newHour = h != h[1]
weekend = weekday is Saturday or Sunday
gap = time - time[1] > 1h
show newHour as event "New hour"
show weekend as event "Weekend"
show gap as event "Data gap"
show hour >= 13 and hour < 17 as event "13–17 UTC"
```

## Sessions

`session` is the trading session of the candle, by its open time: `"Asia"`, `"London"`, `"NewYork"`, or `""` between the sessions. The names `Asia`, `London` and `NewYork` are built in.

| Session | Definition | UTC in European winter | UTC in European summer |
|---|---|---|---|
| Asia | 00:00–08:00 UTC | 00:00–08:00 | 00:00–07:00 (07:00–08:00 counts as London) |
| London | 08:00–13:00 London time | 08:00–13:00 | 07:00–12:00 |
| NewYork | 09:30–16:00 New York time | 14:30–21:00 (US winter) | 13:30–20:00 (US summer) |

European and US daylight saving time are applied separately, each with its own dates.

```wickscript
wickscript 1
indicator "Sessions" in pane
show session is London or NewYork as event "London or New York"
show (session is London) becomes true as event "London open"
show session is not Asia as event "Not Asia"
show session == "" as event "Between sessions"
```

## Killzones

`killzone` is the ICT killzone of the candle, defined in New York time with US daylight saving time: `"Asia"`, `"London"`, `"NewYork"`, `"LondonClose"` or `""`. `in killzone London` is the same as `killzone is London`.

| Killzone | New York time | UTC (US winter) | UTC (US summer) |
|---|---|---|---|
| Asia | 20:00–24:00 | 01:00–05:00 | 00:00–04:00 |
| London | 02:00–05:00 | 07:00–10:00 | 06:00–09:00 |
| NewYork | 07:00–10:00 | 12:00–15:00 | 11:00–14:00 |
| LondonClose | 10:00–12:00 | 15:00–17:00 | 14:00–16:00 |

```wickscript
wickscript 1
indicator "Killzone highs" on chart
inLondon = in killzone London
when high == highest(high, 20) and (inLondon or in killzone NewYork)
    mark "KZ high" above color orange
end
hud "Killzone: {killzone} · session: {session}"
```

`vwap("session")` restarts the VWAP at each session start like the VWAP indicator's session anchor: Asia 00:00, London 08:00 and New York 14:30 UTC, London an hour earlier during European summer time and New York an hour earlier during US summer time – the same sessions as `session`.

## Orderflow from the ticks

These values are calculated per candle from the recorded trades (ticks) of the market:

| Value | Unit | Meaning |
|---|---|---|
| `buyVolume` | amount | volume of aggressive buys (in the base currency, like `volume`) |
| `sellVolume` | amount | volume of aggressive sells |
| `delta` | amount | `buyVolume - sellVolume` |
| `cvd` | amount | cumulative delta: the running sum of `delta` |
| `trades` | number | number of trades in the candle; trades in the same millisecond count as one |

- Candles without tick data are `na`. The Scripts tab tells you the coverage, e.g. "tick data for 1,879 of 2,000 candles – the rest is na".
- `cvd` starts at the first candle with tick data among the loaded candles and continues over gaps. Its level therefore depends on where the loaded history begins – compare its changes (`cvd - cvd[10]`, `cvd - ema(cvd, 50)`), not its level.

```wickscript
wickscript 1
indicator "Delta spikes" in pane
avgDelta = sma(abs(delta), 50)
show delta as histogram "Delta"
show delta > 3 * avgDelta as event "Buy spike"
show delta < -3 * avgDelta as event "Sell spike"
show (cvd - cvd[20]) / sma(volume, 20) as line "CVD change (volumes)" color cyan
show trades as line "Trades"
```

Orderflow values are amounts, so compare them with amounts: `delta > amount(0)`, not `delta > 0`. A strategy filter that lets trades through where no tick data exists:

```wickscript
wickscript 1
strategy "Delta confirmed breakout" risk 1%
top = highest(high, 20)[1]
buyers = isna(delta) or delta > amount(0)
when close crosses above top and buyers
    enter long at market
    stop at lowest(low, 10)
    target at 2R
end
```

## Footprint

| Value | Unit | Meaning |
|---|---|---|
| `footprint.poc` | price | point of control: the price row with the most volume |
| `footprint.vah`, `footprint.val` | price | value area high and low: 70 % of the volume around the POC |
| `footprint.buyImbalances` | number | number of buy imbalances in the candle |
| `footprint.sellImbalances` | number | number of sell imbalances |
| `footprint.imbalance` | number | `buyImbalances - sellImbalances` |

The footprint is built from the ticks of each candle with rows one price step (tick) high. An imbalance is diagonal at 3 : 1 or more – the buy volume of a row against the sell volume one row lower, and the other way round; against an empty row nothing counts. It needs tick data and a timeframe from 1m to 1d that divides the day evenly; elsewhere the values are `na`.

```wickscript
wickscript 1
indicator "Footprint POC" on chart
show footprint.poc as line "POC" color amber
show footprint.vah as line "VAH" color gray
show footprint.val as line "VAL" color gray
when footprint.imbalance >= 3
    mark "buy imb" below color green
end
```

## Every trade: `on tick … end`

```text
on tick
    <calculations>
end
```

The block runs once for every trade (tick) of the candle, in time order. Inside it, `trade` is the current trade:

| Value | Unit | Meaning |
|---|---|---|
| `trade.price` | price | price of the trade |
| `trade.size` | amount | size of the trade |
| `trade.side` | text | `"buy"`, `"sell"` or `""` |
| `trade.buy`, `trade.sell` | yes/no | aggressive buy / sell |
| `trade.time` | time | time of the trade |

Rules:

- `on tick` goes at the top level of the script. Inside it only calculations are allowed: `=`, `if` and `repeat`. `show`, `mark`, `hud`, alerts and strategy statements come after its `end`.
- Results leave the block through variables. Normal variables start every candle as `na`, so set them before the block (`count = 0`); `keep` variables carry over from candle to candle.
- Built-in functions with a history (`ema`, `highest` …) update once per candle, not per trade.
- Use `amount(…)` for a fixed size: `trade.size >= amount(50)`. `trade` outside an `on tick` block is an error.
- Ticks are loaded for the **last 3 days** of the loaded candles. On older candles the block doesn't run, and the Scripts tab reports the coverage ("on tick: ticks for … of … candles (the last 3 days)").

```wickscript
wickscript 1
indicator "Large trades" in pane
minSize = input 50 "Large trade size"
bigBuys = 0
bigSells = 0
bigBuyVolume = amount(0)
topPrice = price(0)
keep totalBig = 0
on tick
    if trade.size >= amount(minSize) then
        if trade.buy then
            bigBuys = bigBuys + 1
            bigBuyVolume = bigBuyVolume + trade.size
        end
        if trade.sell then bigSells = bigSells + 1 end
        totalBig = totalBig + 1
    end
    topPrice = max(topPrice, trade.price)
end
show bigBuys - bigSells as histogram "Large buys - sells"
show bigBuyVolume as line "Large buy volume"
hud "Large trades so far: {totalBig} · highest trade {topPrice}"
```

## Order book

The order book is read once per candle, as it stood at the candle's close.

| Value | Unit | Meaning |
|---|---|---|
| `book.bid`, `book.ask` | price | best bid and best ask |
| `book.spread` | price | `book.ask - book.bid` |
| `book.mid` | price | `(book.bid + book.ask) / 2` |
| `book.available` | yes/no | order book data exists at this candle |
| `book.bidPrice(n)`, `book.askPrice(n)` | price | price of the n-th level, n = 1 … 10 |
| `book.bidSize(n)`, `book.askSize(n)` | amount | size of the n-th level, n = 1 … 10 |
| `book.bidVolume(depth)`, `book.askVolume(depth)` | amount | total size of the best 5, 10, 25 or 50 levels |
| `book.imbalance(depth)` | number | `(bid - ask) / (bid + ask)` over the best 5, 10, 25 or 50 levels, from −1 to 1 |
| `available(book)` | yes/no | the same as `book.available` |

The level `n` and the `depth` must be fixed numbers (or inputs); the depth can be passed by name: `book.bidVolume(depth: 10)`. Order book history exists only for markets that ChartRider records; elsewhere all `book.*` values are `na` and the Scripts tab says "no orderbook data for these candles".

```wickscript
wickscript 1
indicator "Book pressure" in pane
imb = book.imbalance(25)
bidWall = book.bidSize(1) > 5 * book.askSize(1)
show imb as line "Imbalance (25 levels)" color cyan
show bidWall as event "Bid wall at best"
show book.spread / tick as line "Spread (ticks)"
hud "Book data: {available(book)}"
```

## When data is missing

| Data | Needs | Without it |
|---|---|---|
| `on 4h`, `of BTCUSDT` | candles of that timeframe or market (loaded automatically) | `na`, message "no 4h candles yet" |
| `buyVolume`, `sellVolume`, `delta`, `cvd`, `trades` | tick data | `na`, coverage message |
| `footprint.*` | tick data, timeframe 1m … 1d | `na`, coverage message |
| `on tick` | ticks of the last 3 days | the block doesn't run, coverage message |
| `book.*` | recorded order book | `na`, message |

Comparisons with `na` are false, so a condition on missing data never fires. Write `isna(x) or …` to let a filter pass where data is missing, or `not isna(x) and …` / `available(book) and …` to require data.
