Indicator · Pine Script v5 · On the chart

Candlestick Patterns on Backtest

by regalouisei· code credited to MUQWISHI

This indicator simulates and backtests candlestick pattern performance directly on the price chart.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code424
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update8 months ago25 Feb 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

424 lines of Pine Script v5 from pinescript/editors_picks/all-candlestick-patterns-on-backtest-by-muqwishi.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

all-candlestick-patterns-on-backtest-by-muqwishi.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © MUQWISHI

//@version=5
indicator("Candlestick Patterns on Backtest", overlay = true, max_labels_count = 500, max_bars_back = 50)
import MUQWISHI/CandlestickPatterns/2 as cp

// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                   INPUT                                    |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
s = " ‏"
// +++++++++++++++ Table Settings
// Location 
tablePos = input.string("Middle Right", "Table Location ", 
             ["Top Right" , "Middle Right" , "Bottom Right" , 
             "Top Center", "Middle Center" , "Bottom Center", 
             "Top Left"  , "Middle Left"   , "Bottom Left" ], inline = "1", group = "Table Setting")

// Size
tableSiz = input.string("Tiny", "", 
             ["Auto", "Huge", "Large", "Normal", "Small", "Tiny"], inline = "1", group = "Table Setting")

// Table Color
posCol = input.color(#006400, "Positive",   group = "Table Setting", inline = "4")
neuCol = input.color(#ffffff, " Neutral",   group = "Table Setting", inline = "4")
negCol = input.color(#882336, " Negative ", group = "Table Setting", inline = "4")

tBgCol = input.color(#696969, "Titles ",    group = "Table Setting", inline = "2")
txtCl1 = input.color(#ffffff, "    Text",   group = "Table Setting", inline = "2")
txtCl2 = input.color(#000000, "",           group = "Table Setting", inline = "2")

// +++++++++++++++ Label Color
labChk = input.bool(false, "Show Pattern Label", inline = "lab")
labCl1 = input.color(color.blue,  "", inline = "lab")
labCl2 = input.color(color.red,   "", inline = "lab")
labCl3 = input.color(color.white, "", inline = "lab")

// +++++++++++++++ Backtest Setting
sTim  = input.time(timestamp("01 Jan 2000 20:00"), "From", inline = "0", group = "Backtest Setting",
         tooltip = "Backtest Starting Period\n\nNote: If the datetime of the first candle on the chart" +
         " is after the entered datetime, the calculation will start from the first candle on the chart.")
cash  = input.float(100000, "Initial Equity ($)       ", 1, group = "Backtest Setting")
mrgn  = input.float(1, "Leverage", 1, group = "Backtest Setting")
enMod = input.string("At Close", "Entry Mode", ["At Close", "Breakout High (Low for Short)"], group = "Backtest Setting")
cnclC = input.bool(true, "Cancel Entry Within Bars", group = "Backtest Setting", inline = "cnc")
cnclN = input.int(3, "", 1, group = "Backtest Setting", inline = "cnc", 
         tooltip = "This option is applicable with\n  {Entry Mode = Breakout High (Low for Short)}\n"+
                   "\nCancel the Entry Order if it's not executed within certain number of Bars.")

rngTy = input.string("ATR Range", "StopLoss"+s+s+s+s, ["ATR Range", "Pattern Range"], inline = "00")
stpls = input.float(1, ""+s+s, 0, step = 0.1, 
       tooltip = "Example & Illustration\n0.5 is half distance of range."+ "\n1 is distance of range." 
       + "\n2 is twice distance of range.\n\nRange Types:\n1. Pattern Range: high of pattern - low of pattern"
       + "\n2. ATR: Average True Range\n\n*Range is calculated from entry level", inline = "00")

// Risk Rewards Inputs
rw01c = input.bool(true, "", inline = "01")
rw02c = input.bool(true, "", inline = "02")
rw03c = input.bool(true, "", inline = "03")
rw04c = input.bool(true, "", inline = "04")
rw05c = input.bool(true, "", inline = "05")
rw06c = input.bool(true, "", inline = "06")
rw07c = input.bool(true, "", inline = "07")
rw01v = input.float(1.0, "[01] Risk:Reward     ", 0, inline = "01")
rw02v = input.float(1.5, "[02] Risk:Reward     ", 0, inline = "02")
rw03v = input.float(2.0, "[03] Risk:Reward     ", 0, inline = "03")
rw04v = input.float(3.0, "[04] Risk:Reward     ", 0, inline = "04")
rw05v = input.float(4.0, "[05] Risk:Reward     ", 0, inline = "05")
rw06v = input.float(5.0, "[06] Risk:Reward     ", 0, inline = "06")
rw07v = input.float(6.0, "[07] Risk:Reward     ", 0, inline = "07")

// +++++++++++++++ Technical Settings
// Moving Average
maChk   = input.bool(true, "Detect Trend Based on SMA", inline = "0", group = "Technical")
maLen   = input.int(50, "", 1,                          inline = "0", group = "Technical")

// +++++++++++++++ Candle Patterns
// Type
ptrnTyp = input.string("Both", "Pattern Type", ["Bullish", "Bearish", "Both"], group = "Candle Patterns")

// Patterns
abandonedBabyChk       = input.bool(true, "Abandoned Baby",        group = "Candle Patterns", inline = "01") 
dbarkCloudCoverChk     = input.bool(true, "Dark Cloud Cover",      group = "Candle Patterns", inline = "01") 
dojiStarChk            = input.bool(true, "Doji Star",             group = "Candle Patterns", inline = "02") 
downsideTasukiGapChk   = input.bool(true, "Downside Tasuki Gap",   group = "Candle Patterns", inline = "02") 
dragonflyDojiChk       = input.bool(true, "Dragonfly Doji",        group = "Candle Patterns", inline = "03") 
engulfingChk           = input.bool(true, "Engulfing",             group = "Candle Patterns", inline = "03")
eveningDojiStarChk     = input.bool(true, "Evening Doji Star",     group = "Candle Patterns", inline = "03") 
eveningStarChk         = input.bool(true, "Evening Star",          group = "Candle Patterns", inline = "04") 
fallingThreeMethodsChk = input.bool(true, "Falling Three Methods", group = "Candle Patterns", inline = "04") 
fallingWindowChk       = input.bool(true, "Falling Window",        group = "Candle Patterns", inline = "05") 
gravestoneDojiChk      = input.bool(true, "Gravestone Doji",       group = "Candle Patterns", inline = "05") 
hammerChk              = input.bool(true, "Hammer",                group = "Candle Patterns", inline = "05") 
hangingManChk          = input.bool(true, "Hanging Man",           group = "Candle Patterns", inline = "06") 
haramiCrossChk         = input.bool(true, "Harami Cross",          group = "Candle Patterns", inline = "06") 
haramiChk              = input.bool(true, "Harami",                group = "Candle Patterns", inline = "06")
invertedHammerChk      = input.bool(true, "Inverted Hammer",       group = "Candle Patterns", inline = "07") 
kickingChk             = input.bool(true, "Kicking",               group = "Candle Patterns", inline = "07") 
longLowerShadowChk     = input.bool(true, "Long Lower Shadow",     group = "Candle Patterns", inline = "08") 
longUpperShadowChk     = input.bool(true, "Long Upper Shadow",     group = "Candle Patterns", inline = "08") 
marubozuBlackChk       = input.bool(true, "Marubozu Black",        group = "Candle Patterns", inline = "09") 
marubozuWhiteChk       = input.bool(true, "Marubozu White",        group = "Candle Patterns", inline = "09") 
morningDojiStarChk     = input.bool(true, "Morning Doji Star",     group = "Candle Patterns", inline = "10") 
morningStarChk         = input.bool(true, "Morning Star",          group = "Candle Patterns", inline = "10") 
onNeckChk              = input.bool(true, "On Neck",               group = "Candle Patterns", inline = "10") 
piercingChk            = input.bool(true, "Piercing",              group = "Candle Patterns", inline = "11") 
risingThreeMethodsChk  = input.bool(true, "Rising Three Methods",  group = "Candle Patterns", inline = "11") 
risingWindowChk        = input.bool(true, "Rising Window",         group = "Candle Patterns", inline = "12") 
shootingStarChk        = input.bool(true, "Shooting Star",         group = "Candle Patterns", inline = "12") 
threeBlackCrowsChk     = input.bool(true, "Three Black Crows",     group = "Candle Patterns", inline = "14") 
threeWhiteSoldiersChk  = input.bool(true, "Three White Soldiers",  group = "Candle Patterns", inline = "14") 
triStarChk             = input.bool(true, "Tri-Star",              group = "Candle Patterns", inline = "15") 
tweezerBottomChk       = input.bool(true, "Tweezer Bottom",        group = "Candle Patterns", inline = "15") 
tweezerTopChk          = input.bool(true, "Tweezer Top",           group = "Candle Patterns", inline = "15") 
upsideTasukiGapChk     = input.bool(true, "Upside Tasuki Gap",     group = "Candle Patterns", inline = "16") 

pattern(a, x) =>
    switch a
        01 => x == "d" ? "Abandoned Baby (Bear)" : "AB"
        02 => x == "d" ? "Abandoned Baby (Bull)" : "AB"
        03 => x == "d" ? "Dark Cloud Cover (Bear)" : "DCC"
        04 => x == "d" ? "Doji Star (Bear)" : "DS"
        05 => x == "d" ? "Doji Star (Bull)" : "DS"
        06 => x == "d" ? "Downside Tasuki Gap (Bear)" : "DTG"
        07 => x == "d" ? "Dragonfly Doji (Bull)" : "DD"
        08 => x == "d" ? "Engulfing (Bear)" : "BE"
        09 => x == "d" ? "Engulfing (Bull)" : "BE"
        10 => x == "d" ? "Evening Doji Star (Bear)" : "EDS"
        11 => x == "d" ? "Evening Star (Bear)" : "ES"
        12 => x == "d" ? "Falling Three Methods (Bear)" : "FTM"
        13 => x == "d" ? "Falling Window (Bear)" : "FW"
        14 => x == "d" ? "Gravestone Doji (Bear)" : "GD"
        15 => x == "d" ? "Hammer (Bull)" : "H"
        16 => x == "d" ? "Hanging Man (Bear)" : "HM"
        17 => x == "d" ? "Harami Cross (Bear)" : "HC"
        18 => x == "d" ? "Harami Cross (Bull)" : "HC"
        19 => x == "d" ? "Harami (Bear)" : "BH"
        20 => x == "d" ? "Harami (Bull)" : "BH"
        21 => x == "d" ? "Inverted Hammer (Bull)" : "IH"
        22 => x == "d" ? "Kicking (Bear)" : "K"
        23 => x == "d" ? "Kicking (Bull)" : "K"
        24 => x == "d" ? "Long Lower Shadow (Bull)" : "LLS"
        25 => x == "d" ? "Long Upper Shadow (Bear)" : "LUS"
        26 => x == "d" ? "Marubozu Black (Bear)" : "MB"
        27 => x == "d" ? "Marubozu White (Bull)" : "MW"
        28 => x == "d" ? "Morning Doji Star (Bull)" : "MDS"
        29 => x == "d" ? "Morning Star (Bull)" : "MS"
        30 => x == "d" ? "On Neck (Bear)" : "ON"
        31 => x == "d" ? "Piercing (Bull)" : "P"
        32 => x == "d" ? "Rising Three Methods (Bull)" : "RTM"
        33 => x == "d" ? "Rising Window (Bull)" : "RW"
        34 => x == "d" ? "Shooting Star (Bear)" : "SS"
        35 => x == "d" ? "Three Black Crows (Bear)" : "3BC"
        36 => x == "d" ? "Three White Soldiers (Bull)" : "3WS"
        37 => x == "d" ? "Tri-Star (Bear)" : "TS"
        38 => x == "d" ? "Tri-Star (Bull)" : "TS"
        39 => x == "d" ? "Tweezer Bottom (Bull)" : "TB"
        40 => x == "d" ? "Tweezer Top (Bear)" : "TT"
        41 => x == "d" ? "Upside Tasuki Gap (Bull)" : "UTG"

// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                CALCULATION                                 |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// Create Matrices
var strt = sTim
var rwIn = array.new<string>(na)
rwInFun(flg, val) => 
    if flg
        array.push(rwIn, "1:" + str.tostring(val))

if barstate.isfirst
    strt := time > sTim ? time : sTim
    rwInFun(true,    "0"), rwInFun(rw01c, rw01v), rwInFun(rw02c, rw02v), rwInFun(rw03c, rw03v)
    rwInFun(rw04c, rw04v), rwInFun(rw05c, rw05v), rwInFun(rw06c, rw06v), rwInFun(rw07c, rw07v)

var rtnMtx = matrix.new<float>(na,  array.size(rwIn), na) 
var infMtx = matrix.new<string>(na, array.size(rwIn), na)

// Get Label Location
loc  = ta.sma(high - low, 14)/2 

// Label ToolTip
lbTip(id, lb, row, tp, ent, ext, pnl, rtn) => 
    sign1 = (math.sign((rtn - 1)) < 0 ? "-" :  "")
    sign2 = (math.sign((rtn - 1)) < 0 ? "-" : "+")
    label.set_tooltip(lb, "Pattern = " + pattern(row, "d") + "\nRisk:Reward = 1:" + str.tostring(tp) + 
     "\n\nResult = " + id + "\nEntry = "  + str.tostring(ent, format.mintick) + 
     "\nExit = " + str.tostring(ext,  format.mintick) + "\nPnL = " + str.tostring(pnl * 100, format.percent) + 
     "\n\nEquity = " + sign1 + "$" + str.tostring(math.abs((rtn - 1) * cash + cash), "#.00") +
     " (" + sign2 + str.tostring(math.abs(rtn - 1) * 100, format.percent) + ")")

// Matrix ToolTip
mxTip(infMtx, idx, col, nmTrd, nmWin, nmLos, rtn) =>
    matrix.set(infMtx, idx, col, "Number of Trades: " + str.tostring(nmTrd) +
     "\nWon: " + str.tostring(nmWin) + "\nLost: " + str.tostring(nmLos) +
     "\nCum PnL: " + str.tostring((rtn - 1) * 100, format.percent) + 
     "\nEquity: $" + str.tostring((rtn - 1) * cash + cash, "#.00"))

// Pattern Type 
bull = not(ptrnTyp == "Bearish")
bear = not(ptrnTyp == "Bullish")

// Trend Detection (Moving Average)
uTrd = maChk ? close > ta.sma(close, maLen) : true
dTrd = maChk ? close < ta.sma(close, maLen) : true

// Backtest Function
backtest(int side, bool ptrn, int cand, float tp, int row, int col) =>
    // [0] Declaring Variables
    idx = array.indexof(matrix.col(rtnMtx, 0), row)
    var label lb = na, var nmTrd = 0, var nmWin = 0, var nmLos = 0 
    var bn = 0, var rtn = 1.0, var onTrd = false,       
    var enTrd = float(na), var exTrd = float(na),
    var tpTrd = float(na), var slTrd = float(na)

    // [2] Exit Singal
    if onTrd
        // TakeProfit
        if (side == 1 ? high >= tpTrd : low  <= tpTrd)
            exTrd := (side == 1 ? open >= tpTrd ? open : tpTrd :
                                  open <= tpTrd ? open : tpTrd)

            // Calculate Return
            pnl    = math.abs((exTrd - enTrd)/enTrd) * mrgn
            rtn   := rtn * (1 + pnl)
            nmWin += 1

            // Fill Label Tooltip
            lbTip("Won", lb, row, tp, enTrd, exTrd, pnl, rtn)

            // Fill Mtrix
            matrix.set(rtnMtx, idx, col, math.round((rtn - 1) * 100, 2))
            mxTip(infMtx, idx, col, nmTrd, nmWin, nmLos, rtn)

            // Rest
            onTrd := false, enTrd := float(na), exTrd := float(na)

        // StopLoss
        else if (side == 1 ? low <= slTrd : high >= slTrd)
            exTrd := (side == 1 ? open <= slTrd ? open : slTrd : 
                                  open >= slTrd ? open : slTrd)
        
            // Calculate Return
            pnl    = math.abs((exTrd - enTrd)/enTrd) * mrgn
            rtn   := rtn * (1 - pnl)
            nmLos += 1
    
            // Fill Label Tooltip
            lbTip("Lost", lb, row, tp, enTrd, exTrd, -pnl, rtn)
           
            // Fill Mtrix
            matrix.set(rtnMtx, idx, col, math.round((rtn - 1) * 100, 2))
            mxTip(infMtx, idx, col, nmTrd, nmWin, nmLos, rtn)

            // Rest
            onTrd := false, enTrd := float(na), exTrd := float(na)

    // [1] Entry Signals
    var upRng = float(na),  upRng1 = ta.highest(cand)
    var dnRng = float(na),  dnRng1 = ta.lowest(cand)
    var trRng = float(na),  trRng1 = ta.rma(ta.tr, 14)
    if  ptrn and stpls > 0 and na(exTrd) and not(side == 1 ? high > enTrd : low < enTrd)
        upRng := upRng1, dnRng := dnRng1, trRng := na(trRng1) ? ta.tr : trRng1
        enTrd := enMod == "At Close" ? close : side == 1 ? high : low
        bn    := bar_index

    if not(onTrd) 
        if   (enMod == "At Close" ? enTrd : (side == 1 ? high > enTrd : low < enTrd)) and 
             (enMod != "At Close" and cnclC ? cnclN >= bar_index - bn : true) and rtn > 0

            enTrd := side == 1 ? open >= enTrd ? open : enTrd :
                                 open <= enTrd ? open : enTrd

            onTrd := true,   nmTrd += 1,   exTrd := enTrd

            // Set TP & SL
            slRng = (rngTy == "Pattern Range" ? upRng - dnRng : trRng) * stpls 

            tpTrd := enTrd + (side == 1 ?  slRng : -slRng) * tp
            slTrd := enTrd + (side == 1 ? -slRng :  slRng)

            // Draw Trade
            if labChk
                color = side == 1 ? labCl1 : labCl2
                prce  = side == 1 ?  low [bar_index - bn] - loc[bar_index - bn] * col : 
                                     high[bar_index - bn] + loc[bar_index - bn] * col

                lb := label.new(bar_index[bar_index - bn], prce, pattern(row, "") + "\n1:" + str.tostring(tp), 
                         xloc.bar_index, yloc.price, color, label.style_label_center, labCl3, size.small, 
                         tooltip = "Pattern = " + pattern(row, "d") + "\nRisk:Reward = 1:" + str.tostring(tp) 
                         + "\n\n" + "Entry = " + str.tostring(enTrd, format.mintick) + "\nTakeProfit = " + 
                         str.tostring(tpTrd, format.mintick) + "\nStopLoss = " + str.tostring(slTrd, format.mintick))
        
        enTrd := not(onTrd) and enMod != "At Close" and cnclC and cnclN < bar_index - bn ? float(na) : enTrd


// Run Function
run(side, flg, ptrn, cndl, row) =>
    if flg 
        if barstate.isfirst
            matrix.add_row(rtnMtx, matrix.rows(rtnMtx), array.new<float>(array.size(rwIn),            0))
            matrix.add_row(infMtx, matrix.rows(infMtx), array.new<string>(array.size(rwIn), "No Trades"))
            matrix.set(rtnMtx, matrix.rows(rtnMtx) - 1, 0, row)
            matrix.set(infMtx, matrix.rows(infMtx) - 1, 0, str.tostring(row))

        i = 0, p = ptrn and time >= strt
        if rw01c
            i += 1, backtest(side, p, cndl, rw01v, row, i)
        if rw02c
            i += 1, backtest(side, p, cndl, rw02v, row, i)
        if rw03c
            i += 1, backtest(side, p, cndl, rw03v, row, i)
        if rw04c
            i += 1, backtest(side, p, cndl, rw04v, row, i)
        if rw05c
            i += 1, backtest(side, p, cndl, rw05v, row, i)
        if rw06c
            i += 1, backtest(side, p, cndl, rw06v, row, i)
        if rw07c
            i += 1, backtest(side, p, cndl, rw07v, row, i)
        
// Call Run on Patterns
run(-1, bear and abandonedBabyChk, cp.abandonedBaby("bear") and uTrd[2], 3, 1)
run( 1, bull and abandonedBabyChk, cp.abandonedBaby("bull") and dTrd[2], 3, 2)
run(-1, bear and dbarkCloudCoverChk, cp.darkCloudCover() and uTrd[1], 2, 3)
run(-1, bear and dojiStarChk, cp.dojiStar("bear") and uTrd, 2, 4)
run( 1, bull and dojiStarChk, cp.dojiStar("bull") and dTrd, 2, 5)
run(-1, bear and downsideTasukiGapChk, cp.downsideTasukiGap() and dTrd, 3, 6)
run( 1, bull and dragonflyDojiChk, cp.dragonflyDoji(), 1, 7)
run(-1, bear and engulfingChk, cp.engulfing("bear") and uTrd, 2, 08)
run( 1, bull and engulfingChk, cp.engulfing("bull") and dTrd, 2, 09)
run(-1, bear and eveningDojiStarChk, cp.eveningDojiStar() and uTrd, 3, 10)
run(-1, bear and eveningStarChk, cp.eveningStar() and uTrd, 3, 11)
run(-1, bear and fallingThreeMethodsChk, cp.fallingThreeMethods() and dTrd[4], 5, 12)
run(-1, bear and fallingWindowChk, cp.fallingWindow() and dTrd[1], 1, 13)
run(-1, bear and gravestoneDojiChk, cp.gravestoneDoji() and bear, 1, 14)
run( 1, bull and hammerChk, cp.hammer() and dTrd, 1, 15)
run(-1, bear and hangingManChk, cp.hangingMan() and uTrd, 1, 16)
run(-1, bear and haramiCrossChk, cp.haramiCross("bear") and uTrd[1], 2, 17)
run( 1, bull and haramiCrossChk, cp.haramiCross("bull") and dTrd[1], 2, 18)
run(-1, bear and haramiChk, cp.harami("bear") and uTrd[1], 2, 19)
run( 1, bull and haramiChk, cp.harami("bull") and dTrd[1], 2, 20)
run( 1, bull and invertedHammerChk, cp.invertedHammer() and dTrd, 1, 21)
run(-1, bear and kickingChk, cp.kicking("bear") and bear, 2, 22)
run( 1, bull and kickingChk, cp.kicking("bull"), 2, 23)
run( 1, bull and longLowerShadowChk, cp.longLowerShadow(), 1, 24)
run(-1, bear and longUpperShadowChk, cp.longUpperShadow() and bear, 1, 25)
run(-1, bear and marubozuBlackChk, cp.marubozuBlack() and bear, 1, 26)
run( 1, bull and marubozuWhiteChk, cp.marubozuWhite(), 1, 27)
run( 1, bull and morningDojiStarChk, cp.morningDojiStar() and dTrd, 3, 28)
run( 1, bull and morningStarChk, cp.morningStar() and dTrd, 3, 29)
run(-1, bear and onNeckChk, cp.onNeck() and dTrd, 2, 30)
run( 1, bull and piercingChk, cp.piercing() and dTrd[1], 2, 31)
run( 1, bull and risingThreeMethodsChk, cp.risingThreeMethods() and uTrd[4], 5, 32)
run( 1, bull and risingWindowChk, cp.risingWindow() and uTrd[1], 1, 33)
run(-1, bear and shootingStarChk, cp.shootingStar() and uTrd, 1, 34)
run(-1, bear and threeBlackCrowsChk, cp.threeBlackCrows() and bear, 3, 35)
run( 1, bull and threeWhiteSoldiersChk, cp.threeWhiteSoldiers(), 3, 36)
run(-1, bear and triStarChk, cp.triStar("bear") and uTrd[2], 3, 37)
run( 1, bull and triStarChk, cp.triStar("bull") and dTrd[2], 3, 38)
run( 1, bull and tweezerBottomChk, cp.tweezerBottom() and dTrd[1], 2, 39)
run(-1, bear and tweezerTopChk, cp.tweezerTop() and uTrd[1], 2, 40)
run( 1, bull and upsideTasukiGapChk, cp.upsideTasukiGap() and uTrd, 3, 41)

// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                   TABLE                                    |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// Get Tbale Location & Size
locNsze(x) => 
    y   = str.split(str.lower(x), " ")
    out = ""
    for i = 0 to array.size(y) - 1
        out := out + array.get(y, i)
        if i != array.size(y) - 1
            out := out + "_"
    out

// Create Table
nCols = matrix.columns(rtnMtx)
nRows = matrix.rows(rtnMtx)
var tbl = table.new(locNsze(tablePos), nCols, nRows+2, color.new(tBgCol, 100), 
                     color.new(tBgCol, 100), 1, color.new(tBgCol, 100), 1)

// Cell Function
cell(col, row, txt, color, txtCol, tip) => 
    table.cell(tbl, col, row, text = txt, text_color = txtCol, bgcolor = color, 
     text_size = locNsze(tableSiz), tooltip = tip)

if barstate.islast
    table.clear(tbl, 0, 0, nCols-1, nRows+1)

    // Find Max Min Values
    maxVal = 100.0, minVal = -50.0
    if nCols > 1 and nRows > 0
        mtxVal  = matrix.submatrix(rtnMtx, 0, nRows, 1, nCols)
        maxVal := matrix.max(mtxVal) < 100 and matrix.max(mtxVal) != 0 ? matrix.max(mtxVal) : 100
        minVal := matrix.min(mtxVal) > -50 and matrix.min(mtxVal) != 0 ? matrix.min(mtxVal) : -50

    if array.size(rwIn) > 1
        cell(1, 0, "R E T U R N (%)", tBgCol, txtCl1, "Return (%)"), table.merge_cells(tbl, 1, 0, nCols-1, 0)

    start = "Backtest Start From\n" + str.format_time(strt, "yyyy-MM-dd", syminfo.timezone)
    cell(0, 0, start, tBgCol, txtCl1, start)
    cell(0, 1, "P A T T E R N S", tBgCol, txtCl1, "Patterns")
    
    y = 2
    if array.size(rwIn) > 0
        for j = 0 to array.size(rwIn) - 1
            if j > 0 
                a = array.get(rwIn, j), cell(j, 1, a, tBgCol, txtCl1, a)
        
            if nCols - 1 >= j and nRows > 0
                for i = 0 to nRows - 1
                    if j == 0
                        p = pattern(matrix.get(rtnMtx, i, 0), "d"), cell(j, y, p, tBgCol, txtCl1, p)

                    else
                        val = matrix.get(rtnMtx, i, j)
                        col = val >= 0 ? color.from_gradient(val, 0, maxVal, neuCol, posCol) :
                                         color.from_gradient(val, minVal, 0, negCol, neuCol)

                        cell(j, y, str.tostring(val, format.percent), col, txtCl2, matrix.get(infMtx, i, j))
                    y += 1
            y := 2

Overview

Utilizing an imported pattern recognition library, it calculates theoretical trade outcomes based on user-defined entry modes, stop-loss methods (ATR or pattern range), and multiple risk-to-reward ratios. The script displays performance statistics in a customizable on-screen dashboard table, with optional visual pattern labels placed on candles. Settings allow users to adjust backtest start dates, initial equity, leverage, risk settings, and table layout. Because it is an indicator rather than a strategy script, execution relies on custom array-based calculations.

Details

Published by

regalouisei on GitHub

Code credit

MUQWISHI, as written in the script's header

Draws

On the price chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Table Location stringMiddle RighttablePos
tableSizstringTinytableSiz
Positivecolor#006400posCol
 Neutralcolor#ffffffneuCol
 Negative color#882336negCol
Titles color#696969tBgCol
    Textcolor#fffffftxtCl1
txtCl2color#000000txtCl2
Show Pattern LabelboolfalselabChk
labCl1colorcolor.bluelabCl1
labCl2colorcolor.redlabCl2
labCl3colorcolor.whitelabCl3
Show all 40 settings
SettingTypeDefaultVariable
Fromtimetimestamp("01 Jan 2000 20:00")sTim
Initial Equity ($)       float100000cash
Leveragefloat1mrgn
Entry ModestringAt CloseenMod
Cancel Entry Within BarsbooltruecnclC
cnclNint3cnclN
rngTystringATR RangerngTy
stplsfloat1stpls
rw01cbooltruerw01c
rw02cbooltruerw02c
rw03cbooltruerw03c
rw04cbooltruerw04c
rw05cbooltruerw05c
rw06cbooltruerw06c
rw07cbooltruerw07c
[01] Risk:Reward     float1.0rw01v
[02] Risk:Reward     float1.5rw02v
[03] Risk:Reward     float2.0rw03v
[04] Risk:Reward     float3.0rw04v
[05] Risk:Reward     float4.0rw05v
[06] Risk:Reward     float5.0rw06v
[07] Risk:Reward     float6.0rw07v
Detect Trend Based on SMAbooltruemaChk
maLenint50maLen
Pattern TypestringBothptrnTyp
Abandoned BabybooltrueabandonedBabyChk
Dark Cloud CoverbooltruedbarkCloudCoverChk
Doji StarbooltruedojiStarChk
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

575 stars

The indicator plots ICT displacement candles on the price chart and can switch to retracement scanning. Displacement requires a move larger than a set share of the 14-bar average high-low range, lasting at least a chosen number of bars, with optional close, pr

Indicator v6 SMC / ICT / price actionCandlestick patterns
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Displacement Candles Indicator

Confluence Suite

by TamaraKGreen
46 stars

The Confluence Suite indicator draws multiple trading signals and tools directly on the price chart. It generates entry and exit signals based on selected modes and filters, with an AI signal classifier rating quality from 1-4. Additional features include smar

Indicator v5 TrendSMC / ICT / price action
Updated 8 weeks ago · None stated GitHub repository of Confluence Suite
32 stars

Ghost Channels fits dynamic parallel trend channels over a configurable lookback window using linear regression or pivot swing methods. It layers confirmation signals onto the channel geometry, detecting candlestick pattern reactions at the rails, volume-confi

Indicator v6 TrendBreakout
Updated 4 days ago · MIT GitHub repository of Ghost Channels [mph1nance]

Zen OOH OOL v3

by Zen-Tim
29 stars

This indicator identifies whether the opening bar of a new trading day opens at its high (Open = High) or low (Open = Low) within a customizable tick tolerance. It marks matching sessions directly on the price chart using directional arrows, text labels, and t

Indicator v5 Sessions & timeCandlestick patterns
Updated 2 weeks ago · MIT GitHub repository of Zen OOH OOL v3

Fractal Reclaim Strength

by selimgrsoy0-commits
12 stars

The indicator tracks four-bar fractal sweep and reclaim setups on chart timeframes of 15 minutes and above. It calculates Reclaim Strength based on where C2 closes relative to C1's range and plots level lines for the swept C1 extreme and C2 extreme. An on-scre

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 7 weeks ago · None stated GitHub repository of Fractal Reclaim Strength
12 stars

This overlay indicator assigns a next-candle bias from the prior candle: previous-candle high, previous-candle low, an inside-bar version of that bias, or none. Outside bars clear the bias. After each confirmed bar it records whether price tags the prior high

Indicator v5 SMC / ICT / price actionCandlestick patterns
Updated 1 year ago · None stated GitHub repository of Simplified Next Day Bias Model

More Candlestick patterns scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers