SMA weights all N bars equally; EMA front-loads recent bars. Crosses are robust trend filters that are late by construction — the question is whether the trend pays for the lag.
EMA(20) crossing above EMA(50) says "the recent average just overtook the slower one" — a trend-change vote, not a prediction. It will never catch the bottom and always gives back some of the top.
EMA weight k = 2/(N+1), recursively e = price×k + e_prev×(1−k). Because EMA never "forgets" completely, its first ~N bars depend on the seed — one more reason two libraries disagree on the same chart.
The playground EMA-cross template shows the honest fire count on 1,000 real bars. Whether the trend after each cross paid for the lag — that is exactly what our pre-registered experiment measures.
Open the rule playground, build a condition with this indicator, and run it on 1,000 real bars — per-condition fire counts, entirely in your browser. Or lint it in Python with rulelint (MIT).
Research and education. Not investment advice. No indicator makes money by itself — our own arenas' honest records (losses included) are on the scoreboard.