Introduction
Forecasting has a reputation for requiring heavy machinery — ARIMA hyperparameters, Prophet installs, neural networks. But the honest first step is simpler: decompose the past, extend the pattern, and check yourself against reality. This app does exactly that on any CSV with dates and values: trend lines, seasonal patterns, and two forecast methods with a built-in backtest that shows you the error before you trust the future.
It builds on the resampling patterns from the sales analyzer and adds the discipline every forecasting tutorial skips: measuring your own accuracy.
Features
date and value columns.Prerequisites
pip install streamlit pandas numpyStep 1: Create the Script
Save as forecast_app.py:
import streamlit as st
import pandas as pd
import numpy as np
st.set_page_config(page_title="Time Series Forecast", page_icon="🔮", layout="wide")
st.title("🔮 Time Series Forecasting")
uploaded = st.file_uploader("Upload CSV with 'date' and 'value' columns", type=["csv"])
if uploaded:
df = pd.read_csv(uploaded, parse_dates=["date"]).sort_values("date")
s = df.set_index("date")["value"].astype(float)
horizon = st.slider("Forecast periods", 1, 12, 6)
method = st.radio("Method", ["Linear trend", "Seasonal naive"], horizontal=True)
# --- Backtest on the last 20% ---
split = int(len(s) * 0.8)
train, test = s[:split], s[split:]
x_train = np.arange(len(train))
coef = np.polyfit(x_train, train.values, 1)
bt_pred = np.polyval(coef, np.arange(split, len(s)))
mae = np.mean(np.abs(test.values - bt_pred))
st.caption(f"Backtest MAE on last {len(test)} points: **{mae:.1f}** (lower = better)")
# --- Forecast ---
x_all = np.arange(len(s))
future_x = np.arange(len(s), len(s) + horizon)
if method == "Linear trend":
coef_all = np.polyfit(x_all, s.values, 1)
forecast = np.polyval(coef_all, future_x)
else:
season = 12 if len(s) >= 24 else max(2, len(s) // 3)
forecast = np.array([s.values[-season + (i % season)] for i in range(horizon)])
freq = pd.infer_freq(s.index) or "D"
future_index = pd.date_range(s.index[-1], periods=horizon + 1, freq=freq)[1:]
chart_df = pd.DataFrame({
"history": s,
"forecast": pd.Series(forecast, index=future_index),
})
st.line_chart(chart_df, height=350)
with st.expander("Seasonality by month"):
if s.index.month.nunique() > 1:
st.bar_chart(s.groupby(s.index.month).mean())
st.caption("Average value by month — repeating shape means seasonality.")
else:
st.info("Upload a CSV with date and value columns to begin.")Step 2: Run the App
streamlit run forecast_app.pyGenerate test data quickly with the sales analyzer's sample script, resampled monthly.
How It Works
Linear trend forecasting is np.polyfit — fitting a line through history and evaluating it at future x positions. It captures direction and slope but knows nothing about seasons. Seasonal naive is the opposite: it repeats the last full cycle of values (the last 12 months for monthly data), capturing seasonality but not trend. Comparing the two on your data — with the backtest MAE — tells you which pattern dominates.
The backtest is the credibility engine: fit on the first 80%, predict the held-out last 20%, and report mean absolute error. A forecast you can't score against history is a guess; this turns the app into a small forecasting lab. If the backtest MAE is larger than the typical change between periods, no method will save you — the series is mostly noise.
pd.infer_freq guesses the cadence (daily, monthly...) so the future index lines up with history on the chart. The seasonality bar chart — mean value per month — is the visual check for whether the seasonal method even applies.
Common Errors & Fixes
np.arange(len(s))) as above, never raw timestamps.s.resample("D").mean()) to regularize.max(2, len(s)//3) prevents degenerate season=1.Key Concepts
What to Try Next
st.area_chart.statsmodels) once linear/seasonal both feel limiting.FAQ
Why not just use Prophet or ARIMA?
You can — but both hide assumptions behind automation. Fitting a line and a seasonal repeat first teaches you what those libraries add, and often the simple method is within a few percent on stable series.
What does MAE mean in practice?
On average, the backtest predictions missed by that many units. A MAE of 42 on monthly sales averaging 1,000 is ~4% — decent. On a series averaging 60, it's useless.
How much history do I need?
For the seasonal method, at least two full cycles (24 monthly points). For linear trend, 10+ points gives a slope you can semi-trust — the backtest will tell you honestly.