Documentation Index
Fetch the complete documentation index at: https://mintlify.com/andresshm/fini-marketing-intelligence/llms.txt
Use this file to discover all available pages before exploring further.
The Prophet Enriched model builds directly on the Baseline by introducing explicit binary regressors for the three seasonal windows that matter most to a candy brand: Halloween in October, Christmas in December, and the Summer months of June, July, and August. Rather than relying solely on Prophet’s built-in Fourier seasonality to detect these patterns, the enriched approach gives the model a dedicated coefficient for each event, allowing it to learn a distinct lift or suppression effect that generalises better to future years. The result is measurably lower absolute error compared to the baseline, making this the recommended default model for Fini’s daily revenue forecasts.
Event Flag Engineering
The add_event_flags function adds three binary columns to any DataFrame that contains a ds date column. It returns a copy, leaving the original untouched.
def add_event_flags(df):
"""
Añade variables binarias para eventos
estacionales conocidos.
"""
df = df.copy()
df["halloween"] = (
df["ds"].dt.month == 10
).astype(int)
df["christmas"] = (
df["ds"].dt.month == 12
).astype(int)
df["summer"] = (
df["ds"].dt.month.isin([6, 7, 8])
).astype(int)
return df
| Flag | Condition | Months |
|---|
halloween | month == 10 | October |
christmas | month == 12 | December |
summer | month in [6, 7, 8] | June, July, August |
Each flag is 1 for every day in the corresponding month and 0 otherwise. The month-level granularity is intentional — it captures the full run-up and wind-down in consumer demand rather than a single peak date.
To model additional seasonal events, simply extend add_event_flags() with more columns. For example, add df["valentines"] = (df["ds"].dt.month == 2).astype(int) for Valentine’s Day in February, or a narrower window such as (df["ds"].dt.month == 4) & (df["ds"].dt.day <= 15) for Easter. Then register the new column with model.add_regressor("valentines") before calling model.fit().
Data Preparation and Split
The pipeline follows the same aggregation as the Baseline — grouping sales.csv by sale_date and summing revenue — then applies add_event_flags to both the training and test sets before model fitting.
train = add_event_flags(train)
test = add_event_flags(test)
Model Configuration
The Prophet model uses the same core seasonality settings as the Baseline, with the three event regressors registered before fit is called.
model = Prophet(
yearly_seasonality=True,
weekly_seasonality=True,
daily_seasonality=False
)
model.add_regressor("halloween")
model.add_regressor("christmas")
model.add_regressor("summer")
model.fit(train)
Registering regressors before fit allows Prophet to estimate a separate linear coefficient for each seasonal event alongside its standard trend and seasonality components.
Generating the Forecast
The future DataFrame produced by make_future_dataframe must also carry the event flags — otherwise Prophet cannot apply the learned coefficients to future dates. The same add_event_flags function handles this automatically.
future = model.make_future_dataframe(periods=90)
future = add_event_flags(future)
forecast = model.predict(future)
Results are then merged with the original daily series so that actual revenue values are aligned for evaluation, with NaN in the y column for the 90-day future window.
Metrics Calculation
The calculate_metrics function is shared across the enriched and XGBoost pipelines. It accepts two array-like arguments — the ground truth and predictions — and returns a dictionary with MAE, RMSE, and MAPE.
def calculate_metrics(real, pred):
mae = mean_absolute_error(real, pred)
rmse = np.sqrt(
mean_squared_error(real, pred)
)
mape = np.mean(
np.abs((real - pred) / real)
) * 100
return {
"MAE": float(mae),
"RMSE": float(rmse),
"MAPE": float(mape)
}
As with the Baseline, eval_df = results.dropna() strips future-period rows before metrics are computed.
Results
{
"MAE": 52.484035874414865,
"RMSE": 73.58071320246974,
"MAPE": 26.620584285255795
}
Comparison with Baseline
| Model | MAE (€/day) | RMSE (€/day) | MAPE (%) |
|---|
| Prophet Baseline | 54.85 | 77.31 | 27.56 |
| Prophet Enriched | 52.48 | 73.58 | 26.62 |
| Δ improvement | −2.37 | −3.73 | −0.94 pp |
Adding the three seasonal regressors reduces MAE by €2.37 per day, RMSE by €3.73 per day, and MAPE by nearly one percentage point. The gains are modest in absolute terms but consistent across all three metrics, confirming that the event flags carry genuine signal for Fini’s candy demand patterns.
Output Files
| File | Columns | Description |
|---|
outputs/forecast_enriched.csv | ds, yhat, yhat_lower, yhat_upper, y | Full forecast with event-adjusted predictions; y is NaN for future rows |
outputs/metrics_enriched.json | MAE, RMSE, MAPE | Evaluation metrics computed on historical actuals only |