# Preliminaries
import pandas as pd
from exabel_data_sdk.client.api.export_api import ExportApi
from exabel_data_sdk.query.column import Column
export_api = ExportApi()
Exabel offers multiple univariate forecast models directly available in the DSL, from the statsmodels Python library and Facebook’s Prophet library. Forecasts are useful if you want to extend a time series into the future, e.g. for use in models.
All of these statistical methods are by default linear, meaning that they assume growth trends are linear with time and seasonality effects are additive. However, for typical financial KPIs such as revenue, it is more natural to assume that growth trends are exponential, meaning that a company’s revenue grows by a certain percentage each year rather than projecting that it will grow by a fixed amount per year. Similarly, it is more natural to assume that the seasonality trends are multiplicative, meaning that revenue in Q4 is modelled to be e.g. 20% higher than in Q3, rather than modelled to be $50M higher in Q4.
Such time series can be modelled with exponential growth and multiplicative seasonality by taking the logarithm first, forecasting the logarithmic values, and finally exponentiating to get back the original values.
Let's compare the difference in the produced forecasts with an example:
company = "CMG US"
sales_actual = export_api.signal_query("Sales_Actual_fiscal", company, start_time='2011-01-01')
columns = [
Column("Additive", f"Sales_Actual_fiscal.forecast('theta', 'forecast', estimation_end='2016-12-31')"),
Column("Multiplicative", f"Sales_Actual_fiscal.log().forecast('theta', 'forecast', estimation_end='2016-12-31').exp()"),
]
forecasts = export_api.signal_query(columns, company)
df = pd.concat([sales_actual, forecasts], axis=1)
df.plot(figsize=(15, 5));
Let's see the forecasts produced by these methods in a practical example:
methods = ["theta", "holt_winters", "unobserved", "sarima", "prophet"]
columns = [Column(method, f"Sales_Actual_fiscal.log().forecast('{method}', 'forecast').exp()") for method in methods]
forecasts = export_api.signal_query(columns, "AAPL US")
forecasts
theta | holt_winters | unobserved | sarima | prophet | |
---|---|---|---|---|---|
time | |||||
2022-06-25 00:00:00+00:00 | 90507.128575 | 86955.880116 | 84513.287969 | 88328.684952 | 106920.714628 |
2022-09-24 00:00:00+00:00 | 97817.581368 | 95022.870614 | 88431.306327 | 90412.984290 | 106743.704261 |
2022-12-31 00:00:00+00:00 | 148200.463808 | 149468.859883 | 133451.024363 | 134431.497396 | 159461.452593 |
2023-04-01 00:00:00+00:00 | 108777.226415 | 108355.467833 | 102838.611785 | 105508.295507 | 116631.739891 |
2023-07-01 00:00:00+00:00 | 101108.541675 | 99256.009241 | 89786.912293 | 95801.814829 | 105164.403539 |
2023-09-30 00:00:00+00:00 | 109328.187184 | 108464.095944 | 93949.414771 | 98062.458210 | 115343.344803 |
2023-12-30 00:00:00+00:00 | 166261.153256 | 170611.608071 | 141778.360632 | 145805.198213 | 167720.145637 |
2024-03-30 00:00:00+00:00 | 121636.754735 | 123682.622753 | 109255.735264 | 114434.922154 | 130456.082890 |
2024-06-29 00:00:00+00:00 | 112951.734970 | 113296.022734 | 95389.610472 | 103907.215726 | 117792.772597 |
2024-09-28 00:00:00+00:00 | 122193.294353 | 123806.616584 | 99811.852867 | 106359.122925 | 124439.537081 |
2024-12-28 00:00:00+00:00 | 186522.837863 | 194745.051453 | 150625.322207 | 158141.181476 | 171479.223844 |
2025-03-29 00:00:00+00:00 | 136016.522852 | 141177.842494 | 116073.286880 | 124116.794280 | 135505.731651 |
forecasts.plot(figsize=(15, 5));