feat(pattern_recognitions): add 25 remaining Cdl* candlestick pattern wrappers

Complete the TA-Lib candlestick pattern recognition coverage by adding the second
half of the Cdl* function family.

New functions in pattern_recognitions.go (all return []int32, OHLC inputs):
  CdlLadderBottom, CdlLongLeggedDoji, CdlLongLine, CdlMarubozu,
  CdlMatchingLow, CdlMatHold(penetration), CdlMorningDojiStar(penetration),
  CdlMorningStar(penetration), CdlOnNeck, CdlPiercing, CdlRickshawMan,
  CdlRiseFall3Methods, CdlSeparatingLines, CdlShootingStar, CdlShortLine,
  CdlSpinningTop, CdlStalledPattern, CdlStickSandwich, CdlTakuri,
  CdlTasukiGap, CdlThrusting, CdlTristar, CdlUnique3River,
  CdlUpsideGap2Crows, CdlXSideGap3Methods

Supporting changes:
- functions.go: add 25 C function pointer declarations (TA_CDL* signatures)
- loader.go: register all 25 new symbols via purego.RegisterLibFunc in Load()
- cli/main.go: extend smoke harness to exercise all new wrappers
- README.md: document all new patterns in the Pattern Recognition section
This commit is contained in:
2026-07-29 16:24:47 +09:00
parent c7f21b073e
commit 5dcbd4a1cf
4 changed files with 1165 additions and 49 deletions
+823
View File
@@ -1071,3 +1071,826 @@ func CdlKickingByLength(inOpen, inHigh, inLow, inClose []float64) []int32 {
return outReal
}
// CdlLadderBottom - Five-candle bullish reversal pattern: three consecutively lower black candles,
// a fourth black candle with a non-very-short upper shadow,
// then a white candle that opens above the prior open and closes above the prior high.
// Signals a potential bottom reversal. A hit (+100) is a bullish reversal signal, most meaningful after a downtrend.
//
// Note: Does not verify the preceding downtrend that this bullish reversal classically assumes.
//
// @returns
//
// +100 on a detected ladder bottom, 0 otherwise.
// Only ever emits +100 (never -100); inherently bullish
func CdlLadderBottom(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlladderbottom(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlLadderBottom", "result", retCode)
return nil
}
return outReal
}
// CdlLongLeggedDoji - Single-candle doji (open ~ close) with at least one long shadow.
// Signals market indecision, not a directional bias. Marks indecision/uncertainty;
// not inherently bullish or bearish despite the positive sign.
//
// One candle.
// Hit when: real body <= BodyDoji average (doji body) AND (lower shadow > ShadowLong average OR upper shadow > ShadowLong average),
// i.e. at least one long shadow.
//
// Note: Only one long shadow (upper or lower) is required, whereas the classic pattern shows both long upper and lower shadows.
//
// @returns
//
// +100 when the pattern is present, 0 otherwise.
// Only +100 is emitted; the code never emits -100, and the positive sign does NOT mean bullish
func CdlLongLeggedDoji(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdllongleggeddoji(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlLongLeggedDoji", "result", retCode)
return nil
}
return outReal
}
// CdlLongLine - A single-candle pattern: a long real body with short upper and short lower shadow.
// The signal direction follows the candle color (bullish if white, bearish if black).
// Signals strong directional conviction on the bar: +100 white/bullish, -100 black/bearish.
// Not intrinsically a reversal or continuation signal.
//
// @returns
//
// +100 on a white (close>=open) long line, -100 on a black long line, 0 when no pattern
func CdlLongLine(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdllongline(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlLongLine", "result", retCode)
return nil
}
return outReal
}
// CdlMarubozu - Single candle with a long real body and no/very-short upper and lower shadows, so open and close sit at the range extremes.
// Bullish (white) or bearish (black) reversal/strength signal per the body color.
// +100 = white marubozu (strong buying pressure); -100 = black marubozu (strong selling pressure).
//
// One candle at i.
// Match when: realbody(i) > BodyLong average AND upperShadow(i) < ShadowVeryShort average AND lowerShadow(i) < ShadowVeryShort average.
// If matched emit candlecolor(i)*100 (+100 white when close>=open, -100 black when close<open); else 0.
//
// @returns
//
// +100 on a white (bullish) marubozu, -100 on a black (bearish) marubozu, 0 when no pattern.
// Sign follows the candle color
func CdlMarubozu(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlmarubozu(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlMarubozu", "result", retCode)
return nil
}
return outReal
}
// CdlMatchingLow - A two-candle pattern of two consecutive black (bearish) candles with equal closes (within a tolerance).
// Treated as a bullish reversal signal.
// A hit signals a potential bullish reversal (shared support close after two down candles).
//
// Two candles i-1, i.
// Candle i-1: black (close<open).
// Candle i: black (close<open). E
// qual closes: close[i-1]-E <= close[i] <= close[i-1]+E, where E = the Equal average.
// No shadow, body-size, or gap conditions are checked.
//
// Note: The bullish-reversal reading assumes a prior downtrend, which is not verified.
//
// @returns
//
// +100 when the pattern is present, 0 otherwise.
// Only +100 is ever emitted (matching low is always bullish); never -100
func CdlMatchingLow(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlmatchinglow(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlMatchingLow", "result", retCode)
return nil
}
return outReal
}
// CdlMatHold - A five-candle bullish continuation pattern: a long white candle, an upside real-body-gapped small black candle,
// two more small falling candles that hold within the first body, and a final white candle closing above the reaction days' highs.
// Signals continuation of the prior uptrend. Hit = bullish continuation of the existing uptrend.
//
// Note: The colors of the third and fourth (reaction) candles are not checked, although they are classically black.
// The continuation reading assumes a prior uptrend, which is not verified.
//
// @param penetration - Max fraction of the 1st white body the reaction days (3rd, 4th) may penetrate; default is 0.5 (>=0).
// @returns
//
// +100 when the bullish Mat Hold is detected, 0 otherwise.
// Never emits -100
func CdlMatHold(inOpen, inHigh, inLow, inClose []float64, penetration float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlmathold(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
penetration,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlMatHold", "result", retCode)
return nil
}
return outReal
}
// CdlMorningDojiStar - A three-candle bullish reversal pattern:
// a long black candle, then a doji that gaps down, then a white candle closing well up into the first candle's body.
// It is the doji-star variant of the morning star.
// A hit (+100) signals a bullish reversal; most meaningful after a downtrend, which this function does not verify.
//
// Note: The gap-down is measured between the candles' real bodies, not between their high/low ranges.
// A prior downtrend is not verified.
//
// @param penetration - Fraction of the 1st candle's real body the 3rd close must exceed above close[i-2];
// larger values demand deeper penetration into the black body; default is 0.3 (>=0).
//
// @returns
//
// +100 when the pattern is detected, 0 otherwise.
// Always bullish; never emits -100
func CdlMorningDojiStar(inOpen, inHigh, inLow, inClose []float64, penetration float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlmorningdojistar(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose, penetration,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlMorningDojiStar", "result", retCode)
return nil
}
return outReal
}
// CdlMorningStar - A three-candle bottom-reversal pattern:
// a long black candle, a small-bodied star gapping down, then a white candle closing well up into the first candle's body.
// Bullish reversal signal.
// A hit signals a bullish reversal (most meaningful after a downtrend, which the code does not check).
//
// Note: The gap-down is measured between the candles' real bodies, not between their high/low ranges.
// A prior downtrend is not verified.
//
// @param penetration - Fraction of the 1st candle's body the 3rd close must exceed above the 1st close; larger = deeper penetration required; default is 0.3 (>=0).
//
// @returns
//
// +100 when the morning star is detected, 0 otherwise. Never negative (pattern is exclusively bullish)
func CdlMorningStar(inOpen, inHigh, inLow, inClose []float64, penetration float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlmorningstar(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose, penetration,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlMorningStar", "result", retCode)
return nil
}
return outReal
}
// CdlOnNeck - A two-candle on-neck pattern:
// a long black candle followed by a white candle that opens below the prior candle's low and closes right at that low.
// Bearish continuation signal.
// A hit is bearish (bearish continuation); the code does not verify the assumed prior downtrend.
//
// Two candles.
// 1st: black (close<open) with long real body (realbody > BodyLong average).
// 2nd: white (close>=open); open < prior low; close within the Equal band of the prior low,
// i.e. (prior_low - EqualAvg) <= close2 <= (prior_low + EqualAvg).
//
// Note: The bearish-continuation reading assumes a prior downtrend, which is not verified.
//
// @returns
//
// -100 on a match, 0 otherwise.
// Only -100 is ever emitted (never +100); on-neck is always bearish
func CdlOnNeck(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlonneck(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlOnNeck", "result", retCode)
return nil
}
return outReal
}
// CdlPiercing - Two-candle pattern:
// a long black candle followed by a long white candle that opens below the prior low and closes back above the midpoint of the prior black body.
// Bullish reversal signal.
// A hit (+100) is a bullish reversal signal.
//
// Note: A prior downtrend is not verified.
//
// @returns
//
// +100 when the piercing pattern is detected; 0 otherwise.
// Always bullish, never emits -100
func CdlPiercing(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlpiercing(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlPiercing", "result", retCode)
return nil
}
return outReal
}
// CdlRickshawMan - Single-candle doji with two long shadows whose body sits near the midpoint of the high-low range.
// It is a neutral indecision signal, not a directional (bullish/bearish) reversal.
// A hit marks market indecision/uncertainty; neutral, neither bullish nor bearish.
//
// @returns
//
// +100 when the pattern is present, 0 otherwise.
// Never -100; the code notes the positive value does NOT imply bullish, it signals uncertainty
func CdlRickshawMan(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlrickshawman(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlRickshawMan", "result", retCode)
return nil
}
return outReal
}
// CdlRiseFall3Methods - A five-candle continuation pattern:
// a long candle, three small counter-color candles that stay partly within the first candle's high-low range, then a long same-color candle that resumes the trend.
// Bullish (rising) or bearish (falling) continuation signal.
// A hit signals trend continuation: +100 = bullish (rising three methods), -100 = bearish (falling three methods).
//
// Note: Only the three-small-candle variant is detected; the classic pattern allowing two or more small candles is not supported.
// The middle candles need only partially overlap the first candle's range, not be fully contained within it.
// The prior trend the continuation reading assumes is not verified.
//
// @returns
//
// +100 when candle 1 is white (rising/bullish continuation), -100 when candle 1 is black (falling/bearish continuation), 0 otherwise.
// Sign = 100 * color of candle 1
func CdlRiseFall3Methods(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlrisefall3methods(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlRiseFall3Methods", "result", retCode)
return nil
}
return outReal
}
// CdlSeparatingLines - A two-candle continuation pattern:
// the second candle opposes the first in color, opens at the same price as the first, and is a long-bodied belt hold.
// Bullish (white second candle) or bearish (black second candle) continuation signal.
// Trend continuation: +100 = bullish (white belt hold), -100 = bearish (black belt hold).
//
// Two consecutive candles i-1, i:
// (1) opposite colors: color(i-1) == -color(i);
// (2) same open: open[i-1]-Equal_avg <= open[i] <= open[i-1]+Equal_avg;
// (3) long body: realbody(i) > BodyLong_avg;
// (4) belt hold: if i is white, lowershadow(i) < ShadowVeryShort_avg; if i is black, uppershadow(i) < ShadowVeryShort_avg.
//
// Note: A prior trend is not verified, nor that the pattern aligns with it.
//
// @returns
//
// +100 for a bullish (white second candle) hit, -100 for a bearish (black second candle) hit, 0 otherwise
func CdlSeparatingLines(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlseparatinglines(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlSeparatingLines", "result", retCode)
return nil
}
return outReal
}
// CdlShootingStar - Single-candle pattern:
// a small real body with a long upper shadow and little-to-no lower shadow that gaps up from the prior candle's real body.
// Bearish reversal signal. A hit (-100) flags a bearish reversal at the top of an uptrend.
//
// Note: A preceding uptrend is not verified.
//
// @returns
//
// -100 when the shooting star is detected, 0 otherwise.
// Only ever emits negative (bearish); never +100
func CdlShootingStar(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlshootingstar(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlShootingStar", "result", retCode)
return nil
}
return outReal
}
// CdlShortLine - Single-candle pattern: a short real body with short upper and lower shadows (a small-range candle).
// Not a directional signal — the output sign encodes candle color, not bullish/bearish sentiment.
// A hit only flags a small-range candle; the +/- sign is the candle's color (white/black), not a reversal or continuation call.
//
// One candle at i, all three:
//
// short real body: real body < the BodyShort average
// short upper shadow: upper shadow < the ShadowShort average
// short lower shadow: lower shadow < the ShadowShort average
// If matched: output = candle color * 100 (+100 white, -100 black); else 0.
//
// @returns
//
// +100 for a matching white candle (close>=open), -100 for a matching black candle (close<open), 0 when no pattern.
// Sign is candle color, NOT bullish/bearish
func CdlShortLine(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlshortline(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlShortLine", "result", retCode)
return nil
}
return outReal
}
// CdlSpinningTop - Single-candle pattern:
// a small real body with both an upper and a lower shadow longer than the body.
// Signals indecision; the code does not classify it as bullish or bearish.
// A hit marks indecision (small body, both shadows long); the sign only reports candle color, not direction.
//
// One candle where: upper shadow > real body AND lower shadow > real body AND real body < the BodyShort average.
// The BodyShort average is the factor-scaled mean body over the prior avgPeriod candles.
//
// @returns
//
// +100 when the candle is white (close>=open), -100 when black (close<open), 0 when no pattern.
// Sign is candle color, NOT bullish/bearish
func CdlSpinningTop(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlspinningtop(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlSpinningTop", "result", retCode)
return nil
}
return outReal
}
// CdlStalledPattern - A three-candle pattern of three white candles with consecutively higher closes where the third loses momentum
// (a small body riding on the shoulder of the second's long body).
// It is a bearish reversal signal of a stalling advance.
// A hit (-100) is bearish: the uptrend is stalling and may reverse.
//
// Note: The pattern classically appears in an uptrend, but this function does not verify a prior uptrend; the caller must confirm it.
//
// @returns
//
// -100 when the pattern is detected (always bearish), 0 otherwise.
// Never emits +100
func CdlStalledPattern(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlstalledpattern(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlStalledPattern", "result", retCode)
return nil
}
return outReal
}
// CdlStickSandwich - A three-candle bullish reversal pattern:
// two black candles (1st and 3rd) sandwiching a white candle, where the 3rd black candle closes at the same level as the 1st (the "bread").
// A hit signals a bullish reversal (code comment notes it is significant in a downtrend, which the function does not verify).
//
// @returns
//
// +100 when the pattern is present, 0 otherwise.
// Never -100 — Stick Sandwich is always bullish
func CdlStickSandwich(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlsticksandwich(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlStickSandwich", "result", retCode)
return nil
}
return outReal
}
// CdlTakuri - Single-candle pattern:
// a doji whose open and close sit at the high (no/very short upper shadow) with a very long lower shadow,
// i.e. a dragonfly doji with an exceptionally long lower shadow.
// Emitted as a positive signal, but its directional meaning depends on the prevailing trend, which the code does not check.
// A hit marks a takuri (dragonfly-doji) line; a potential reversal only when read against the trend
// (typically a bottom/bullish reversal after a downtrend), which the code itself does not verify.
//
// @returns
//
// +100 when the takuri pattern is detected, 0 otherwise.
// Never negative; the positive sign is a convention and does not by itself imply bullishness
func CdlTakuri(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdltakuri(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlTakuri", "result", retCode)
return nil
}
return outReal
}
// CdlTasukiGap - A three-candle pattern:
// a real-body-gapping candle followed by an opposite-color candle that opens inside its body and closes back into the gap without filling it.
// An upside gap is a bullish continuation signal; a downside gap is a bearish continuation signal.
// Hit signals trend continuation: +100 bullish (in an uptrend), -100 bearish (in a downtrend).
//
// Note: This continuation pattern does not verify the prior trend it classically assumes; the caller must confirm the trend.
//
// @returns
//
// +100 on a bullish (upside-gap) tasuki gap, -100 on a bearish (downside-gap) tasuki gap, 0 otherwise.
// Sign equals the color of the gap candle i-1 (candlecolor(i-1)*100)
func CdlTasukiGap(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdltasukigap(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlTasukiGap", "result", retCode)
return nil
}
return outReal
}
// CdlThrusting - A two-candle pattern:
// a long black candle followed by a white candle that opens below the prior low and closes back into the prior body but below its midpoint.
// It is a bearish continuation signal.
// A hit is bearish: the failed white push back into the black body signals continuation of the down move.
//
// Note: The pattern is classically meaningful only in a downtrend, but this function does not verify any prior trend.
// Although the pattern can be read as bullish in an uptrend or when it recurs,
// this function ignores trend and always reports it as bearish.
//
// @returns
//
// -100 when the pattern is detected, 0 otherwise.
// Always bearish; never emits +100
func CdlThrusting(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlthrusting(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlThrusting", "result", retCode)
return nil
}
return outReal
}
// CdlTristar - A three-candle pattern of three consecutive doji where the middle doji is a star (its body gaps away from the first).
// Bullish or bearish reversal signal. +100 = bullish reversal (middle doji gapped down), -100 = bearish reversal (middle doji gapped up).
//
// Note: This reversal pattern does not verify the prior trend it classically assumes.
//
// @returns
//
// +100 (bullish, star gapped down), -100 (bearish, star gapped up), or 0 when no pattern.
// Both signs are emitted
func CdlTristar(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdltristar(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlTristar", "result", retCode)
return nil
}
return outReal
}
// CdlUnique3River - A three-candle bullish reversal pattern:
// a long black candle, then a black harami candle that makes a lower low, then a small white candle.
// Signals a potential bullish reversal, ideally in a downtrend (trend not checked by the code).
// A hit (+100) marks a bullish reversal; significant in a downtrend, which the function does not verify.
//
// @returns
//
// +100 when the pattern is present, 0 otherwise.
// Bullish-only: never emits -100
func CdlUnique3River(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlunique3river(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlUnique3River", "result", retCode)
return nil
}
return outReal
}
// CdlUpsideGap2Crows - A three-candle bearish reversal pattern:
// a long white candle, then a small black candle gapping up (a gap between the real bodies),
// then a black candle that engulfs the second candle's real body but still closes above the first candle's close.
// Signals a bearish reversal. A hit (-100) is a bearish reversal signal, most meaningful in an uptrend.
//
// Note: The pattern classically assumes a prior uptrend, but this function does not verify any trend.
//
// @returns
//
// -100 on a pattern bar, 0 otherwise.
// Bearish-only: this pattern never emits +100
func CdlUpsideGap2Crows(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlupsidegap2crows(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlUpsideGap2Crows", "result", retCode)
return nil
}
return outReal
}
// CdlXSideGap3Methods - A three-candle continuation pattern: two same-color candles separated by a real-body gap,
// followed by an opposite-color candle that fills into the gap.
// Bullish (upside) when the first two candles are white, bearish (downside) when they are black.
// A hit signals trend continuation: +100 bullish (uptrend resumes), -100 bearish (downtrend resumes).
//
// Note: This continuation pattern does not verify the prior trend it classically assumes; the caller must confirm the trend.
//
// @returns
//
// +100 when the two same-color candles are white (bullish/upside continuation),
// -100 when black (bearish/downside continuation), 0 otherwise.
// Equals candlecolor(1st candle) * 100
func CdlXSideGap3Methods(inOpen, inHigh, inLow, inClose []float64) []int32 {
var (
startIdx int32
endIdx = int32(len(inClose) - 1)
outBegIdx int32
outNBElement int32
outReal = make([]int32, len(inClose))
)
if retCode := cdlxsidegap3methods(
startIdx, endIdx,
inOpen, inHigh, inLow, inClose,
&outBegIdx, &outNBElement, outReal,
); SUCCESS != taResult(retCode) {
slog.Debug("CdlXSideGap3Methods", "result", retCode)
return nil
}
return outReal
}