Mark Minervini's Trend Template
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © omkar_banne

//@version=5
indicator("Mark Minervini's Trend Template", overlay = true)

position = input.string(position.top_right, 'Table \nPosition\n', options= [position.top_left, position.top_right, position.bottom_left, position.bottom_right], group='--------------Table Properties--------------', inline = "1")
textcolor = input(color.white, "Text Color", group='--------------Table Properties--------------', inline = "1")

textsize = input.string(size.normal, 'Text Size', options=[size.auto, size.small, size.normal, size.large], group='--------------Table Properties--------------', inline = "2")
panelbgcolor = input(color.gray, "Background Color", group='--------------Table Properties--------------', inline = "2")


//Moving Averages
type = input.string(defval='EMA', options=['EMA', 'SMA'] , title='Moving Average Type', tooltip='EMA / SMA?.', group = '--------------Moving Average Settings--------------')

// Table
var table1 = table.new(position, 3, 15, frame_color=color.rgb(49, 71, 131), border_width = 1, frame_width = 2, border_color = color.black)
table.merge_cells(table1,0,0,2,0)
table.cell(table1, 0, 0, 'Mark Minervini Template', bgcolor = color.rgb(88, 247, 114), text_size=textsize, text_color=color.black)


ma50 = ta.ema(close, 50)
ma150 = ta.ema(close, 150)
ma200 = ta.ema(close, 200)
ma200_22 = ma200[22]

if type == 'EMA'
    ma50 := ta.ema(close, 50)
    ma150 := ta.ema(close, 150)
    ma200 := ta.ema(close, 200)
    
if type == 'SMA'
    ma50 := ta.sma(close, 50)
    ma150 := ta.sma(close, 150)
    ma200 := ta.sma(close, 200)


bgcolor = panelbgcolor

// CMP > 50MA

close_greaterthan_50ma = close > ma50

close_greaterthan_50ma_color = color.gray
if not close_greaterthan_50ma
    close_greaterthan_50ma_color := color.red

if na(ma50)
    close_greaterthan_50ma_color := color.gray

isDaily = ta.change(time("D")) == 0

if timeframe.isdaily
    per50 = (1-(ma50/close))*100
    table.cell(table1, 0, 1, (close_greaterthan_50ma ? '✓' : 'x'), bgcolor = close_greaterthan_50ma_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 1,  str.tostring("CMP > 50MA"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 1, str.tostring(ma50,'#.#') + " (" + str.tostring(per50,'#.#') + " %" + ")", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "50 MA and % Distance from 50 MA")

// CMP > 150MA

close_greaterthan_150ma = close > ma150

close_greaterthan_150ma_color = color.gray
if not close_greaterthan_150ma
    close_greaterthan_150ma_color := color.red

if na(ma150)
    close_greaterthan_150ma_color := color.gray

if timeframe.isdaily
    per150 = (1-(ma150/close))*100
    table.cell(table1, 0, 2, (close_greaterthan_150ma ? '✓' : 'x'), bgcolor = close_greaterthan_150ma_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 2,  str.tostring("CMP > 150MA"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 2, str.tostring(ma150,'#.#') + " (" + str.tostring(per150,'#.#') + " %" + ")", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "150 MA and % Distance from 150 MA")

// CMP > 200MA

close_greaterthan_200ma = close > ma200

close_greaterthan_200ma_color = color.gray
if not close_greaterthan_200ma
    close_greaterthan_200ma_color := color.red

if na(ma200)
    close_greaterthan_200ma_color := color.gray

if timeframe.isdaily
    per200 = (1-(ma200/close))*100
    table.cell(table1, 0, 3, (close_greaterthan_200ma ? '✓' : 'x'), bgcolor = close_greaterthan_200ma_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 3, str.tostring("CMP > 200MA"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 3, str.tostring(ma200,'#.#') + " (" + str.tostring(per200,'#.#') + " %" + ")", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "200 MA and % Distance from 200 MA")

// 50MA > 150MA

ma50_greaterthan_150ma = ma50 > ma150

ma50_greaterthan_150ma_color = color.gray
if not ma50_greaterthan_150ma
    ma50_greaterthan_150ma_color := color.red

if na(ma50) or na(ma150)
    ma50_greaterthan_150ma_color := color.gray

if timeframe.isdaily
    per50_150 = (1-(ma50/ma150))*100
    table.cell(table1, 0, 4, (ma50_greaterthan_150ma ? '✓' : 'x'), bgcolor = ma50_greaterthan_150ma_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 4,  str.tostring("50 MA > 150 MA"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 4, str.tostring(per50_150,'#.#') + " %", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "Distance between 50 & 150 MA")

// 50MA > 200MA

ma50_greaterthan_200ma = ma50 > ma200

ma50_greaterthan_200ma_color = color.gray
if not ma50_greaterthan_200ma
    ma50_greaterthan_200ma_color := color.red

if na(ma50) or na(ma200)
    ma50_greaterthan_200ma_color := color.gray

if timeframe.isdaily
    per50_200 = (1-(ma50/ma200))*100
    table.cell(table1, 0, 5, (ma50_greaterthan_200ma ? '✓' : 'x'), bgcolor = ma50_greaterthan_200ma_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 5,  str.tostring("50 MA > 200 MA"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 5, str.tostring(per50_200,'#.#') + " %", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "Distance between 50 & 200 MA")


// 150MA > 200MA

ma150_greaterthan_200ma = ma50 > ma200

ma150_greaterthan_200ma_color = color.gray
if not ma150_greaterthan_200ma
    ma150_greaterthan_200ma_color := color.red

if na(ma150) or na(ma200)
    ma150_greaterthan_200ma_color := color.gray

if timeframe.isdaily
    per150_200 = (1-(ma150/ma200))*100
    table.cell(table1, 0, 6, (ma150_greaterthan_200ma ? '✓' : 'x'), bgcolor = ma150_greaterthan_200ma_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 6,  str.tostring("150 MA > 200 MA"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 6, str.tostring(per150_200,'#.#') + " %", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "Distance between 150 & 200 MA")


//200MA trending up

ma200_uptrend = ma200 > ma200_22

ma200_uptrend_color = color.gray
if not ma200_uptrend
    ma200_uptrend_color := color.red

if na(ma200) or na(ma200_22)
    ma200_uptrend_color := color.gray

if timeframe.isdaily
    per200_22 = (1-(ma200/close))*100
    table.cell(table1, 0, 7, (ma200_uptrend ? '✓' : 'x'), bgcolor = ma200_uptrend_color, text_size=textsize, text_color=textcolor)
    table.cell(table1, 1, 7,  str.tostring("200 MA trending up?"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
    table.cell(table1, 2, 7, str.tostring(per200_22,'#.#') + " %", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "Distance from 200 MA")

// 52-week High
price_52wh = request.security(syminfo.tickerid,"1D", ta.highest(high,252), lookahead=barmerge.lookahead_off, gaps = barmerge.gaps_off)

get_all_time_high() =>
    hi  = 0.0
    hi := bar_index == 0 ? high : high > hi[1] ? high : hi[1]
    [hi]

[ath] = request.security(syminfo.tickerid, 'D', get_all_time_high())
if high > ath
    ath := high

if bar_index <= 252
    price_52wh := ath

per_52wh = (1-(price_52wh/close))*100

bgcolor52wh = color.red
per52 = 0
if (per_52wh>-25)
    per52 := 1
    bgcolor52wh := color.gray


table.cell(table1, 0, 8, (per52 ? '✓' : 'x'), bgcolor = bgcolor52wh, text_size=textsize, text_color=textcolor)
table.cell(table1, 1, 8, str.tostring("Within 25% of 52-week High"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
table.cell(table1, 2, 8, str.tostring(price_52wh,'#.#') + " (" + str.tostring(per_52wh,'#.#') + " %" + ")", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "52-week High and % Distance from 52-week High")


// 52-week Low
price_52wl = request.security(syminfo.tickerid,"1D", ta.lowest(low,252), lookahead=barmerge.lookahead_off, gaps = barmerge.gaps_off)

get_all_time_low() =>
    lo  = 0.0
    lo := bar_index == 0 ? low : low < lo[1] ? low : lo[1]
    [lo]

[atl] = request.security(syminfo.tickerid, 'D', get_all_time_low())
if low < atl
    atl := low

if bar_index <= 252
    price_52wl := atl

per_52wl = ((close/price_52wl)-1)*100

bgcolor52wl = color.gray
per52l = 1
if (per_52wl<25)
    per52l := 0
    bgcolor52wl := color.red

table.cell(table1, 0, 9, (per52l ? '✓' : 'x'), bgcolor = bgcolor52wl, text_size=textsize, text_color=textcolor)
table.cell(table1, 1, 9, str.tostring(">25% up from 52-week Low"), bgcolor = color.rgb(6, 192, 224), text_size=textsize, text_color=color.black)
table.cell(table1, 2, 9, str.tostring(price_52wl,'#.#') + " (" + str.tostring(per_52wl,'#.#') + " %" + ")", bgcolor = panelbgcolor, text_size=textsize, text_color=textcolor, tooltip = "52-week Low and % Distance from 52-week Low")


// Does it fulfil Mark Minervini's Criteria?

bgcolor_criteria = color.red
textcolor_satisfy = color.white
fulfil = 0
if close_greaterthan_50ma==1 and close_greaterthan_150ma==1 and close_greaterthan_200ma==1 and ma50_greaterthan_150ma==1 and ma50_greaterthan_200ma==1 and ma150_greaterthan_200ma==1 and ma200_uptrend==1 and per52==1 and per52l==1
    fulfil :=1
    bgcolor_criteria := color.rgb(88, 247, 114)
    textcolor_satisfy := color.black

if timeframe.isdaily
    table.merge_cells(table1,0,10,1,10)
    table.cell(table1, 0, 10, str.tostring("Does it satisfy Minervini's criteria?"), bgcolor = bgcolor_criteria, text_size=textsize, text_color=textcolor_satisfy)
    table.cell(table1, 2, 10, (fulfil ? '✓✓✓' : 'X'), bgcolor = bgcolor_criteria, text_size=textsize, text_color=textcolor_satisfy)


        