contextby

Syntax

contextby(func, funcArgs, groupingCol, [sortingCol], [semanticFilter=1])

or

funcArg func:X groupingCol

or

func:X(funcArgs, groupingCol, [sortingCol], [semanticFilter=1])

Arguments

func is a function. For the second use case, func can only have one parameter (funcArg).

funcArgs are the parameters of func. It is a tuple if there are more than 1 parameter of func.

groupingCol is the grouping variable(s). It can be one or multiple vectors.

sortingCol is an optional argument for within group sorting before applying func.

semanticFilter (optional) is a positive integer indicating which columns to include in calculations when funcArgs is a table. The possible values are:

  • 0 - All columns
  • 1 (default) - Columns of FLOATING, INTEGRAL, and DECIMAL categories, excluding the COMPRESSED data type.
  • 2 - Columns of TEMPORAL category.
  • 3 - Columns of LITERAL category, excluding the BLOB data type.
  • 4 - Columns of FLOATING, INTEGRAL, DECIMAL, and TEMPORAL categories, excluding the COMPRESSED data type.

The vectors in groupingCol, sortingCol and each of the function argument in funcArgs all have the same size.

Details

Calculate func(funcArgs) for each groupingCol group. The result is a vector of the same size as each of the input arguments other than func. If func is an aggregate function, all elements within the same group have identical result. We can use sortingCol to sort the within-group data before the calculation.

Note: The keyword defg must be used to declare an aggregate function.

Examples

sym=`IBM`IBM`IBM`MS`MS`MS
price=172.12 170.32 175.25 26.46 31.45 29.43
qty=5800 700 9000 6300 2100 5300
trade_date=2013.05.08 2013.05.06 2013.05.07 2013.05.08 2013.05.06 2013.05.07;
contextby(avg, price, sym);
// output
[172.563,172.563,172.563,29.113,29.113,29.113]

price avg :X sym;
// output
[172.563,172.563,172.563,29.113,29.113,29.113]

price at price>contextby(avg, price,sym);
// output
[175.25,31.45,29.43]

price at price>price avg :X sym;
// output
[175.25,31.45,29.43]

sym at price>contextby(avg, price,sym);
// output
["IBM","MS","MS"]

// calculate volume-weighted average price (vwap)
contextby(wavg, [price, qty], sym);
// output
[173.856,173.856,173.856,28.374,28.374,28.374]

contextby(ratios, price, sym, trade_date) - 1;
// output
[-0.01786,,0.028946,-0.100917,,-0.064229]

Multiple vectors for groupingCol :

sym=`IBM`IBM`IBM`IBM`IBM`IBM`MS`MS`MS`MS`MS`MS
date=2020.12.01 + 0 0 0 1 1 1 0 0 0 1 1 1
qty=5800 700 9000 1000 3500 3900 6300 2100 5300 7800 1200 4300
contextby(cumsum, qty, [sym,date]);
// output
[5800,6500,15500,1000,4500,8400,6300,8400,13700,7800,9000,13300]

We can embed a contextby template into a SQL query:

t1=table(trade_date,sym,qty,price);
t1;
trade_date sym qty price
2013.05.08 IBM 5800 172.12
2013.05.06 IBM 700 170.32
2013.05.07 IBM 9000 175.25
2013.05.08 MS 6300 26.46
2013.05.06 MS 2100 31.45
2013.05.07 MS 5300 29.43
// select orders with a price higher than the average price of the group
select trade_date, sym, qty, price from t1 where price > contextby(avg, price,sym);
trade_date sym qty price
2013.05.07 IBM 9000 175.25
2013.05.06 MS 2100 31.45
2013.05.07 MS 5300 29.43
// add 1 day to all trade dates in t1
contextby(temporalAdd{,1d}, t1, t1.sym,,2)

trade_date

sym

qty

price

2013.05.09 IBM 5,800 172.12
2013.05.07 IBM 700 170.32
2013.05.08 IBM 9,000 175.25
2013.05.09 MS 6,300 26.46
2013.05.07 MS 2,100 31.45
2013.05.08 MS 5,300 29.43