Files
fn_registry/python/functions/datascience/forecast_seasonal_median.md
T
egutierrez 5a4f82cf76 chore: auto-commit (26 archivos)
- python/functions/bigquery/bq_auth.md
- python/functions/bigquery/bq_load_from_file.md
- python/functions/bigquery/bq_load_from_gcs.md
- python/functions/bigquery/client.py
- python/functions/bigquery/queries.py
- python/functions/datascience/__init__.py
- python/functions/datascience/decode_qr_image.py
- python/functions/datascience/load_bq_table_to_duckdb.md
- python/functions/datascience/load_bq_table_to_duckdb.py
- python/functions/pipelines/profile_bq_table.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-02 19:00:13 +02:00

5.5 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
forecast_seasonal_median function py datascience 1.0.0 pure def forecast_seasonal_median(history: list[dict], horizon_dates: list[str], as_of: str, dow_weeks: int = 8, trend_recent_weeks: int = 4, trend_clip: tuple = (0.5, 2.0)) -> list[dict] Forecast diario por mediana estacional (mismo dia de semana) mas factor de tendencia acotado, para una o varias series temporales. Base estacional = mediana del valor en las ultimas dow_weeks fechas con el mismo dia de semana que la fecha objetivo (dias ausentes = 0, para series intermitentes). Factor de tendencia por serie = razon de la suma de las ultimas trend_recent_weeks semanas frente a las trend_recent_weeks anteriores, clipped a trend_clip. y_pred = max(0, base * factor). Funcion pura y determinista (solo stdlib, sin I/O ni datetime.now). Nucleo del forecast de ventas diarias Aurgi (dia x centro x subcategoria CGQ).
forecast
bigquery
timeseries
seasonal
median
baseline
sales
aurgi
python
false
name desc
history lista de observaciones {series_id: str, date: 'YYYY-MM-DD', value: float}. Filas duplicadas (misma serie+fecha) se suman. Los dias sin fila dentro de las ventanas cuentan como valor 0 (series intermitentes: sin fila = sin venta)
name desc
horizon_dates fechas futuras a predecir, strings ISO 'YYYY-MM-DD'. Tipicamente as_of+1..as_of+horizon
name desc
as_of fecha de corte 'YYYY-MM-DD': ultimo dia de historia utilizable, inclusive. Todas las ventanas se calculan hacia atras desde aqui
name desc
dow_weeks numero de fechas del mismo dia de semana que la objetivo a promediar (mediana) para la base estacional. Default 8 (8 semanas)
name desc
trend_recent_weeks tamano en semanas de cada una de las dos ventanas de tendencia (reciente y anterior). Default 4: compara 4 semanas recientes vs las 4 previas
name desc
trend_clip tupla (min, max) al que se acota el factor de tendencia. Default (0.5, 2.0): la prediccion no puede caer a menos de la mitad ni superar el doble por tendencia
list[dict]: una fila {series_id: str, date: str, y_pred: float} por cada serie presente en history y cada fecha de horizon_dates. Ordenada por series_id (asc) y luego por el orden de horizon_dates. y_pred siempre >= 0.0 true
serie regular con patron semanal claro da la mediana correcta
serie intermitente: los dias ausentes cuentan como 0 en la mediana
serie con tendencia creciente aplica factor >1 acotado a trend_clip
sin datos en la ventana anterior, el factor de tendencia es 1.0
horizon de 7 dias produce una fila por serie y fecha, ordenadas
python/functions/datascience/forecast_seasonal_median_test.py python/functions/datascience/forecast_seasonal_median.py

Ejemplo

from datascience import forecast_seasonal_median

# Historia diaria por serie (centro|subcategoria). Sin fila = sin venta = 0.
history = [
    {"series_id": "12|NEUMATICOS", "date": "2026-06-23", "value": 1450.0},
    {"series_id": "12|NEUMATICOS", "date": "2026-06-16", "value": 1380.0},
    {"series_id": "12|NEUMATICOS", "date": "2026-06-09", "value": 1500.0},
    # ... mas historia (idealmente >= 8 semanas para la base estacional) ...
]

# as_of = ultimo dia cerrado; predice los 7 dias siguientes.
horizon = ["2026-06-30", "2026-07-01", "2026-07-02", "2026-07-03",
           "2026-07-04", "2026-07-05", "2026-07-06"]

preds = forecast_seasonal_median(history, horizon, as_of="2026-06-29")
for p in preds:
    print(p["series_id"], p["date"], round(p["y_pred"], 2))

Cuando usarla

Cuando necesites un baseline de forecast diario robusto y explicable para series con estacionalidad semanal fuerte (ventas por dia de la semana) y posibles huecos (dias sin venta). Es el nucleo puro del pipeline run_sales_forecast: se llama una vez con toda la historia agregada y devuelve todas las predicciones de golpe. Usala como punto de partida antes de modelos mas pesados (Prophet, ARIMA, gradient boosting): captura el patron dia-de-semana + una correccion de tendencia acotada sin dependencias externas ni entrenamiento. Ideal para muchas series a la vez (miles de pares centro x subcategoria) donde entrenar un modelo por serie no compensa.

Notas

  • Funcion pura y determinista: no hace I/O, no llama datetime.now(); el corte temporal siempre es el argumento as_of explicito. Solo stdlib (datetime, statistics), sin numpy ni pandas.
  • La base estacional toma las fechas EXACTAS del calendario: la mas reciente <= as_of con el mismo dia de semana que la objetivo, y de ahi 7 dias hacia atras por punto (hasta dow_weeks puntos). Una fecha ausente en history cuenta como 0, por lo que la mediana refleja bien las series intermitentes.
  • El factor de tendencia se calcula UNA vez por serie (no depende de la fecha objetivo) como razon de sumas de dos ventanas contiguas de trend_recent_weeks semanas. Denominador 0 => factor 1.0 (evita division por cero y no infla series que arrancan). El clip a trend_clip evita que un pico reciente dispare la prediccion.
  • y_pred = max(0.0, base * factor): nunca negativo. No modela festivos ni eventos puntuales; para eso se necesitaria una capa de calendario adicional.
  • Para que la base estacional sea fiable conviene aportar >= dow_weeks semanas de historia. Con menos historia, los puntos ausentes (=0) empujan la mediana hacia abajo.