Elder Impulse System (Alexander Elder, Come Into My Trading Room) —
a per-bar verdict on whether trend and momentum agree, as +1, 0 or
−1:
${output}[i] =+1ifEMA(emaPeriod) rose AND the MACD histogram rose = −1ifEMA(emaPeriod) fell AND the MACD histogram fell =0 otherwise
Elder's reading is that +1 (his green bar) means both the trend and its
momentum are pushing up, so short positions are forbidden; −1 (red)
likewise forbids longs; and 0 (blue) is the common case where the two
disagree and neither side is barred. It is a censoring rule rather
than an entry signal — that is why the three-valued output is the whole
study.
Appends one column. The EMA and the MACD themselves are
ema and macd's business and are not emitted here; a caller
who wants to chart them calls those studies too, and gets exactly the same
numbers because this study calls them.
The column is NUMERIC, and that is forced
Elder's own presentation is a colour — green / blue / red — and the
corpus describes the output as a "categorical color column (string col
OK)". It is not OK here, and the reason is mechanical rather than
stylistic: TimeSeries.withColumn takes a Float64Array or a
(number | undefined)[] and appends a number column. There is no door
on it for a string column, so a study cannot append one (verified against
packages/core/src/batch/time-series.ts). +1 / 0 / −1 is the natural
numeric encoding — it is signed, so it sorts and sums the way the reading
does, and a chart maps the sign to Elder's colours in one expression.
Composition — it does not re-implement MACD
The histogram comes from calling macd under a scratch prefix and
reading its Hist column back; the trend EMA comes from
emaValues, which is what ema() runs on. Both matter: the study is
then by construction the same MACD and the same EMA a caller charts
beside it, rather than a second derivation that could drift by a seed
convention. It inherits macd's EMA seed (pond's first-sample seed, not
TA-Lib's SMA seed — see that study's note) and, through it, macd's
per-column warm-up.
Ties are 0, and the comparison is strict on both sides
"Rose" means strictly greater than the previous bar and "fell"
strictly less. A flat EMA or a flat histogram therefore reads 0, not the
previous verdict: the rule is a statement about this bar, and a machine
that carried the last verdict across a flat bar would be a different
study (contrast tradeVolumeIndex, where persistence across an
undecided bar IS the definition). It also means the study has no carried
state at all — every bar is a function of two adjacent bars of two arrays
— so it needs no foldRows and has no gap-reset rule of its own.
Warm-up
The verdict needs bar i and bar i − 1 of both inputs, so it first
prints one bar after the slower of the two has two values: at the defaults
the histogram starts at bar 33 (slowPeriod + signalPeriod − 2) and the
EMA at bar 12, so the impulse starts at bar 34. Length-preserving, as
everywhere else.
A missing cell in either input blanks the bar that reads it and the next
one — the ordinary consequence of comparing adjacent bars, not a
propagation rule. The EMA recursion skips a gap and recovers; the MACD's
does too, so the impulse comes back rather than dying at the hole.
Edges
Invariant under any positive scale and any shift of the price. Every
average here is affine-equivariant (EMA(k·x + a) = k·EMA(x) + a for
k > 0), the histogram is a difference of such averages so the shift
cancels outright, and only the sign of each change is read — so the
verdicts are identical. Both are pinned as property tests. A negative
scale would flip every comparison, and is not claimed.
Only three values ever appear, and a test asserts the column is a
subset of {−1, 0, +1} with all three present on a real fixture.
No division anywhere, so there is no zero-denominator case.
Elder Impulse System (Alexander Elder, Come Into My Trading Room) — a per-bar verdict on whether trend and momentum agree, as
+1,0or−1:Elder's reading is that
+1(his green bar) means both the trend and its momentum are pushing up, so short positions are forbidden;−1(red) likewise forbids longs; and0(blue) is the common case where the two disagree and neither side is barred. It is a censoring rule rather than an entry signal — that is why the three-valued output is the whole study.Appends one column. The EMA and the MACD themselves are ema and macd's business and are not emitted here; a caller who wants to chart them calls those studies too, and gets exactly the same numbers because this study calls them.
The column is NUMERIC, and that is forced
Elder's own presentation is a colour — green / blue / red — and the corpus describes the output as a "categorical color column (string col OK)". It is not OK here, and the reason is mechanical rather than stylistic:
TimeSeries.withColumntakes aFloat64Arrayor a(number | undefined)[]and appends a number column. There is no door on it for a string column, so a study cannot append one (verified againstpackages/core/src/batch/time-series.ts).+1 / 0 / −1is the natural numeric encoding — it is signed, so it sorts and sums the way the reading does, and a chart maps the sign to Elder's colours in one expression.Composition — it does not re-implement MACD
The histogram comes from calling macd under a scratch prefix and reading its
Histcolumn back; the trend EMA comes from emaValues, which is whatema()runs on. Both matter: the study is then by construction the same MACD and the same EMA a caller charts beside it, rather than a second derivation that could drift by a seed convention. It inheritsmacd's EMA seed (pond's first-sample seed, not TA-Lib's SMA seed — see that study's note) and, through it,macd's per-column warm-up.Ties are
0, and the comparison is strict on both sides"Rose" means strictly greater than the previous bar and "fell" strictly less. A flat EMA or a flat histogram therefore reads
0, not the previous verdict: the rule is a statement about this bar, and a machine that carried the last verdict across a flat bar would be a different study (contrast tradeVolumeIndex, where persistence across an undecided bar IS the definition). It also means the study has no carried state at all — every bar is a function of two adjacent bars of two arrays — so it needs no foldRows and has no gap-reset rule of its own.Warm-up
The verdict needs bar
iand bari − 1of both inputs, so it first prints one bar after the slower of the two has two values: at the defaults the histogram starts at bar 33 (slowPeriod + signalPeriod − 2) and the EMA at bar 12, so the impulse starts at bar 34. Length-preserving, as everywhere else.A missing cell in either input blanks the bar that reads it and the next one — the ordinary consequence of comparing adjacent bars, not a propagation rule. The EMA recursion skips a gap and recovers; the MACD's does too, so the impulse comes back rather than dying at the hole.
Edges
EMA(k·x + a) = k·EMA(x) + afork > 0), the histogram is a difference of such averages so the shift cancels outright, and only the sign of each change is read — so the verdicts are identical. Both are pinned as property tests. A negative scale would flip every comparison, and is not claimed.{−1, 0, +1}with all three present on a real fixture.