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
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.
| Method | What it is | Default parameters | Adaptive | Causal | Gaps |
|---|---|---|---|---|---|
| SMA | Simple Moving Average | window 7 | — | yes | skips |
| Linear WMA | Linear Weighted Moving Average | window 7 | — | yes | skips |
| EWMA | Exponentially Weighted Moving Average | α 0.10 | — | yes | fills |
| Hacker's Diet | John Walker's filter | α 0.10 fixed | — | yes | skips |
| DEMA | Double Exponential Moving Average | α 0.10 | — | yes | fills |
| TEMA | Triple Exponential Moving Average | α 0.10 | — | yes | fills |
| HMA | Hull Moving Average | window 7 | — | yes | fills |
| KAMA | Kaufman's Adaptive Moving Average | α 0.04–0.22, window 10 | efficiency ratio | yes | fills |
| Kalman Filter | Constant-velocity Kalman filter | q 0.01, r 0.35 | Kalman gain | yes | fills |
| LOESS | Tricube-weighted moving mean | span 7–31 | — | NO | fills |
| Savitzky-Golay | Centred moving average | window 7 | — | NO | fills |
| Holt-Winters | Holt's linear method | α 0.18, β 0.04 | — | yes | fills |
| Rolling Median | Trailing median | window 7 | — | yes | skips |
| Robust Adaptive EWMA | Adaptive α with MAD outlier rejection | α 0.04–0.22, k 2.5 | ER × MAD weight | yes | fills |
| Weekly Average | Calendar-week mean | ISO week | — | yes | n/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.
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.
| Method | Moves/day | Ignored | Last day |
|---|---|---|---|
| KAMA | 0.080 | 81.3% | 187.0 |
| Hacker's Diet | 0.229 | 80.3% | 186.0 |
| Rolling Median | 0.304 | 73.9% | 185.0 |
| Robust Adaptive EWMA | 0.094 | 78.1% | 185.0 |
| LOESS | 0.074 | 82.8% | 184.7 |
| SMA | 0.295 | 74.7% | 184.7 |
| EWMA | 0.103 | 75.9% | 184.5 |
| Linear WMA | 0.345 | 70.4% | 184.3 |
| DEMA | 0.152 | 64.7% | 183.6 |
| Holt-Winters | 0.150 | 65.1% | 183.5 |
| Savitzky-Golay | 0.163 | 62.0% | 183.4 |
| TEMA | 0.196 | 54.4% | 183.3 |
| Kalman Filter | 0.406 | 5.5% | 183.0 |
| Weekly Average | 0.196 | 83.1% | 183.0 |
| HMA | 0.368 | 14.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 = α · wThe 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.