incline: Estimate Local Trend in a Noisy Time Series
How fast is this series moving right now? Differencing consecutive observations amplifies noise rather than revealing signal, so incline smooths the series first and differentiates the smooth.
The second half is the part worth having: every estimator can report uncertainty, and which machinery produces it is decided by what the smoother is rather than by what it is called.
import numpy as np
import pandas as pd
from incline import sgolay_trend
df = pd.DataFrame(
{"value": np.linspace(0, 10, 100) + np.random.normal(0, 0.5, 100)},
index=pd.date_range("2020-01-01", periods=100),
)
result = sgolay_trend(df, with_uncertainty=True)
result[
[
"derivative_value",
"derivative_standard_error",
"significant_trend",
"uncertainty_method",
]
].head()
significant_trend tells you where the data support saying the series is moving
at all. uncertainty_method tells you how that was established.
How uncertainty is computed
| Route | When it applies | What you get |
|---|---|---|
operator |
The derivative is a fixed linear map of the data | The sampling variance conditional on the fitted or supplied noise covariance — no asymptotics, no resampling |
native |
The smoother is a probability model (Gaussian process, state space) | Its own posterior variance |
bootstrap |
Everything else | A simulated sampling distribution |
Which case a smoother falls into is settled by probing it, not by assumption:
| Linear — exact variance | Nonlinear — bootstrapped |
|---|---|
| Savitzky-Golay | Smoothing spline with GCV |
| Local polynomial | LOESS with robust=True (the default) |
Smoothing spline at fixed λ |
L1 trend filter |
LOESS with robust=False |
|
| Naive differencing |
A smoother that claims to be linear has its operator checked against its own output before any exact standard error is issued, so a wrong claim raises rather than quietly producing wrong inference.
Do the standard errors work?
Measured, not asserted. tests/test_econometrics.py simulates from known truth
and checks the classic properties — unbiasedness, coverage, size and power. Over
400 replicates, with the truth inside each estimator's approximation space so
that smoothing bias is exactly zero:
| estimator | bias (t) | reported SE ÷ actual spread | coverage of a nominal 95% interval |
|---|---|---|---|
| local polynomial, degree 2 | −2.18 | 0.997 | 0.943 |
| Savitzky-Golay, degree 3 | −0.53 | 0.958 | 0.945 |
| naive differencing | −0.98 | 0.974 | 0.953 |
| LOESS | −1.29 | 0.975 | 0.932 |
| smoothing spline | −1.24 | 0.953 | 0.920 |
Every result passes the predeclared, replicate-count-aware simcheck gate:
absolute bias stays within three Monte Carlo standard errors and coverage stays
inside the binomial band for 0.95. Under the null the significance flag fires
4.8–8.0% of the time against a nominal 5%; for slopes of 0, 0.02, 0.05 and 0.20,
the Savitzky-Golay test rejects 6.0%, 21.0%, 79.2% and 100% of the time.
What the intervals do not tell you
They describe the derivative of the fitted curve, not of reality. The gap is
smoothing bias, and it is set by your bandwidth. At an oversmoothed bandwidth a
perfectly calibrated interval still misses the truth — bias_correct=True
re-centers it, at roughly five times the width.
The default also assumes independent noise. Under AR(1) errors with φ=0.7
that reports standard errors about a quarter of their true size and covers 39%
of the time; noise="ar1" recovers most of it. See
Limitations for both
in full, with numbers.
Methods
from incline import (
naive_trend, # central differences; the baseline to beat
sgolay_trend, # local polynomial on a fixed window
local_polynomial_trend, # kernel-weighted local regression
loess_trend, # LOESS
smoothing_spline_trend, # cubic smoothing spline
l1_trend_filter, # piecewise-polynomial with sparse kinks
gp_trend, # Gaussian process derivative posterior
kalman_trend, # local linear trend state-space model
)
Plus SiZer for multi-scale analysis, deseasonalize for seasonal adjustment,
and trending for ranking thousands of series by how fast they are moving. It
propagates uncertainty for supported summaries so the ranking can say which
leaders are distinguishable from flat.
Installation
pip install incline
Documentation
finite-sample.github.io/incline — including an interactive explorer where you can move the smoothing slider and watch the interval trade width for bias.
For background on what "the trend over a window" even means, see this note.
Authors
Gaurav Sood and contributors.
License
MIT
Metadata
Release files for incline 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| incline-2.0.0.tar.gz | 65.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| incline-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 139.0 kB
Release files / incline-2.0.0.tar.gz
| Download URL | incline-2.0.0.tar.gz |
|---|---|
| Size | 65.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1b0110f7a5621d794f6f71a5c9f215bade7238d5c2c89dbe019da53f50723c14
|
|
BLAKE2b-256 checksum How to use checksums |
d6b880e7696812eef84ecd3a5fee1a8b1948eb0a263c98051ceba9261369eb79
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency logRelease files / incline-2.0.0-py3-none-any.whl
| Download URL | incline-2.0.0-py3-none-any.whl |
|---|---|
| Size | 73.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b8e863c1945578fe131f3cd505b8c414e964e444b6aa5254eabbc6caced9bff3
|
|
BLAKE2b-256 checksum How to use checksums |
97b4f52263333d7ad370e06f9d3aec8df77caa38ab42b2635083dc4d38d8da78
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.
Transparency log