| name | timesfm-forecasting |
| description | Zero-shot time series forecasting with Google's TimesFM foundation model. Use for any univariate time series (sales, sensors, energy, vitals, weather) without training a custom model. Supports CSV/DataFrame/array inputs with point forecasts and prediction intervals. Includes a preflight system checker script to verify RAM/GPU before first use. |
| allowed-tools | Read Write Edit Bash |
| license | Apache-2.0 license |
| metadata | version: "1.0" skill-author: Clayton Young / Superior Byte Works, LLC (@borealBytes) skill-version: "1.0.0" |
TimesFM Forecasting
Overview
TimesFM (Time Series Foundation Model) is a pretrained decoder-only foundation model
developed by Google Research for time-series forecasting. It works zero-shot โ feed it
any univariate time series and it returns point forecasts with calibrated quantile
prediction intervals, no training required.
This skill wraps TimesFM for safe, agent-friendly local inference. It includes a
mandatory preflight system checker that verifies RAM, GPU memory, and disk space
before the model is ever loaded so the agent never crashes a user's machine.
Key numbers: TimesFM 2.5 uses 200M parameters (~800 MB on disk, ~1.5 GB in RAM on
CPU, ~1 GB VRAM on GPU). The archived v1/v2 500M-parameter model needs ~32 GB RAM.
Always run the system checker first.
When to Use This Skill
Use this skill when:
- Forecasting any univariate time series (sales, demand, sensor, vitals, price, weather)
- You need zero-shot forecasting without training a custom model
- You want probabilistic forecasts with calibrated prediction intervals (quantiles)
- You have time series of any length (the model handles 1โ16,384 context points)
- You need to batch-forecast hundreds or thousands of series efficiently
- You want a foundation model approach instead of hand-tuning ARIMA/ETS parameters
Do not use this skill when:
- You need classical statistical models with coefficient interpretation โ use
statsmodels
- You need time series classification or clustering โ use
aeon
- You need multivariate vector autoregression or Granger causality โ use
statsmodels
- Your data is tabular (not temporal) โ use
scikit-learn
Note on Anomaly Detection: TimesFM does not have built-in anomaly detection, but you can
use the quantile forecasts as prediction intervals โ values outside the 90% CI (q10โq90)
are statistically unusual. See the examples/anomaly-detection/ directory for a full example.
โ ๏ธ Mandatory Preflight: System Requirements Check
CRITICAL โ ALWAYS run the system checker before loading the model for the first time.
python scripts/check_system.py
This script checks:
- Available RAM โ warns if below 4 GB, blocks if below 2 GB
- GPU availability โ detects CUDA/MPS devices and VRAM
- Disk space โ verifies room for the ~800 MB model download
- Python version โ requires 3.10+
- Existing installation โ checks if
timesfm and torch are installed
Note: Model weights are NOT stored in this repository. TimesFM weights (~800 MB)
download on-demand from HuggingFace on first use and cache in ~/.cache/huggingface/.
The preflight checker ensures sufficient resources before any download begins.
flowchart TD
accTitle: Preflight System Check
accDescr: Decision flowchart showing the system requirement checks that must pass before loading TimesFM.
start["๐ Run check_system.py"] --> ram{"RAM โฅ 4 GB?"}
ram -->|"Yes"| gpu{"GPU available?"}
ram -->|"No (2-4 GB)"| warn_ram["โ ๏ธ Warning: tight RAM<br/>CPU-only, small batches"]
ram -->|"No (< 2 GB)"| block["๐ BLOCKED<br/>Insufficient memory"]
warn_ram --> disk
gpu -->|"CUDA / MPS"| vram{"VRAM โฅ 2 GB?"}
gpu -->|"CPU only"| cpu_ok["โ
CPU mode<br/>Slower but works"]
vram -->|"Yes"| gpu_ok["โ
GPU mode<br/>Fast inference"]
vram -->|"No"| cpu_ok
gpu_ok --> disk{"Disk โฅ 2 GB free?"}
cpu_ok --> disk
disk -->|"Yes"| ready["โ
READY<br/>Safe to load model"]
disk -->|"No"| block_disk["๐ BLOCKED<br/>Need space for weights"]
classDef ok fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
classDef warn fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#713f12
classDef block fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#7f1d1d
classDef neutral fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
class ready,gpu_ok,cpu_ok ok
class warn_ram warn
class block,block_disk block
class start,ram,gpu,vram,disk neutral
Hardware Requirements by Model Version
| Model | Parameters | RAM (CPU) | VRAM (GPU) | Disk | Context |
|---|
| TimesFM 2.5 (recommended) | 200M | โฅ 4 GB | โฅ 2 GB | ~800 MB | up to 16,384 |
| TimesFM 2.0 (archived) | 500M | โฅ 16 GB | โฅ 8 GB | ~2 GB | up to 2,048 |
| TimesFM 1.0 (archived) | 200M | โฅ 8 GB | โฅ 4 GB | ~800 MB | up to 2,048 |
Recommendation: Always use TimesFM 2.5 unless you have a specific reason to use an
older checkpoint. It is smaller, faster, and supports 8ร longer context.
๐ง Installation
Step 1: Verify System (always first)
python scripts/check_system.py
Step 2: Install TimesFM
uv pip install timesfm[torch]
pip install timesfm[torch]
uv pip install timesfm[flax]
Step 3: Install PyTorch for Your Hardware
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cu121
pip install torch>=2.0.0 --index-url https://download.pytorch.org/whl/cpu
pip install torch>=2.0.0
Step 4: Verify Installation
import timesfm
import numpy as np
print(f"TimesFM version: {timesfm.__version__}")
print("Installation OK")
๐ฏ Quick Start
Minimal Example (5 Lines)
import torch, numpy as np, timesfm
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=1024, max_horizon=256, normalize_inputs=True,
use_continuous_quantile_head=True, force_flip_invariance=True,
infer_is_positive=True, fix_quantile_crossing=True,
))
point, quantiles = model.forecast(horizon=24, inputs=[
np.sin(np.linspace(0, 20, 200)),
])
Forecast from CSV
import pandas as pd, numpy as np
df = pd.read_csv("monthly_sales.csv", parse_dates=["date"], index_col="date")
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]
point, quantiles = model.forecast(horizon=12, inputs=inputs)
for i, col in enumerate(df.columns):
last_date = df[col].dropna().index[-1]
future_dates = pd.date_range(last_date, periods=13, freq="MS")[1:]
forecast_df = pd.DataFrame({
"date": future_dates,
"forecast": point[i],
"lower_80": quantiles[i, :, 2],
"upper_80": quantiles[i, :, 8],
})
print(f"\n--- {col} ---")
print(forecast_df.to_string(index=False))
Forecast with Covariates (XReg)
TimesFM 2.5+ supports exogenous variables through forecast_with_covariates(). Requires timesfm[xreg].
point, quantiles = model.forecast_with_covariates(
inputs=inputs,
dynamic_numerical_covariates={"price": price_arrays},
dynamic_categorical_covariates={"holiday": holiday_arrays},
static_categorical_covariates={"region": region_labels},
xreg_mode="xreg + timesfm",
)
| Covariate Type | Description | Example |
|---|
dynamic_numerical | Time-varying numeric | price, temperature, promotion spend |
dynamic_categorical | Time-varying categorical | holiday flag, day of week |
static_numerical | Per-series numeric | store size, account age |
static_categorical | Per-series categorical | store type, region, product category |
XReg Modes:
"xreg + timesfm" (default): TimesFM forecasts first, then XReg adjusts residuals
"timesfm + xreg": XReg fits first, then TimesFM forecasts residuals
See examples/covariates-forecasting/ for a complete example with synthetic retail data.
Anomaly Detection (via Quantile Intervals)
TimesFM does not have built-in anomaly detection, but the quantile forecasts naturally provide
prediction intervals that can detect anomalies:
point, q = model.forecast(horizon=H, inputs=[values])
lower_90 = q[0, :, 1]
upper_90 = q[0, :, 9]
actual = test_values
anomalies = (actual < lower_90) | (actual > upper_90)
is_warning = (actual < q[0, :, 2]) | (actual > q[0, :, 8])
is_critical = anomalies
| Severity | Condition | Interpretation |
|---|
| Normal | Inside 80% CI | Expected behavior |
| Warning | Outside 80% CI | Unusual but possible |
| Critical | Outside 90% CI | Statistically rare (< 10% probability) |
See examples/anomaly-detection/ for a complete example with visualization.
point, quantiles = model.forecast_with_covariates(
inputs=inputs,
dynamic_numerical_covariates={"temperature": temp_arrays},
dynamic_categorical_covariates={"day_of_week": dow_arrays},
static_categorical_covariates={"region": region_labels},
xreg_mode="xreg + timesfm",
)
๐ Understanding the Output
Quantile Forecast Structure
TimesFM returns (point_forecast, quantile_forecast):
point_forecast: shape (batch, horizon) โ the median (0.5 quantile)
quantile_forecast: shape (batch, horizon, 10) โ ten slices:
| Index | Quantile | Use |
|---|
| 0 | Mean | Average prediction |
| 1 | 0.1 | Lower bound of 80% PI |
| 2 | 0.2 | Lower bound of 60% PI |
| 3 | 0.3 | โ |
| 4 | 0.4 | โ |
| 5 | 0.5 | Median (= point_forecast) |
| 6 | 0.6 | โ |
| 7 | 0.7 | โ |
| 8 | 0.8 | Upper bound of 60% PI |
| 9 | 0.9 | Upper bound of 80% PI |
Extracting Prediction Intervals
point, q = model.forecast(horizon=H, inputs=data)
lower_80 = q[:, :, 1]
upper_80 = q[:, :, 9]
lower_60 = q[:, :, 2]
upper_60 = q[:, :, 8]
median = q[:, :, 5]
flowchart LR
accTitle: Quantile Forecast Anatomy
accDescr: Diagram showing how the 10-element quantile vector maps to prediction intervals.
input["๐ Input Series<br/>1-D array"] --> model["๐ค TimesFM<br/>compile + forecast"]
model --> point["๐ Point Forecast<br/>(batch, horizon)"]
model --> quant["๐ Quantile Forecast<br/>(batch, horizon, 10)"]
quant --> pi80["80% PI<br/>q[:,:,1] โ q[:,:,9]"]
quant --> pi60["60% PI<br/>q[:,:,2] โ q[:,:,8]"]
quant --> median["Median<br/>q[:,:,5]"]
classDef data fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef model fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#581c87
classDef output fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
class input data
class model model
class point,quant,pi80,pi60,median output
๐ง ForecastConfig Reference
All forecasting behavior is controlled by timesfm.ForecastConfig:
timesfm.ForecastConfig(
max_context=1024,
max_horizon=256,
normalize_inputs=True,
per_core_batch_size=32,
use_continuous_quantile_head=True,
force_flip_invariance=True,
infer_is_positive=True,
fix_quantile_crossing=True,
return_backcast=False,
)
| Parameter | Default | When to Change |
|---|
max_context | 0 | Set to match your longest historical window (e.g., 512, 1024, 4096) |
max_horizon | 0 | Set to your maximum forecast length |
normalize_inputs | False | Always set True โ prevents scale-dependent instability |
per_core_batch_size | 1 | Increase for throughput; decrease if OOM |
use_continuous_quantile_head | False | Set True for calibrated prediction intervals |
force_flip_invariance | True | Keep True unless profiling shows it hurts |
infer_is_positive | True | Set False for series that can be negative (temperature, returns) |
fix_quantile_crossing | False | Set True to guarantee monotonic quantiles |
๐ Common Workflows
Workflow 1: Single Series Forecast
flowchart TD
accTitle: Single Series Forecast Workflow
accDescr: Step-by-step workflow for forecasting a single time series with system checking.
check["1. Run check_system.py"] --> load["2. Load model<br/>from_pretrained()"]
load --> compile["3. Compile with ForecastConfig"]
compile --> prep["4. Prepare data<br/>pd.read_csv โ np.array"]
prep --> forecast["5. model.forecast()<br/>horizon=N"]
forecast --> extract["6. Extract point + PI"]
extract --> plot["7. Plot or export results"]
classDef step fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#1f2937
class check,load,compile,prep,forecast,extract,plot step
import torch, numpy as np, pandas as pd, timesfm
torch.set_float32_matmul_precision("high")
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=512, max_horizon=52, normalize_inputs=True,
use_continuous_quantile_head=True, fix_quantile_crossing=True,
))
df = pd.read_csv("weekly_demand.csv", parse_dates=["week"])
values = df["demand"].values.astype(np.float32)
point, quantiles = model.forecast(horizon=52, inputs=[values])
forecast_df = pd.DataFrame({
"forecast": point[0],
"lower_80": quantiles[0, :, 1],
"upper_80": quantiles[0, :, 9],
})
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(values[-104:], label="Historical")
x_fc = range(len(values[-104:]), len(values[-104:]) + 52)
ax.plot(x_fc, forecast_df["forecast"], label="Forecast", color="tab:orange")
ax.fill_between(x_fc, forecast_df["lower_80"], forecast_df["upper_80"],
alpha=0.2, color="tab:orange", label="80% PI")
ax.legend()
ax.set_title("52-Week Demand Forecast")
plt.tight_layout()
plt.savefig("forecast.png", dpi=150)
print("Saved forecast.png")
Workflow 2: Batch Forecasting (Many Series)
import pandas as pd, numpy as np
df = pd.read_csv("all_stores.csv", parse_dates=["date"], index_col="date")
inputs = [df[col].dropna().values.astype(np.float32) for col in df.columns]
point, quantiles = model.forecast(horizon=30, inputs=inputs)
results = {}
for i, col in enumerate(df.columns):
results[col] = {
"forecast": point[i].tolist(),
"lower_80": quantiles[i, :, 1].tolist(),
"upper_80": quantiles[i, :, 9].tolist(),
}
import json
with open("batch_forecasts.json", "w") as f:
json.dump(results, f, indent=2)
print(f"Forecasted {len(results)} series โ batch_forecasts.json")
Workflow 3: Evaluate Forecast Accuracy
import numpy as np
H = 24
train = values[:-H]
actual = values[-H:]
point, quantiles = model.forecast(horizon=H, inputs=[train])
pred = point[0]
mae = np.mean(np.abs(actual - pred))
rmse = np.sqrt(np.mean((actual - pred) ** 2))
mape = np.mean(np.abs((actual - pred) / actual)) * 100
lower = quantiles[0, :, 1]
upper = quantiles[0, :, 9]
coverage = np.mean((actual >= lower) & (actual <= upper)) * 100
print(f"MAE: {mae:.2f}")
print(f"RMSE: {rmse:.2f}")
print(f"MAPE: {mape:.1f}%")
print(f"80% PI Coverage: {coverage:.1f}% (target: 80%)")
โ๏ธ Performance Tuning
GPU Acceleration
import torch
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")
elif hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
print("Apple Silicon MPS available")
else:
print("CPU only โ inference will be slower but still works")
torch.set_float32_matmul_precision("high")
Batch Size Tuning
model.compile(timesfm.ForecastConfig(
max_context=1024,
max_horizon=256,
per_core_batch_size=32,
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
Memory-Constrained Environments
import gc, torch
gc.collect()
if torch.cuda.is_available():
torch.cuda.empty_cache()
model = timesfm.TimesFM_2p5_200M_torch.from_pretrained(
"google/timesfm-2.5-200m-pytorch"
)
model.compile(timesfm.ForecastConfig(
max_context=512,
max_horizon=128,
per_core_batch_size=4,
normalize_inputs=True,
use_continuous_quantile_head=True,
fix_quantile_crossing=True,
))
CHUNK = 50
all_results = []
for i in range(0, len(inputs), CHUNK):
chunk = inputs[i:i+CHUNK]
p, q = model.forecast(horizon=H, inputs=chunk)
all_results.append((p, q))
gc.collect()
๐ Integration with Other Skills
With statsmodels
Use statsmodels for classical models (ARIMA, SARIMAX) as a comparison baseline:
tfm_point, tfm_q = model.forecast(horizon=H, inputs=[values])
from statsmodels.tsa.arima.model import ARIMA
arima = ARIMA(values, order=(1,1,1)).fit()
arima_forecast = arima.forecast(steps=H)
print(f"TimesFM MAE: {np.mean(np.abs(actual - tfm_point[0])):.2f}")
print(f"ARIMA MAE: {np.mean(np.abs(actual - arima_forecast)):.2f}")
With matplotlib / scientific-visualization
Plot forecasts with prediction intervals as publication-quality figures.
With exploratory-data-analysis
Run EDA on the time series before forecasting to understand trends, seasonality, and stationarity.
๐ Available Scripts
scripts/check_system.py
Mandatory preflight checker. Run before first model load.
python scripts/check_system.py
Output example:
=== TimesFM System Requirements Check ===
[RAM] Total: 32.0 GB | Available: 24.3 GB โ
PASS
[GPU] NVIDIA RTX 4090 | VRAM: 24.0 GB โ
PASS
[Disk] Free: 142.5 GB โ
PASS
[Python] 3.12.1 โ
PASS
[timesfm] Installed (2.5.0) โ
PASS
[torch] Installed (2.4.1+cu121) โ
PASS
VERDICT: โ
System is ready for TimesFM 2.5 (GPU mode)
Recommended: per_core_batch_size=128
scripts/forecast_csv.py
End-to-end CSV forecasting with automatic system check.
python scripts/forecast_csv.py input.csv \
--horizon 24 \
--date-col date \
--value-cols sales,revenue \
--output forecasts.csv
๐ Reference Documentation
Detailed guides in references/:
| File | Contents |
|---|
references/system_requirements.md | Hardware tiers, GPU/CPU selection, memory estimation formulas |
references/api_reference.md | Full ForecastConfig docs, from_pretrained options, output shapes |
references/data_preparation.md | Input formats, NaN handling, CSV loading, covariate setup |
Common Pitfalls
- Not running system check โ model load crashes on low-RAM machines. Always run
check_system.py first.
- Forgetting
model.compile() โ RuntimeError: Model is not compiled. Must call compile() before forecast().
- Not setting
normalize_inputs=True โ unstable forecasts for series with large values.
- Using v1/v2 on machines with < 32 GB RAM โ use TimesFM 2.5 (200M params) instead.
- Not setting
fix_quantile_crossing=True โ quantiles may not be monotonic (q10 > q50).
- Huge
per_core_batch_size on small GPU โ CUDA OOM. Start small, increase.
- Passing 2-D arrays โ TimesFM expects a list of 1-D arrays, not a 2-D matrix.
- Forgetting
torch.set_float32_matmul_precision("high") โ slower inference on Ampere+ GPUs.
- Not handling NaN in output โ edge cases with very short series. Always check
np.isnan(point).any().
- Using
infer_is_positive=True for series that can be negative โ clamps forecasts at zero. Set False for temperature, returns, etc.
Model Versions
timeline
accTitle: TimesFM Version History
accDescr: Timeline of TimesFM model releases showing parameter counts and key improvements.
section 2024
TimesFM 1.0 : 200M params, 2K context, JAX only
TimesFM 2.0 : 500M params, 2K context, PyTorch + JAX
section 2025
TimesFM 2.5 : 200M params, 16K context, quantile head, no frequency indicator
| Version | Params | Context | Quantile Head | Frequency Flag | Status |
|---|
| 2.5 | 200M | 16,384 | โ
Continuous (30M) | โ Removed | Latest |
| 2.0 | 500M | 2,048 | โ
Fixed buckets | โ
Required | Archived |
| 1.0 | 200M | 2,048 | โ
Fixed buckets | โ
Required | Archived |
Hugging Face checkpoints:
google/timesfm-2.5-200m-pytorch (recommended)
google/timesfm-2.5-200m-flax
google/timesfm-2.0-500m-pytorch (archived)
google/timesfm-1.0-200m-pytorch (archived)
Resources
Examples
Three fully-working reference examples live in examples/. Use them as ground truth for correct API usage an