Skip to content

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