Time-Series Operation Documentation

Introduction

In the FRB/US model, equations are written in a domain-specific notation for time series:

ptr - ptr_aerr = 0.9 * ptr(-1) + 0.05 * picxfe(-1) + 0.05 * pitarg(-1)

This notation declaratively expresses a relationship that holds recursively, i.e. the expression refers to past values of other series to denote a relation that holds at all points in time.

The TimeSeriesData object in the PyFRB/US package is a DataFrame wrapper that enables the use of this notation to perform recursive operations on time-series datasets.

Let’s say that, over the date range periods you want the variable lur in data_frame to converge towards lurnat with an inertia of 0.9:

from pyfrbus.time_series_data import TimeSeriesData
d = TimeSeriesData(data_frame)
d.range = periods
d.lur = 0.9 * d.lur(-1) + 0.1 * d.lurnat(0)

This modifies the underlying series lur in data_frame. After running this code, you can inspect data_frame to see that, at each point in time, the previously-modified value of lur(-1) is used to compute the new value in the next period (rather than using the original value of lur in data_frame).

Usage

To initialize the TimeSeriesData object, we pass it a reference to our dataset:

d = TimeSeriesData(data_frame)

Then, we specify the range over which to operate as a quarterly pandas PeriodIndex object:

from pandas import period_range
d.range = period_range("2019Q4", "2030Q4", freq="Q")

TimeSeriesData will also optionally accept the range on initialization, and it can be changed later:

d = TimeSeriesData(data_frame, periods)
d.lur = 0.9 * d.lur(-1) + 0.1 * d.lurnat(0)
# Second set of operations occur on a different horizon
d.range = other_periods
d.xgdp = d.xgdp(-1) * 1.007

As seen in the examples, the left-hand side has the series to be assigned attached as a suffix to the TimeSeriesData object. The right-hand side is an expression of time-series operations where series are referred to by attaching their names to the TimeSeriesData object.

Previous and contemporaneous values from series are indicated by indices - e.g. d.lur(-1) for the value of lur one period previous, and d.lurnat(0) for the value of lurnat in the current period.

Series present in the dataset can be used in time-series operations along with floating point numbers.

Functions

Common functions (log, exp, abs, max, and min) can be used in time-series operations as well, if they are imported:

from pyfrbus.time_series_data import log, min
d.xgdp = min(d.xgdp(-1) * 1.007, d.xgdpt(0))
d.loggdp = log(d.xgdp(0))

Defining New Series

Time-series operations can be used to define new series as well, as in loggdp above. These series will be appended to the DataFrame.

Caveats

Series Must Exist Before Use

To use a series in time-series operations, that series must first exist in the data frame.

For example, this will work, because the right-hand side expressions only refer to scalars and already-extant series:

d.newexo = 9.99
d.newgdp = d.xgdp(-1) * 0.98

But this will not work, because it references lags of the series newgdp in a recursive expression before it was created:

d.newgdp = d.newgdp(-1) * 1.007

The correct way to handle this situation is to first add baseline data for the new series to data_frame.

Future Indices

Only references to past and present time periods can be used in time-series operations.

Expressions like lur(-2) and xgdpt(0) are acceptable, but forward-looking expressions like picxfe(1) will not work:

# This works
d.xgdp = d.xgdp(-1) * 1.007
# This throws a ValueError
d.zpicxfe = d.picxfe(1)