CDLPatternPack

Incremental, causal technical analysis documentation

Summary

CDLPatternPack is RTTA's streaming detector for the CDL pattern pack candlestick pattern. Runs a fixed set of common CDL detectors from one OHLC update and returns all codes together.

Output follows the TA-Lib convention: +100 for a bullish match, -100 for a bearish match, and 0 when the pattern does not fire.

Update API

result = rtta.CDLPatternPack(fillna=True).update(open, high, low, close)
# result.doji, result.hammer, result.engulfing, result.morning_star, ...
batch = rtta.CDLPatternPack(fillna=True).batch(open, high, low, close)

update(...) consumes one OHLC bar and returns a multi-field result of TA-Lib-style codes (+100 / 0 / -100) for each packed pattern. advance(...) updates state without returning a Python object. Array batch(...) matches sequential update on a fresh instance.

Theory Of Operation

Candlestick patterns are short causal labels on bar geometry. They do not forecast returns by themselves; they tag structure (indecision, rejection, engulfing pressure, multi-bar reversals) that you can combine with trend, volatility, or volume context.

Useful when you want many labels without instantiating thirty-two separate objects. Each field is identical to the corresponding standalone CDL* class on the same stream.

On every bar the engine forms:

\[\begin{aligned} \mathrm{body}_t &= |C_t - O_t| \\ \mathrm{range}_t &= H_t - L_t \\ \mathrm{upper}_t &= H_t - \max(O_t, C_t) \\ \mathrm{lower}_t &= \min(O_t, C_t) - L_t \\ \mathrm{top}_t &= \max(O_t, C_t),\quad \mathrm{bot}_t = \min(O_t, C_t) \\ \mathrm{mid}_t &= \tfrac12(O_t + C_t) \end{aligned}\]

A bar is bullish when \(C_t \ge O_t\) and bearish when \(C_t < O_t\). Bars are stored in a short ring; age \(0\) is the newest bar, age \(1\) the prior bar, and so on.

Shared predicates used below:

\[\begin{aligned} \mathrm{doji}(b) &\iff \mathrm{body} \le 0.1\cdot \mathrm{range} \quad(\text{or range}=0) \\ \mathrm{longBody}(b,\overline B,f) &\iff \mathrm{body} \ge f\cdot \overline B \\ \mathrm{shortBody}(b,\overline B,f) &\iff \mathrm{body} \le f\cdot \overline B \\ \mathrm{longLower}(b,m) &\iff \mathrm{lower} \ge m\cdot \mathrm{body} \\ \mathrm{longUpper}(b,m) &\iff \mathrm{upper} \ge m\cdot \mathrm{body} \\ \mathrm{smallUpper}(b,f) &\iff \mathrm{upper} \le f\cdot \mathrm{range} \\ \mathrm{smallLower}(b,f) &\iff \mathrm{lower} \le f\cdot \mathrm{range} \\ \mathrm{engulf}(c,p) &\iff \mathrm{top}_c \ge \mathrm{top}_p \land \mathrm{bot}_c \le \mathrm{bot}_p \land \mathrm{body}_c > \mathrm{body}_p \\ \mathrm{inside}(c,p) &\iff \mathrm{top}_c \le \mathrm{top}_p \land \mathrm{bot}_c \ge \mathrm{bot}_p \end{aligned}\]

\(\overline B\) is the average body over the last up to five ring bars; \(\overline R\) is the average range over the same window.

For hammer-family patterns, a light prior trend uses the previous close versus the SMA of the two closes before it:

\[\tau = \begin{cases} +1 & C_{-1} > 1.0001\cdot \mathrm{SMA}(C_{-1},C_{-2}) \\ -1 & C_{-1} < 0.9999\cdot \mathrm{SMA}(C_{-1},C_{-2}) \\ 0 & \text{otherwise} \end{cases}\]

Recurrence

Push \((O_t,H_t,L_t,C_t)\) into the ring. Detection runs only when the ring has at least 3 bar(s).

On each bar, independently update (and emit) the packed detectors:

Field Detector
doji CDLDoji
hammer CDLHammer
hanging_man CDLHangingMan
inverted_hammer CDLInvertedHammer
shooting_star CDLShootingStar
engulfing CDLEngulfing
harami CDLHarami
piercing CDLPiercing
dark_cloud_cover CDLDarkCloudCover
morning_star CDLMorningStar
evening_star CDLEveningStar
three_white_soldiers CDL3WhiteSoldiers
three_black_crows CDL3BlackCrows
marubozu CDLMarubozu
spinning_top CDLSpinningTop

Each component keeps its own ring state; the pack does not share history between detectors (same as running them side by side).

If the predicate fails, emit \(0\). The C++ path is \(O(1)\) per update (fixed ring, no full-window rescan beyond a few bars).

Implementation Notes

The recurrence is implemented in src/rtta/indicator.cpp in class CDLPatternPack, built on shared CdlHistory / cdl:: geometry helpers. Thresholds are streaming-friendly geometric rules; they are not a line-by-line port of every TA-Lib average-body lookback table.

Reference