MACD (Moving Average Convergence/Divergence, Gerald Appel) — the spread
between a fast and a slow EMA, with its own EMA as a signal line:
${prefix}Line = EMA(fastPeriod) − EMA(slowPeriod)
${prefix}Signal = EMA(signalPeriod) of that line
${prefix}Hist = line − signal
Appends three columns. Each warms up when it can rather than all three
waiting for the slowest: at the defaults the line starts at bar 25 (the slow
EMA's own warm-up) and the signal and histogram at bar 33. TA-Lib instead
masks all three to bar 33; emitting the line where it is genuinely defined
keeps eight real values TA-Lib discards, and matches how every other study
here warms up per column.
Which EMA
The EMAs are pond's own — emaValues, i.e. α = 2/(span+1) seeded on
the first sample, which is what ema() already ships and what the
oracle already pins. TA-Lib instead seeds each EMA on the SMA of its first
n values, so its MACD differs slightly from this one.
That delta is small and shrinking, unlike RSI's. Measured on the package's
oracle input, as a fraction of the line's own magnitude (3.74) throughout:
3.80% at the first bar the two share, decaying to 0.089% by bar 79 —
and the signal line likewise, 2.10% to 0.132%. It is small because MACD
is a difference of two EMAs, so the seed error largely cancels, and
because it decays at (1−α)^k with α = 2/13 and 2/27 — far faster than
RSI's 1/14.
The alternative would be to seed these EMAs TA-Lib's way. That was rejected:
it would make macd() disagree with ema(fast) − ema(slow)inside this
package, which is a worse and more confusing surprise than a sub-percent
divergence from a vendor whose bar-for-bar parity is an explicit non-goal.
Making pond's MACD TA-Lib-identical means changing ema()'s seed
convention everywhere — a breaking, package-wide decision, not something to
smuggle in under a new study. Contrast rsi, where the same choice
was worth a dedicated kernel because the error there was 7 points on a
bounded 0–100 oscillator and crossed its conventional thresholds.
MACD (Moving Average Convergence/Divergence, Gerald Appel) — the spread between a fast and a slow EMA, with its own EMA as a signal line:
${prefix}Line=EMA(fastPeriod) − EMA(slowPeriod)${prefix}Signal=EMA(signalPeriod)of that line${prefix}Hist= line − signalAppends three columns. Each warms up when it can rather than all three waiting for the slowest: at the defaults the line starts at bar 25 (the slow EMA's own warm-up) and the signal and histogram at bar 33. TA-Lib instead masks all three to bar 33; emitting the line where it is genuinely defined keeps eight real values TA-Lib discards, and matches how every other study here warms up per column.
Which EMA
The EMAs are pond's own — emaValues, i.e.
α = 2/(span+1)seeded on the first sample, which is whatema()already ships and what the oracle already pins. TA-Lib instead seeds each EMA on the SMA of its firstnvalues, so its MACD differs slightly from this one.That delta is small and shrinking, unlike RSI's. Measured on the package's oracle input, as a fraction of the line's own magnitude (3.74) throughout: 3.80% at the first bar the two share, decaying to 0.089% by bar 79 — and the signal line likewise, 2.10% to 0.132%. It is small because MACD is a difference of two EMAs, so the seed error largely cancels, and because it decays at
(1−α)^kwithα = 2/13and2/27— far faster than RSI's1/14.The alternative would be to seed these EMAs TA-Lib's way. That was rejected: it would make
macd()disagree withema(fast) − ema(slow)inside this package, which is a worse and more confusing surprise than a sub-percent divergence from a vendor whose bar-for-bar parity is an explicit non-goal. Making pond's MACD TA-Lib-identical means changingema()'s seed convention everywhere — a breaking, package-wide decision, not something to smuggle in under a new study. Contrast rsi, where the same choice was worth a dedicated kernel because the error there was 7 points on a bounded 0–100 oscillator and crossed its conventional thresholds.