3

I'm working on a project that involves developing a financial forecasting model. The equations used in the model will largely be linear difference equations (estimated via some form of regression analysis). Along with the difference equations will be additional equations that are simple identities, e.g., a[t] == b[t] + c[t], with no sort of time lag.

I've been experimenting with RecurrenceTable, using some simple hypothetical examples. For instance, this set of equations evaluates correctly:

 In[763]:= 
    model1 = RecurrenceTable[
      {
       x[t + 2] ==  
        0.25 + x[t + 1]  - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2]  ,
       y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2] ,
       z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2] ,
       x[0] == 1, x[1] == 1,
       y[0] == 0, y[1] == 2,
       z[0] == 0, z[1] == 1},
      {x, y, z}, {t, 1, 10}
      ]

Out[763]= {{1., 2., 1.}, {0.428571, -0.321429, -0.3625}, {0.0612245, 
  1.04337, 0.574821}, {-0.200437, -0.390488, 0.150742}, {0.0103603, 
  0.247878, 0.52746}, {0.270717, -0.414239, -0.0462812}, {0.478779, 
  0.180722, -0.245145}, {0.398813, -0.0142515, -0.689967}, {0.214079, 
  0.29056, -0.776897}, {0.0436432, 0.0325037, -0.918937}}

If I modify this to include an additional equation, q[t+2] that simply sums the results of the other equations:

In[761]:= fcstB = RecurrenceTable[
  {
   x[t + 2] ==  
    0.25 + x[t + 1]  - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2]  ,
   y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2] ,
   z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2] ,
   q[t + 2] == x[t + 2] + y[t + 2] + z[t + 2],
   x[0] == 1, x[1] == 1,
   y[0] == 0, y[1] == 2,
   z[0] == 0, z[1] == 1,
   q[0] == 1, q[1] == 4},
  {x, y, z, q}, {t, 1, 10}
  ]

Out[761]= RecurrenceTable[{x[2 + t] == 
   0.25 - 1.5 x[t] + x[1 + t] + 0.5 y[1 + t] + y[2 + t], 
  y[2 + t] == x[1 + t] - 0.75 x[2 + t] + 0.25 y[t] - 0.5 y[1 + t], 
  z[2 + t] == -1.5 x[2 + t] - 0.25 y[2 + t] + z[t] + 0.2 z[1 + t], 
  q[2 + t] == x[2 + t] + y[2 + t] + z[2 + t], x[0] == 1, x[1] == 1, 
  y[0] == 0, y[1] == 2, z[0] == 0, z[1] == 1, q[0] == 1, 
  q[1] == 4}, {x, y, z, q}, {t, 1, 10}]

The result does not evaluate. In looking through the documentation, it appears that RecurrenceTable will not handle trivial recurrence equations. I'm hoping someone can verify this for me, or perhaps suggest an alternative. The actual model I'm developing will consist of thousands of equations, and so it seems I will need to organize blocks of equations in such a way to isolate identities in order to evaluate the entire system

Thanks!

bbgodfrey
  • 61,439
  • 17
  • 89
  • 156
MSC02476
  • 699
  • 4
  • 12

4 Answers4

2

q can be generated and combined with the corresponding values of {x, y, z}by

fcstB = Join[#, {Total@#}] & /@ model1
(* {{1., 2., 1., 4.}, 
    {0.428571, -0.321429, -0.3625, -0.255357}, 
    {0.0612245, 1.04337, 0.574821, 1.67941}, 
    {-0.200437, -0.390488, 0.150742, -0.440183}, 
    {0.0103603, 0.247878, 0.52746, 0.785699}, 
    {0.270717, -0.414239, -0.0462812, -0.189803}, 
    {0.478779, 0.180722, -0.245145, 0.414356}, 
    {0.398813, -0.0142515, -0.689967, -0.305405}, 
    {0.214079, 0.29056, -0.776897, -0.272258}, 
    {0.0436432, 0.0325037, -0.918937, -0.84279}} *)

Another approach is to solve these linear equations for {x, y, z, q} at t + 2 and then apply RecurrenceTable:

rs = Solve[{x[t + 2] == 0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
            y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2],
            z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2], 
            q[t + 2] == x[t + 2] + y[t + 2] + z[t + 2]}, 
           {x[t + 2], y[t + 2], z[t + 2], q[t + 2]}] /. Rule -> Equal;
fcstB = RecurrenceTable[{rs, x[0] == 1, x[1] == 1, y[0] == 0, y[1] == 2, 
     z[0] == 0, z[1] == 1, q[0] == 1, q[1] == 4}, {x, y, z, q}, {t, 1, 10}]

which gives the same values as above. It appears that RecurrenceTable was unhappy, because the original expression for q[t +2] did not depend explicitly on variables at earlier times. But, who can say for sure without knowing the inner workings of the function.

Addendum

To test the hypothesis posed in the last paragraph above, let us add an infinitesimal amount of q[t] to the last equation in the original system.

fcstB = RecurrenceTable[{x[t + 2] == 0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
    y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2], 
    z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2], 
    q[t + 2] == x[t + 2] + y[t + 2] + z[t + 2] + 10^-30 q[t], 
    x[0] == 1, x[1] == 1, y[0] == 0, y[1] == 2, z[0] == 0, z[1] == 1, q[0] == 1, q[1] == 4}, 
    {x, y, z, q}, {t, 1, 10}]

which again evaluates to the desired answer. I do not, of course, recommend this last approach for evaluating the RecurrenceTable.

bbgodfrey
  • 61,439
  • 17
  • 89
  • 156
2

Another option is to put it into a state-space form and then use OutputResponse.

I used AffineStateSpaceModel and not StateSpaceModel because the equations have residue terms.

AffineStateSpaceModel[{x[t + 2] == 
    0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
   y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2], 
   z[t + 2] == 
    0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2]}, {x[t], y[t],
    z[t]}, {u[t]}, {x[t], y[t], z[t]}, t];
OutputResponse[{%, {1, 1, 0, 2, 0, 1}}, Table[0, 11]] // Transpose

(*{{1, 0, 0}, {1., 2., 1.}, {0.428571, -0.321429, -0.3625}, {0.0612245, 
  1.04337, 0.574821}, {-0.200437, -0.390488, 0.150742}, {0.0103603, 
  0.247878, 0.52746}, {0.270717, -0.414239, -0.0462812}, {0.478779, 
  0.180722, -0.245145}, {0.398813, -0.0142515, -0.689967}, {0.214079, 
  0.29056, -0.776897}, {0.0436432, 0.0325037, -0.918937}}*)

With the additional equation:

AffineStateSpaceModel[{x[t + 2] == 
    0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
   y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2], 
   z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2], 
   q[t + 2] == x[t + 2] + y[t + 2] + z[t + 2]}, {x[t], y[t], z[t], 
   q[t]}, {u[t]}, {x[t], y[t], z[t], q[t]}, t];
OutputResponse[{%, {1, 1, 0, 2, 0, 1, 1, 4}}, Table[0, 11], 
  Method -> "RecurrenceTable"] // Transpose

(*{{1, 0, 0, 1}, {1., 2., 1., 
  4.}, {0.428571, -0.321429, -0.3625, -0.255357}, {0.0612245, 1.04337,
   0.574821, 1.67941}, {-0.200437, -0.390488, 
  0.150742, -0.440183}, {0.0103603, 0.247878, 0.52746, 
  0.785699}, {0.270717, -0.414239, -0.0462812, -0.189803}, {0.478779, 
  0.180722, -0.245145, 
  0.414356}, {0.398813, -0.0142515, -0.689967, -0.305405}, {0.214079, 
  0.29056, -0.776897, -0.272258}, {0.0436432, 
  0.0325037, -0.918937, -0.84279}}*)

If you want you can explicitly ask OutputResponse to use RecurrenceTable as I showed above. But it's not necessary.

Also applying Normal to the state-space model will give you equations in a form that can be solved by RecurrenceTable.

Suba Thomas
  • 8,716
  • 1
  • 17
  • 32
1

Why not find an other equation for q[t+2] with Eliminate.

eli = Eliminate[{x[t + 2] == 
0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2], 
z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2], 
q[t + 2] == x[t + 2] + y[t + 2] + z[t + 2]}, 
{x[t + 2], y[t + 2], z[t + 2]}]

(*   0.166667\[VeryThinSpace]+ 1.09804 q[2 + t] + 0.509804 x[1 + t] - 
 0.0392157 y[t] + 0.411765 y[1 + t] - 1.09804 z[t] - 
 0.219608 z[1 + t] == x[t]   *)

Insert equation eli instead of q[t+2] == ...

fcstB = RecurrenceTable[{x[t + 2] == 
0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2], 
z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2], 
eli, x[0] == 1, x[1] == 1, y[0] == 0, y[1] == 2, z[0] == 0, 
z[1] == 1, q[0] == 1, q[1] == 4}, {x, y, z, q}, {t, 0, 10}]

(*   {{1., 0., 0., 1.}, {1., 2., 1., 4.}, {0.428571, -0.321429, -0.3625, -0.255357}, {0.0612245, 1.04337,
0.574821, 1.67941}, {-0.200437, -0.390488, 
0.150742, -0.440183}, {0.0103603, 0.247878,  0.52746, 
0.785699}, {0.270717, -0.414239, -0.0462812, -0.189803}, {0.478779, 
0.180722, -0.245145, 
0.414356}, {0.398813, -0.0142515, -0.689967,  -0.305405}, {0.214079, 
0.29056, -0.776897, -0.272258}, {0.0436432, 
0.0325037, -0.918937, -0.84279}}   *)
Akku14
  • 17,287
  • 14
  • 32
0

I ran into a similar problem here. The same workaround -- add Unevaluated[0 q[t]] -- works here:

fcstB = RecurrenceTable[{
   x[t + 2] == 0.25 + x[t + 1] - 1.5*x[t] + 0.5*y[t + 1] + y[t + 2], 
   y[t + 2] == -0.50*y[t + 1] + 0.25*y[t] + x[t + 1] - 0.75*x[t + 2], 
   z[t + 2] == 0.20*z[t + 1] + z[t] - 0.25*y[t + 2] - 1.5*x[t + 2], 
   q[t + 2] == x[t + 2] + y[t + 2] + z[t + 2] + Unevaluated[0 q[t]], 
   x[0] == 1, x[1] == 1, y[0] == 0, y[1] == 2, z[0] == 0, z[1] == 1, 
   q[0] == 1, q[1] == 4}, {x, y, z, q}, {t, 1, 10}]

(* {{1., 2., 1., 4.}, {0.428571, -0.321429, -0.3625, -0.255357},
{0.0612245, 1.04337, 0.574821, 1.67941}, {-0.200437, -0.390488, 0.150742, -0.440183},
{0.0103603, 0.247878, 0.52746, 0.785699}, {0.270717, -0.414239, -0.0462812, -0.189803},
{0.478779, 0.180722, -0.245145, 0.414356}, {0.398813, -0.0142515, -0.689967, -0.305405},
{0.214079, 0.29056, -0.776897, -0.272258}, {0.0436432, 0.0325037, -0.918937, -0.84279}} *)
Chris K
  • 20,207
  • 3
  • 39
  • 74