peptrendGet the app

Fifteen ways to draw one line

A weigh-in is a measurement with a large error term. Every method below is an estimator of the quantity underneath it. They disagree, sometimes by pounds, and the disagreement is information.

Classic

From technical analysis

Statistical

Robust

185190195200205AprJul4.0lb apart187.0182.9
Methods drawn15
Spread on the last day4.0 lb
Range182.9–187.0

Every line is the same 84 weigh-ins under a different filter. Pick one to ink it.

The comparison

"Causal" means the value for a given day uses only that day and earlier ones. Two methods here are not causal: they read points on both sides, which makes them beautifully smooth in the middle of your history and unreliable at today's edge.

"Gaps" is what happens on a day you did not weigh in. Filling interpolates a value; skipping treats your weigh-ins as consecutive steps regardless of the calendar. It sounds like a detail. It is the entire difference between two lines that otherwise share a formula.

MethodWhat it isDefault parametersAdaptiveCausalGaps
SMASimple Moving Averagewindow 7yesskips
Linear WMALinear Weighted Moving Averagewindow 7yesskips
EWMAExponentially Weighted Moving Averageα 0.10yesfills
Hacker's DietJohn Walker's filterα 0.10 fixedyesskips
DEMADouble Exponential Moving Averageα 0.10yesfills
TEMATriple Exponential Moving Averageα 0.10yesfills
HMAHull Moving Averagewindow 7yesfills
KAMAKaufman's Adaptive Moving Averageα 0.04–0.22, window 10efficiency ratioyesfills
Kalman FilterConstant-velocity Kalman filterq 0.01, r 0.35Kalman gainyesfills
LOESSTricube-weighted moving meanspan 7–31NOfills
Savitzky-GolayCentred moving averagewindow 7NOfills
Holt-WintersHolt's linear methodα 0.18, β 0.04yesfills
Rolling MedianTrailing medianwindow 7yesskips
Robust Adaptive EWMAAdaptive α with MAD outlier rejectionα 0.04–0.22, k 2.5ER × MAD weightyesfills
Weekly AverageCalendar-week meanISO weekyesn/a

The trade-off, plotted

Responsiveness against noise rejection, for all fifteen. The two pull against each other, which is why the choice is a choice and not a ranking.

0%20%40%60%80%0.050.100.150.200.250.300.350.40HMAKAMAKalman FilterRobust Adaptive EWMAWeekly Averageresponsiveness — lb the line moves per day →noise rejected

Pearson r = -0.665 across the fifteen. Real, and imperfect — which is why the plot has something to read.

What a chartist notices

KAMA, the quiet corner
Barely moves, ignores almost everything. The app squares the smoothing constant, so a perfectly efficient move gives an effective α near 0.048 rather than 0.22. That is why it sits there.
Hull and Kalman, the fast corner
Low lag, paid for in whipsaw — exactly what a Hull average does to a price series. Hull passes through four fifths of the scale's daily movement.
Weekly Average breaks the frontier
High on both axes, which looks impossible. It steps once a calendar week, so its per-day figure is a week's step divided by seven. It is not better than everything; it is measured differently.
MethodMoves/dayIgnoredLast day
KAMA0.08081.3%187.0
Hacker's Diet0.22980.3%186.0
Rolling Median0.30473.9%185.0
Robust Adaptive EWMA0.09478.1%185.0
LOESS0.07482.8%184.7
SMA0.29574.7%184.7
EWMA0.10375.9%184.5
Linear WMA0.34570.4%184.3
DEMA0.15264.7%183.6
Holt-Winters0.15065.1%183.5
Savitzky-Golay0.16362.0%183.4
TEMA0.19654.4%183.3
Kalman Filter0.4065.5%183.0
Weekly Average0.19683.1%183.0
HMA0.36814.3%182.9

The mathematics

EWMA, and the whole family under it

The exponentially weighted moving average is the backbone. One state, one constant:

T₀ = W₀
Tₜ = α·Wₜ + (1 − α)·Tₜ₋₁

At α = 0.10 today's weigh-in contributes a tenth of the answer and the remaining nine tenths come from everything before it, decaying geometrically. The half-life of a shock is about 6.6 days. That is why a heavy Sunday takes a week to leave the line.

The dose side of the app runs on the same kind of constant. Each medication preset carries a published half-life that sets an exponential decay, and the medication pages set the six approved presets beside their labels and chart the curve each one draws: half-lives and level curves, medication by medication.

Hacker's Diet

John Walker's 1991 book proposed exactly this filter for bodyweight, and Peptrend ships it with α locked at 0.10 and interpolation forced off. The lock is deliberate: with interpolation on and a configurable α it becomes indistinguishable from the plain EWMA above, and shipping two names for one line is a way of lying about how many features you have.

DEMA and TEMA

An EMA lags. Both of these estimate the lag and subtract it:

DEMA = 2·EMA₁ − EMA₂
TEMA = 3·EMA₁ − 3·EMA₂ + EMA₃

where each EMA is applied to the previous one's output. You buy responsiveness with overshoot — after a genuine step change both will swing past the new level before settling. The app labels DEMA "experimental, noise-sensitive" for that reason.

KAMA

Kaufman's insight was that the right amount of smoothing depends on whether the series is trending or chopping. The efficiency ratio measures that directly: net displacement divided by total path length over a window. A straight line scores 1; a random walk that ends where it started scores 0.

ER = |Wₜ − Wₜ₋ₙ| / Σ|Wᵢ − Wᵢ₋₁|
α  = (α_slow + ER·(α_fast − α_slow))²

Note the square. It is in Kaufman's original formulation and it is in the app, and it means a perfectly efficient move gives an effective α of 0.22² ≈ 0.048 — slower than you would guess from the constants alone.

The Kalman filter

The only method here that models a rate rather than inferring one afterwards. State is [level, velocity]; each day the filter predicts the level moved by the velocity, then corrects both against the measurement in proportion to the Kalman gain. With q = 0.01 and r = 0.35 it treats the scale as roughly 35 times noisier than the underlying process, which is about right for a bathroom scale.

Because velocity is part of the state, the rate it reports is the model's own estimate, not a look-back over the last fortnight. That is a genuinely different number, and often a better one.

Robust Adaptive EWMA

The default. Three things stacked: an efficiency ratio drives α between 0.04 and 0.22, then a median-absolute-deviation estimate of the recent residual scale sets an outlier threshold at k = 2.5σ, and any weigh-in beyond it has its influence scaled down in proportion to how far out it is.

α    = α_slow + ER·(α_fast − α_slow)
σ    = 1.4826 · median(|residual − median|)     [floor 0.05 kg]
w    = residual ≤ 2.5σ ? 1 : 2.5σ / residual
α_eff = α · w

The practical effect: the 5.4 lb jump this user's log actually contains moves the line by a fraction of a pound instead of dragging it up for a fortnight.

Where the names are bigger than the implementations

Three methods carry names from the literature that promise more than the code delivers, and it is better that you hear it here:

  • LOESS is implemented as a tricube-weighted moving mean, not a local linear regression. The weighting function is the real one; the regression is not there.
  • Savitzky-Golay is a centred moving average. There is no polynomial fit, so it does not preserve peak heights or derivatives the way the real filter does.
  • Holt-Winters has no seasonal component. It is Holt's linear method — level plus trend — so it will not find your weekend pattern.

All three still produce useful, well-behaved lines. They are just not the textbook algorithms their names invoke, and you should not pick one expecting the textbook behaviour.

So which one

If you want an answer rather than a menu: leave it on Robust Adaptive EWMA. It is the default because it is the one that behaves best on real weigh-in data, where the errors are fat-tailed and the signal is small.

Change it when you have a reason. Rolling Median if your scale is genuinely unreliable rather than your body. Kalman if you care more about the rate than the level. Weekly Average if you weigh in twice a week and daily smoothing is pretending to a precision you have not earned.

Version 1.4.0, coming to the App Store after 1.3.3, changes the starting set: a fresh install will show three of these on the chart's method strip, Rolling Median, Robust Adaptive EWMA and Weekly Average, with the rest a tap away in Settings and the advanced list in Pro. Switching methods will morph the line into its new shape instead of redrawing it.