Legal
Technical Indicators and Candlestick Patterns
Effective: 2026-12-01Last updated: 2026-11-01Version 0.9.6-draft
Not yet in force. This document takes effect on 2026-12-01. It is published here in advance so it can be reviewed; until that date it does not form part of any agreement.
Technical Indicators and Candlestick Patterns
0. Status of this document
This is a DRAFT. It is not yet in force and must not be published to clients until the platform's conformance test suite passes against it.
This document is normative. It defines, exactly, every technical indicator and every candlestick pattern that the Trading Lab makes available for building a strategy. Where the platform's behaviour and this document disagree, this document is correct and the platform is defective.
It exists because a strategy rule such as "RSI below 30" or "bullish engulfing formed" is only meaningful if both parties agree what those words mean. A client who writes that rule is entitled to know that it means the same thing here as it does in the charting package they already use.
0.1 Conformance standard
The reference implementation is TA-Lib, the open-source technical analysis library on which MetaTrader, TradingView and substantially all commercial charting and screening software is built.
Every definition below is the TA-Lib definition. Where TA-Lib's published documentation is explicit about a rule it does not enforce — most commonly the prior trend that a reversal pattern classically assumes — this document states the same limitation rather than silently adding a rule of our own.
We do not define our own variants of standard instruments. An indicator or pattern offered under an industry name behaves as the industry defines it, or it is not offered under that name.
0.2 What this document does not promise
Nothing here is a statement that any indicator or pattern is predictive, profitable, or suitable for any purpose. These are definitions of arithmetic, not claims of efficacy. Where an authoritative statistical source reports that a widely-taught pattern performs near chance, that finding is stated alongside the definition, because a client is better served by a correct and unflattering number than by a definition presented without one.
Past performance does not indicate future results. Nothing in this document is investment advice.
1. Common conventions
These apply to every indicator and every pattern in this document.
1.1 The candle
A candle is a tuple of four prices — open, high, low, close — over a fixed interval, plus the timestamp at which that interval began. Derived quantities used throughout:
| Term | Definition |
|---|---|
| real body | abs(close − open) |
| range | high − low |
| body top | max(open, close) |
| body bottom | min(open, close) |
| upper shadow | high − body top |
| lower shadow | body bottom − low |
| bullish candle | close > open |
| bearish candle | close < open |
1.2 Evaluation is on closed bars only
Every indicator value and every pattern verdict is computed on closed candles only, and is evaluated at the close of the most recent completed candle.
No value in this platform repaints. A signal that was true at a bar's close remains true for that bar permanently. The currently-forming candle is never read.
1.3 Warm-up, and the history window
An indicator requires a minimum number of prior candles before it can produce a value at all. Until that count is reached, no value is produced and no rule referencing it can be true. A strategy in warm-up is silent, not failing.
Separately from that minimum, the recursively smoothed indicators — EMA, MACD, RSI and ATR — carry a diminishing influence from wherever their series began. Two correct implementations of RSI(14) agree exactly when given the same history; they diverge when one has been fed more history than the other.
This platform therefore specifies a minimum history window, below which the value is not published. The required depth is not the same for both families, because they decay at different rates:
| Family | Smoothing constant | Minimum history |
|---|---|---|
| RSI, ATR (Wilder) | α = 1 / n | 7 × n |
| EMA, MACD | α = 2 / (n + 1) | 4 × n (MACD: 4 × slow) |
The factor is ln(0.001) / ln(1 − α) in each case — the depth at which the seed retains one part in a thousand. Wilder's constant decays at half the rate of the EMA's, which is the whole of the difference between the two rows.
Measured, with a correctly seeded series, against a fully converged one:
| 1.5 × n | 3 × n | 7 × n | |
|---|---|---|---|
| RSI(14) | −10.6 pts | +0.74 pts | −0.004 pts |
| RSI(200) | +0.61 pts | −0.14 pts | −0.003 pts |
| EMA(400) | 0.256% of price | 0.0064% of price | negligible |
A consequence that constrains the product. A parameter is only offerable if the platform can supply the history it requires. The platform shall not offer a parameter value for which it cannot serve the required history, because an indicator that is permanently in warm-up is a control that can never do anything. The maximum selectable length is therefore bounded by the available history window, and the ranges quoted in §2 are subject to that bound.
The size of this effect is not theoretical. For RSI(14), the weight still carried by the seed is:
| History fed | Seed weight remaining | Divergence from a fully-warmed RSI |
|---|---|---|
| 19 candles | 24.5% | over 11 RSI points |
| 30 candles | 10.8% | ~5.8 RSI points |
| 60 candles | 1.2% | ~0.4 RSI points |
140 candles (10 × length) | 0.004% | negligible |
| 500 candles | 8 × 10⁻¹⁷ | zero to floating-point precision |
A difference of five RSI points is the difference between "RSI below 30" being true and being false. Any execution path that evaluates an indicator on a short window is therefore producing values that will not reconcile against a client's own chart, and must either extend its window or decline to evaluate.
1.4 Degenerate candles
A candle whose high equals its low has zero range. Every pattern test divides by range, so such a candle is refused — every pattern returns absent for it. This is a deliberate refusal, not an incidental one: without it a floating-point NaN would compare false against every threshold and report "no pattern" for the wrong reason.
1.5 Pattern output values
Every pattern returns exactly one of three values for the bar under test:
| Value | Meaning |
|---|---|
+100 | the pattern is present, in its bullish sense |
−100 | the pattern is present, in its bearish sense |
0 | the pattern is absent |
Some patterns can only ever return a subset of these. The builder offers, for each pattern, only the directions that pattern can actually produce, so a rule that is false by construction cannot be written.
On the unsigned patterns. Doji, dragonfly doji, gravestone doji and long-legged doji return +100 on presence. In these four cases the positive sign is a presence flag and is not a direction. TA-Lib makes the same choice and states the same caveat. The builder exposes these as formed / did not form rather than bullish/bearish, so the distinction cannot be misread.
On TA-Lib's weak grades. TA-Lib grades engulfing, harami and harami cross at ±80 instead of ±100 when one edge of the two bodies is exactly equal rather than strictly beyond. The pattern has still formed. Because a strategy rule asks only did this pattern form, this platform **maps ±80 to ±100, preserving the sign.** Detection is identical to TA-Lib; only the strength grade is not surfaced. This mapping is stated here because it is a deliberate simplification, not an accident.
1.6 The CandleSettings model
TA-Lib does not define "long body" or "short shadow" as a fixed fraction of the candle being tested. It defines each as an average over recent candles, multiplied by a factor. This matters: it makes a pattern adaptive to the instrument's current volatility rather than to one bar's shape.
A threshold is computed as:
**threshold = ( mean of RangeType over the previous AvgPeriod candles ) × *Factor***
where RangeType is one of:
| RangeType | Measures |
|---|---|
RealBody | abs(close − open) |
HighLow | high − low |
Shadows | the mean of the upper and lower shadows — (upper + lower) / 2, not their sum |
An AvgPeriod of 0 means use the current candle only — the threshold is then a fixed multiple of that candle's own measure, not an average.
The settings, at their standard values:
| Setting | RangeType | AvgPeriod | Factor |
|---|---|---|---|
BodyLong | RealBody | 10 | 1.0 |
BodyVeryLong | RealBody | 10 | 3.0 |
BodyShort | RealBody | 10 | 1.0 |
BodyDoji | HighLow | 10 | 0.1 |
ShadowLong | RealBody | 0 | 1.0 |
ShadowVeryLong | RealBody | 0 | 2.0 |
ShadowShort | Shadows | 10 | 1.0 |
ShadowVeryShort | HighLow | 10 | 0.1 |
Near | HighLow | 5 | 0.2 |
Far | HighLow | 5 | 0.6 |
Equal | HighLow | 5 | 0.05 |
Consequence for warm-up. Because the thresholds are averages over the preceding 10 candles, a pattern's warm-up is its own bar count plus 10. A one-bar pattern needs 11 candles; a three-bar pattern needs 13. A newly started strategy is therefore silent on patterns for its first several bars. This is correct behaviour, and it is the price of thresholds that adapt to the instrument instead of being guessed.
1.7 Weekends, holidays, and holes in the data
Three different things are loosely called "a gap", and they are not the same thing. One is market structure, one is market structure of a different kind, and one is a defect. Arithmetically they are indistinguishable, which is why each is dealt with explicitly here.
| What it is | How it is treated | |
|---|---|---|
| Weekend close | Spot FX stops trading Friday evening and resumes Sunday evening. Roughly 48 hours with no candles, every week. | Market structure. Evaluated normally. |
| Holiday close | A scheduled closure. Rare on spot FX; routine on CFDs over equities and indices, which follow their underlying exchange's calendar. | Market structure. Evaluated normally. |
| A hole in the feed | Candles the market produced that this platform failed to retrieve or store. | A defect. Must not be evaluated across. |
Weekends and holidays are evaluated normally
When the market reopens, the first new candle is treated as the next candle in the series, exactly as if no time had passed. Its price change from the previous close is a single price change like any other.
This is what every charting and screening platform does, and conformance requires it. The consequences are worth stating plainly because they are not obvious:
- Average True Range absorbs the reopen correctly by design. True Range is defined as the greatest of the bar's own range and its two distances from the previous close precisely so that a reopen away from the last close is counted as range rather than ignored. Wilder designed it that way for this reason. No special handling is needed or wanted.
- RSI treats the whole closure as one bar's move. Two days of accumulated news arrive as a single gain or loss and influence the average for roughly
lengthbars afterwards. This is standard and universal, not a defect. - A multi-bar pattern may straddle the closure. A two-bar pattern can read Friday's last candle and Sunday's first; a three-bar pattern can span the whole weekend. The pattern makes no claim about elapsed time, only about consecutive candles, and this is how every platform computes it.
A client who wants to exclude the reopen can do so already, using the strategy's own trading-hours settings. This platform does not make that choice on their behalf, because silently skipping bars would make our output irreproducible against their chart.
A hole in the feed is not a market event
If the market traded and this platform holds no candle for that interval, every formula above will treat the two candles either side of the hole as consecutive. They are not. A pattern asserting "a decisive sell-off, then hesitation, then recovery" across a hole is describing a sequence that did not occur. An indicator is smoothing a series with pieces missing.
No indicator value and no pattern verdict may be published for a bar whose required history contains an unexplained discontinuity. The correct output is the same as during warm-up: silence. A rule referencing it is not true; it is simply not evaluable, and the strategy makes no claim about that bar.
The distinguishing question is not how long the gap is — a holiday closure is longer than a weekend — but whether the instrument was trading. A gap that the instrument's trading calendar accounts for is market structure. A gap it does not account for is a defect in the data, and must be refused rather than smoothed over.
2. Indicators
Seven indicators are available. Each is defined below by its formula, not by reference to a library.
2.1 Simple Moving Average — SMA
Parameter: length (default 20, range 2–400)
The arithmetic mean of the last n closing prices:
SMA(n)ᵢ = ( Σ closeᵢ₋ⱼ for j = 0…n−1 ) / n
Minimum bars: n. No history-window requirement — the value depends on exactly n candles and no others.
Output: sma.
2.2 Exponential Moving Average — EMA
Parameter: length (default 20, range 2–400)
α = 2 / (n + 1) EMAᵢ = α × closeᵢ + (1 − α) × EMAᵢ₋₁
Seed. The recursion is seeded with the **simple average of the first n closing prices**, which is the TA-Lib and the published definition. Seeding with the first observation instead — the default in several numerical libraries — is not equivalent and produces a different series for many bars.
Minimum bars: n. Minimum history window: 4 × n (see §1.3, which also bounds the usable maximum).
Output: ema.
2.3 Relative Strength Index — RSI
Parameter: length (default 14, range 2–200)
For each bar, the change Δᵢ = closeᵢ − closeᵢ₋₁ is split:
gainᵢ = max(Δᵢ, 0) lossᵢ = max(−Δᵢ, 0)
Both are smoothed by Wilder's method, which is an exponential average with α = 1 / n — not 2/(n+1):
avgGainᵢ = ( avgGainᵢ₋₁ × (n − 1) + gainᵢ ) / n avgLossᵢ = ( avgLossᵢ₋₁ × (n − 1) + lossᵢ ) / n
Seed. Both averages are seeded with the **simple mean of the first n gains and the first n losses** respectively. This is Wilder's published method.
RS = avgGain / avgLoss RSI = 100 − ( 100 / (1 + RS) )
Defined edges. Where avgLoss = 0 and avgGain > 0, RSI is 100. Where avgGain = 0 and avgLoss > 0, RSI is 0. Where both are zero — a perfectly flat series — RSI is 50. These are conventional and are stated so that a monotonic input cannot silently produce an undefined value.
Range: 0–100. Minimum bars: n + 1. Minimum history window: 7 × n (see §1.3, which also bounds the usable maximum).
Output: rsi.
2.4 Moving Average Convergence Divergence — MACD
Parameters: fast (default 12), slow (default 26), signal (default 9)
MACD line = EMA(fast) − EMA(slow) Signal line = EMA(signal) of the MACD line Histogram = MACD line − Signal line
Each EMA is as defined in §2.2, including its seeding rule. The signal line is an EMA of the MACD line, not of price.
Minimum bars: slow + signal. Minimum history window: 4 × slow (see §1.3, which also bounds the usable maximum).
Outputs: macd, signal, histogram.
2.5 Stochastic Oscillator — STOCH
Parameters: k (default 14), smooth (default 3), d (default 3)
raw %K = 100 × ( close − lowest low over k ) / ( highest high over k − lowest low over k ) **%K = simple moving average of raw %K oversmoothperiods %D = simple moving average of %K overdperiods**
This is the slow stochastic. The smooth parameter at 1 yields the fast stochastic.
Where the highest high equals the lowest low over the window — a perfectly flat window — raw %K is undefined; the oscillator returns 50.
Range: 0–100. Minimum bars: k + smooth + d − 2. No history-window requirement — %K and %D depend on a fixed window and nothing earlier.
Outputs: k, d.
2.6 Bollinger Bands — BBANDS
Parameters: length (default 20, range 2–400), std (default 2.0, range 0.5–5.0)
middle = SMA(length) of close **σ = POPULATION standard deviation of the last length closes upper = middle + std × σ lower = middle − std × σ****The standard deviation is the population standard deviation — divisor n, not n − 1.** This is not a stylistic choice. Bollinger Bands are defined on the population standard deviation, and TA-Lib computes them that way.
Using the sample standard deviation instead — the default in several numerical libraries, including pandas — inflates σ by a factor of √( n / (n−1) ). At the default length of 20 that is 1.0260, making the bands 2.6% wider than every other platform's, permanently and in both directions. A client comparing our upper band to their charting package would find a persistent discrepancy.
Minimum bars: length. No history-window requirement.
Outputs: upper, middle, lower.
2.7 Average True Range — ATR
Parameter: length (default 14, range 2–200)
True Range for a bar is the greatest of three spans:
TRᵢ = max( highᵢ − lowᵢ , |highᵢ − closeᵢ₋₁| , |lowᵢ − closeᵢ₋₁| )
True Range is undefined on the first bar, because two of its three terms need a prior close. It is not substituted with high − low; no value is emitted for that bar. The reference implementation does the same — TA-Lib's TRANGE returns nothing at bar 0.
ATR is True Range smoothed by Wilder's method (α = 1/n, as in §2.3):
ATRᵢ = ( ATRᵢ₋₁ × (n − 1) + TRᵢ ) / n
Seed. The simple mean of TR[1] … TR[n] — the first n True Range values that exist, which begin at bar 1, not bar 0.
This sentence is load-bearing and was wrong in an earlier draft. Seeding on TR[0…n−1], with a substituted high − low at bar 0, diverges from the reference by 2.9 × 10⁻⁴; seeding on TR[1…n] matches it to 2.2 × 10⁻¹⁸. Four orders of magnitude, worst exactly where a freshly started strategy lives, on a value used to size stops.
ATR is non-negative and unbounded above. It is expressed in the instrument's price units, not as a percentage.
Minimum bars: n + 1. Minimum history window: 7 × n (see §1.3, which also bounds the usable maximum).
Output: atr.
3. Candlestick patterns
Fourteen patterns are available, in four groups. For each: the bars it reads, the directions it can return, and its exact geometry.
A pattern reads the most recent closed bar and, where its bar count exceeds one, the bars immediately preceding it. A pattern never reports the most recent bar on which it fired at some point in the past; it reports whether it is present now.
On gaps. A pattern may read candles that straddle a weekend or a holiday closure; it is computed normally, as every platform computes it. It is not computed across a hole in the data. See §1.7.
On prior trend. Most of these are classically reversal patterns, meaningful only against a preceding trend. TA-Lib does not verify a prior trend for any of them, and neither does this platform. This is stated plainly rather than patched over with a substitute test, because a one- or two-bar proxy for "a downtrend" is not a downtrend, and a client who believes trend context is being checked would be misled. Where trend context matters to a strategy, it should be expressed as a separate rule — a moving-average comparison, for example — and combined with the pattern rule using ALL.
3.1 One bar
Doji — CDL_DOJI · 1 bar · unsigned
The open and close are at or near the same price: the session fought to a draw.
- **real body ≤
BodyDoji**
That is the only condition. Shadows are not tested. Returns +100 on presence, 0 otherwise; the sign is a flag, not a direction.
In the builder: formed / did not form.
Dragonfly Doji — CDL_DRAGONFLY_DOJI · 1 bar · unsigned
A doji whose price fell through the session and returned to the open.
- **real body ≤
BodyDoji** - **upper shadow <
ShadowVeryShort** - **lower shadow >
ShadowVeryShort**
Returns +100 / 0. Unsigned. Its bullish or bearish reading depends on the prior trend, which is not verified.
Bulkowski's testing finds this pattern reverses the prior trend about 50% of the time — a coin flip — ranking 98th of 103 patterns.
Gravestone Doji — CDL_GRAVESTONE_DOJI · 1 bar · unsigned
The mirror: price rose through the session and gave it all back.
- **real body ≤
BodyDoji** - **lower shadow <
ShadowVeryShort** - **upper shadow >
ShadowVeryShort**
Returns +100 / 0. Unsigned, for the same reason.
Long-Legged Doji — CDL_LONG_LEGGED_DOJI · 1 bar · unsigned
A doji with a wide excursion on at least one side — maximum indecision.
- **real body ≤
BodyDoji** - **upper shadow >
ShadowLongOR lower shadow >ShadowLong**
Note that one long shadow suffices; the classical form shows two. This follows TA-Lib rather than the textbook, and is noted here as a departure from the classical description in favour of the reference implementation.
Returns +100 / 0. Unsigned.
Marubozu — CDL_MARUBOZU · 1 bar · bullish or bearish
"Shaven head and shaven bottom" — a bar that is all body. One side held the whole session.
- **real body >
BodyLong** - **upper shadow <
ShadowVeryShort** - **lower shadow <
ShadowVeryShort**
Each shadow is tested separately, not as a sum. The long-body requirement is part of the pattern: a tiny clean bar in a dead hour is not a marubozu.
+100 whenclose ≥ open· −100 whenclose < open. The direction is the bar's own colour.
3.2 Two bars — the single-candle reversals
These four share one shape family and are distinguished by where the candle sits relative to the one before it. All four read two bars.
| Body position | Long shadow | Prior-bar relation | Returns | |
|---|---|---|---|---|
| Hammer | top of range | below | at or near prior candle's low | +100 |
| Hanging Man | top of range | below | at or near prior candle's high | −100 |
| Inverted Hammer | bottom of range | above | real body gaps down from the prior body | +100 |
| Shooting Star | bottom of range | above | real body gaps up from the prior body | −100 |
Hammer — CDL_HAMMER · 2 bars · bullish only
- **real body <
BodyShort** - **lower shadow >
ShadowLong** - **upper shadow <
ShadowVeryShort** - the body sits at or near the prior candle's low
Returns +100 / 0. **Never −100.** The same shape appearing after an advance is a hanging man, which is a different pattern with a different name — which is why "bearish hammer" is not a rule that can be written.
The hammer candle's own colour does not matter; only its shape and position.
Bulkowski's testing finds the hammer reverses a preceding downtrend about 60% of the time, which TA-Lib's own documentation describes as "not far from random (50%)".
Hanging Man — CDL_HANGING_MAN · 2 bars · bearish only
Identical shape to the hammer, found at the top instead of the bottom.
- **real body <
BodyShort** - **lower shadow >
ShadowLong** - **upper shadow <
ShadowVeryShort** - the body sits at or near the prior candle's high
Returns −100 / 0. **Never +100.**
*Bulkowski finds this acts as a bullish continuation 59% of the time — the opposite of its textbook reading — ranking 87th of 103.*
Inverted Hammer — CDL_INVERTED_HAMMER · 2 bars · bullish only
- **real body <
BodyShort** - **upper shadow >
ShadowLong** - **lower shadow <
ShadowVeryShort** - the real body gaps DOWN from the prior real body — this bar's body top sits below the previous bar's body bottom, with no overlap and no shared price
This is the reference's own condition. An earlier draft substituted "the prior candle is bearish", on the ground that a within-session gap was unreachable; that ground was measured on simulated candles which could not gap, and real broker candles gap on 155 of 156 adjacent bars. The substitution has been withdrawn — see §6.
Returns +100 / 0. **Never −100.**
Shooting Star — CDL_SHOOTING_STAR · 2 bars · bearish only
Identical shape to the inverted hammer, found at the top.
- **real body <
BodyShort** - **upper shadow >
ShadowLong** - **lower shadow <
ShadowVeryShort** - the real body gaps UP from the prior real body — this bar's body bottom sits above the previous bar's body top
The reference's own condition, and the only thing distinguishing this pattern from the inverted hammer above: the two shapes are identical and the gap direction separates them completely, since a bar cannot gap both ways. An earlier draft substituted the prior candle's direction; that substitution has been withdrawn — see §6.
Returns −100 / 0. **Never +100.**
Why the substitute is a direction and not nothing. The shooting star and the inverted hammer are the same shape. In TA-Lib the only thing separating them is the direction of the gap. Remove the gap from both and they collapse into a single pattern returning two contradictory directions on the same bar. The replacement condition therefore has to keep them apart, and the prior candle's direction — an advance into the bar, or a decline into it — is the minimum that does so while remaining a property of the data rather than an invention.
3.3 Two bars — the containment pair
Engulfing — CDL_ENGULFING · 2 bars · bullish or bearish
The second real body wholly contains the first, and they are opposite colours. Shadows are not part of the definition.
- the two real bodies are opposite colours
- the second real body contains the first, top and bottom
+100 when the first is bearish and the second bullish −100 when the first is bullish and the second bearish
Per §1.5, TA-Lib's ±80 grade — one edge exactly equal — is reported here as ±100.
Harami — CDL_HARAMI · 2 bars · bullish or bearish
The mirror of engulfing: a long body, then a small one tucked inside it. Harami is Japanese for pregnant — the large bar carrying the small one.
- **first real body >
BodyLong** - **second real body <
BodyShort** - the second real body sits inside the first real body
+100 when the first candle is bearish −100 when the first candle is bullish
The direction is taken from the first candle. The second candle's colour is not part of the pattern and is not tested. A long bearish bar followed by a small bar of either colour inside it is a bullish harami. The second candle is usually, but not always, the opposite colour — requiring it would reject a substantial share of genuine harami.
Bulkowski finds the bearish harami acts as a bullish continuation 53% of the time, rating it near random at rank 72 of 103.
Harami Cross — CDL_HARAMI_CROSS · 2 bars · bullish or bearish
A harami whose inner candle is a doji. Classically the stronger form.
- **first real body >
BodyLong** - **second real body ≤
BodyDoji** — the inner candle is a doji - the doji's real body sits inside the first real body
+100 when the first candle is bearish −100 when the first candle is bullish
Direction is taken from the first candle, as for the plain harami.
Bulkowski finds the bearish harami cross acts as a bullish continuation 57% of the time, and the bullish form fails to reverse 55% of the time — both contradicting their textbook labels.
3.4 Three bars
Morning Star — CDL_MORNING_STAR · 3 bars · bullish only
A hard sell-off, a small indecisive bar beneath it, then a decisive recovery back into the first bar's body. Named for the morning star: the light before dawn.
- bar 1: bearish, **real body >
BodyLong** - bar 2: **real body <
BodyShort, and its body gaps clear below bar 1's body** — no overlap and no shared price - bar 3: bullish, **real body >
BodyShort, and close > bar 1's body bottom + ( penetration × bar 1's real body )**
Penetration = 0.30, the standard value. Bar 3 must close at least 30% back into bar 1's body; a weak bounce does not qualify.
On the gap. It is measured between REAL BODIES, never high-low ranges, and it is the reference's strict test: clear air between the two bodies. An earlier draft relaxed it to non-overlap. That relaxation has been withdrawn, and it turned out to have changed nothing — on gap-bearing candles the strict and relaxed conditions select the same bars (28 of 28 for this pattern, 18 of 18 for the evening star). See §6.
Returns +100 / 0. **Never −100.**
Evening Star — CDL_EVENING_STAR · 3 bars · bearish only
The morning star mirrored: a strong rally, a hesitant bar above it, then a decisive sell-off back into the first body.
- bar 1: bullish, **real body >
BodyLong** - bar 2: **real body <
BodyShort, and its body gaps clear above bar 1's body** - bar 3: bearish, **real body >
BodyShort, and close < bar 1's body top − ( penetration × bar 1's real body )**
Penetration = 0.30.
Returns −100 / 0. **Never +100.**
4. Summary of direction sets
The builder offers, for each pattern, only what that pattern can return.
| Pattern | Bars | +100 | −100 | In the builder |
|---|---|---|---|---|
| Doji | 1 | flag | — | formed / did not form |
| Dragonfly Doji | 1 | flag | — | formed / did not form |
| Gravestone Doji | 1 | flag | — | formed / did not form |
| Long-Legged Doji | 1 | flag | — | formed / did not form |
| Marubozu | 1 | ✓ | ✓ | bullish / bearish / did not form |
| Hammer | 2 | ✓ | — | bullish / did not form |
| Hanging Man | 2 | — | ✓ | bearish / did not form |
| Inverted Hammer | 2 | ✓ | — | bullish / did not form |
| Shooting Star | 2 | — | ✓ | bearish / did not form |
| Engulfing | 2 | ✓ | ✓ | bullish / bearish / did not form |
| Harami | 2 | ✓ | ✓ | bullish / bearish / did not form |
| Harami Cross | 2 | ✓ | ✓ | bullish / bearish / did not form |
| Morning Star | 3 | ✓ | — | bullish / did not form |
| Evening Star | 3 | — | ✓ | bearish / did not form |
Three patterns can point either way. Four point one way only. Four are unsigned presence flags. Three are directional-by-name and appear only in their one direction because their mirror image is a separately named pattern in this table.
"Formed, in either direction" is not expressible as a single rule: the rule grammar compares a pattern's value against zero, and has no not-equal comparator. To match either direction, write two rules and combine them with ANY.
5. Declared departures
This platform claims conformance with the reference implementation. Every point at which it knowingly differs is set out here. The list is exhaustive. If behaviour differs from this document in a way not listed below, it is a defect in the platform.
5.1 The continuous-instrument identity, and the two things it still breaks
While an instrument is trading without interruption — spot FX, CFDs, crypto — each candle would open at the price the previous candle closed at, because the two are adjacent slices of one unbroken stream of trades:
open[i] = close[i−1]That identity is weaker on real broker data than this section once claimed, and the correction is recorded in full in §6 rather than quietly applied. Measured on 157 consecutive BTCUSD 5-minute candles taken from this platform's own candle store (2026-10-31 16:00 to 2026-11-01 05:00 UTC, an unbroken crypto session): 155 of the 156 adjacent pairs open at a price other than the previous close, and 38 of 156 — 24.4% — open with the whole real body clear of the previous body. Mean absolute offset 0.41 on a price of ~77,666.
A previous version of this section declared four patterns unreachable on that basis and substituted conditions for them. That declaration has been withdrawn and those four patterns now use the reference's own conditions unchanged — see §6, and §5.3.
Two consequences of the identity remain declared, because they are real on the instruments where candles DO open at the previous close, and because this platform's handling of them is a genuine departure from the reference rather than a reading of it.
(b) The ±80 grade is a formation, and this platform publishes no grade
The reference grades Engulfing, Harami and Harami Cross at ±100 when the two bodies are strictly beyond one another at both edges, and at ±80 when one edge is exactly equal. This platform maps both to the same published verdict (§1.5).
The reason stated here previously was false, and it was false in the same way §5.1(a) was. It read: on a continuous instrument one body edge is always exactly equal, so ±100 can never be produced — with a table of 0 at ±100 across all three patterns. That table was measured on a series that sets open[i] = close[i−1] by construction, so the zero described the generator and not any instrument. Re-measured on production-shaped candles, ±100 is not merely reachable but ordinary. The correction is recorded in §6; the mapping itself is unchanged, because it was never the mapping that was wrong.
The correct justification is the rule grammar, not the arithmetic. §1.5 publishes one occurrence verdict per candle pattern — formed or not formed. The reference's two grades do not disagree about whether the pattern formed; they record how the bodies sit once it has. ±80 is a formation with one edge equal, and ±100 a formation with neither. A platform that surfaces no grade at all has exactly one correct mapping for both, and treating ±80 as "not formed" would discard real detections of a pattern the reference says occurred.
The magnitude of that mapping is instrument-dependent, and both ends are measured. 3,000 candles per series, TA-Lib 0.8.3 run directly:
continuous open[i] = close[i−1] | production-shaped gaps | |
|---|---|---|
CDLENGULFING | 500 firings — 500 at ±80, 0 at ±100 | 379 firings — 4 at ±80, 375 at ±100 |
CDLHARAMI | 342 firings — 342 at ±80, 0 at ±100 | 200 firings — 1 at ±80, 199 at ±100 |
CDLHARAMICROSS | 52 firings — 52 at ±80, 0 at ±100 | 38 firings — 0 at ±80, 38 at ±100 |
So the two ends invert. Where the identity holds, ±80 is every detection and the mapping is the only reason these three patterns signal at all — treating it as "not formed" would take the count of silent patterns from four to seven. Where candles gap, ±100 is the normal outcome and the mapping touches 4, 1 and 0 detections respectively: close to a no-op. Neither figure is a property of the rule; both are properties of the instrument, which is why the justification above does not rest on either.
**CDLHARAMICROSS fires ±80 zero times on gapped bars, so the mapping never differs there at all.** That is stated rather than left to be rediscovered: the continuous fixture is the only place this pattern's ±80 condition is exercised, and it is universal there. The coverage for it sits in that fixture on purpose, and a reader checking the gapped one will find nothing to look at.
(c) A harami's second candle cannot share the first's colour
A consequence worth stating because it bounds a real conformance question. Containment plus the identity forces the inner body's direction: after a bearish outer bar, body_bottom[i] ≥ body_bottom[i−1] = close[i−1] = open[i] requires close[i] ≥ open[i], so the inner candle is bullish. Measured: 0 of 342 harami and 0 of 52 harami crosses had same-coloured bodies.
The reference does not test the second candle's colour (§3.3), and neither does this platform. An implementation that did test it would be non-conformant — but on a continuously traded instrument it would also be inert, because the case it rejects does not arise. The difference appears only on instruments that gap: equities, index CFDs, and at any session reopen.
What this platform does instead
| Pattern | Reference requires | This platform requires |
|---|---|---|
| Engulfing · Harami · Harami Cross | ±80 where one edge is equal | reported as ±100, sign preserved |
That is the whole of it. The four gap-dependent patterns — Morning Star, Evening Star, Shooting Star and Inverted Hammer — required a substituted condition in earlier drafts of this document and no longer do. Each now applies the reference's real-body gap exactly as published, and was verified against TA-Lib 0.8.3 run directly over 3,000 gap-bearing candles: identical firings, in both directions, with no bar on which this platform and the reference disagree.
What a client should take from this. On these five patterns this platform and a strictly conformant screener pointed at the same data agree bar for bar. The only remaining difference in this section is the grade: where the reference reports ±80, this platform reports ±100 with the sign preserved, because the rule grammar asks whether a pattern formed and not how strongly. No rule offered in the Trading Lab carries a condition this document does not state.
5.2 Other departures
| # | Departure | Reason |
|---|---|---|
| 1 | Long-legged doji requires one long shadow, not two. | This follows TA-Lib rather than the classical description, which shows two. Stated in §3.1. |
| 2 | Prior trend is not verified for any reversal pattern. | TA-Lib does not verify it either, and a one- or two-bar substitute is not a trend. Where trend context matters, express it as a separate rule and combine with ALL. Stated at the head of §3. |
5.3 Everything else conforms
Outside §5.1 and §5.2 — which between them now cover ONE departure, the ±80 grade — every indicator formula and every pattern geometry in this document is the reference definition. In particular, and because each has been a source of divergence in implementations elsewhere:
- Bollinger Bands use the population standard deviation, not the sample one.
- RSI and ATR use Wilder's smoothing at
α = 1/n, not2/(n+1). - All recursively smoothed indicators are seeded with a simple average of their first n values, not with their first observation.
- The harami and harami cross take their direction from the first candle, and do not test the second candle's colour.
- The hammer and hanging man are distinguished positionally, by where the body sits relative to the prior candle's low or high.
6. Revision history
| Version | Date | Change |
|---|---|---|
| 0.9.6-draft | 2026-11-01 | §5.1(b)'s justification replaced; its mapping unchanged. The subsection argued that ±100 "can never be produced" on a continuous instrument, with a table of 0 at ±100 — measured on a series that sets open[i] = close[i−1] by construction, so the zero described the generator. The same circularity as the withdrawn §5.1(a), surviving one subsection along. Re-measured on 3,000 production-shaped candles: ±100 is the ORDINARY outcome — 375 of 379 engulfing, 199 of 200 harami, 38 of 38 harami cross. The mapping is now justified from the rule grammar instead: §1.5 publishes one occurrence verdict, both grades are formations, and a platform surfacing no grade has one correct mapping for both. Magnitude is reported as instrument-dependent at both ends rather than asserted. A stale count is corrected with it: CDLENGULFING on the continuous series is 500 firings, not the 760 previously tabled. No threshold, no CandleSetting and no containment rule changed. |
| 0.9.5-draft | 2026-11-01 | §5.1's gap substitution WITHDRAWN. The four gap-dependent patterns — Morning Star, Evening Star, Shooting Star, Inverted Hammer — now apply the reference's own real-body gap, unchanged. The withdrawn clause declared that gap unreachable within a session and cited "0 of 200,000 simulated within-session candles". That simulation set open[i] = close[i−1] by construction, so the figure described the generator and not any instrument. Re-measured on 157 consecutive BTCUSD 5-minute candles from this platform's own candle store (2026-10-31 16:00 → 2026-11-01 05:00 UTC): 155 of 156 adjacent pairs gap, and 38 of 156 — 24.4% — gap by a whole real body. Conformance re-verified against TA-Lib 0.8.3 run directly over 3,000 gap-bearing candles: all four patterns now agree with the reference bar for bar and sign for sign (43 / 38 / 28 / 18 firings, no disagreement in either direction). |
| And two of the four relaxations had never changed an outcome. On gap-bearing candles the Morning Star fired 28 times and the Evening Star 18 times both before and after the change — the reference's strict gap and the relaxed non-overlap test select the same bars. Those two were declared departures that did not depart, and they are retired as such rather than being quietly dropped. The Shooting Star and Inverted Hammer substitutions were NOT no-ops: they fired 146 and 142 times against the reference's 43 and 38, and returned identical results on gapping and non-gapping data alike, because a candle's direction does not change when its open moves. | ||
§5.1 is retained for the two consequences that remain real where candles DO open at the previous close: the ±80 grade (b) and the harami colour bound (c). Its §5.1(a) subsection and the four substitution rows in its table are removed. The rows below are kept deliberately: a client must be able to see that this departure was declared, relied upon, and withdrawn. | ||
| 1.0.0-draft | 2026-10-30 | First issue. Not in force. |
| 0.9.4-draft | 2026-10-30 | §5.2 rows renumbered 1–2; they were left at 2–3 when the ±80 row moved to §5.1(b). |
| 0.9.3-draft | 2026-10-30 | §2.7 corrected: TR is undefined at bar 0 and ATR seeds on TR[1…n], not TR[0…n−1] — the earlier wording diverged from the reference by 2.9e-04. §5.1 restructured as one identity with three measured consequences; the ±80 grade moved into it, being the reason three further patterns fire at all. §5.1 shape counts corrected to 288/295, measured with the reference's own CandleSettings. |
| 0.9.2-draft | 2026-10-30 | §5.1 evidence upgraded: claim now verified by running TA-Lib 0.8.3 directly, not derived. |
| 0.9.1-draft | 2026-10-30 | §1.6 corrected: Shadows is the MEAN of the two shadows, not their sum. §1.3 corrected: history window is 7×n for Wilder and 4×n for the EMA family, measured, replacing a flat 10×; parameter maxima now explicitly bounded by available history. |
| §5.1 added: the real-body gap is unreachable within a session; substitutions declared for four patterns. §1.7 added: weekends, holidays and holes in the data. |