Skip to main content
Version: Python

How to use EMA

This guide will show you how to calculate the Exponential Moving Average (EMA) of data in Deephaven.

The update_by table operation can implement many operations, including EMA. This includes a time-based EMA, where the decay rate is determined by a timestamp column, as well as a tick-based EMA, where the decay rate depends on a number of rows (ticks).

The equations for an EMA is as follows:

a=edtτa = e^{\frac{-dt}{\tau}}

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

Where:

  • dtdt is the time since the previous observation for time-based EMA, and 1 for tick-based EMA.
  • τ\tau is the decay rate, an input parameter to the method.
  • ϵ\epsilon is the EMA.
  • xx is the current value.
  • nn denotes the step. The current step is nn, and the previous step is n1n - 1.

Examples

The following examples calculate the EMA of a table with random data. EMA is calculated for each unique character in a column called Sym, which emulates a real-time feed of stock, crypto, or other asset symbols.

Each example uses empty_table and update to populate a table with data. The EMA is calculated using update_by. Plots are created to visualize what the 10 second EMA looks like for a single unique value in the Sym column. For more information on XY series plots, see How to create XY series plots.

Time-based EMA

This first example calculates a time-based EMA via ema_time. A 10-second decay rate has been chosen. The EMA is stored in the output column NumbersEMA.

from deephaven.time import to_j_instant
from deephaven.updateby import ema_time
from deephaven.plot import Figure
from deephaven import empty_table
import random

base_time = to_j_instant("2023-04-01T12:00:00 UTC")


def random_char() -> str:
return random.choice(["A", "B", "C", "D", "E", "F"])


result = empty_table(100).update(
formulas=[
"Timestamp = base_time + i * SECOND",
"Sym = random_char()",
"Numbers = randomInt(0, 100)",
]
)

result_w_ema = result.update_by(
[ema_time("Timestamp", "PT10S", "NumbersEMA = Numbers")], by=["Sym"]
)

ema_A = result_w_ema.where(["Sym == `A`"])

ema_fig = Figure()
ema_plot = (
ema_fig.plot_xy(series_name="Numbers", t=ema_A, x="Timestamp", y="Numbers")
.plot_xy(series_name="EMA", t=ema_A, x="Timestamp", y="NumbersEMA")
.show()
)

The following example is performed on real-time data.

from deephaven.updateby import ema_time
from deephaven.plot import Figure
from deephaven import time_table
import random


def random_char() -> str:
return random.choice(["A", "B", "C"])


result = time_table("PT0.2S").update(
formulas=["Sym = random_char()", "Numbers = randomInt(0, 100)"]
)

result_w_ema = result.update_by(
[ema_time("Timestamp", "PT0.4S", "NumbersEMA = Numbers")], by=["Sym"]
)

ema_A = result_w_ema.where(["Sym == `A`"])

ema_fig = Figure()
ema_plot = (
ema_fig.plot_xy(series_name="Numbers", t=ema_A, x="Timestamp", y="Numbers")
.plot_xy(series_name="EMA", t=ema_A, x="Timestamp", y="NumbersEMA")
.show()
)

img

Tick-based EMA

This first example calculates a time-based EMA via ema_tick. A 10-row decay rate has been chosen. The EMA is stored in the output column NumbersEMA.

from deephaven.updateby import ema_tick
from deephaven.plot import Figure
from deephaven import empty_table
import random


def random_char() -> str:
return random.choice(["A", "B", "C", "D", "E", "F"])


result = empty_table(100).update(
formulas=["X = i", "Sym = random_char()", "Numbers = randomInt(0, 100)"]
)

result_w_ema = result.update_by([ema_tick(10, "NumbersEMA = Numbers")], by=["Sym"])

ema_A = result_w_ema.where(["Sym == `A`"])

ema_fig = Figure()
ema_plot = (
ema_fig.plot_xy(series_name="Numbers", t=ema_A, x="X", y="Numbers")
.plot_xy(series_name="EMA", t=ema_A, x="X", y="NumbersEMA")
.show()
)

The following example is identical to the one above, except it's performed on real-time data instead.

from deephaven.updateby import ema_tick
from deephaven.plot import Figure
from deephaven import time_table
import random


def random_char() -> str:
return random.choice(["A", "B", "C", "D", "E", "F"])


result = (
time_table("PT1S")
.update(formulas=["Sym = random_char()", "Numbers = randomInt(0, 100)"])
.reverse()
)

result_w_ema = result.update_by([ema_tick(10, "NumbersEMA = Numbers")], by=["Sym"])

ema_A = result_w_ema.where(["Sym == `A`"])

ema_fig = Figure()
ema_plot = (
ema_fig.plot_xy(series_name="Numbers", t=ema_A, x="Timestamp", y="Numbers")
.plot_xy(series_name="EMA", t=ema_A, x="Timestamp", y="NumbersEMA")
.show()
)

img