Timeseries

<< Click to Display Table of Contents >>

Navigation:  Gekko User Guide > Data Management User Guide > Databanks and variables >

Timeseries

Previous pageReturn to chapter overviewNext page

Show/Hide Hidden Text

Note: There is an additional kind of timeseries available in Gekko, namely so-called array-timeseries. These are explained in a later section.

 

Timeseries variables can be defined and transformed easily, and variables from any open databank can be used in a series expression. The syntax is as follows:

 

var1 <per1 per2> = value  |  list of values  |  expression;

 

The variable name, var1, is here the name of the timeseries that is created or assigned with values. You may prepend SERIES to the statement to indicate the variable type, but this is not necessary (see more on this: +toggle)

 

If only one value is specified, this value will be applied to the entire update period. If several values ​​are specified, the number of values ​​must match the number of periods. The following examples set values ​​for the timeseries var1 over the period per1 to per2:

 

var1 <per1  per2> = value;
var1 <per1  per2> = value_1, ... , value_n;

 

The var1-var4 examples below shows the use of a value, a list of values, or an expression:

 

time 2021 2023;
%= 120;
 
var1 = 100;
var2 = 110, 120, 115;
var3 = var1 + var2;  //210, 220, 215
var4 = (%v-10, %v, 100+15); //note parentheses
 
prt var1, var2, var3, var4;

 

Note that var4 is not simple numbers like var2, and therefore the right-hand side has to defined with parentheses (list syntax). It is possible to define the variable over a specific period of time. For example, if you want to form a Laspeyres chain price index, with 2010 equal to 1, on the basis of two quantities in current prices, q1 and q2, as well as their prices p1 and p2:

 

reset;
time 2010 2015;
p1 = 1, 1.02, 1.04, 1.04, 1.06, 1.05; //price
p2 = 1, 0.99, 1.03, 1.06, 1.05, 1.08; //price
q1 = 10, 12, 9, 14, 13, 15;           //quantity
q2 = 20, 19, 22, 23, 22, 25;          //quantity
 
// --- compute laspeyres chain indexes ---
<2010 2010> = 1;      //aggregate price index
<2011 2020 dyn> = p.* (p1*q1 + p2*q2)/(p1.1*q1 + p2.1*q2);
= (p1*q1 + p2*q2)/p;  //aggregate volume index
prt p, q;
 
// --- use in-built function ---
#= p1, p2;  //prices
#= q1, q2;  //quantities
#= laspchain(#p, #q, 2010);  //#m is a map
prt #m.p, #m.q;

 

Result:

 

                    p         %              q         % 
  2010         1.0000         M        30.0000         M 
  2011         1.0016      0.16        31.0000      3.33 
  2012         1.0359      3.42        30.9101     -0.29 
  2013         1.0546      1.80        36.9242     19.46 
  2014         1.0557      0.11        34.9329     -5.39 
  2015         1.0708      1.42        39.9247     14.29 
 
                 #m.p         %           #m.q         % 
  2010         1.0000         M        30.0000         M 
  2011         1.0016      0.16        31.0000      3.33 
  2012         1.0359      3.42        30.9101     -0.29 
  2013         1.0546      1.80        36.9242     19.46 
  2014         1.0557      0.11        34.9329     -5.39 
  2015         1.0708      1.42        39.9247     14.29 

 

First of all, note that in general, you can state a timeseries lag more compactly as x.1 instead of x[-1]. In the formula, (p1*q1 + p2*q2)/(p1.1*q1 + p2.1*q2) means taking the total expenses in the numerator, and the total expenses in the previous year's prices in the denominator. This fraction is used to construct the price index p successively year for year. Note also the <dyn> tag in the formula. Without it, Gekko will complain that because of the accumulating lag p.1, you need to decorate the statement with either <dyn> or <dyn = no> (the latter would not make sense here). Read more about <dyn> and the reason why Gekko does not just run with implicit <dyn> tags added in all cases like this: +toggle.

 

Instead of constructing the Laspeyres chain index by hand, Gekko has an in-built function to compute these values. The function laspchain() returns a map, containing the two timeseries (aggregated price and quantity).

 

The following is an example of changing the base year of a variable:

 

reset;
time 2010 2015;
p1 = 1, 1.02, 1.04, 1.04, 1.06, 1.05;
p1a = p1 / p1[2012]; //p1a is 1 in 2012
prt p1, p1a;

 

The growth rates of p1 and p1a are identical, but p1a has value 1 in 2012 rather than in 2010.

 

In the following example, the series x1, x2, x3, and x4 are added together into a sum series called xsum.

 

reset;
time 2010 2015;
x1 = 1; x2 = 2; x3 = 3; x4 = 4;
xsum = x1 + x2 + x3 + x4;
prt xsum;  //value: 10

 

Instead of this, you can define a list of series names and use the sum() function to sum over this list:

 

//...continued
#xlist = x1, x2, x3, x4;  //naked list, list of strings
xsum = sum({#xlist});     //you can also use sum(x1, x2, x3, x4);
prt xsum;  //still 10

 

Note the use of {}-parentheses. First, it should be noted that we are using a so-called 'naked' list definition, being short hand for the more strict #xlist = ('x1', 'x2', 'x3', 'x4');, more about this in the user guide section on lists. So the elements of #xlist are the four strings 'x1', 'x2', 'x3', 'x4', and not a list of four timeseries objects. Using sum(#xlist) would amount to sum('x1', 'x2', 'x3', 'x4'), and in that case Gekko will complain that it cannot extract a value from a string type. In a sense, the {}-parentheses 'eat' quotes ('), transforming the sum into sum(x1, x2, x3, x4).

 

If confused about the use of {}-parentheses, try to read the elevator pitch.

 

The user may aks why Gekko does not just 'know' that sum('x1', 'x2', 'x3', 'x4') is to be understood as the sum of the variables that these string names refer to? But such contextual interpretation is bound to create other problems. For instance, when printing out #xlist,  how should Gekko 'know' whether the user wants to have the four raw strings printed, or the four timeseries that the strings refer to? The PRT statement here has the exact same {}-logic:

 

//...continued
prt #xlist;    //prints the strings 'x1', 'x2', 'x3', 'x4'
prt {#xlist};  //prints the series x1, x2, x3, x4

 

It is often convenient to use name-parts ('codes') instead of full names, and use lists to compose the names from these name parts. For instance, you may use a name-composition with the name x{#xcodes} in the following way: #xcodes = ('1', '2', '3', '4'); prt x{#xcodes};. This also prints x1, x2, x3, and x4. Note that #xcodes does not use the syntax #xcodes = 1, 2, 3, 4;, because in that case, the four elements become values, and Gekko will complain that it cannot convert values directly into strings (but you could use #xcodes = #xcodes.strings() to convert the list elements into strings).

 

In addition to sum(), there is a number of other functions that can replace the corresponding expressions on the right side of the equals sign.

 

 

Transformations and operators

 

Gekko also allows you to use a number of operators for easy transformations. Some of the most used are the following:

 

^= absolute time-change:

 

^= 15;               //absolute time-change, same as x <d>= 15;
<dyn> = x[-1] + 15;  //corresponds to this

 

%= relative time-change:

 

%= 15;                //relative time-change, same as x <p>= 15;
<dyn> = x[-1] * 1.15; //corresponds to this

 

+= absolute change (same period)

 

+= 15;     //absolute change (same period), same as x <m>= 15;
= x + 15;  //corresponds to this

 

*= relative change (same period)

 

*= 1.15;     //absolute change (same period), same as x <q>= 15;
= x * 1.15;  //corresponds to this

 

#= change in growth rate

 

#= 15;                        //absolute change (same period), same as x <mp>= 15;
gx = x/x[-1];                   //corresponds to ...
<dyn> = x[-1] * (gx + 0.15);  //... these two lines

 

Instead of ^=, %=, +=, *= and #=, you may use the equivalent <d>, <p>, <m>, <q>, or <mp> operators, for instance <d>= 15; instead of ^= 15; These <> operators correspond exactly with the corresponding operators used in PRT, PLOT, SHEET, etc. There is also a third possibility, namely using left-hand side functions, for instance dif(x) = 15; which is equal to both ^= 15; and <d>= 15;

 

The choice of operator type is mostly a question of taste, and perhaps habit.

 

If <keep=p> is used as option, Gekko will keep the growth rate of the left-hand series intact after the period over which the series is updated. For instance, <2020 2025 m keep=p> x = 100; will add 100 to x over the period 2020-25, since <m> is the operator for absolute change (same period). The keep=p setting makes sure that the growth rate of x regarding 2026 and on is the same as before the update.

 

Data tracing

 

Gekko timeseries variables support data tracing, that is, the ability for a given timeseries to "remember" how it has been constructed. Consider the statements x1 = 1; x2 = 2; x = x1 + x2;. Data tracing implies that x remembers that it has been produced according to the expression x1 + x2, and x will also remember how both x1 and x2 were constructed (as sub-traces: even if x1 and x2 are subsequently deleted). Data tracing also works through Gekko databanks (.gbk files). Think "Trace Precedents" from Excel, just more powerful. See more here.