Skip to content

ntpstats.estimators

Pluggable clock-offset estimators for benchmarking synchronisation algorithms.

An estimator turns noisy measurements into an estimate of the true offset (reference - local) at the measurement times::

class MyEstimator(Estimator):
    name = "mine"
    def fit(self, series):            # TimeSeries -> TimeSeries
        ...

register(MyEstimator())

Third-party packages can expose estimators through the entry-point group ntpstats.estimators (value: an :class:Estimator instance, class or factory); they are picked up by :func:available and ntpstats bench.

Multi-server estimators set multi = True and receive a list of series (one per server); they return one combined series.

Built-in reference algorithms

raw the measurements themselves kalman two-state Kalman filter (no delay information) kalman-dw Kalman filter with delay-weighted measurement noise rts-dw RTS smoother, delay weighted (offline optimum for the model) mindelay NTP clock filter: minimum delay of the last 8 samples (RFC 5905 s10) regression chrony-style weighted linear regression over a window sized by a runs test on the residuals feedforward RADclock-style: rate from long-baseline low-RTT packets, offset from a quality-weighted recent window rfc5905 (multi) clock filter + selection (intersection), cluster and combine algorithms of RFC 5905 s11 median (multi) median of the servers' clock-filter outputs

regression(series, max_samples=64, min_samples=6, sigma=None)

Causal weighted linear regression per sample, chrony style.

Weights are 1 / (sigma^2 + q^2) with q the queueing error bound; the window shrinks (dropping the oldest half) while the residual signs fail a runs test, i.e. while a straight line no longer describes the recent phase (frequency change).

feedforward(series, rate_window=6 * 3600, offset_window=16, e_star=None)

Feed-forward estimator in the spirit of RADclock (Veitch, Ridoux et al.).

  • rate: slope between low-RTT packets separated by a long baseline (causal, up to rate_window seconds back), robust to queueing;
  • offset: for each sample, quality-weighted average of the last offset_window rate-corrected offsets, weights exp(-(q / E*)^2).

rfc5905_combine(series_list, nmin=1, maxclock=3, dispersion=0.001)

Selection, cluster and combine (RFC 5905 s11.2) over several servers.

At each epoch (times of the first server) the latest clock-filter output of every server gives an offset and a root distance lambda = delay/2 + dispersion + jitter. The intersection algorithm keeps the truechimers, the cluster algorithm prunes outliers by selection jitter down to maxclock survivors, and the survivors are combined weighted by 1/lambda.