roll

Syntax

roll(X, step, [stepType='time'], [fill='none'], [closed='left'], [origin='start_day'], [exclude], [label])

Details

roll is a dummy function to define a user-defined sliding window in SQL queries. In standard CONTEXT BY or GROUP BY with analytic functions, the step is fixed at 1 row. With a dummy function interval, GROUP BY supports arbitrary steps but requires equal window sizes. While roll removes these limits, allowing user-defined window size and step.

roll should appear as the first expression in the SELECT clause and be used together with CONTEXT BY.

Return value: A vector with a length equal to the number of windows. Each element of the vector represents the last value of column X in the corresponding window, except when stepType = 'window', in which case it represents the label.

Windowing Logic

To use the roll function with the SELECT clause, the step and the window size are determined by different windowing logics:

  • If stepType='window': window size is determined by the window parameter.
  • If stepType ≠ 'window': roll only defines the step. The window size is determined by the function type in the SELECT clause:
    • Aggregate functions (built-in or user-defined): window size = step.
    • m-functions:
      • If stepType = 'time': when window is of DURATION type, window size = window; when window is an integer, window size = window * step.
      • If stepType = 'row': window must be an integer, window size = window.
      • If stepType = 'volume' / 'cumvol': window must be an integer, window size = window * step.
    • tm functions (only support stepType = 'time'): window size = window.
    • Columns in the table: window size = step, with results equivalent to applying function last on the column.

Arguments

X A column representing time or trading volume.

  • If stepType is 'time', X must be of DATETIME/TIMESTAMP/NANOTIME/NANOTIMESTAMP type, and sorted in ascending order.
  • If stepType is 'volume', X must be a numeric column (ascending order) representing the trading volume.
  • If stepType is 'cumvol', X must be a numeric column (ascending order) representing cumulative trading volume.

step Step of the sliding window, which can be:

  • A DURATION scalar, representing time interval. Supported time units: M, w, d, H, m, s, ms, us, and ns.
  • A tuple of length 2, if stepType = ‘window’, used to specify a user-defined window. The first element specifies the start time, and the second specifies the end time (must be greater than the start time), both of which must be of the same type as the X parameter and in ascending order. By default, the window is left-closed and right-open, which can be adjusted using the closed parameter.

stepType (optional) A STRING scalar specifying the step type, which can be:

  • 'time' (default): X is a temporal column, the calculation slide by the temporal column.
  • 'row': slide by row count.
  • 'volume': X is the trading volume (non-cumulative). The system automatically converts it into cumulative volume for sliding.
  • 'cumvol': X is the cumulative trading volume, calculation slide by cumulative trading volume.
  • 'window': step is a series of user-defined windows.

fill (optional) A STRING scalar specifying how to handle empty windows, which can be:

  • 'none' (default): no output.
  • 'null': output null.
  • 'prev': fill with the previous non-null value.

closed (optional) A STRING scalar specifying the closure of a user-defined window, which can be:

  • 'left' (default): left-closed, right-open.
  • 'right': left-open, right-closed.

origin (optional) A STRING scalar specifying the start point for time-based sliding, effective only when stepType='time', which can be:

  • 'start_day' (default): the start is 00:00:00 of the date corresponding to the first value in the time series.
  • 'start': the start is the first value in the time series.
  • 'epoch': the start is 1970-01-01.

exclude (optional) A tuple specifying time periods to exclude, effective only when stepType='time'. Each element is a pair of TIME, NANOTIME, MINUTE and SECOND type, e.g., the lunch break for A-shares: (11:30:00:13:00:00, 15:00:00:16:00:00). If data exists within the specified time period, it must be filtered via the WHERE clause.

label (optional) A STRING vector indicating the name of the user-defined window, with a length equal to the number of user-defined windows. Specified only when stepType='window'.

Examples

Example 1. Group by symbol and use a sliding window with step=60s to compute the average price over the past 180 and 300 seconds.

timestamp = 2025.08.10T00:00:00 + 30 * 0..19
symbol = take(`A`B`C, 20)
price = [20.81,20.34,20.42,20.99,20.01,20.60,20.45,20.70,20.05,20.25,20.52,20.32,20.15,20.67,20.28,20.70,20.98,20.48,20.01,20.42]
vol = [1002,1091,1035,1041,1016,1038,1007,1007,1062,1030,1064,1012,1007,1007,1035,1038,1015,1041,1029,1048]
t = table(timestamp as timestamp, symbol as symbol, vol as vol, price as price)

select * from t order by symbol
// compute 180s and 300s moving averages via roll and mavg.
select
    roll(X=timestamp, step=60s, stepType='time') as period,
    mavg(price, 180s) as avg_60s,
    mavg(price, 300s) as avg_300s,
    symbol,
    price,
    vol
from t
context by symbol

Part of the result:

period avg_60s avg_300s symbol price vol
2025.08.10 00:01:00 20.81 20.81 A 20.81 1,002
2025.08.10 00:02:00 20.9 20.9 A 20.99 1,041
2025.08.10 00:04:00 20.72 20.75 A 20.45 1,007
2025.08.10 00:05:00 20.35 20.625 A 20.25 1,030
2025.08.10 00:07:00 20.2 20.28333333333333 A 20.15 1,007
2025.08.10 00:08:00 20.424999999999997 20.3875 A 20.7 1,038
2025.08.10 00:10:00 20.355 20.286666666666665 A 20.01 1,029

Example 2. Group by symbol with step=2 to compute the average volume over the past 2 rows and the sum of volume over the past 3 rows.

select roll(X=vol, step=2, stepType='row') as window, avg(vol), msum(vol, 3), symbol, price, vol from t context by symbol
window avg_vol msum_vol symbol price vol
1,041 1,021.5 2,043 A 20.99 1,041
1,030 1,018.5 3,078 A 20.25 1,030
1,038 1,022.5 3,075 A 20.7 1,038
1,016 1,053.5 2,107 B 20.01 1,016
1,064 1,035.5 3,087 B 20.52 1,064
1,015 1,011 3,086 B 20.98 1,015
1,038 1,036.5 2,073 C 20.6 1,038
1,012 1,037 3,112 C 20.32 1,012
1,041 1,038 3,088 C 20.48 1,041

Example 3. Group by symbol, after excluding the 11:30–13:00 lunch break, set step=60s to calculate the average price over the past 180 and 300 seconds.

timestamp = (2025.08.10T11:20:00 + 30 * 0..8) join 2025.08.10T11:40:00.000 join 2025.08.10T11:40:30.000 join (2025.08.10T13:00:00 + 30 * 0..8)
symbol = take(`A`B`C, 20)
price = [20.81,20.34,20.42,20.99,20.01,20.60,20.45,20.70,20.05,20.25,20.52,20.32,20.15,20.67,20.28,20.70,20.98,20.48,20.01,20.42]
vol = [1002,1091,1035,1041,1016,1038,1007,1007,1062,1030,1064,1012,1007,1007,1035,1038,1015,1041,1029,1048]
t = table(timestamp as timestamp, symbol as symbol, vol as vol, price as price)

select
    roll(X=timestamp, step=60s, stepType='time', exclude=(11:30:00 : 13:00:00)) as period,
    mavg(price, 180s) as avg_60s,
    mavg(price, 300s) as avg_300s,
    symbol,
    price,
    vol
from t where second(timestamp) notBetween 11:30:00 and 13:00:00
context by symbol
period avg_60s avg_300s symbol price vol
2025.08.10 11:21:00 20.8100 20.8100 A 20.8100 1,002
2025.08.10 11:22:00 20.9000 20.9000 A 20.9900 1,041
2025.08.10 11:24:00 20.7200 20.7500 A 20.4500 1,007
2025.08.10 13:01:00 20.1500 20.1500 A 20.1500 1,007
2025.08.10 13:03:00 20.4250 20.4250 A 20.7000 1,038
2025.08.10 13:04:00 20.3550 20.2867 A 20.0100 1,029
2025.08.10 11:21:00 20.3400 20.3400 B 20.3400 1,091
2025.08.10 11:23:00 20.1750 20.1750 B 20.0100 1,016
2025.08.10 11:24:00 20.3550 20.3500 B 20.7000 1,007
2025.08.10 13:02:00 20.6700 20.6700 B 20.6700 1,007
2025.08.10 13:03:00 20.8250 20.8250 B 20.9800 1,015
2025.08.10 13:05:00 20.7000 20.6900 B 20.4200 1,048
2025.08.10 11:22:00 20.4200 20.4200 C 20.4200 1,035
2025.08.10 11:23:00 20.5100 20.5100 C 20.6000 1,038
2025.08.10 11:25:00 20.3250 20.3567 C 20.0500 1,062
2025.08.10 13:02:00 20.2800 20.2800 C 20.2800 1,035
2025.08.10 13:04:00 20.3800 20.3800 C 20.4800 1,041

Example 4. Define 3 user-defined time windows via stepType='window' to compute each stock's volume and weighted average price over the past 1, 3, and 7 days. The roll function uses incremental computation, significantly improving efficiency.

date = stretch(2025.08.01+ 0..8, 24)
time = take([09:30:00, 10:00:00, 10:30:00],24)
symbol = take(`A`B, 24)   
price = [22.40, 24.00, 23.50, 29.30, 24.10, 27.60, 20.10, 21.00, 23.60, 22.40,
               24.60, 23.30, 21.20, 20.60, 27.30, 29.30, 26.90, 25.20, 20.20, 20.10,
               28.30, 22.50, 28.20, 23.50]

vol = [1088, 1074, 1081, 1018, 1045, 1007, 1023, 1009, 1018, 1019,
           1013, 1017, 1039, 1057, 1045, 1062, 1046, 1033, 1022, 1007,
           1087, 1012, 1091, 1074]         
timestamp=concatDateTime(date,time)
t = table(timestamp as timestamp, symbol as symbol, price as price, vol as vol)
t = select * from t order by symbol, timestamp

startDates = [datetime(2025.08.01), datetime(2025.08.01), datetime(2025.08.01)]
endDates = [datetime(2025.08.02), datetime(2025.08.04), datetime(2025.08.07)]
labels = ["1d", "3d", "7d"]


select 
    roll(X=datetime(timestamp), step=(startDates, endDates), stepType='window', label=labels, fill='none') as period,
    timestamp,
    symbol,
    vol,
    price,
    sum(vol) as vol_sum,
    wavg(price, vol) as vwap
from t context by symbol
period timestamp symbol vol price vol_sum vwap
1d 2025.08.01 10:30:00 A 1,081 23.5000 2,169 22.9482
3d 2025.08.03 10:30:00 A 1,018 23.6000 5,255 22.7491
7d 2025.08.06 10:00:00 A 1,046 26.9000 9,398 23.7454
1d 2025.08.01 10:00:00 B 1,074 24.0000 1,074 24.0000
3d 2025.08.03 10:00:00 B 1,009 21.0000 4,108 25.4590
7d 2025.08.06 10:30:00 B 1,033 25.2000 9,296 24.7450