MichaelWang66

Finding candle patterns, hanging man as an example

COINBASE:BTCUSD   Bitcoin
When doing technical analysis, I often find myself looking for candle patterns: shooting star, doji, hanging man...

For example, when I tried to use following parameter to find hanging man on daily candles:
Range (High - Low) >= 10%
Body < 50%
UpWick < 10%
LowWick >= 45%
Price direction: both

I find it quite useful in marking top of 2017 and 2021 bull markets. And according to this info, there is no warning sign of current bull run. But please noticed that, no single tool/pattern/indicator can provide 100% correct prediction of price movement. It's just another piece of info to help us doing TA.

I would like to share my script (candle pattern finder) with public, BUT I find I can't do that nowadays on trading view (there are rules I don't have time to comply...). So I'd just post source code here, for anyone who find it useful. Do whatever you want with it (modify, share, or even publish as your indicator).

//@version=5
indicator("Candle Pattern Finder", shorttitle="candle finder", overlay=true, max_labels_count = 500, max_lines_count = 500)

// groups
range_ = "Price Move"
body = "% of Body in candle"
upwick = "% of Upwick in candle"
lowick = "% of Lowick in candle"
// conditions
gt = ">=", lt = "<", nop = "do not apply", goUp = "Up", goDown = "Down", both = "Both"

// Inputs
rgHeight = input.bool(false, "High - Low", group = range_, tooltip = "Set true to use candole height as range, false for abs(close - open)")
rgCp = input.string(gt, "Rule", options = [nop, gt, lt], group = range_)
rgMv = input.float(6, "in %", minval = 0, maxval = 100, group = range_)

bdCp = input.string(lt, "Rule", options = [nop, gt, lt], group = body)
bdMv = input.float(25, "in %", minval = 0, maxval = 100, step = 5, group = body)

uwCp = input.string(lt, "Rule", options = [nop, gt, lt], group = upwick)
uwMv = input.float(15, "in %", minval = 0, maxval = 100, step = 5, group = upwick)

lwCp = input.string(gt, "Rule", options = [nop, gt, lt], group = lowick)
lwMv = input.float(50, "in %", minval = 0, maxval = 100, step = 5, group = lowick)

dir = input.string(both, "Price Up or Down", options = [both, goUp, goDown])

dx = input.int(0, title="Bar Index Offset", tooltip = "There is limit how many candlesticks a script can go back, by setting offset to, e.g. 365, you can move finding range 1 year back. Must >= 0", minval=0)

// Prepare data
height = high[dx] - low[dx]
Range = (rgHeight ? height : math.abs(close[dx] - open[dx])) / open[dx] * 100
Body = math.abs(open[dx] - close[dx]) / height * 100
Upwick = (high[dx] - math.max(open[dx], close[dx])) / height * 100
Lowick = (math.min(open[dx], close[dx]) - low[dx]) / height * 100

// Matching pattern
fmt(part, move) => str.format("{0}: {1, number, #.#}" + "%", part, move)

match = switch rgCp
    gt => Range >= rgMv
    lt => Range < rgMv
    => false
sRange = match ? fmt("rg", Range) : ""


match := switch bdCp
    gt => Body >= bdMv
    lt => Body < bdMv
    => false
sBody = match ? fmt("bd", Body) : ""

match := switch uwCp
    gt => Upwick >= uwMv
    lt => Upwick < uwMv
    => false
sUpwick = match ? fmt("uw", Upwick) : ""

match := switch lwCp
    gt => Lowick >= lwMv
    lt => Lowick < lwMv
    => na
sLowick = match ? fmt("lw", Lowick) : ""

match := switch dir
    goUp => close[dx] > open[dx]
    goDown => close[dx] < open[dx]
    => na
sDir = match ? (dir == goUp ? "up" : "down") : ""

up = (close[dx] - open[dx]) >= 0

c0 = rgCp == nop or sRange != ""
c1 = bdCp == nop or sBody != ""
c2 = uwCp == nop or sUpwick != ""
c3 = lwCp == nop or sLowick != ""
c4 = dir == both or sDir != ""
match := c0 and c1 and  c2 and c3 and c4

// Present result
mark(bool up, string msg) =>
    label.new(bar_index-dx, 0, yloc=up ? yloc.belowbar : yloc.abovebar, style=up ? label.style_arrowup : label.style_arrowdown, color=up ? color.green : color.red, text=msg, textcolor = up ? color.green : color.red, size=size.normal)
str(s) => na(s) ? "" : s
newline(v) => na(v) ? "" : "\n"

if match and str.format("{0}{1}{2}{3}", sRange, sBody, sUpwick, sLowick) != ""
    msg = str(sRange) + newline(sRange) + str(sBody) + newline(sBody) + str(sUpwick) + newline(sUpwick) + str(sLowick)
    mark(up, msg)

Disclaimer

The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.