Skip to main content

incline: Estimate Local Trend in a Noisy Time Series

PyPI version Downloads CI Docs

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)

Source distribution for incline 2.0.0
File Size Uploaded
incline-2.0.0.tar.gz 65.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for incline 2.0.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

0.4.0

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page