# Time-series forecasting

**URL:** <https://discourse.nodered.org/t/time-series-forecasting/21835>\
**Category:** General\
**Created:** [17 February 2020 09:14 UTC](https://discourse.nodered.org/t/time-series-forecasting/21835 "2020-02-17T09:14:43Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![gilad](https://avatars.discourse-cdn.com/v4/letter/g/5f9b8f/32.png) [@gilad](https://discourse.nodered.org/u/gilad)\
**Post date:** [17 February 2020 09:14 UTC](https://discourse.nodered.org/t/time-series-forecasting/21835/1 "2020-02-17T09:14:43Z")

</div>

Hi all,  
I'm trying to implement the popular [Triple Exponential Smoothing](https://grisha.org/blog/2016/01/29/triple-exponential-smoothing-forecasting/) (Holt-Winters), much like the [FORECAST.ETS function in Excel](https://support.office.com/en-us/article/create-a-forecast-in-excel-for-windows-22c500da-6da7-45e5-bfdc-60a7062329fd), to predict the next data points in a sequence.

I used the [Smooth node](https://flows.nodered.org/node/node-red-node-smooth) for this task, with α=25 (α=0.25) to predict the following seasonal random sequence:

Values:  
`[0.755154261,0.912094449,0.884490302,0.722404901,0.917280197,0.825058562,0.880320681,0.796308845,0.79255487,0.76197476]`  
Timeline:  
`[9:49,9:50,9:51,9:52,9:53,9:54,9:55,9:56,9:57,9:58]`

Here's the expected result: (`9:59=>0.786928627,10:00=>0.782188051,10:01=>0.777447474`)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/3/f3c0c74f9dc7c15fb3cbf865680a9905bf07c857.png)

Here's what I have so far:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/3/c362b65245c283cb7c72eba2fcd589bc24c4973a.png)

My flow:

```auto
[{"id":"9071add5.fb751","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.755154261","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1380,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"8cfa28e1.2d6e88","type":"smooth","z":"f71e5505.8bfbf8","name":"Mean","property":"payload","action":"mean","count":"10","round":"","mult":"single","reduce":true,"x":490,"y":1560,"wires":[["b3061169.2ecb3"]]},{"id":"df715d88.163c4","type":"debug","z":"f71e5505.8bfbf8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":1600,"wires":[]},{"id":"93b42cdf.d04b3","type":"smooth","z":"f71e5505.8bfbf8","name":"HPF = α","property":"payload","action":"high","count":"25","round":"","mult":"single","reduce":true,"x":500,"y":1640,"wires":[["c9803255.0832d"]]},{"id":"e592ccaa.befed","type":"smooth","z":"f71e5505.8bfbf8","name":"LPF = α","property":"payload","action":"low","count":"25","round":"","mult":"single","reduce":true,"x":500,"y":1600,"wires":[["cef6c815.723e18"]]},{"id":"ce89aa4a.ce84c8","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.912094449","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1420,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"c252aaad.b24838","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.884490302","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1460,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"82e9371c.e17a08","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.722404901","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1500,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"30bf94e0.d792bc","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.917280197","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1540,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"b36d2602.c44c88","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.880320681","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1620,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"7127abe6.7989d4","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.825058562","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1580,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"caabea11.f761a8","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.796308845","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1660,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"5ba5006b.3bc27","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.79255487","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1700,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"2ef04fce.f3cb2","type":"inject","z":"f71e5505.8bfbf8","name":"","topic":"","payload":"0.76197476","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":1740,"wires":[["8cfa28e1.2d6e88","e592ccaa.befed","93b42cdf.d04b3"]]},{"id":"c9803255.0832d","type":"change","z":"f71e5505.8bfbf8","name":"hpf","rules":[{"t":"set","p":"topic","pt":"msg","to":"hpf","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":1640,"wires":[["df715d88.163c4"]]},{"id":"cef6c815.723e18","type":"change","z":"f71e5505.8bfbf8","name":"lpf","rules":[{"t":"set","p":"topic","pt":"msg","to":"lpf","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":1600,"wires":[["df715d88.163c4"]]},{"id":"b3061169.2ecb3","type":"change","z":"f71e5505.8bfbf8","name":"mean","rules":[{"t":"set","p":"topic","pt":"msg","to":"mean","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":630,"y":1560,"wires":[["df715d88.163c4"]]}]

```

Any idea how to extend this flow make it work for this sequence, and even bigger ones?  
all sequences are evenly spaced and varies from 0.01 to 0.99.

Thanks, highly appreciated

---

<div class="post-metadata">

**Author:** ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)\
**Post date:** [17 February 2020 10:58 UTC](https://discourse.nodered.org/t/time-series-forecasting/21835/2 "2020-02-17T10:58:45Z")

</div>

Hi,

instead of may Inject nodes you could try one with an JSON formated array. either with single values (same result as when you click on each inject node in your flow) or an array of objects where you can use timestamp / value pairs. Then you split to feed split the array into a sequence of messages.

Perhaps this could help you:

```auto
[{"id":"234870ae.be8f1","type":"inject","z":"339ad8dc.ba3688","name":"values","topic":"","payload":"[0.755154261,0.912094449,0.884490302,0.722404901,0.917280197,0.825058562,0.880320681,0.796308845,0.79255487,0.76197476]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":186,"y":544,"wires":[["e47a9588.3df638"]]},{"id":"afba5a54.2e3438","type":"debug","z":"339ad8dc.ba3688","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":521,"y":544,"wires":[]},{"id":"e47a9588.3df638","type":"split","z":"339ad8dc.ba3688","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":348,"y":544,"wires":[["afba5a54.2e3438"]]},{"id":"5b516680.de7398","type":"inject","z":"339ad8dc.ba3688","name":"values","topic":"","payload":"[{\"time\":\"9:49\",\"value\":0.755154261},{\"time\":\"9:50\",\"value\":0.912094449},{\"time\":\"9:51\",\"value\":0.884490302},{\"time\":\"9:52\",\"value\":0.722404901},{\"time\":\"9:53\",\"value\":0.917280197},{\"time\":\"9:54\",\"value\":0.825058562},{\"time\":\"9:55\",\"value\":0.880320681},{\"time\":\"9:56\",\"value\":0.796308845},{\"time\":\"9:57\",\"value\":0.79255487},{\"time\":\"9:58\",\"value\":0.76197476}]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":186,"y":646,"wires":[["5bcdcbf1.ac4ed4"]]},{"id":"f818f2b9.059b2","type":"debug","z":"339ad8dc.ba3688","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":521,"y":646,"wires":[]},{"id":"5bcdcbf1.ac4ed4","type":"split","z":"339ad8dc.ba3688","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":348,"y":646,"wires":[["f818f2b9.059b2"]]},{"id":"423ed781.76ed48","type":"inject","z":"339ad8dc.ba3688","name":"values","topic":"","payload":"[{\"9:49\":0.755154261},{\"9:50\":0.912094449},{\"9:51\":0.884490302},{\"9:52\":0.722404901},{\"9:53\":0.917280197},{\"9:54\":0.825058562},{\"9:55\":0.880320681},{\"9:56\":0.796308845},{\"9:57\":0.79255487},{\"9:58\":0.76197476}]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":186,"y":595,"wires":[["d0ddd84f.bc23c8"]]},{"id":"b525f4bd.38f8f8","type":"debug","z":"339ad8dc.ba3688","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":521,"y":595,"wires":[]},{"id":"d0ddd84f.bc23c8","type":"split","z":"339ad8dc.ba3688","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":348,"y":595,"wires":[["b525f4bd.38f8f8"]]}]

```

Or using the csv in node ...

---

<div class="post-metadata">

**Author:** ![gilad](https://avatars.discourse-cdn.com/v4/letter/g/5f9b8f/32.png) [@gilad](https://discourse.nodered.org/u/gilad)\
**Post date:** [17 February 2020 12:00 UTC](https://discourse.nodered.org/t/time-series-forecasting/21835/3 "2020-02-17T12:00:48Z")

</div>

Thanks @Christian-Me, indeed it simplify things. The new flow:

```auto
[{"id":"45217fc3.dac7d","type":"debug","z":"44a70066.170c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":650,"y":380,"wires":[]},{"id":"bb19fae3.0f2858","type":"change","z":"44a70066.170c","name":"mean","rules":[{"t":"set","p":"topic","pt":"msg","to":"mean","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":380,"wires":[["45217fc3.dac7d"]]},{"id":"1fb723f8.6f2cac","type":"smooth","z":"44a70066.170c","name":"Mean","property":"payload","action":"mean","count":"10","round":"","mult":"single","reduce":true,"x":390,"y":380,"wires":[["bb19fae3.0f2858"]]},{"id":"3776469.15bc2ba","type":"split","z":"44a70066.170c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":270,"y":380,"wires":[["1fb723f8.6f2cac"]]},{"id":"b2b4d521.783a68","type":"inject","z":"44a70066.170c","name":"values","topic":"","payload":"[0.755154261,0.912094449,0.884490302,0.722404901,0.917280197,0.825058562,0.880320681,0.796308845,0.79255487,0.76197476]","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":380,"wires":[["3776469.15bc2ba"]]}]

```

However, the issue here is the predicted result. I get now this reult:

> 0.8247641827999999

by applying only the "mean function" after evenly time-spaced 10 messages within the smooth node. This result should be smoothed to get the expected value of:

> 0.786928627

i.e. we still have a potential of _4.587%_ error.  
I used only the Low-Pass-Filter with α=20 and got now only _0.61%_ error at the last value.  
The question remains, is Low-Pass-Filter is the right way to "smooth" and predict the next value in a sequence?

Thanks

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [17 April 2020 12:00 UTC](https://discourse.nodered.org/t/time-series-forecasting/21835/4 "2020-04-17T12:00:49Z")

</div>

Closed on 17 April 2020 12:00 UTC

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
