Rolling average, Rolling Sdeviation, etc.
A function that maps a 1-D array to a scalar is called an array-reducing function. Examples are Sum, Average, SDeviation, Product, Min, Max, etc. Occasionally I get asked the question: How do I compute the rolling metric (e.g., the rolling average or rolling sdeviation), in which you want the array reducing function to be applied to the most recent «windowSize» values (i.e., applied to a window).
Here is a User-Defined Function that can be used with any array reducing function, including your own UDFs, given that they have the form
Function F( x : [I] ; I : Index ).
Function Rolling( metric : Function( z:[I] ; I : Index ) ; x : [T] ; T : Index ; windowSize : positive atom ) ::= LocalIndex Window := 1-windowSize .. 0; metric( X[@T=@T+Window], Window )
You could use this to compute the rolling Sdeviation of revenue over the previous 12 months using:
Rolling( SDeviation, Revenue, Time, 12 )
Rolling has a time-complexity of O( N * windowSize * s(windowSize) ), where N is the length of your array's index (e.g., Time), and s(k) is the complexity of computing the metric (which is often O(k)).
You can use the Rolling function to compute these:
Rolling( Sum, Revenue, Time, 12 ) Rolling( Average, Revenue, Time, 12 ) Rolling( Kurtosis, Revenue, Time, 12 ) Rolling( Max, Revenue, Time, 12 )
and others. However, a rolling Sum and rolling Ave can be easily computed in O(n) time, which can be noticeably faster. For that, you can add this UDF:
Function RollingAve( X : Array[T] ; T : Index ; windowSize : positive atom ) := Local cum := cumulate(X,T) Do (cum - cum[@T=@T-windowSize,defVal:0]) / min([@T,windowSize])
For RollingSum, use the same definition but just remove the denominator.