Insight on EMA and leg calculation
How My Coin Classifier Uses an EMA to Find Where a Leg Starts
Part of the Crypto Opportunity Classifier project →
One update, step by step
Each new close pulls the EMA a fixed fraction of the way toward it. That fraction is α = 2 ÷ (span + 1). Slide to any bar. The dashed line on the chart is the gap between the old EMA and the new close, and the orange dot sits α of the way up it.
Where the weight goes
The final EMA value is a weighted mix of all 24 closes. Recent bars count most and each older one counts 1 − α of the one after it. The first bar is special: the EMA starts at that close, so whatever weight hasn't decayed yet stays on it.
What the classifier does with it
Three checks in opportunity_payload.py read the EMA. Values update with the span above. At span 20 they match the live payload: EMA 0.22492, slope +2.35%, leg start at bar 0.
From EMA to leg start
The EMA is only a yardstick. To find where the current up-leg began, the classifier walks backward from the newest bar and counts closes that sit below the EMA. Three in a row means the previous leg ended there, and the leg is everything from that point on. WIF never dipped below its EMA three bars running, so this section uses a window where it did.
run = 0
for i from newest bar back to oldest:
if close[i] < ema[i]: run = run + 1
else: run = 0
if run == 3: leg_start = i ; stop
(never reaches 3: leg_start = 0, the whole window is the leg)Verticality: one big bar, or a staircase?
Once the leg is found, the classifier asks what shape it has. Two numbers answer that, both measured over the leg only. One says how much of the climb came from a single bar. The other says how straight the climb is on a log-price line. Slide the blend to turn this leg into a steady climb and watch both numbers move.
1 · How much of the climb came from one bar?
max_single_bar_share. At 45% or more the classifier calls the leg vertical.2 · How straight is the climb?
logprice_r2 measures how small those gaps are, from 0 (no line at all) to 1 (a perfect line).ewm(span, adjust=False). That is why the seed keeps weight at the end of a short window.