# Models

## Shared Configuration

All models share these three options:

**type**- The type of the model, for example 'Linear'.**name**- The name of the model, must be unique and not shared by multiple models.**perSyncPeriod**- The frequency that the model is used to recalculate and store values - tied to the sync period as a base unit, with a value of`1`

resulting in the model being recalculated every sync period, a value of`2`

meaning recalculated every other sync period,`3`

waits for two sync periods after every calculation and so on.**calculationTimeout**- The timeout for calculating using an algorithm, if this timeout is exceeded the calculation is skipped. Defaults set based on the algorithm used, see below.

All models use `syncPeriod`

as a base unit, so if the sync period is defined as `10000`

(10 seconds), the models will
base their timings and calculations as multiples of 10 seconds.

## Linear Regression

The linear regression model uses a default calculation timeout of `30000`

(30 seconds).

Example:

```
models:
- type: Linear
name: simple-linear
perSyncPeriod: 1
calculationTimeout: 25000
linear:
lookAhead: 10000
historySize: 6
```

**linear**component of the configuration handles configuration of the Linear regression options:

**lookAhead**- sets up the model to try to predict`10 seconds`

ahead of time (time in milliseconds).**historySize**- sets up the model to store the past`6`

evaluations and to use these for predictions. If there are`> 6`

evaluations, the oldest will be removed.

For a more detailed example, see the example in
`/examples/simple-linear`

.

## Holt-Winters Time Series prediction

The Holt-Winters time series model uses a default calculation timeout of `30000`

(30 seconds).

Example:

```
models:
- type: HoltWinters
name: simple-holt-winters
perSyncPeriod: 1
holtWinters:
alpha: 0.9
beta: 0.9
gamma: 0.9
seasonalPeriods: 6
storedSeasons: 4
trend: additive
seasonal: additive
```

The **holtWinters** component of the configuration handles configuration of the Linear regression options:

**alpha**,**beta**,**gamma**- these are the smoothing coefficients for level, trend and seasonality respectively, requires tweaking and analysis to be able to optimise. See here or here for more details.**seasonalPeriods**- the length of a season in base unit sync periods, for example if your sync period was`10000`

(10 seconds), and your repeated season was 60 seconds long, this value would be`6`

.**storedSeasons**- the number of seasons to store, for example`4`

, if there are`>4`

seasons stored, the oldest season will be removed.**trend**- Either`add`

/`additive`

or`mul`

/`multiplicative`

, defines the method for the trend element.**seasonal**- Either`add`

/`additive`

or`mul`

/`multiplicative`

, defines the method for the seasonal element.

This is the model in action, taken from the `simple-holt-winters`

example:
The red value is the predicted values, the blue value is the actual values. From this you can see that the prediction
is overestimating, but still pre-emptively scaling - storing more seasons and adjusting alpha, beta and gamma values
would reduce the overestimation and produce more accurate results.

For a more detailed example, see the example in
`/examples/simple-holt-winters`

.

### Advanced tuning

There are more configuration options for the Holt-Winters algorithm, which in this project uses the statsmodels Python package. These are the additional configuration options, which are documented by the Holt-Winters Exponential Smoothing statsmodels documentation - the names of the variables in this documentation map to the camelcase names described here.

**dampedTrend**- Boolean value to determine if the trend should be damped.**initializationMethod**- Which initialization method to use, see statsmodels for details, either`estimated`

,`heuristic`

,`known`

, or`legacy-heuristic`

**initialLevel**- The initial level value, required if`initializationMethod`

is`known`

.**initialTrend**- The initial trend value, required if`initializationMethod`

is`known`

.**initialSeasonal**- The initial seasonal value, required if`initializationMethod`

is`known`

.

### Holt-Winters Runtime Tuning

The PHPA supports dynamically fetching the tuning values for the Holt-Winters algorithm (`alpha`

, `beta`

, and `gamma`

).

This is done using a `hook`

system, to see more information of how the dynamic hook system works visit the hooks
user guide

For example, a hook using a HTTP request to fetch the values of runtime is configured as:

```
models:
- type: HoltWinters
name: simple-holt-winters
perSyncPeriod: 1
holtWinters:
runtimeTuningFetchHook:
type: "http"
timeout: 2500
http:
method: "GET"
url: "http://tuning/holt_winters"
successCodes:
- 200
parameterMode: query
seasonalPeriods: 6
storedSeasons: 4
trend: additive
seasonal: additive
```

The hook is defined with the name `runtimeTuningFetchHook`

.

The supported hook types for the PHPA are:

- HTTP requests

The process is as follows:

- PHPA begins Holt-Winters calculation.
- The values are initially set to any hardcoded values supplied in the configuration.
- A runtime tuning configuration has been supplied, using this configuration a hook is executed (for example a HTTP request is sent).
- If the hook execution is successful, and the response is valid, the tuning values are extracted and any provided values overwrite the hardcoded values.
- If all required tuning values are provided the tuning values are used to calculate.

The tuning values can be both hardcoded and fetched at runtime, for example the `alpha`

value could be calculated at
runtime, and the `beta`

and `gamma`

values could be hardcoded in configuration:

```
models:
- type: HoltWinters
name: simple-holt-winters
perSyncPeriod: 1
holtWinters:
runtimeTuningFetchHook:
type: "http"
timeout: 2500
http:
method: "GET"
url: "http://tuning/holt_winters"
successCodes:
- 200
parameterMode: query
beta: 0.9
gamma: 0.9
seasonalPeriods: 6
storedSeasons: 4
trend: additive
seasonal: additive
```

Or the values could be provided, and if they are not returned by the external source the hardcoded values will be used as a backup:

```
models:
- type: HoltWinters
name: simple-holt-winters
perSyncPeriod: 1
holtWinters:
runtimeTuningFetchHook:
type: "http"
timeout: 2500
http:
method: "GET"
url: "http://tuning/holt_winters"
successCodes:
- 200
parameterMode: query
alpha: 0.9
beta: 0.9
gamma: 0.9
seasonalPeriods: 6
storedSeasons: 4
trend: additive
seasonal: additive
```

If any value is missing, the PHPA will report it as an error (e.g.
`No alpha tuning value provided for Holt-Winters prediction`

) and not calculate and scale.

#### Request Format

The data that the external source will recieve will be formatted as:

```
{
"model": {
"type": "HoltWinters",
"name": "HoltWintersPrediction",
"perInterval": 1,
"linear": null,
"holtWinters": {
"alpha": null,
"beta": null,
"gamma": null,
"runtimeTuningFetchHook": {
"type": "http",
"timeout": 2500,
"shell": null,
"http": {
"method": "GET",
"url": "http://tuning/holt_winters",
"successCodes": [
200
],
"parameterMode": "query"
}
},
"seasonalPeriods": 6,
"storedSeasons": 4,
"trend": "additive"
}
},
"replicaHistory": [
{
"time": "2020-10-19T19:12:20Z",
"replicas": 0
},
{
"time": "2020-10-19T19:12:40Z",
"replicas": 0
},
{
"time": "2020-10-19T19:13:00Z",
"replicas": 0
},
]
}
```

This provides information around the model being used, how it is configured, and previous replica values
(`replicaHistory`

). This data could be used to help calculate the tuning values, or it could be ignored.

#### Response Format

The response that the external tuning source should return must be in JSON, and in the following format:

This is a simple JSON structure, for example:

Each of these values is optional, for example perhaps only the `alpha`

and `beta`

should be runtime, and `gamma`

should
rely on the hardcoded configuration value, this response would be valid:

For a more detailed example, see the example in
`/examples/dynamic-holt-winters`

.