Candlestick Patterns¶
TulipRS includes a dedicated candlestick recognition engine covering 77+ classical patterns — from single-bar formations such as Hammer and Shooting Star through to four-bar structures such as Concealing Baby Swallow. Every pattern carries a Japanese name and a forecast type (bullish/bearish reversal or continuation), and all patterns are detected in a single pass over the input bars. The candlestick engine uses internally computed body and wick size averages, plus a trend signal, to ensure that context-dependent patterns (e.g. Hanging Man vs Hammer) are classified correctly.
Output shape differs from regular indicators
The candlestick API takes the same NumPy array inputs as every other indicator in TulipRS, but its output is different — instead of a numeric series it returns a list of pattern-match lists (one entry per output bar, each entry being a list of matched pattern dicts).
Options¶
The candlestick engine accepts three options in the following order:
| Position | Name | Description |
|---|---|---|
options[0] |
candle_period |
Lookback window used to compute rolling averages for body size and upper/lower wick size. A larger value smooths out the reference size over more bars — use a value greater than 5 in practice. |
options[1] |
trend_period |
Lookback window for the raw trend calculation. Controls how many bars are included when determining whether the market is in an uptrend or downtrend at the point of pattern detection. |
options[2] |
trend_signal_period |
Smoothing period applied to the raw trend value to produce a trend signal. Higher values reduce noise in trend classification. |
Basic Usage¶
use tulip_rs::indicators::candlestick::CandleStick;
let open = vec![81.85_f64, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25];
let high = vec![82.15_f64, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00];
let low = vec![81.29_f64, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11];
let close = vec![81.59_f64, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36];
let inputs = [open.as_slice(), high.as_slice(), low.as_slice(), close.as_slice()];
let options = [5.0_f64, 1.0, 1.0]; // candle_period, trend_period, trend_signal_period
// result is Vec<Option<Vec<Pattern>>> — one entry per output bar
// Pattern is an enum; call .get_info() on each variant to retrieve its metadata
let (result, mut state) = CandleStick::indicator(&inputs, &options, None).unwrap();
for (i, bar) in result.iter().enumerate() {
if let Some(patterns) = bar.as_ref() {
for pattern in patterns {
let info = pattern.get_info();
println!("Bar {i}: {} ({})",
info.full_name, info.japanese_name);
}
}
}
#include <tulip_rs_ffi.h>
const double open[] = {81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25};
const double high[] = {82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00};
const double low[] = {81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11};
const double close[] = {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36};
const double *inputs[4] = {open, high, low, close}; // open, high, low, close order
const double options[3] = {5.0, 1.0, 1.0}; // candle_period, trend_period, trend_signal_period
CCandleStickResult result = candlestick_indicator(inputs, 10, options, -1); // -1 = no filter
for (uintptr_t i = 0; i < result.num_bars; i++) {
uint32_t start = result.bar_offsets[i];
uint32_t end = result.bar_offsets[i + 1];
printf("Bar %zu: ", i);
if (start == end) {
printf("None\n");
} else {
for (uint32_t k = start; k < end; k++) {
CCandlePatternInfo info = candlestick_pattern_info(result.pattern_ids[k]);
printf("%s (%s), bars: %u ", info.full_name, info.japanese_name, info.bars);
}
printf("\n");
}
}
candlestick_result_free(result); // frees CSR buffers only
candlestick_state_free(result.state); // frees state when done streaming
import (
"fmt"
"github.com/me60732/tulip_rs_go/indicators"
"github.com/me60732/tulip_rs_go/tulip"
)
open := []float64{81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25}
high := []float64{82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00}
low := []float64{81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11}
close := []float64{81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36}
options := []float64{5.0, 1.0, 1.0} // candle_period, trend_period, trend_signal_period
res, st, _ := indicators.Candlestick.Indicator(open, high, low, close, options, indicators.ForecastNone)
defer res.Close()
defer st.Close()
for i := 0; i < res.NumBars; i++ {
pats := res.Patterns(i) // pattern ids detected on bar i
if len(pats) == 0 {
fmt.Printf("Bar %d: None\n", i)
} else {
names := res.Names(i) // short names for the patterns
fmt.Printf("Bar %d:", i)
for _, name := range names {
fmt.Printf(" %s", name)
}
fmt.Println()
}
}
import org.tuliprs.*;
import org.tuliprs.indicators.Candlestick;
double[] open = {81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25};
double[] high = {82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00};
double[] low = {81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11};
double[] close = {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36};
double[] options = {5.0, 1.0, 1.0}; // candle_period, trend_period, trend_signal_period
CandleOutcome oc = Candlestick.indicator(new double[][] {open, high, low, close}, options);
try (CandleResult res = oc.result(); CandleState st = oc.state()) {
for (int bar = 0; bar < res.numBars(); bar++) {
String[] names = res.names(bar);
if (names.length > 0) {
System.out.printf("Bar %d: %s%n", bar, String.join(", ", names));
} else {
System.out.printf("Bar %d: None%n", bar);
}
}
}
import numpy as np
import tulip_rs
cdl = tulip_rs.indicators.candlestick
open_ = np.array([81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25,
87.30, 86.40, 84.30, 85.60], dtype=np.float64)
high_ = np.array([82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00,
87.30, 86.40, 85.50, 85.65], dtype=np.float64)
low_ = np.array([81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11,
86.30, 85.30, 84.00, 83.85], dtype=np.float64)
close_ = np.array([81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36,
86.30, 85.30, 84.00, 83.90], dtype=np.float64)
options = [5.0, 1.0, 1.0] # candle_period, trend_period, trend_signal_period
# Run all patterns (matching current trend direction)
result, state = cdl.candlestick(open_, high_, low_, close_, options=options)
# result is a list — one entry per output bar — each entry is a list of pattern dicts
for i, bar_patterns in enumerate(result):
if bar_patterns:
for p in bar_patterns:
print(f"Bar {i}: {p['full_name']} ({p['japanese_name']}) — {p['forecast']}")
import * as ti from 'tulip-rs-node';
const open = Float64Array.from([81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25,
84.03, 85.45, 86.18, 88.00, 87.30, 87.30, 86.40, 84.30, 85.60]);
const high = Float64Array.from([82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00,
85.90, 86.58, 86.98, 88.00, 87.31, 87.30, 86.40, 85.50, 85.65]);
const low = Float64Array.from([81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11,
84.03, 85.39, 85.76, 87.17, 87.20, 86.30, 85.30, 84.00, 83.85]);
const close = Float64Array.from([81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36,
85.53, 86.54, 86.89, 87.77, 87.29, 86.30, 85.30, 84.00, 83.90]);
const options = [5, 1, 1]; // candle_period, trend_period, trend_signal_period
const [result, state] = ti.candlestick.indicator([open, high, low, close], options);
result.forEach((patterns, i) => {
if (patterns && patterns.length > 0) {
patterns.forEach(p => {
console.log(`Bar ${i}: ${p.fullName} (${p.japaneseName}), bars: ${p.bars}, forecast: ${p.forecast}`);
});
}
});
Each matched pattern is returned as a dict (Python) or a struct (Rust) with the following fields:
| Field | Type | Description |
|---|---|---|
name |
str |
Short machine-readable pattern name |
full_name |
str |
Full English pattern name |
japanese_name |
str |
Traditional Japanese name |
bars |
int |
Number of bars the pattern spans (1–4) |
forecast |
str / enum |
One of BullishReversal, BearishReversal, BullishContinuation, BearishContinuation |
The C API exposes these same fields via CCandlePatternInfo — call candlestick_pattern_info(id) for each pattern ID to retrieve metadata.
Filtering by Forecast Type¶
Pass a forecast_type argument to return only patterns with a specific forecast. This is useful when you only care about, for example, bullish reversal setups.
use tulip_rs::indicators::candlestick::{CandleStick, ForecastType};
let inputs = [open.as_slice(), high.as_slice(), low.as_slice(), close.as_slice()];
let options = [5.0_f64, 1.0, 1.0];
// Only bullish reversal patterns
let (result, _) = CandleStick::indicator(&inputs, &options, Some(ForecastType::BullishReversal)).unwrap();
// Inspect the last bar for matches
if let Some(patterns) = result.last().and_then(|bar| bar.as_ref()) {
for pattern in patterns {
let info = pattern.get_info();
println!(" - {} ({}), bars: {}",
info.full_name, info.japanese_name, info.bars);
}
}
// Other available variants:
// ForecastType::BearishReversal
// ForecastType::BullishContinuation
// ForecastType::BearishContinuation
const double *inputs[4] = {open, high, low, close};
const double options[3] = {5.0, 1.0, 1.0};
// Only bullish reversal patterns (enum value from header)
CCandleStickResult result = candlestick_indicator(inputs, 10, options,
C_FORECAST_TYPE_BULLISH_REVERSAL);
// Inspect the last bar for matches
uint32_t last_start = result.bar_offsets[result.num_bars - 1];
uint32_t last_end = result.bar_offsets[result.num_bars];
if (last_start != last_end) {
printf("BullishReversal patterns:\n");
for (uint32_t k = last_start; k < last_end; k++) {
CCandlePatternInfo info = candlestick_pattern_info(result.pattern_ids[k]);
printf(" - %s (%s), bars: %u\n", info.full_name, info.japanese_name, info.bars);
}
}
// Enum values available:
// C_FORECAST_TYPE_BEARISH_REVERSAL
// C_FORECAST_TYPE_BULLISH_REVERSAL
// C_FORECAST_TYPE_BEARISH_CONTINUATION
// C_FORECAST_TYPE_BULLISH_CONTINUATION
// C_FORECAST_TYPE_BEARISH_REVERSAL_OR_CONTINUATION
// C_FORECAST_TYPE_BULLISH_REVERSAL_OR_CONTINUATION
candlestick_result_free(result);
candlestick_state_free(result.state);
import tulip_rs
cdl = tulip_rs.indicators.candlestick
ForecastType = cdl.ForecastType
options = [5.0, 1.0, 1.0]
# Only bullish reversal patterns
result, _ = cdl.candlestick(open_, high_, low_, close_, options=options,
forecast_type=ForecastType.BullishReversal)
# Other available values:
# ForecastType.BearishReversal
# ForecastType.BullishContinuation
# ForecastType.BearishContinuation
for i, bar_patterns in enumerate(result):
if bar_patterns:
for p in bar_patterns:
print(f"Bar {i}: {p['full_name']} — {p['forecast']}")
import * as ti from 'tulip-rs-node';
const options = [5, 1, 1];
// Only bullish reversal patterns — pass the filter string as the third argument
const [result] = ti.candlestick.indicator([open, high, low, close], options, 'BullishReversal');
result.forEach((patterns, i) => {
if (patterns && patterns.length > 0) {
patterns.forEach(p => console.log(`Bar ${i}: ${p.fullName} — ${p.forecast}`));
}
});
// Other available filter strings:
// 'BearishReversal'
// 'BullishContinuation'
// 'BearishContinuation'
// 'BullishReversalOrContinuation'
// 'BearishReversalOrContinuation'
Omit the third argument (or pass undefined) to return all trend-matching patterns.
import (
"fmt"
"github.com/me60732/tulip_rs_go/indicators"
)
options := []float64{5.0, 1.0, 1.0}
// Only bullish reversal patterns — pass the filter enum
fres, fst, _ := indicators.Candlestick.Indicator(open, high, low, close, options, indicators.ForecastBullishReversal)
defer fres.Close()
defer fst.Close()
fmt.Printf("Bullish-reversal-filtered detections: %d ids across %d bars\n",
fres.TotalPatterns, fres.NumBars)
// Other available filter values:
// indicators.ForecastBearishReversal
// indicators.ForecastBullishContinuation
// indicators.ForecastBearishContinuation
// indicators.ForecastBearishReversalOrContinuation
// indicators.ForecastBullishReversalOrContinuation
import org.tuliprs.*;
import org.tuliprs.indicators.Candlestick;
double[] open = {81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25};
double[] high = {82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00};
double[] low = {81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11};
double[] close = {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36};
double[] options = {5.0, 1.0, 1.0}; // candle_period, trend_period, trend_signal_period
// Only bullish reversal patterns — pass the forecast filter
CandleOutcome oc = Candlestick.indicator(
new double[][] {open, high, low, close}, options,
CandlePattern.FORECAST_BULLISH_REVERSAL);
try (CandleResult res = oc.result()) {
System.out.printf("Bullish-reversal-filtered detections: %d ids across %d bars%n",
res.totalPatterns(), res.numBars());
}
// Other available filter values:
// CandlePattern.FORECAST_BEARISH_REVERSAL
// CandlePattern.FORECAST_BULLISH_CONTINUATION
// CandlePattern.FORECAST_BEARISH_CONTINUATION
// CandlePattern.FORECAST_BEARISH_REVERSAL_OR_CONTINUATION
// CandlePattern.FORECAST_BULLISH_REVERSAL_OR_CONTINUATION
When forecast_type is omitted (or None), all matched patterns are returned regardless of their forecast direction.
State Continuation¶
Like every other indicator in TulipRS, the candlestick engine returns a state object that you can use to continue detection on new bars without reprocessing history. Pass only the new bars to batch_indicator.
use tulip_rs::indicators::candlestick::CandleStick;
let open = vec![81.85_f64, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25];
let high = vec![82.15_f64, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00];
let low = vec![81.29_f64, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11];
let close = vec![81.59_f64, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36];
let inputs = [open.as_slice(), high.as_slice(), low.as_slice(), close.as_slice()];
let options = [5.0_f64, 1.0, 1.0];
// Step 1: run on historical data and capture state
let (_, mut state) = CandleStick::indicator(&inputs, &options, None).unwrap();
// Step 2: feed only the new bars
let new_open = [84.00_f64];
let new_high = [84.50_f64];
let new_low = [83.20_f64];
let new_close = [83.50_f64];
let new_inputs = [new_open.as_slice(), new_high.as_slice(),
new_low.as_slice(), new_close.as_slice()];
let result = state.batch_indicator(&new_inputs, None).unwrap();
if let Some(patterns) = result.last().and_then(|bar| bar.as_ref()) {
for pattern in patterns {
let info = pattern.get_info();
println!(" - {} ({}), bars: {}",
info.full_name, info.japanese_name, info.bars);
}
}
const double open[] = {81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25};
const double high[] = {82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00};
const double low[] = {81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11};
const double close[] = {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36};
const double *inputs[4] = {open, high, low, close};
const double options[3] = {5.0, 1.0, 1.0};
// Step 1: run on historical data and capture state
CCandleStickResult seed = candlestick_indicator(inputs, 10, options, -1);
void *state = seed.state;
candlestick_result_free(seed); // frees CSR only; state stays alive
// Step 2: feed only the new bars
const double new_open[] = {84.00};
const double new_high[] = {84.50};
const double new_low[] = {83.20};
const double new_close[] = {83.50};
const double *new_inputs[4] = {new_open, new_high, new_low, new_close};
CCandleStickBatchResult result = candlestick_batch(state, new_inputs, 1, -1);
uint32_t start = result.bar_offsets[0];
uint32_t end = result.bar_offsets[1];
if (start != end) {
for (uint32_t k = start; k < end; k++) {
CCandlePatternInfo info = candlestick_pattern_info(result.pattern_ids[k]);
printf(" - %s (%s), bars: %u\n", info.full_name, info.japanese_name, info.bars);
}
}
candlestick_batch_result_free(result); // frees CSR buffers
candlestick_state_free(state); // free state when done streaming
import numpy as np
import tulip_rs
cdl = tulip_rs.indicators.candlestick
options = [5.0, 1.0, 1.0]
# Step 1: run on historical data and capture state
_result, state = cdl.candlestick(open_, high_, low_, close_, options=options)
# Step 2: feed new bars as NumPy arrays
new_open = np.array([84.00], dtype=np.float64)
new_high = np.array([84.50], dtype=np.float64)
new_low = np.array([83.20], dtype=np.float64)
new_close = np.array([83.50], dtype=np.float64)
new_result = state.batch_indicator([new_open, new_high, new_low, new_close])
entry = new_result[0] # patterns detected on this new bar
if entry:
for p in entry:
print(f"{p['full_name']} — {p['forecast']}")
import * as ti from 'tulip-rs-node';
const options = [5, 1, 1];
// Step 1: run on historical data and capture state
const [, state] = ti.candlestick.indicator([open, high, low, close], options);
// Step 2: feed only the new bar
const newOpen = Float64Array.from([84.00]);
const newHigh = Float64Array.from([84.50]);
const newLow = Float64Array.from([83.20]);
const newClose = Float64Array.from([83.50]);
// Continue without filter
const newResult = state.batchIndicator([newOpen, newHigh, newLow, newClose]);
// Or with a forecast filter
const bullishOnly = state.batchIndicator([newOpen, newHigh, newLow, newClose], 'BullishReversal');
const entry = newResult[0];
if (entry && entry.length > 0) {
entry.forEach(p => {
console.log(`${p.fullName} (${p.japaneseName}), bars: ${p.bars}, forecast: ${p.forecast}`);
});
} else {
console.log('No patterns on new bar.');
}
import (
"fmt"
"github.com/me60732/tulip_rs_go/indicators"
)
options := []float64{5.0, 1.0, 1.0}
// Step 1: run on historical data and capture state
res, st, _ := indicators.Candlestick.Indicator(open, high, low, close, options, indicators.ForecastNone)
defer res.Close()
// Step 2: feed only the new bars
newOpen := []float64{84.00}
newHigh := []float64{84.50}
newLow := []float64{83.20}
newClose := []float64{83.50}
continued, _ := st.Batch(newOpen, newHigh, newLow, newClose, indicators.ForecastNone)
defer continued.Close()
entry := continued.Patterns(continued.NumBars - 1) // patterns on last bar
if len(entry) > 0 {
names := continued.Names(continued.NumBars - 1)
for _, name := range names {
fmt.Printf("%s\n", name)
}
} else {
fmt.Println("No patterns on new bar.")
}
import org.tuliprs.*;
import org.tuliprs.indicators.Candlestick;
double[] open = {81.85, 81.20, 81.55, 82.91, 83.10, 83.41, 82.71, 82.70, 84.20, 84.25};
double[] high = {82.15, 81.89, 83.03, 83.30, 83.85, 83.90, 83.33, 84.30, 84.84, 85.00};
double[] low = {81.29, 80.64, 81.31, 82.65, 83.07, 83.11, 82.49, 82.30, 84.15, 84.11};
double[] close = {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36};
double[] options = {5.0, 1.0, 1.0}; // candle_period, trend_period, trend_signal_period
// Step 1: run on historical data and capture state
CandleOutcome seed = Candlestick.indicator(
new double[][] {open, high, low, close}, options);
try (CandleResult seedRes = seed.result()) {
CandleState st = seed.state();
// result is closed; state stays alive for continuation
}
// Step 2: feed only the new bars
double[] newOpen = {84.00};
double[] newHigh = {84.50};
double[] newLow = {83.20};
double[] newClose = {83.50};
// Continue without filter
try (CandleResult continued = st.batch(
new double[][] {newOpen, newHigh, newLow, newClose})) {
int lastBar = continued.numBars() - 1;
String[] names = continued.names(lastBar);
if (names.length > 0) {
System.out.printf("%s%n", String.join(", ", names));
} else {
System.out.println("No patterns on new bar.");
}
}
// Or with a forecast filter
try (CandleResult bullishOnly = st.batch(
new double[][] {newOpen, newHigh, newLow, newClose},
CandlePattern.FORECAST_BULLISH_REVERSAL)) {
int lastBar = bullishOnly.numBars() - 1;
String[] names = bullishOnly.names(lastBar);
if (names.length > 0) {
System.out.printf("%s%n", String.join(", ", names));
} else {
System.out.println("No patterns on new bar.");
}
}
Pattern Reference¶
One-Bar Patterns¶
| Pattern | Japanese Name | Forecast |
|---|---|---|
| Hammer | Kanazuchi | BullishReversal |
| Hanging Man | Kubitsuri | BearishReversal |
| Bullish Belt Hold | Yorikiri | BullishReversal |
| Bearish Belt Hold | Yorikiri | BearishReversal |
| Bullish Strong Line | Yorikiri Sen | BullishContinuation |
| Bearish Strong Line | Yorikiri Sen | BearishContinuation |
| Northern Doji | Kita no Doji | BearishReversal |
| Southern Doji | Minami no Doji | BullishReversal |
| Gapping Up Doji | Ue-hanare Doji | BearishReversal |
| Gapping Down Doji | Shita-hanare Doji | BullishReversal |
| Shooting Star | Nagare Boshi | BearishReversal |
| Takuri Line | Takuri | BullishReversal |
Two-Bar Patterns¶
| Pattern | Forecast |
|---|---|
| Bullish Engulfing | BullishReversal |
| Bearish Engulfing | BearishReversal |
| Dark Cloud Cover | BearishReversal |
| Piercing | BullishReversal |
| Bullish Harami | BullishReversal |
| Bearish Harami | BearishReversal |
| Bullish Harami Cross | BullishReversal |
| Bearish Harami Cross | BearishReversal |
| Inverted Hammer | BullishReversal |
| Bullish Doji Star | BullishReversal |
| Bearish Doji Star | BearishReversal |
| Kicking Bullish | BullishReversal |
| Kicking Bearish | BearishReversal |
| Meeting Lines Bullish | BullishReversal |
| Meeting Lines Bearish | BearishReversal |
| On Neck | BearishContinuation |
| In Neck | BearishContinuation |
| Thrusting | BearishContinuation |
Three-Bar Patterns¶
| Pattern | Forecast |
|---|---|
| Three White Soldiers | BullishReversal |
| Three Black Crows | BearishReversal |
| Morning Star | BullishReversal |
| Morning Doji Star | BullishReversal |
| Evening Star | BearishReversal |
| Evening Doji Star | BearishReversal |
| Three Inside Up | BullishReversal |
| Three Inside Down | BearishReversal |
| Three Outside Up | BullishReversal |
| Three Outside Down | BearishReversal |
| Bullish Tristar | BullishReversal |
| Bearish Tristar | BearishReversal |
| Advance Block | BearishReversal |
| Deliberation | BearishReversal |
| Unique Three River Bottom | BullishReversal |
| Three Stars in the South | BullishReversal |
| Upside Gap Three Methods | BullishContinuation |
| Downside Gap Three Methods | BearishContinuation |
| Upside Tasuki Gap | BullishContinuation |
| Downside Tasuki Gap | BearishContinuation |
| Upside Gap Two Crows | BearishReversal |
| Two Crows | BearishReversal |
| Identical Three Crows | BearishReversal |
| Bull Side-by-Side White Lines | BullishContinuation |
| Bear Side-by-Side White Lines | BearishContinuation |
| Collapsing Doji Star | BearishReversal |
| Bull Abandoned Baby | BullishReversal |
| Bear Abandoned Baby | BearishReversal |
Four-Bar Patterns¶
| Pattern | Forecast |
|---|---|
| Concealing Baby Swallow | BullishReversal |
| Bullish Three Line Strike | BullishContinuation |
| Bearish Three Line Strike | BearishContinuation |