Skip to main content
Version: Java (Groovy)

Ema

Ema creates an EMA (exponential moving average) for an updateBy table operation. The formula for an EMA is:

a=e1τa = e^{\frac{-1}{\tau}}

ϵn=aϵn1+(1a)x\epsilon_{n} = a\epsilon_{n - 1} + (1 - a)x

Where:

  • τ\tau is the window size, an input parameter to the method.
  • ϵ\epsilon is the EMA.
  • xx is the current value.

Syntax

Ema(tickDecay, pairs...)
Ema(control, tickDecay, pairs...)
Ema(control, timestampColumn, timeDecay, pairs...)
Ema(control, timestampColumn, durationDecay, pairs...)
Ema(timestampColumn, timeDecay, pairs...)
Ema(timestampColumn, durationDecay, pairs...)

Parameters

ParameterTypeDescription
tickDecaylong

The decay rate in ticks (rows).

pairsString...

The input/output column name pairs.

controlOperationControl

Defines how special cases should behave. If not given, default OperationControl settings are used.

timestampColumnString

The column in the source table to use for timestamps.

timeDecaylong

The decay rate in nanoseconds.

durationDecayDuration

The decay rate in a Duration object.

Returns

An UpdateByOperation to be used in an updateBy table operation.

Examples

One column, no groups

The following example calculates the tick-based and time-based EMA of the X column, renaming the resultant column to EmaX. The tick decay rate is set to 5 rows, and the time decay rate is set to 5 seconds. No grouping columns are specified, so the EMA is calculated for all rows.

baseTime = parseInstant("2023-01-01T00:00:00 ET")

source = emptyTable(10).update("Timestamp = baseTime + i * SECOND", "Letter = (i % 2 == 0) ? `A` : `B`", "X = i")

result = source.updateBy([Ema(5, "EmaTickX = X"), Ema("Timestamp", 5 * SECOND, "EmaTimeX = X")])

One EMA column, one grouping column

The following example builds on the previous by specifying Letter as the key column. Thus, the EMA is calculated on a per-letter basis.

baseTime = parseInstant("2023-01-01T00:00:00 ET")

source = emptyTable(10).update("Timestamp = baseTime + i * SECOND", "Letter = (i % 2 == 0) ? `A` : `B`", "X = i")

result = source.updateBy([Ema(5, "EmaTickX = X"), Ema("Timestamp", 5 * SECOND, "EmaTimeX = X")], "Letter")

Multiple EMA columns, multiple grouping columns

The following example builds on the previous by calculating the EMA of multiple columns with each UpdateByOperation. Also, the groups are defined by unique combinations of letter and boolean in the Letter and Truth columns, respectively.

baseTime = parseInstant("2023-01-01T00:00:00 ET")

source = emptyTable(20).update("Timestamp = baseTime + i * SECOND", "Letter = (i % 2 == 0) ? `A` : `B`", "Truth = randomBool()", "X = i", "Y = randomInt(5, 10)")

result = source.updateBy([Ema(2, "EmaTickX = X", "EmaTickY = Y"), Ema("Timestamp", 3 * SECOND, "EmaTimeX = X", "EmaTimeY = Y")], "Letter", "Truth")

Multiple UpdateByOperations, multiple grouping columns

The following example builds on the previous by calculating the tick- and time-based EMA of the X and Y columns using different EMA UpdateByoperations. This allows each EMA to have its own decay rate. The decay rates are reflected in the renamed resultant columns.

baseTime = parseInstant("2023-01-01T00:00:00 ET")

source = emptyTable(20).update("Timestamp = baseTime + i * SECOND", "Letter = (i % 2 == 0) ? `A` : `B`", "Truth = randomBool()", "X = i", "Y = randomInt(5, 10)")

emaTickX = Ema(1, "EmaTickX_1row = X")
emaTickY = Ema(5, "EmaTickY_5rows = Y")
emaTimeX = Ema("Timestamp", 2 * SECOND, "EmaTimeX_2sec = X")
emaTimeY = Ema("Timestamp", 4 * SECOND, "EmaTimeY_4sec = Y")

result = source.updateBy([emaTickX, emaTickY, emaTimeX, emaTimeY], "Letter", "Truth")