Indicator · Pine Script v5 · On the chart

MarketSmith Indicator

by klevler

The MarketSmith Indicator enhances price action visualization by applying custom candle coloring and overlaying configurable moving averages on the main chart.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code2,138
Settings40inputs
LicenceMIT
Last update2 years ago27 Apr 2024

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

2,138 lines of Pine Script v5 from indicators/MarketSmith/MarketSmith.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

MarketSmith.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// 

//@version=5
indicator('MarketSmith Indicator', overlay=true, max_bars_back = 500, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500)

//------------------  BARS ---------------------//
// Color of bars
prevClose   = input(true, title='Color Based On Previous Close',  group='----------BARS----------', inline='x')
i_posColor = input(color.rgb(39, 54,233,0), title='Candle Color Positive', group='----------BARS----------', inline = '1')
i_negColor = input(color.rgb(222,50,174,0), title='Negative', group='----------BARS----------', inline = '1')
colorCandle = close>=open ? i_posColor:i_negColor
if(prevClose)
    colorCandle := close>=close[1] ? i_posColor:i_negColor
// Full Body (without border without wick)
plotcandle(low, high, low, high, title='MarketSmith Bars', color = colorCandle, wickcolor = color.rgb(255,255,255,100), bordercolor = color.rgb(255,255,255,100), editable = true)
// PlotChar - on close
plotchar(close, char='-', location=location.absolute, size=size.small, color=colorCandle, editable = true)

//------------------  SMA's ---------------------//
// Input SMA for Daily TF and others
iSma10    = input(true, title='MA 1',  group='----------SMAs----------', inline='sma10')
iSmaV10   = input(10, title='Lenght',  group='----------SMAs----------', inline='sma10')
iExp10    = input(true, title='Exponential',  group='----------SMAs----------', inline='sma10')
iCol10    = input(color.rgb(68,186,76), title='', group='----------SMAs----------', inline='sma10')
iSma21    = input(true, title='MA 2',  group='----------SMAs----------', inline='sma21')
iSmaV21   = input(21, title='Lenght',  group='----------SMAs----------', inline='sma21')
iExp21    = input(true, title='Exponential',  group='----------SMAs----------', inline='sma21')
iCol21    = input(color.rgb(240,141,240,0), title='', group='----------SMAs----------', inline='sma21')
iSma50    = input(true, title='MA 3',  group='----------SMAs----------', inline='sma50')
iSmaV50   = input(50, title='Lenght',  group='----------SMAs----------', inline='sma50')
iExp50    = input(false, title='Exponential',  group='----------SMAs----------', inline='sma50')
iCol50    = input(color.rgb(255,33,33), title='', group='----------SMAs----------', inline='sma50')
iSma200   = input(true, title='MA 4', group='----------SMAs----------', inline='sma200')
iSmaV200  = input(200, title='Lenght',  group='----------SMAs----------', inline='sma200')
iExp200   = input(false, title='Exponential',  group='----------SMAs----------', inline='sma200')
iCol200    = input(color.rgb(0,0,0,0), title='', group='----------SMAs----------', inline='sma200')

// Input SMA for Weekly TimeFrame
iSma10We    = input(true, title='SMA 1',  group='----------SMAs We----------', inline='sma10We')
iSmaV10We   = input(10, title='Lenght',  group='----------SMAs We----------', inline='sma10We')
iExp10We    = input(false, title='Exponential',  group='----------SMAs We----------', inline='sma10We')
iCol10We    = input(color.rgb(255,33,33), title='', group='----------SMAs We----------', inline='sma10We')
iEma20We    = input(true, title='EMA 2',  group='----------SMAs We----------', inline='ema20We')
iSmaV20We   = input(20, title='Lenght',  group='----------SMAs We----------', inline='ema20We')
iExp20We    = input(true, title='Exponential',  group='----------SMAs We----------', inline='ema20We')
iCol20We    = input(color.rgb(240,141,240,0), title='', group='----------SMAs We----------', inline='ema20We')
iSma30We    = input(true, title='SMA 3',  group='----------SMAs We----------', inline='sma30We')
iSmaV30We   = input(30, title='Lenght',  group='----------SMAs We----------', inline='sma30We')
iExp30We    = input(false, title='Exponential',  group='----------SMAs We----------', inline='sma30We')
iCol30We    = input(color.rgb(68,186,76), title='', group='----------SMAs We----------', inline='sma30We')
iSma40We    = input(true, title='SMA 4',  group='----------SMAs We----------', inline='sma40We')
iSmaV40We   = input(40, title='Lenght',  group='----------SMAs We----------', inline='sma40We')
iExp40We    = input(false, title='Exponential',  group='----------SMAs We----------', inline='sma40We')
iCol40We    = input(color.rgb(0,0,0,0), title='', group='----------SMAs We----------', inline='sma40We')


// SMA calculation Daily & others TF
sma10  = iExp10  ? ta.ema(close,iSmaV10) :ta.sma(close,iSmaV10)
sma21  = iExp21  ? ta.ema(close,iSmaV21) :ta.sma(close,iSmaV21)
sma50  = iExp50  ? ta.ema(close,iSmaV50) :ta.sma(close,iSmaV50)
sma200 = iExp200 ? ta.ema(close,iSmaV200):ta.sma(close,iSmaV200)

// SMA calculation We
sma10We  = iExp10We ? ta.ema(close,iSmaV10We):ta.sma(close,iSmaV10We)
ema20We  = iExp20We ? ta.ema(close,iSmaV20We):ta.sma(close,iSmaV20We)
sma30We  = iExp30We ? ta.ema(close,iSmaV30We):ta.sma(close,iSmaV30We)
sma40We  = iExp40We ? ta.ema(close,iSmaV40We):ta.sma(close,iSmaV40We)

// Ploting SMA/EMA Daily and other TF
tfWeekly = timeframe.isweekly
psma10  = plot(iSma10 and not tfWeekly ?  sma10:na,  linewidth=1, color=iCol10)
pema21  = plot(iSma21 and not tfWeekly ?  sma21:na,  linewidth=1, color=iCol21)
psma50  = plot(iSma50 and not tfWeekly ?  sma50:na,  linewidth=1, color=iCol50)
psma200 = plot(iSma200 and not tfWeekly ? sma200:na, linewidth=1, color=iCol200)

// Ploting SMA/EMA We
psma10We =  plot(iSma10We and tfWeekly  ? sma10We:na, linewidth=1, color=iCol10We)
pema20We =  plot(iEma20We and tfWeekly  ? ema20We:na, linewidth=1, color=iCol20We)
psma30We =  plot(iSma30We and tfWeekly  ? sma30We:na, linewidth=1, color=iCol30We)
psma40We =  plot(iSma40We and tfWeekly  ? sma40We:na, linewidth=1, color=iCol40We)

//------------------  RS Rating  ---------------------// and // SP500 -> 0S&P5 //

//Relative Price Strength (RS) Rating or Relative Strenght.
//This is a measure of a stock's price performance over the last
//twelve months, compared to all stocks in IBD's Database.
//The rating scale ranges frome 1 (lowest) to 99 (highest)
//At least this is the IBD proprietary rating's defintion.
//Let's create an equivalent here for TradingView!
//
// © RaviYendru thanks for providing the intial script
// Fred6724 - Let's see if it is possible to get better results

// Constant Value
comparativeTickerId = 'SP:SPX'  // For RS Score Calculation, the SPX Value only makes sens because of the GitHub project


hideRSLine  = input(false, title='Hide RS Line', group='----------RS Rating----------', inline='0')
hideRSRat   = input(false, title='Hide Rating', group = '----------RS Rating----------', inline='0')
//seedetail   = input(false, title='Display the 3 results', group = 'Parameters', inline='0')
ratingOnly  = input(false, title='Rating Only', group = '----------RS Rating----------')
lineTicker  = input('SP:SPX', title='Comparative Symbol for Line', group = '----------RS Rating----------', tooltip = 'Reference ticker used for calculation of the RS Line.')
SpxValue    = input(4200, title='Value of Comparative Symbol', group = '----------RS Rating----------', tooltip = 'Used to gather a constant value')
offset      = input.int(80, minval = 0, maxval = 300, title='Offset (%)', group = '----------RS Rating----------', tooltip = 'Used to display the RS Line under the price.')
colorRS     = input(color.rgb(0, 0, 255), title = 'Color of RS Line & Rating', group = '----------RS Rating----------')
plotNewHigh = input(true, title = 'Plot RS New Highs', group = '----------RS Rating----------')
rsNewHigh   = input.string('RS New Highs', title = 'Type', options=['RS New Highs','RS New Highs Before Price', 'Historical RS New Highs', 'Historical RS New Highs  Before Price'], group = '----------RS Rating----------')
blueDotCol  = input(color.rgb(121, 213, 242,62), title = 'Color of Dots', group = '----------RS Rating----------')
lookback    = input.int(250, title = 'Look-back', minval = 1, maxval = 252, group = '----------RS Rating----------', tooltip = 'The lookback for calculation of price and RS New Highs.')
sizeLabHigh = input.string('Tiny', title = 'Size', options = ['Tiny', 'Small', 'Normal', 'Large'], group = '----------RS Rating----------')
plotNewLow  = input(false, title = 'Plot RS New Lows', group = '----------RS Rating----------')
rsNewLow    = input.string('Historical RS New Lows', title = 'Type', options=['RS New Lows','RS New Lows Before Price', 'Historical RS New Lows', 'Historical RS New Lows  Before Price'], group = '----------RS Rating----------')
redDotCol   = input(color.rgb(255, 82, 82, 62), title = 'Color', group = '----------RS Rating----------')
lookback2   = input.int(250, title = 'Look-back', minval = 1, maxval = 252, group = '----------RS Rating----------', tooltip = 'The lookback for calculation of price and RS New Lows.')
sizeLabLow  = input.string('Tiny', title = 'Size', options = ['Tiny', 'Small', 'Normal', 'Large'], group = '----------RS Rating----------')
boolMa      = input(false, title = 'Display MA 1 on RS Line', group = '1st MA on RS Line')
lenMa       = input(21, title = 'Lenght Da', group = '1st MA on RS Line', inline = 'c')
colMa       = input(color.orange, title = 'Color', group = '1st MA on RS Line', inline = 'c')
typMa       = input.string('EMA', title = 'Type Da', options = ['SMA', 'EMA'], group = '1st MA on RS Line', inline = 'c')
lenMaWe     = input(10, title = 'Lenght We', group = '1st MA on RS Line', inline = 'c')
typMaWe     = input.string('SMA', title = 'Type We', options = ['SMA', 'EMA'], group = '1st MA on RS Line', inline = 'c')
fillMa      = input(false, title = 'Area Color', group = '1st MA on RS Line')
posCol      = input(color.rgb(0, 230, 119, 75), title = 'Positive Area', group = '1st MA on RS Line', inline = 'd')
negCol      = input(color.rgb(255, 82, 82, 75),  title = 'Negative Area', group = '1st MA on RS Line', inline = 'd')
boolMa2     = input(false, title = 'Display MA 2 on RS Line', group = '2nd MA on RS Line')
lenMa2      = input(50, title = 'Lenght Da', group = '2nd MA on RS Line', inline = 'c')
colMa2      = input(color.red, title = 'Color', group = '2nd MA on RS Line', inline = 'c')
typMa2      = input.string('EMA', title = 'Type Da', options = ['SMA', 'EMA'], group = '2nd MA on RS Line', inline = 'c')
lenMa2We    = input(21, title = 'Lenght We', group = '2nd MA on RS Line', inline = 'c')
typMa2We    = input.string('SMA', title = 'Type We', options = ['SMA', 'EMA'], group = '2nd MA on RS Line', inline = 'c')
allowReplay = input(false, title = 'Use fix values for replay mode', group = 'RS Replay mode (Approximate Method)', tooltip = 'Here we use constant values in order to provide the environment regardless of the date. See RSRATING ticker and report close values to have the last data.')
first2      = input(195.93, title='For 99 stocks' , group = 'RS Replay mode (Approximate Method)')
scnd2       = input(117.11, title='For 90+ stocks', group = 'RS Replay mode (Approximate Method)')
thrd2       = input(99.04, title='For 70+ stocks' , group = 'RS Replay mode (Approximate Method)')
frth2       = input(91.66, title='For 50+ stocks' , group = 'RS Replay mode (Approximate Method)')
ffth2       = input(80.96, title='For 30+ stocks' , group = 'RS Replay mode (Approximate Method)')
sxth2       = input(53.64, title='For 10+ stocks' , group = 'RS Replay mode (Approximate Method)')
svth2       = input(24.86, title='For 1- stocks'  , group = 'RS Replay mode (Approximate Method)')

// Blue Dot
// If Blue Dot is ste to 250 Da, than we want it to be set on 52 We on the Weekly TimeFrame
if (lookback  == 250 and timeframe.isweekly)
    lookback  := 52
if (lookback2 == 250 and timeframe.isweekly)
    lookback2 := 52

// Switch Label Size
highLabel = switch sizeLabHigh
    'Normal'  => size.normal
    'Tiny'    => size.tiny
    'Small'   => size.small
    'Large'   => size.large

lowLabel  = switch sizeLabLow
    'Normal'  => size.normal
    'Tiny'    => size.tiny
    'Small'   => size.small
    'Large'   => size.large

// Using bar index in case of IPO to avoid NaN results
// Added max_bars_max = 253 to improve display speed
n63      = bar_index < 63  ? bar_index:63 
n126     = bar_index < 126 ? bar_index:126
n189     = bar_index < 189 ? bar_index:189
n252     = bar_index < 252 ? bar_index:252


// Comparative Ticker for RS Line
comparativeSymbol   = request.security(lineTicker, timeframe.period, close)
// RS Line but multiplied by a little bit less than the constant value of the comparative ticker for correct display
rsCurve             = (close/comparativeSymbol)
// Adapt Ratio for Sectors and Indices
if (syminfo.industry == 'Investment Trusts/Mutual Funds')
    offset := 90
// We use a wider offset for Weekly timeframe for a smoother display
rsRatio             = timeframe.isweekly ? SpxValue*(offset-10)/100:SpxValue*offset/100
rs                  = rsCurve*rsRatio
prevlookback  = lookback
prevlookback2 = lookback2 // For RS New Lows
lookback := math.min(lookback - 1, bar_index)
rsPlot = plot(hideRSLine ? na:rs, title='RS Line', style=plot.style_line, linewidth=1, color=colorRS)

// 1st MA on RS Line
// SMA and EMA
rsMA      = ta.sma(rs, lenMa)
if(typMa == 'SMA' and not timeframe.isweekly)
    rsMA      := ta.sma(rs, lenMa)
if(typMa == 'EMA' and not timeframe.isweekly)  
    rsMA      := ta.ema(rs, lenMa)
if(typMaWe == 'SMA' and timeframe.isweekly)
    rsMA      := ta.sma(rs, lenMaWe)
if(typMaWe == 'EMA' and timeframe.isweekly)
    rsMA      := ta.ema(rs, lenMaWe)

maPlot    = plot(boolMa ? rsMA :na,    color = colMa, linewidth = 1)

// Color Filling
// I will use an invisible MA to be able to choose or not the display of the fill
maPlot2    = plot(boolMa and fillMa ? rsMA:na,    color = color.rgb(0,0,0,100), linewidth = 1)
// This variable gets the color that will be used for the fill
fillCol = rs > rsMA ? posCol:negCol
// Here if a MA is missing, there is no fill
fill(rsPlot, maPlot2 ,   color=fillCol)

// 2nd MA on RS Line
// SMA and EMA
rsMA2      = ta.sma(rs, lenMa2)
if (typMa2 == 'SMA' and not timeframe.isweekly)
    rsMA2      := ta.sma(rs, lenMa2)
if (typMa2 == 'EMA' and not timeframe.isweekly)  
    rsMA2      := ta.ema(rs, lenMa2)
if (typMa2We == 'SMA' and timeframe.isweekly)
    rsMA2      := ta.sma(rs, lenMa2We)
if (typMa2We == 'EMA' and timeframe.isweekly)
    rsMA2      := ta.ema(rs, lenMa2We)

maPlot3  = plot(boolMa2 ? rsMA2 :na,    color = colMa2, linewidth = 1)



// Historical New Highs & New Highs Before Price
var label newHigh = na
histNH = ta.highest(rs  , prevlookback)
histCl = ta.highest(high, prevlookback)
// Historical RS New High
if(rsNewHigh == 'Historical RS New Highs' and plotNewHigh and rs == histNH)
    newHigh := label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = highLabel)
// Historical RS New High Before Price
if(rsNewHigh == 'Historical RS New Highs  Before Price' and plotNewHigh and rs == histNH and high < histCl)
    newHigh := label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = highLabel)
// RS New High
if(barstate.islast and rsNewHigh == 'RS New Highs' and plotNewHigh and rs == histNH)
    label.delete(newHigh)
    newHigh := label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = highLabel)
// RS New High Before Price
if(barstate.islast and rsNewHigh == 'RS New Highs Before Price' and plotNewHigh and rs == histNH and high < histCl)
    label.delete(newHigh)
    newHigh := label.new(x = bar_index, y = rs, color = blueDotCol, style = label.style_circle, size = highLabel)


// Historical New Lows & New Lows Before Price
var label newLow  = na
histNL  = ta.lowest(rs , prevlookback2)
histClL = ta.lowest(low, prevlookback2)
// Historical RS New Low
if(rsNewLow == 'Historical RS New Lows' and plotNewLow and rs == histNL)
    newLow := label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = lowLabel)
// Historical RS New Low Before Price
if(rsNewLow == 'Historical RS New Lows  Before Price' and plotNewLow and rs == histNL and low > histClL)
    newLow := label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = lowLabel)
// RS New Low
if(barstate.islast and rsNewLow == 'RS New Lows' and plotNewLow and rs == histNL)
    label.delete(newLow)
    newLow := label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = lowLabel)
// RS New Low Before Price
if(barstate.islast and rsNewLow == 'RS New Lows Before Price' and plotNewLow and rs == histNL and low > histClL)
    label.delete(newLow)
    newLow := label.new(x = bar_index, y = rs, color = redDotCol, style = label.style_circle, size = lowLabel)



// Calculation of the RS Rating
// Getting ticker and reference ticker daily data
closeDa    = request.security(syminfo.tickerid,    'D', close)
spxCloseDa = request.security(comparativeTickerId, 'D', close)

// Calculation of the performance from 1 to 4 last quarters
// Ticker
perfTicker63   = closeDa/closeDa[n63]
perfTicker126  = closeDa/closeDa[n126]
perfTicker189  = closeDa/closeDa[n189]
perfTicker252  = closeDa/closeDa[n252]

// SP500 of reference ticker
perfComp63     = spxCloseDa/spxCloseDa[n63]
perfComp126    = spxCloseDa/spxCloseDa[n126]
perfComp189    = spxCloseDa/spxCloseDa[n189]
perfComp252    = spxCloseDa/spxCloseDa[n252]

// Using Formula to calculate a relative score of the ticker and the SP500 with the last quarter weighted double
float rs_stock = 0.4*perfTicker63 + 0.2*perfTicker126 + 0.2*perfTicker189 + 0.2*perfTicker252
float rs_ref   = 0.4*perfComp63   + 0.2*perfComp126   + 0.2*perfComp189   + 0.2*perfComp252

// Calculation of the total relative score or rs performance
float totalRsScore  = (rs_stock) / (rs_ref) * 100
float totalRsRating = -1

// Here we calculated the relative score of the stock. The goal is now to assign the percentile correctly
// For this I took the curve given by my fork repo of Skyte on Rs Log and tried to calibrate the better possible
// the output curve of the relative performance of the 6,6xx stocks.
// Link: https://github.com/Fred6725/rs-log/blob/main/output/rs_stocks.csv
// Here is the curve in ASCII Art; on the x-axis, the Rs Rating and on the y-axis, the calculated performance.
      
//                      
//                                                                                        /                               
//                                                                                        /                               
//                                                                                        /                               
//                                                                                        /                               
//,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,/,,,,,,,,,,,,,,,,,              
//                                                                                        /                               
//                                                                                        /                               
//                                                                                        /                               
//                                                                                        /                               
//                                                                                       |                               
//                                                                                       /                               
//                                                                                      ‾                                 
//                                                                                     ‾                                   
//                                                                                   -‾                                    
//                                                                           _____, ‾                                     
//                                         _____----------------‾‾‾‾‾‾‾‾‾‾‾‾‾                                                   
//                        __ */‾‾‾‾‾‾‾‾‾‾‾‾                                                                                       
//             __ ,,----‾‾                                                                                                 
//          _/                                                                                                           
//        /                                                                                                               
//       |                                                                                                     
// ______|________________ _______________________________ _____________________________________            
//       |0               |20             |40             |60             |80              |100   
//
// I decided to cut this curve in 7 different levels that needs to be entered each day.
// These are relative strength scores corresponding to percentiles 98, 89, 69, 49, 29, 9 and 1.
// Finally I used the request.seed() function to auto update these levels automatically on a daily basis.
// Everything is managed in this repo if you're curious:
// https://github.com/Fred6725/relative-strength/tree/main    (Fork from Skyte)
// More precisly in rs_ranking.py for extracting what I needed and in workflows/output.yml for the auto update.
// The update is done in the private fork of the seed tradingview original repo, checked and synchronised automatically
// I tried to uplad the full 6,6xx list of relative strength score and rs rating but the display speed was too long.


// Use the request.seed() function to access the RS Score environment of all the market
curveRsPerf  = request.seed('seed_fred6725_rs_rating', 'RSRATING', close)

// To prevent loosing data because of week-ends and public holidays I decided to send the value 5 times in a row.
// Which gives 5*7 = 35 bars.
// Depending of the day we look at the graph we will have a variable amount of bars. 
// The goal is to get these 7 numbers anyway.

// In case the graph is not updated, we count the number of bars since we have the first data.
// Calculation of the number of bar since we have the first data
delta  = ta.barssince(na(curveRsPerf)!=true)

// Table to store the different values
var float[] different_values = array.new_float(7)

// Counter for stored values
var int counter = 0

// Variable for storage of the environment
float first = 0
float scnd  = 0
float thrd  = 0
float frth  = 0
float ffth  = 0
float sxth  = 0
float svth  = 0

// Browse seed's values and store the first 7 different values
if (not allowReplay)
    for i = delta to 34+delta
        close_value = nz(curveRsPerf[i])
        if (not array.includes(different_values, close_value) and counter < 7 and close_value!=0)
            array.set(different_values, counter, close_value)
            counter := counter + 1

    // Assign stored values to variables
    first := array.get(different_values, 0)
    scnd  := array.get(different_values, 1)
    thrd  := array.get(different_values, 2)
    frth  := array.get(different_values, 3)
    ffth  := array.get(different_values, 4)
    sxth  := array.get(different_values, 5)
    svth  := array.get(different_values, 6)

// Replay mode
if (allowReplay)
    first := first2
    scnd  := scnd2 
    thrd  := thrd2 
    frth  := frth2 
    ffth  := ffth2 
    sxth  := sxth2 
    svth  := svth2 

// Now that we've recovered the environment, we can assign a percentile using a simple linear approximation of the curve (+ adjustment).
if(totalRsScore >= first)
    totalRsRating := 99
if(totalRsScore <= svth)
    totalRsRating := 1

// Function to attribute the percentile with a simple linear approximation
f_attributePercentile(totalRsScore, tallerPerf, smallerPerf, rangeUp, rangeDn, weight) =>
    sum = totalRsScore + (totalRsScore-smallerPerf)*weight // weight is used for manual calibration
    if(sum > tallerPerf - 1)
        sum := tallerPerf - 1
    k1 = smallerPerf/rangeDn
    k2 = (tallerPerf-1)/rangeUp
    k3 = (k1-k2)/(tallerPerf-1-smallerPerf)
    RsRating = sum/(k1-k3*(totalRsScore-smallerPerf))
    if (RsRating > rangeUp)
        RsRating := rangeUp
    if (RsRating < rangeDn)
        RsRating := rangeDn
    RsRating

// Between 199 & 120 the score where approx 98 to 90.
if(totalRsScore < first and totalRsScore >= scnd)
    totalRsRating := f_attributePercentile(totalRsScore, first, scnd, 98, 90, 0.33)
// Between 119 and 100 we ave scores between 89 and 70.
if (totalRsScore < scnd and totalRsScore >= thrd)
    totalRsRating := f_attributePercentile(totalRsScore, scnd, thrd, 89, 70, 2.1)
// Between 100 and 91 we ave scores between 69 and 50.
if (totalRsScore < thrd and totalRsScore >= frth)
    totalRsRating := f_attributePercentile(totalRsScore, thrd, frth, 69, 50, 0)
// Between 90 and 82 we ave scores between 49 and 30.
if (totalRsScore < frth and totalRsScore >= ffth)
    totalRsRating := f_attributePercentile(totalRsScore, frth, ffth, 49, 30, 0)
// Between 81 and 56 we ave scores between 29 and 10.
if (totalRsScore < ffth and totalRsScore >= sxth)
    totalRsRating := f_attributePercentile(totalRsScore, ffth, sxth, 29, 10, 0)
// Between 55 and 28 we ave scores between 9 and 2.
if (totalRsScore < sxth and totalRsScore >= svth)
    totalRsRating := f_attributePercentile(totalRsScore, sxth, svth, 9, 2, 0)


// Check if one of this value is empty for replay mode
for i = 0 to 6
    if (nz(array.get(different_values, i)) == 0 and not allowReplay)
        totalRsRating := -1


// Display the RS Rating
// The results can only be used in Daily TimeFrame
isDaily = timeframe.isdaily
labelText1 = '                RS Rating'
labelText2 = ''
// Here we want to display 'RS' without value if one of the constants is missing
if(isDaily and totalRsRating != -1)
    labelText2 := '\n\n       '+str.tostring(totalRsRating,'#0')
// Rating Only
if (ratingOnly)
    labelText1 := ''
    labelText2 := '\n    '+str.tostring(totalRsRating,'#0')
// Display the labels
label1 = (hideRSRat == false) and barstate.islast ? label.new(bar_index, rs, text=labelText1 , color = color.rgb(0,0,0,100), size=size.normal, textcolor=colorRS, style=label.style_label_center, textalign=text.align_left, yloc=yloc.price) : na
label2 = (hideRSRat == false) and barstate.islast ? label.new(bar_index, rs, text=labelText2 , color = color.rgb(0,0,0,100), size=size.large,  textcolor=colorRS, style=label.style_label_center, textalign=text.align_left, yloc=yloc.price) : na

// Delete previous Labels (When new candle opens or when replay mode, the labels were piling on)
label.delete(label1[1])
label.delete(label2[1])


// Weekly Tight Closes Detector
//input
WtClose          = input(false, title='Weekly Tight Closes Detector', group='TIGHT CLOSES DETECTOR')
colorTightCloses = input(color.aqua, title='Color of Tight Closes Boxes', group='TIGHT CLOSES DETECTOR')
// Calculation
if(tfWeekly)
    // Open
    WkO2   = open[2]
    //Closes
    WkC    = close
    WkC1   = close[1]
    WkC2   = close[2]
    // Highs
    WkH    = high
    WkH1   = high[1]
    WkH2   = high[2]
    // Lows
    WkL    = low
    WkL1   = low[1]
    WkL2   = low[2]
    // WEMA
    Wema10 = ta.ema(close,10)
    Wema20 = ta.ema(close,20)
    // ATR Weekly (Used to have an auto-adaptive tight closes detector. Formula = Averages High-Low of the 14 previous bars. (Volatility measurement)
    atr    = ta.atr(14)
    // Conditions (I like to have 3 tiny candle with tight closes so I add High and Low cond as well)
    condTightClose = WkC < WkC1+(WkC1*atr/(close*2)) and WkC > WkC1-(WkC1*atr/(close*2)) and WkC1 < WkC2+(WkC2*atr/(close*2)) and WkC1 > WkC2-(WkC2*atr/(close*2)) and WkC < WkC2+(WkC2*atr/(close*2)) and WkC > WkC2-(WkC2*atr/(close*2))
    condTightHigh = WkH < WkH1+(WkH1*atr/(close*2)) and WkH > WkH1-(WkH1*atr/(close*2)) and WkH1 < WkH2+(WkH2*atr/(close*2)) and WkH1 > WkH2-(WkH2*atr/(close*2))
    condTightLow = WkL < WkL1+(WkL1*atr/(close*2)) and WkL > WkL1-(WkL1*atr/(close*2)) and WkL1 < WkL2+(WkL2*atr/(close*2)) and WkL1 > WkL2-(WkL2*atr/(close*2))
    //condNotLowerLows  = WkL2 > WkL1 and WkL1 > WkL
    // I would like the script not to show me 3 tight candles when the first candle of the three is nearly full and big
    // For that I wrote that the total size of the weekly wick of the candle must be 2 times bigger than the body
    // But I noticed somtimes very small candle with little or no wick are still valide so added an exception ! (Yes it is far-fetched)
    condFirstCandle = false
    // For positive bars
    if(WkC2 >= WkO2)
        condFirstCandle := WkH2 - WkC2 + WkO2 - WkL2 > 2*(WkC2 - WkO2) or (WkH2-WkL2<WkH1-WkL1)
    // For negative bars
    if(WkC2 < WkO2)
        condFirstCandle := WkH2 - WkO2 + WkC2 - WkL2 > 2*(WkO2 - WkC2) or (WkH2-WkL2<WkH1-WkL1)
    // All condition together
    condTot3WTight = condTightClose and (condTightHigh or condTightLow) and condFirstCandle //and not condNotLowerLows


    //Plot Boxes Arround Weekly Tight Closes
    highestW = ta.highest(WkH,3)
    lowestW  = ta.lowest (WkL,3)
    if(condTot3WTight and WtClose)
        box.new(bar_index[2], highestW, bar_index, lowestW, border_color = color.new(colorTightCloses,20), border_width = 1, border_style=line.style_dotted, bgcolor = color.new(colorTightCloses,85))



//------------------  Marked Highs and Lows  ---------------------//

// Price Peak/Valley Points
// Highlights exact price at high or low points over a 19-period interval.
// For example, on a Daily chart, a High Price point is marked on the date
// where there has been no higher price the 9 days prior to that date and
// the 9 days following that date.

// Inputs
i_displayHL = input(true, title='Display H/L Points', group='High/Low Price Points')
i_colorHL   = input(color.rgb(0,0,0,0), title='Labels Color', group='High/Low Price Points')
i_displayPc = input(false, title='%Change', group='High/Low Price Points')
i_colorPctP = input(color.rgb(0, 0, 255), title='Positive % Color', group='High/Low Price Points', inline = 'z')
i_colorPctN = input(color.rgb(222,50,174,0), title='Negative %', group='High/Low Price Points', inline = 'z')
i_pivot     = input(9, title='Length for peak/valey points', group='High/Low Price Points')

// Definr arrays to store pivot values
var pivotHighValues = array.new_float(0)
var pivotLowValues  = array.new_float(0)

if(i_displayHL and not tfWeekly)
    // Use the function ta.pivothigh/low()
    pivotHigh = ta.pivothigh(high, i_pivot, i_pivot)
    pivotLow  = ta.pivotlow (low,  i_pivot, i_pivot)
    // High Price Point
    if(pivotHigh)
        array.unshift(pivotHighValues, high[i_pivot])
        textHigh9   = i_displayPc ? str.tostring(high[i_pivot], '0.00')+'\n':str.tostring(high[i_pivot], '0.00')
        highestHigh = label.new(bar_index-i_pivot, array.get(pivotHighValues, 0), xloc=xloc.bar_index, yloc=yloc.price, style=label.style_none, text=textHigh9, textcolor=i_colorHL)
    // Low Price Point
    if(pivotLow)
        array.unshift(pivotLowValues, low[i_pivot])    //low[i_pivot]
        textLow9    = '\n' + str.tostring(low[i_pivot], '0.00')
        lowestLow   = label.new(bar_index-i_pivot, array.get(pivotLowValues, 0), xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_center, text=textLow9, textcolor=i_colorHL, color=color.rgb(0,0,0,100))
    // Percentage Variation
    float pHigh = na
    float pLow  = na
    if array.size(pivotHighValues) > 0
        pHigh := array.get(pivotHighValues, 0)
    if array.size(pivotLowValues) > 0
        pLow  := array.get(pivotLowValues, 0)
    prcVarHigh = (pHigh - pLow)/pLow * 100
    prcVarLow  = (pLow/pHigh - 1) * 100  // Formula to calculate percentage decline
    prcVarHighText = prcVarHigh>=0 ? '+'+str.tostring(prcVarHigh, '0.0') + '%':str.tostring(prcVarHigh, '0.0') + '%'
    prcVarLowText  = prcVarLow>=0 ? '+'+str.tostring(prcVarLow , '0.0') + '%':str.tostring(prcVarLow, '0.0') + '%'
    colorPctUp = prcVarHigh>=0 ? i_colorPctP:i_colorPctN
    colorPctDn = prcVarLow >=0 ? i_colorPctP:i_colorPctN
    // High Price Point Percent Variation 
    if(pivotHigh and i_displayPc)
        pctPivotHigh = na(prcVarHigh)==true ? na:label.new(bar_index-i_pivot, array.get(pivotHighValues, 0), xloc=xloc.bar_index, yloc=yloc.price, style=label.style_none, text=prcVarHighText, textcolor=colorPctUp)
    if(pivotLow and i_displayPc)
        pctPivotLow  = na(prcVarLow)==true ? na:label.new(bar_index-i_pivot, array.get(pivotLowValues, 0), xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_center, text='\n\n\n' + prcVarLowText, textcolor=colorPctDn, color=color.rgb(0,0,0,100))




//------------------  Chart Pattern Recognition  ---------------------//


// INPUTS
i_displayPattern         = input(true,  title='Display Pattern',                group='Chart Pattern Recognition')
i_displayBoxes           = input(true,  title='Display Trade Boxes',            group='Chart Pattern Recognition')
i_displayHistoricalBoxes = input(false, title='Display Historical Trade Boxes', group='Chart Pattern Recognition')
i_baseDepth              = input(50,    title='Base: Depth (%)',                group='Chart Pattern Recognition', inline='Parameters Base')
i_baseLength             = input(65,    title='Length (Weeks)',                 group='Chart Pattern Recognition', inline='Parameters Base')
i_dbDepth                = input(50,    title='Double Bottom: Depth (%)',       group='Chart Pattern Recognition', inline='Parameters DB')
i_dbLength               = input(65,    title='Length (Weeks)',                 group='Chart Pattern Recognition', inline='Parameters DB')

// FUTURE PART TO HANDLE WE TF
i_baseDepth  := i_baseDepth  /100
i_dbDepth    := i_dbDepth    /100
// if (timeframe.isdaily)
i_baseLength := i_baseLength *5
i_dbLength   := i_dbLength   *5
// if (timeframe.isweekly)
    // i_pivot := 2


// ARRAYS
// PIVOTS
var pivotHighPrices      = array.new_float(0)
var pivotLowPrices       = array.new_float(0)
// BASE PATTERN
// Prices
var startBasePrice       = array.new_float(0)
var lowBasePrice         = array.new_float(0)
var lowOfpivotHighPrices = array.new_float(0)
var float lowOfBaseHigh  = 0
// Bars
var int startBaseBar     = 0
var int lowerBaseBar     = 0
var pivotHighBars        = array.new_int(0)
var pivotLowBars         = array.new_int(0)
// DOUBLE BOTTOM PATTERN
// Prices
var topDBPrice           = array.new_float(0)
var bottomDBPrice        = array.new_float(0)
// Bars
var int topDBBar         = 0
var int bottomDBBar      = 0
// CUP PATTERN
var baseCloses           = array.new_float(0)


// PIVOTS HIGH/LOW
// Use the function ta.pivothigh/low()
pivotHigh = ta.pivothigh(high, i_pivot, i_pivot)
pivotLow  = ta.pivotlow (low,  i_pivot, i_pivot)
// When it occurs, store key points values in arrays
if (pivotHigh)
    array.unshift(pivotHighPrices, high[i_pivot])
    array.unshift(lowOfpivotHighPrices, low[i_pivot])
    array.unshift(pivotHighBars, bar_index[i_pivot])
if (pivotLow)
    array.unshift(pivotLowPrices, low[i_pivot])
    array.unshift(pivotLowBars, bar_index[i_pivot])


// Calculation for the conditions of base detection (out of scope)
boolHighbase   = false
boolHigherPiv  = false
highestOfBase  = ta.highest(high, 25 )
highestOfComp  = ta.highest(high, 50 )
lowestBaseLow  = ta.lowest (low , 25 )
lowestPointLeg = ta.lowest (low , 103)
var baseCond   = false
isBase         = false


// CONDITIONS FOR BASE DETECTION (Consolidation: (6 to 65 weeks)(8% to 50%)  Flat Base: (5 to 65 week) (0% with a maximum of 15%)
if(array.size(pivotHighPrices) > 2)
    // In case the base is made of multiple Pivots High without Pivot Low
    boolHighbase  := high[25]==array.get(pivotHighPrices, 0) or  high[25]==array.get(pivotHighPrices, 1) or high[25]==array.get(pivotHighPrices, 2)
    boolHigherPiv := high[25]>=highestOfComp
    // Minimal Leg Up Calculation
    legUp          = lowestPointLeg * 1.20  // 20%
    legUpCond      = high[25] >= legUp
    // Maximal Base Depth
    firstBaseDepth = high[25] * (1-i_baseDepth)  <= lowestBaseLow
    // No candle is above high[25]
    noCandleAbove  = highestOfBase <= high[25]
    // The candle of the begining of the base isn't in a previous base
    noBaseInBase   = isBase[25] == false
    // Every Conditions with spikes for detection
    baseCond := boolHighbase and boolHigherPiv and legUpCond and firstBaseDepth and noCandleAbove and noBaseInBase
// If Base Detected we store key points
lowestBar = ta.barssince(low==lowestBaseLow)
if (baseCond and not isBase[1])
    array.unshift(startBasePrice, high[25])
    startBaseBar := bar_index[25]
    array.unshift(lowOfpivotHighPrices, low[25])
    lowOfBaseHigh := low[25]
    array.unshift(lowBasePrice    , lowestBaseLow)
    lowerBaseBar := bar_index[lowestBar] // Needs to be incremented and reset when base is over
    // Get every close of the Base for Cup Detection
    for i = 0 to 25
        array.unshift(baseCloses, close[i])


// Bool for base that is true while the base is still valid
if (baseCond or isBase[1])
    isBase := true

// Candle Base Counter
var int baseCount    = 0
// When a base is detected, reset the bar count
if (baseCond and not isBase[1])
    baseCount := bar_index-startBaseBar
// Increment the bar count if we are in a base
if (isBase)
    baseCount     := baseCount + 1

// Boolean for Trades Box Gestion
isBox   = false
boxOver = true
if(isBox[1] and not boxOver[1])
    isBox := true
 
// CONDITIONS FOR DOUBLE BOTTOM DETECTION (10% to 50%) (7 to 65 weeks)
detectDoubleBottom = false
if(isBase)
    if (array.size(pivotHighPrices) > 1 and array.size(pivotLowPrices) > 1)
        firstPivHigh = array.get(pivotHighPrices, 1)
        scndPivHigh  = array.get(pivotHighPrices, 0)
        firstPivLow  = array.get(pivotLowPrices, 1)
        scndPivLow   = array.get(pivotLowPrices, 0)
        // Price Conditions
        condPricesA  = firstPivHigh > scndPivHigh and firstPivLow*0.97 > scndPivLow and firstPivLow < scndPivHigh
        condPricesB  = scndPivLow >= (1-i_dbDepth) * firstPivHigh                        // Depth Condition
        condPricesC  = scndPivLow <= 0.9       * firstPivHigh
        condPricesD  = (firstPivHigh-scndPivLow) * 0.6  + scndPivLow <= scndPivHigh   // Buy point is above 60% of the base
        condPricesE  = (firstPivHigh-scndPivLow) * 0.95 + scndPivLow >= scndPivHigh // Buy point is at least under 10% of the high of the base
        condPricesF  = (firstPivHigh-firstPivLow)/(scndPivHigh-scndPivLow) >= 0.70
        condPricesG  = (firstPivHigh-firstPivLow)/2 + firstPivLow <= scndPivHigh // The first up leg of the first V must retrace at least 50% of the first down leg
        condPricesH  = true
        if (array.size(startBasePrice) > 0)
            condPricesH  := firstPivHigh == array.get(startBasePrice, 0)
        // Assigned in order of Time
        firstPivTime = array.get(pivotHighBars, 1)
        scndPivTime  = array.get(pivotLowBars, 1)
        thrdPivTime  = array.get(pivotHighBars, 0)
        frthPivTime  = array.get(pivotLowBars, 0)
        // Time Conditions
        condTimeA    = firstPivTime < scndPivTime and scndPivTime < thrdPivTime and thrdPivTime < frthPivTime
        condTimeB    = frthPivTime - firstPivTime <= 100
        condTimeC    = (thrdPivTime-firstPivTime) * 2 >= (bar_index-thrdPivTime) // Pattern Propreties A-C x 2 > E-D
        condTimeD    = (thrdPivTime-firstPivTime) <= (bar_index-thrdPivTime) * 2 // Same as above but for the other side
        // Here we use bars between the two first legs. For the 2 last legs it will be done later as the pattern is being created
        condTimeE    = scndPivTime-firstPivTime <= 2 * (thrdPivTime-scndPivTime) and thrdPivTime-scndPivTime <= (scndPivTime-firstPivTime) * 2
        condTimeF    = frthPivTime-thrdPivTime <= 2 * (thrdPivTime-scndPivTime)  and frthPivTime-thrdPivTime >= 0.5 * (thrdPivTime-scndPivTime) // Third leg must match size against second leg
        // Time and Price Conditions
        condBothA    = ta.highest(high, bar_index-frthPivTime) <= scndPivHigh
        // All Conditions
        if (condPricesA and condPricesB and condPricesC and condPricesD and condPricesE and condPricesF and condPricesG and condPricesH and condTimeA and condTimeB and condTimeC and condTimeD and condTimeE and condTimeF and condBothA)
            detectDoubleBottom := true
            array.unshift(bottomDBPrice, scndPivLow)
            array.unshift(topDBPrice, firstPivHigh)
            topDBBar := array.get(pivotHighBars, 1)

// Boolean to store the information of a current Double Bottom
isDoubleBottom = false
if (detectDoubleBottom or isDoubleBottom[1])
    isDoubleBottom := true

// For every bar in the base we store the closes in an array in order to compare
if (isBase)
    array.unshift(baseCloses, close)

// CONDITIONS FOR CUP DETECTION (6 to 65 weeks) (8% to 50% depth)
detectCup = false
isCup     = false
// Depth
float highCup = 0
float lowCup  = 0
//Condition Cup
condThird         = false
condFourth        = false
condThirdTwo      = false
condFourthTwo     = false
// condPartThree     = false
// Reference points
float middleOfCup = 0
baseTier          = baseCount/3
baseFourth        = baseCount/4
numberOfValidCl1  = 0
numberOfValidCl2  = 0
if (isBase)
    if (array.size(startBasePrice) > 0 and array.size(lowBasePrice) > 0)
        highCup     := array.get(startBasePrice, 0)
        lowCup      := array.get(lowBasePrice, 0)
    middleOfCup := lowCup + (highCup-lowCup)*0.5
    // Depth
    condMaxDepth = lowCup >= (1-i_baseDepth) * highCup
    condMinDepth = lowCup <= 0.92        * highCup
    // Length
    condMaxLength    = bar_index-startBaseBar <= i_baseLength
    condMinLength    = bar_index-startBaseBar >= 30
    // Asolute Position against the Cup (50%)
    condAbsolutePos  = (highCup-lowCup)*0.5 + lowCup <= high
    // Technical (80% of closes above 40% of base in the first tier, 80% under in the second.)
    for i= baseCount to 2*baseTier
        if (close[i]>=middleOfCup)
            numberOfValidCl1 := numberOfValidCl1+1
    condThirdTwo := numberOfValidCl1/baseTier >= 0.3
    for i = baseCount-baseTier to baseTier
        if (close[i]<=middleOfCup)
            numberOfValidCl2 := numberOfValidCl2+1
    condThird := numberOfValidCl2/baseTier >= 0.90 // 85% of closes must be contained in the middle thrid of the cup
    // Technical 2 (Same with 2*Fourth (half))
    numberOfValidCl1  := 0
    numberOfValidCl2  := 0
    for i= baseCount to 3*baseFourth
        if (close[i]>=middleOfCup)
            numberOfValidCl1 := numberOfValidCl1+1
    condThirdTwo := numberOfValidCl1/baseFourth >= 0.3
    for i = baseCount-baseFourth to baseFourth
        if (close[i]<=middleOfCup)
            numberOfValidCl2 := numberOfValidCl2+1
    condFourth := numberOfValidCl2/(2*baseFourth) >= 0.90  // or 85% of the closes must be contained in the middle half of the cup
    cupForm     = (condThird and condThird[1] and condThirdTwo and condThirdTwo[1]) or (condFourth and condFourth[1] and condFourthTwo and condFourthTwo[1])
    detectCup  := condMaxDepth and condMinDepth and condMaxLength and condMinLength and condAbsolutePos and cupForm


// Boolean to store the information
if (detectCup or isCup[1])
    isCup := true

// CUP MAINTENANCE
// plot (condThirdTwo ? 15:13, color=color.red)
// plot (condFourthTwo ? 12:9,  color=color.orange)
// plot (detectCup   ? 25:20, color=color.lime)

// Graphical Objects Declaration
// Horizontal Lines
var line highLine = na
var line lowLine  = na
var line dbLine1  = na
var line dbLine2  = na
var line dbLine3  = na
var line cupLineLeft      = na
var line cupLineRight     = na
var line cupLineLeftLive   = na
var line cupLineRightLive = na

// Box for Entry/Take Profit/ SL
var box entryBox = na
var box slBox    = na
var box tpBox    = na


// DRAWING BASE ON CHART IF DETECTION
if (baseCond and not isBase[1] and timeframe.isdaily and i_displayPattern)
    highLine := line.new(x1=startBaseBar, y1=array.get(startBasePrice, 0), x2=bar_index, y2=array.get(startBasePrice, 0), width=3, style = line.style_dotted, color=color.rgb(146,193,131,0))
    lowLine  := line.new(x1=startBaseBar, y1=array.get(lowBasePrice, 0),   x2=bar_index, y2=array.get(lowBasePrice, 0),   width=2, style = line.style_solid,  color=color.rgb(146,193,131,0))
    select = i_displayHistoricalBoxes ? false:boxOver
    // Optional Trade Boxes
    if(select)
        box.delete(entryBox)
        box.delete(slBox)
        box.delete(tpBox)
        isBox   := false
        boxOver := true

// // // DRAWING CURRENT CUP IF DETECTED
var line[] linesLeft  = array.new_line(na)
var line[] linesRight = array.new_line(na)
// Exception with ta.lowest() series not equal to lower low (eg IOT)
if (lowerBaseBar-startBaseBar <= 0)
    lowValue = low
    for i=baseCount to 0
        if(low[i]<lowValue)
            lowerBaseBar := bar_index[i]
            lowValue     := low[i]
lengthLeft   = lowerBaseBar-startBaseBar
lengthRight  = bar_index-lowerBaseBar
if (detectCup and isBase and timeframe.isdaily and i_displayPattern and not isDoubleBottom[1] and barstate.islast)
    // Draw Current Cup
    if (array.size(linesRight) > (lengthRight-1))
        for i = 0 to (lengthRight-1)
            line.delete(array.get(linesRight, i))
    line.delete(lowLine)
    var int   x1 = 0
    var float y1 = na
    var int   x2 = 0
    var float y2 = na
    // Some Reference Points
    var float startUpPrice = 0
    var float bottomPrice  = 0
    // Drawing Informations
    isLeftDrawn = false
    // Out of scope calculation
    if(array.size(lowBasePrice) > 0)   // array.size(lowOfpivotHighPrices) > 0 and 
        startUpPrice := lowOfBaseHigh * (1-0.01)
        bottomPrice  := array.get(lowBasePrice, 0) * (1-0.01)
    endUpPrice   = low[1]*(1-0.01)
    // We want a curve with an exp(x) form
    if(timeframe.isdaily and i_displayPattern and array.size(lowBasePrice) > 0 and startUpPrice>bottomPrice) // and array.size(lowOfpivotHighPrices) > 0
        // First Part
        for i = 0 to (lengthLeft-1)
            float k = 1/math.exp(0)/(startUpPrice-bottomPrice)
            x1 := bar_index[(lengthLeft-1)-(i-1)]
            x2 := bar_index[(lengthLeft-1)-(i  )]
            y1 := bottomPrice + (1/math.exp(i    *6/lengthLeft))/k
            y2 := bottomPrice + (1/math.exp((i+1)*6/lengthLeft))/k
            // Remove spread at the bottom of the cup
            if (i==lengthLeft-1)
                y2 := bottomPrice
            // Magical Drawing Left Part
            cupLineLeftLive := line.new(x1=x1-lengthRight, y1=y1, x2=x2-lengthRight, y2=y2, color=color.rgb(146,193,131,0), width=3)
            array.unshift(linesLeft, cupLineLeftLive)
            isLeftDrawn := true
        // Second Part
        if (isLeftDrawn)
            for i = 0 to (lengthRight-1) // 1 to 6 is the sample from e^1 to e^6 for the part of the curve I've selected
                float k = math.exp(6)/(endUpPrice-bottomPrice)
                x1 := bar_index[(lengthRight-1)-(i-1)]
                x2 := bar_index[(lengthRight-1)-i    ]
                y1 := bottomPrice + (math.exp(i    *6/lengthRight)-1)/k
                // Remove spread at the bottom of the cup
                if(i==0)
                    y1 := bottomPrice
                y2 := bottomPrice + (math.exp((i+1)*6/lengthRight)-1)/k
                // Magical Drawing Right Part
                cupLineRightLive := line.new(x1=x1, y1=y1, x2=x2, y2=y2, color=color.rgb(146,193,131,0), width=3)
                array.unshift(linesRight, cupLineRightLive)   
// Deletes Current cup if not a cup anymore
// if (not isCup and array.size(linesLeft) > (lengthLeft-1))
//     for i = 0 to (lengthLeft-1)
//         line.delete(array.get(linesLeft, i))

// if (not isCup and array.size(linesRight) > (lengthRight-1))
//     for i = 0 to (lengthRight-1)
//         line.delete(array.get(linesRight, i))


// DRAWING DOUBLE BOTTOM ON CHART IF DETECTION
lowCompare = bar_index-topDBBar > 0 ? ta.lowest(low, bar_index-topDBBar):low
if (detectDoubleBottom and not isDoubleBottom[1]  and timeframe.isdaily and i_displayPattern)
    line.delete(highLine)
    line.delete(lowLine )
    bottomDBBar := array.get(pivotLowBars,  0)
    // If Lower Low But Double Bottom Still valid (CASY)
    //if (array.size(bottomDBPrice) > 0)   // This part is generating Error on SPX ticker due to too much candle on study
        // if (lowCompare < array.get(bottomDBPrice, 0))
        //     array.unshift(bottomDBPrice, lowCompare)
            // bottomDBBar := bar_index - ta.barssince(low==lowCompare)
            // if (low[1] == array.get(bottomDBPrice, 0))
            //     bottomDBBar := bar_index[1]
    highLine := line.new(x1=array.get(pivotHighBars, 0), y1=array.get(pivotHighPrices, 0), x2=bar_index, y2=array.get(pivotHighPrices, 0), width=3, style = line.style_dotted, color=color.rgb(146,193,131,0))
    dbLine1 := line.new(x1=array.get(pivotHighBars, 1), y1=array.get(lowOfpivotHighPrices, 1)*(100-1)/100 , x2=array.get(pivotLowBars,  1), y2=array.get(pivotLowPrices,  1)*(100-1)/100    , width=2, style = line.style_solid, color=color.rgb(146,193,131,0))
    dbLine2 := line.new(x1=array.get(pivotLowBars,  1), y1=array.get(pivotLowPrices,     1)*(100-1)/100, x2=array.get(pivotHighBars, 0), y2=array.get(lowOfpivotHighPrices, 0)*(100-1)/100  , width=2, style = line.style_solid, color=color.rgb(146,193,131,0))
    dbLine3 := line.new(x1=array.get(pivotHighBars, 0), y1=array.get(lowOfpivotHighPrices, 0)*(100-1)/100 , x2=bottomDBBar                 , y2=array.get(bottomDBPrice,  0)*(100-1)/100  , width=2, style = line.style_solid, color=color.rgb(146,193,131,0))
    lowLine := line.new(x1=bottomDBBar                 , y1=array.get(bottomDBPrice,  0)*(100-1)/100 , x2=bar_index                 , y2=low * (100-1)/100                             , width=2, style = line.style_solid, color=color.rgb(146,193,131,0))
    select = i_displayHistoricalBoxes ? false:boxOver
    // Optional Trade Boxes
    if(select)
        box.delete(entryBox)
        box.delete(slBox)
        box.delete(tpBox)
        isBox   := false
        boxOver := true


// Check Bottom Break
// Adjust Double Bottom Base
if (array.size(bottomDBPrice) > 0)
    if (low < array.get(bottomDBPrice, 0) and isDoubleBottom)
        line.delete(highLine)
        line.delete(lowLine )
        line.delete(dbLine1 )
        line.delete(dbLine2 )
        line.delete(dbLine3 )
        isDoubleBottom := false
        // Redraw Original base if Double Bottom disabled
        highLine := line.new(x1=startBaseBar, y1=array.get(startBasePrice, 0), x2=bar_index, y2=array.get(startBasePrice, 0), width=3, style = line.style_dotted, color=color.rgb(146,193,131,0))
        lowLine  := line.new(x1=startBaseBar, y1=array.get(lowBasePrice,0),    x2=bar_index, y2=array.get(lowBasePrice, 0),   width=2, style = line.style_solid,  color=color.rgb(146,193,131,0))
// Check Double Bottom base Length
if (isDoubleBottom and bar_index-topDBBar>i_dbLength)
    line.delete(highLine)
    line.delete(lowLine )
    line.delete(dbLine1 )
    line.delete(dbLine2 )
    line.delete(dbLine3 )
    isDoubleBottom := false
// Check Double Bottom Pattern Propreties
firstPivTime = line.get_x1(dbLine1)
thrdPivTime  = line.get_x2(dbLine2)
if (isDoubleBottom and (thrdPivTime-firstPivTime) * 2 <= bar_index-thrdPivTime or (thrdPivTime-firstPivTime) >= (bar_index-thrdPivTime) * 2)
    line.delete(highLine)
    line.delete(lowLine )
    line.delete(dbLine1 )
    line.delete(dbLine2 )
    line.delete(dbLine3 )
    isDoubleBottom := false
    // Redraw Original base if Double Bottom disabled
    highLine := line.new(x1=startBaseBar, y1=array.get(startBasePrice, 0), x2=bar_index, y2=array.get(startBasePrice, 0), width=3, style = line.style_dotted, color=color.rgb(146,193,131,0))
    lowLine  := line.new(x1=startBaseBar, y1=array.get(lowBasePrice,0),    x2=bar_index, y2=array.get(lowBasePrice,0),    width=2, style = line.style_solid,  color=color.rgb(146,193,131,0))


// Adjust Base Bottom
if (low < line.get_y1(lowLine) and isBase and not isDoubleBottom)
    line.set_y1(lowLine, low)
    line.set_y2(lowLine, low)
    lowerBaseBar := bar_index
    if (array.size(lowBasePrice) > 0)
        array.unshift(lowBasePrice, low)
// Check Base Max Depth and Max Length
if ((low < line.get_y1(highLine) * (1-i_baseDepth) or baseCount>i_baseLength) and isBase[1] and not isDoubleBottom[1])
    line.delete(highLine)
    line.delete(lowLine)
    isBase       := false
// Check Depth of base to adjust style of line (Depth above 15% = Dashed Line, defined as flat base by IBD)
if (line.get_y1(highLine) * 0.85 >= line.get_y1(lowLine) and isBase and not isDoubleBottom)
    line.set_style(lowLine, line.style_dotted)
    line.set_width(lowLine, 3)
// While the base is still valid, we extend lines
if (high<=line.get_y1(highLine) and low>=line.get_y1(lowLine) and isBase)
    line.set_x2(highLine, bar_index)
    line.set_x2(lowLine , bar_index)
    if (isDoubleBottom)
        line.set_y2(lowLine, low*(100-1)/100)
        line.set_x2(lowLine,  bar_index)



// Check Top Break
if (high>line.get_y1(highLine) and (isBase[1] or isDoubleBottom[1]))
    isBase := false  
    if (isDoubleBottom)
        isDoubleBottom := false
    // Drawing historical cups if they are cups during the break out
    if (detectCup and timeframe.isdaily and i_displayPattern and not isDoubleBottom[1])
        // Draw historical fix Cups
        line.delete(lowLine)
        var int   x1 = 0
        var float y1 = na
        var int   x2 = 0
        var float y2 = na
        // Some reference points
        var float startUpPrice = 0
        var float bottomPrice  = 0
        // Drawing Informations
        isLeftDrawn = false
        // Out of scope calculation
        if(array.size(lowBasePrice) > 0)   // array.size(lowOfpivotHighPrices) > 0 and 
            startUpPrice := lowOfBaseHigh * (1-0.01)
            bottomPrice  := array.get(lowBasePrice, 0) * (1-0.01)
        endUpPrice   = low[1]*(1-0.01)
        // Exception with ta.lowest() series not equal to lower low (eg IOT)
        if (lowerBaseBar-startBaseBar <= 0)
            lowValue = low
            for i=baseCount-1 to 0
                if(low[i]<lowValue)
                    lowerBaseBar := bar_index[i]
                    lowValue     := low[i]
        lengthLeft  := lowerBaseBar-startBaseBar // := au lieu de =
        lengthRight := bar_index-lowerBaseBar
        // We want a curve with an exp(x) form
        if(timeframe.isdaily and i_displayPattern and array.size(lowBasePrice) > 0 and startUpPrice>bottomPrice) // and array.size(lowOfpivotHighPrices) > 0
            // First Part
            for i = 0 to (lengthLeft-1)
                float k = 1/math.exp(0)/(startUpPrice-bottomPrice)
                x1 := bar_index[(lengthLeft-1)-(i-1)]
                x2 := bar_index[(lengthLeft-1)-(i  )]
                y1 := bottomPrice + (1/math.exp(i    *6/lengthLeft))/k
                y2 := bottomPrice + (1/math.exp((i+1)*6/lengthLeft))/k
                // Remove spread at the bottom of the cup
                if (i==lengthLeft-1)
                    y2 := bottomPrice
                // Magical Drawing Left Part
                cupLineLeft := line.new(x1=x1-lengthRight, y1=y1, x2=x2-lengthRight, y2=y2, color=color.rgb(146,193,131,0), width=3)
                isLeftDrawn := true
            // Second Part
            if (isLeftDrawn)
                for i = 0 to (lengthRight-1) // 1 to 6 is the sample from e^1 to e^6 for the part of the curve I've selected
                    float k = math.exp(6)/(endUpPrice-bottomPrice)
                    x1 := bar_index[(lengthRight-1)-(i-1)]
                    x2 := bar_index[(lengthRight-1)-i    ]
                    y1 := bottomPrice + (math.exp(i    *6/lengthRight)-1)/k
                    // Remove spread at the bottom of the cup
                    if(i==0)
                        y1 := bottomPrice
                    y2 := bottomPrice + (math.exp((i+1)*6/lengthRight)-1)/k
                    // Magical Drawing Right Part
                    cupLineRight := line.new(x1=x1, y1=y1, x2=x2, y2=y2, color=color.rgb(146,193,131,0), width=3)
        // END CUP DRAWING
    if(i_displayBoxes)
        topBase   = line.get_y1(highLine)
        entryBox := box.new(bar_index[1], topBase*(1+0.05), bar_index, topBase         , border_color=color.rgb(0,0,0,100), border_width=0, bgcolor=color.rgb(0,0,255,92))
        slBox    := box.new(bar_index[1], topBase*(1-0.05), bar_index, topBase*(1-0.08), border_color=color.rgb(0,0,0,100), border_width=0, bgcolor=color.rgb(255, 0, 0, 92))
        tpBox    := box.new(bar_index[1], topBase*(1+0.20), bar_index, topBase*(1+0.25), border_color=color.rgb(0,0,0,100), border_width=0, bgcolor=color.rgb(60, 243, 4, 88))
        isBox    := true
        boxOver  := false
    

// TRADE BOX GESTION
// Extend Boxes while the trade runs
if (high<=line.get_y1(highLine)*(1+0.25) and low>=line.get_y1(highLine)*(1-0.08) and isBox) 
    box.set_right(entryBox, bar_index)
    box.set_right(slBox   , bar_index)
    box.set_right(tpBox   , bar_index)
    isBox   := true
    boxOver := false

// MEMORY LIMIT GESTION (ARRAY SIZE)
if (array.size(linesLeft)  > 500)
    line.delete(array.pop(linesLeft))
if (array.size(linesRight) > 500)
    line.delete(array.pop(linesRight))



// EPS & SALES INTEGRATION
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Fred6724

// === USER INPUTS ====
// ARROWS
i_ArrowOnGraph = input(true,  title='Displays Arrows', inline='1', group='EPS Arrows')
i_ArrowQoq     = input(false, title='Arrow QoQ', inline='1', group='EPS Arrows')
i_salesOnGraph = input(false, title='Sales', inline='1', group='EPS Arrows')
i_arrowSize    = input.string(size.small, title='Arrow Size', options=[size.tiny,size.small,size.normal, size.large], inline='2', group='EPS Arrows')
i_arrowColor   = input(color.rgb(0,0,0,0), title='Arrow Colors', inline='3', group='EPS Arrows')
i_posArrowColor= input(color.rgb(13,7,201,0), title='%Pos' ,group='EPS Arrows', inline='3')
i_negArrowColor= input(color.red, title='%Neg' ,group='EPS Arrows', inline='3')
// TABLE SETTINGS
i_tableStyle   = input.string('Table', title = 'Type of Table', options = ['Table', 'HeadBand'], group='Table Settings', inline='0')
i_tableSize    = input.string(size.normal, title='Table Size   ', options=[size.tiny,size.small,size.normal, size.large] ,group='Table Settings' ,inline='5')
i_posTable     = input.string(defval=position.bottom_left, title='Table Position', options=[position.top_left,position.top_center,position.top_right, position.middle_left, position.middle_center, position.middle_right, position.bottom_left, position.bottom_center, position.bottom_right] ,group='Table Settings' ,inline='6', tooltip = 'Available in Weekly Table Only.')
i_frameWidth   = input.int(1, title='Frame Width', group='Table Settings', options= [0,1,2,3,4,5], inline='0.25')
i_frameColor   = input(color.rgb(209, 212, 220), title='Color' , group='Table Settings', inline='0.25')
i_tableBorder  = input(true, title='Table Border', group='Table Settings', inline='0.5')
i_borderColor  = input(color.rgb(209, 212, 220), title='| Color' ,group='Table Settings', inline='0.5')
i_resultBackgroundColorOdd  = input(color.rgb(255,255,255,0), title='Odd Rows' ,group='Table Settings', inline='7')
i_resultBackgroundColorEven = input(color.rgb(230,234,243,0), title='Even Rows' ,group='Table Settings', inline='7') // Previous Color version color.rgb(192,192,192,0)
// DIGIT SETTINGS
i_estimates    = input(true,  title='Estimates', group='Digit Settings', tooltip = 'Available in Weekly Table Only.')
i_moreData     = input(false, title='Less Quarters' ,group='Digit Settings', inline='1',tooltip = 'Available in Weekly Table Only.')
i_alwaysDispP  = input(false, title='Avoid N/A', group='Digit Settings', inline='1',tooltip = 'Available in Weekly Table Only.')
i_compare      = input(false, title='Show VS YoY' ,group='Digit Settings' ,inline='2', tooltip = 'Available in Weekly Table Only.')
i_YoY          = input(true, title='YoY' ,group='Digit Settings' ,inline='2', tooltip = 'Available in Weekly Table Only.')
i_QoQ          = input(false, title='QoQ' ,group='Digit Settings' ,inline='2', tooltip = 'Available in Weekly Table Only.')
i_surprises    = input(false, title='% Surprise' ,group='Digit Settings', inline='3', tooltip = 'Available in Weekly Table Only.')
i_posSurp      = input(color.rgb(56,142,60,0), title='%Pos' ,group='Digit Settings', inline='3')
i_negSurp      = input(color.red, title='%Neg' ,group='Digit Settings', inline='3')
i_grossMargin  = input(false, title='Gross Margin' ,group='Digit Settings' ,inline='4')
i_ROE          = input(false, title='Return On Equity' ,group='Digit Settings' ,inline='4')
i_RowAndColumnTextColor  = input(color.black, title='Row & Column Text Color' ,group='Digit Settings')
i_poscolorT = input(color.rgb(0,0,255,0), title='% Positive' ,group='Digit Settings', inline='8')
i_negColorT = input(color.red, title='% Negative' ,group='Digit Settings', inline='8')
// Not input
datasize = 10
blankUnderUp = i_moreData == false ? 3 : 6 // Because there is a blank between the top of the table and the second line but Tradingview doesn't display it.


// Declare tables
// Weekly Table
var table epsTable   = table.new(i_posTable, 15, 15, frame_color = i_frameColor, frame_width = i_frameWidth, border_width=i_tableBorder ? 1:0, border_color=i_borderColor)
// Daily Table
var table epsTableDa = table.new(position.bottom_center,17, 4, frame_color = i_frameColor, frame_width = i_frameWidth, border_width=i_tableBorder ? 1:0, border_color=i_borderColor)

// === FUNCTIONS AND CALCULATIONS ===.
// Current earnings per share
// Modified line to get (actual) and (standard) earnings with 'request.earnings'. HUGE key point here to have closer results to IBD - MarketSmith
EPS            = request.earnings(syminfo.tickerid, earnings.actual, ignore_invalid_symbol=true, lookahead = barmerge.lookahead_on)
EPS_Standard   = request.earnings(syminfo.tickerid, earnings.standardized, ignore_invalid_symbol=true, lookahead = barmerge.lookahead_on)
EPS_Estimate   = request.earnings(syminfo.tickerid, earnings.estimate, ignore_invalid_symbol=true, lookahead = barmerge.lookahead_on) // To reduce the probability of not detecting a change if EPS are the same quarters over quarters
SALES          = request.financial(syminfo.tickerid, 'TOTAL_REVENUE', 'FQ', ignore_invalid_symbol=true)
SALES_Estimate = request.financial(syminfo.tickerid, 'SALES_ESTIMATES', 'FQ', ignore_invalid_symbol=true)
SALES_GROWTH   = request.financial(syminfo.tickerid, 'REVENUE_ONE_YEAR_GROWTH', 'FQ', ignore_invalid_symbol=true)
grossMargin = i_grossMargin ? request.financial(syminfo.tickerid, 'GROSS_MARGIN', 'FQ', ignore_invalid_symbol=true):na
ROE = request.financial(syminfo.tickerid, 'RETURN_ON_EQUITY', 'FQ', ignore_invalid_symbol=true)
//Date
rev = request.financial(syminfo.tickerid,'TOTAL_REVENUE','FQ',barmerge.gaps_on, ignore_invalid_symbol=true)


// GET EPS NUMBERS FROM TRADINGVIEW

// Estimates Next Earning
futureEPS   = earnings.future_eps
futureSales = earnings.future_revenue
futureTime  = earnings.future_time

// EPS & SALES
barSince = ta.barssince(EPS != EPS[1] or EPS_Standard != EPS_Standard[1] or EPS_Estimate != EPS_Estimate[1]) // To reduce the probability of not detecting a change if EPS are the same quarters over quarters
EPSTime  = barSince == 0 
// If the number of (bars since the value of EPS, is different, from previous EPS) equals 0, we are in an EPS event. (You can do it)
// (Better method, using the time since the last public EPS/Sales (Before we were using default 3M that was causing errors in case of non-regular period publishing))
// Now we are using sometimes Actual EPS, somtimes Standard EPS, based on my observations with MarketSmith numbers.
// Actual EPS
// Use if() function to get number before the first earning event - If return na we get the first EPS value except if the line before us already done it
firstEPS = ta.valuewhen(bar_index==0, EPS, 0)
actualEPS   = ta.valuewhen(EPSTime, EPS, 0)
if(na(actualEPS))
    actualEPS  := firstEPS
actualEPS1  = ta.valuewhen(EPSTime, EPS, 1) // With '1' to search the previous EPS value, etc
if(na(actualEPS1) and actualEPS  != firstEPS)
    actualEPS1 := firstEPS
actualEPS2  = ta.valuewhen(EPSTime, EPS, 2)
if(na(actualEPS2) and actualEPS1 != firstEPS)
    actualEPS2 := firstEPS
actualEPS3  = ta.valuewhen(EPSTime, EPS, 3)
if(na(actualEPS3) and actualEPS2 != firstEPS)
    actualEPS3 := firstEPS
actualEPS4  = ta.valuewhen(EPSTime, EPS, 4)
if(na(actualEPS4) and actualEPS3 != firstEPS)
    actualEPS4 := firstEPS
actualEPS5  = ta.valuewhen(EPSTime, EPS, 5)
if(na(actualEPS5) and actualEPS4 != firstEPS)
    actualEPS5 := firstEPS
actualEPS6  = ta.valuewhen(EPSTime, EPS, 6)
if(na(actualEPS6) and actualEPS5 != firstEPS)
    actualEPS6 := firstEPS
actualEPS7  = ta.valuewhen(EPSTime, EPS, 7)
if(na(actualEPS7) and actualEPS6 != firstEPS)
    actualEPS7 := firstEPS
actualEPS8  = ta.valuewhen(EPSTime, EPS, 8)
if(na(actualEPS8) and actualEPS7 != firstEPS)
    actualEPS8 := firstEPS
actualEPS9  = ta.valuewhen(EPSTime, EPS, 9)
if(na(actualEPS9) and actualEPS8 != firstEPS)
    actualEPS9 := firstEPS
actualEPS10 = ta.valuewhen(EPSTime, EPS, 10)
if(na(actualEPS10) and actualEPS9 != firstEPS)
    actualEPS10 := firstEPS
actualEPS11 = ta.valuewhen(EPSTime, EPS, 11)
if(na(actualEPS11) and actualEPS10 != firstEPS)
    actualEPS11 := firstEPS
// Standard EPS
standardEPS   = ta.valuewhen(EPSTime, EPS_Standard, 0) 
standardEPS1  = ta.valuewhen(EPSTime, EPS_Standard, 1) 
standardEPS2  = ta.valuewhen(EPSTime, EPS_Standard, 2)
standardEPS3  = ta.valuewhen(EPSTime, EPS_Standard, 3)
standardEPS4  = ta.valuewhen(EPSTime, EPS_Standard, 4)
standardEPS5  = ta.valuewhen(EPSTime, EPS_Standard, 5)
standardEPS6  = ta.valuewhen(EPSTime, EPS_Standard, 6)
standardEPS7  = ta.valuewhen(EPSTime, EPS_Standard, 7)
standardEPS8  = ta.valuewhen(EPSTime, EPS_Standard, 8)
standardEPS9  = ta.valuewhen(EPSTime, EPS_Standard, 9)
standardEPS10 = ta.valuewhen(EPSTime, EPS_Standard, 10)
standardEPS11 = ta.valuewhen(EPSTime, EPS_Standard, 11)
// Estimate EPS
estimateEPS   = ta.valuewhen(EPSTime, EPS_Estimate, 0) 
estimateEPS1  = ta.valuewhen(EPSTime, EPS_Estimate, 1) 
estimateEPS2  = ta.valuewhen(EPSTime, EPS_Estimate, 2)
estimateEPS3  = ta.valuewhen(EPSTime, EPS_Estimate, 3)
estimateEPS4  = ta.valuewhen(EPSTime, EPS_Estimate, 4)
estimateEPS5  = ta.valuewhen(EPSTime, EPS_Estimate, 5)
estimateEPS6  = ta.valuewhen(EPSTime, EPS_Estimate, 6)
estimateEPS7  = ta.valuewhen(EPSTime, EPS_Estimate, 7)
// EPS Surprise
EpsSurprise0 = (actualEPS -estimateEPS )/math.abs(estimateEPS )*100
EpsSurprise1 = (actualEPS1-estimateEPS1)/math.abs(estimateEPS1)*100
EpsSurprise2 = (actualEPS2-estimateEPS2)/math.abs(estimateEPS2)*100
EpsSurprise3 = (actualEPS3-estimateEPS3)/math.abs(estimateEPS3)*100
EpsSurprise4 = (actualEPS4-estimateEPS4)/math.abs(estimateEPS4)*100
EpsSurprise5 = (actualEPS5-estimateEPS5)/math.abs(estimateEPS5)*100
EpsSurprise6 = (actualEPS6-estimateEPS6)/math.abs(estimateEPS6)*100
EpsSurprise7 = (actualEPS7-estimateEPS7)/math.abs(estimateEPS7)*100

// Same with Sales 
// Use if() function to get number before the first earning event - If return na we get the first sales value except if the line before us already done it
firstSale = ta.valuewhen(bar_index==0, SALES, 0)
sales   = ta.valuewhen(EPSTime, SALES, 0)
if(na(sales))
    sales  := firstSale
sales1  = ta.valuewhen(EPSTime, SALES, 1)
if(na(sales1) and sales  != firstSale)
    sales1 := firstSale
sales2  = ta.valuewhen(EPSTime, SALES, 2)
if(na(sales2) and sales1 != firstSale)
    sales2 := firstSale
sales3  = ta.valuewhen(EPSTime, SALES, 3)
if(na(sales3) and sales2 != firstSale)
    sales3 := firstSale
sales4  = ta.valuewhen(EPSTime, SALES, 4)
if(na(sales4) and sales3 != firstSale)
    sales4 := firstSale
sales5  = ta.valuewhen(EPSTime, SALES, 5)
if(na(sales5) and sales4 != firstSale)
    sales5 := firstSale
sales6  = ta.valuewhen(EPSTime, SALES, 6)
if(na(sales6) and sales5 != firstSale)
    sales6 := firstSale
sales7  = ta.valuewhen(EPSTime, SALES, 7)
if(na(sales7) and sales6 != firstSale)
    sales7 := firstSale
sales8  = ta.valuewhen(EPSTime, SALES, 8)
if(na(sales8) and sales7 != firstSale)
    sales8 := firstSale
sales9  = ta.valuewhen(EPSTime, SALES, 9)
if(na(sales9) and sales8 != firstSale)
    sales9 := firstSale
sales10 = ta.valuewhen(EPSTime, SALES, 10)
if(na(sales10) and sales9 != firstSale)
    sales10 := firstSale
sales11 = ta.valuewhen(EPSTime, SALES, 11)
if(na(sales11) and sales10 != firstSale)
    sales11 := firstSale

// Sales One Year Growth to get more Historical Data
// We use if() condition to get one more line
firstSaleGrowth = ta.valuewhen(bar_index==0, SALES_GROWTH, 0)
salesChange0   = ta.valuewhen(EPSTime, SALES_GROWTH, 0)
if(na(salesChange0))
    salesChange0  := firstSaleGrowth
salesChange1  = ta.valuewhen(EPSTime, SALES_GROWTH, 1)
if(na(salesChange1) and salesChange0  != firstSaleGrowth)
    salesChange1 := firstSaleGrowth
salesChange2  = ta.valuewhen(EPSTime, SALES_GROWTH, 2)
if(na(salesChange2) and salesChange1 != firstSaleGrowth)
    salesChange2 := firstSaleGrowth
salesChange3  = ta.valuewhen(EPSTime, SALES_GROWTH, 3)
if(na(salesChange3) and salesChange2 != firstSaleGrowth)
    salesChange3 := firstSaleGrowth
salesChange4  = ta.valuewhen(EPSTime, SALES_GROWTH, 4)
if(na(salesChange4) and salesChange3 != firstSaleGrowth)
    salesChange4 := firstSaleGrowth
salesChange5  = ta.valuewhen(EPSTime, SALES_GROWTH, 5)
if(na(salesChange5) and salesChange4 != firstSaleGrowth)
    salesChange5 := firstSaleGrowth
salesChange6  = ta.valuewhen(EPSTime, SALES_GROWTH, 6)
if(na(salesChange6) and salesChange5 != firstSaleGrowth)
    salesChange6 := firstSaleGrowth
salesChange7  = ta.valuewhen(EPSTime, SALES_GROWTH, 7)
if(na(salesChange7) and salesChange6 != firstSaleGrowth)
    salesChange7 := firstSaleGrowth

// Sometimes the sales number is actualised but not the sales variation..
if(salesChange0 == salesChange1 and not (na(sales4) or sales4 == 0))
    salesChange0 := (sales - sales4)/math.abs(sales4)*100

// Case where earning are very close, should check if the % variation is good (VRRM Mar-22 - Dec-21) -> 70 90 and not 90 90
salesChangeF = (futureSales - sales3)/math.abs(sales3)*100
if(salesChange1 == salesChange0 and sales1 == sales)
    salesChange1 := (sales1 - sales5)/math.abs(sales5)*100
if(salesChange2 == salesChange1 and sales2 == sales1)
    salesChange2 := (sales2 - sales6)/math.abs(sales6)*100
if(salesChange3 == salesChange2 and sales3 == sales2)
    salesChange3 := (sales3 - sales7)/math.abs(sales7)*100
if(salesChange4 == salesChange3 and sales4 == sales3)
    salesChange4 := (sales4 - sales8)/math.abs(sales8)*100
if(salesChange5 == salesChange4 and sales5 == sales4)
    salesChange5 := (sales5 - sales9)/math.abs(sales9)*100
if(salesChange6 == salesChange5 and sales6 == sales5)
    salesChange6 := (sales6 - sales10)/math.abs(sales10)*100
if(salesChange7 == salesChange6 and sales7 == sales6)
    salesChange7 := (sales7 - sales11)/math.abs(sales11)*100

// Sales Estimaate
salesEstimate   = ta.valuewhen(EPSTime, SALES_Estimate, 0)
salesEstimate1  = ta.valuewhen(EPSTime, SALES_Estimate, 1)
salesEstimate2  = ta.valuewhen(EPSTime, SALES_Estimate, 2)
salesEstimate3  = ta.valuewhen(EPSTime, SALES_Estimate, 3)
salesEstimate4  = ta.valuewhen(EPSTime, SALES_Estimate, 4)
salesEstimate5  = ta.valuewhen(EPSTime, SALES_Estimate, 5)
salesEstimate6  = ta.valuewhen(EPSTime, SALES_Estimate, 6)
salesEstimate7  = ta.valuewhen(EPSTime, SALES_Estimate, 7)

// Detect same sales for TradingView bug correction (Same sales than previous display)
bool sameSales  = SALES==sales1 and SALES_GROWTH==salesChange1
bool recentEarn = ta.barssince(EPSTime)<=6

// Function to define previous quarters gross margin & roe (Less precise than EPS and Sales Data)
f_grossMargin(i) =>
    request.security(syminfo.tickerid, '3M', grossMargin[i])
f_roe(i) =>
    request.security(syminfo.tickerid, '3M', ROE[i])

// Same with Gross Margin
// Use if() function to get number before the first earning event - If return na we get the first sales value except if the line before us already done it
firstGrossMargin = ta.valuewhen(bar_index==0, grossMargin, 0)
GM0   = ta.valuewhen(EPSTime, grossMargin, 0)
if(na(GM0))
    GM0  := firstGrossMargin
GM1  = ta.valuewhen(EPSTime, grossMargin, 1)
if(na(GM1) and GM0  != firstGrossMargin)
    GM1 := firstGrossMargin
GM2  = ta.valuewhen(EPSTime, grossMargin, 2)
if(na(GM2) and GM1 != firstGrossMargin)
    GM2 := firstGrossMargin
GM3  = ta.valuewhen(EPSTime, grossMargin, 3)
if(na(GM3) and GM2 != firstGrossMargin)
    GM3 := firstGrossMargin
GM4  = ta.valuewhen(EPSTime, grossMargin, 4)
if(na(GM4) and GM3 != firstGrossMargin)
    GM4 := firstGrossMargin
GM5  = ta.valuewhen(EPSTime, grossMargin, 5)
if(na(GM5) and GM4 != firstGrossMargin)
    GM5 := firstGrossMargin
GM6  = ta.valuewhen(EPSTime, grossMargin, 6)
if(na(GM6) and GM5 != firstGrossMargin)
    GM6 := firstGrossMargin
GM7  = ta.valuewhen(EPSTime, grossMargin, 7)
if(na(GM7) and GM6 != firstGrossMargin)
    GM7 := firstGrossMargin

// Same with Return On Equity
// Use if() function to get number before the first earning event - If return na we get the first sales value except if the line before us already done it
firstReturnOnEquity = ta.valuewhen(bar_index==0, ROE, 0)
ROE0   = ta.valuewhen(EPSTime, ROE, 0)
if(na(ROE0))
    ROE0  := firstReturnOnEquity
ROE1  = ta.valuewhen(EPSTime, ROE, 1)
if(na(ROE1) and ROE0  != firstReturnOnEquity)
    ROE1 := firstReturnOnEquity
ROE2  = ta.valuewhen(EPSTime, ROE, 2)
if(na(ROE2) and ROE1 != firstReturnOnEquity)
    ROE2 := firstReturnOnEquity
ROE3  = ta.valuewhen(EPSTime, ROE, 3)
if(na(ROE3) and ROE2 != firstReturnOnEquity)
    ROE3 := firstReturnOnEquity
ROE4  = ta.valuewhen(EPSTime, ROE, 4)
if(na(ROE4) and ROE3 != firstReturnOnEquity)
    ROE4 := firstReturnOnEquity
ROE5  = ta.valuewhen(EPSTime, ROE, 5)
if(na(ROE5) and ROE4 != firstReturnOnEquity)
    ROE5 := firstReturnOnEquity
ROE6  = ta.valuewhen(EPSTime, ROE, 6)
if(na(ROE6) and ROE5 != firstReturnOnEquity)
    ROE6 := firstReturnOnEquity
ROE7  = ta.valuewhen(EPSTime, ROE, 7)
if(na(ROE7) and ROE6 != firstReturnOnEquity)
    ROE7 := firstReturnOnEquity


// Calculation using IBD/Marketsmith principle : current quarter EPS vs the same quartar's EPS of previous year. (YoY) 
EpsChangeF  = futureEPS  < 0 and actualEPS3  <= 0 ? na: actualEPS3  < 0 and standardEPS3  > 0 ? (futureEPS -actualEPS3) /math.abs(actualEPS3) *100:futureEPS    < 0 and actualEPS3  > 0 ? na:(futureEPS -actualEPS3) /math.abs(actualEPS3) *100
EpsChange0  = actualEPS  < 0 and actualEPS4  <= 0 ? na: actualEPS4  < 0 and standardEPS4  > 0 ? (EPS-actualEPS4)        /math.abs(actualEPS4) *100:EPS          < 0 and actualEPS4  > 0 ? na:(EPS-actualEPS4)        /math.abs(actualEPS4) *100
EpsChange1  = actualEPS1 < 0 and actualEPS5  <= 0 ? na: actualEPS5  < 0 and standardEPS5  > 0 ? (actualEPS1-actualEPS5) /math.abs(actualEPS5) *100:actualEPS1   < 0 and actualEPS5  > 0 ? na:(actualEPS1-actualEPS5) /math.abs(actualEPS5) *100
EpsChange2  = actualEPS2 < 0 and actualEPS6  <= 0 ? na: actualEPS6  < 0 and standardEPS6  > 0 ? (actualEPS2-actualEPS6) /math.abs(actualEPS6) *100:actualEPS2   < 0 and actualEPS6  > 0 ? na:(actualEPS2-actualEPS6) /math.abs(actualEPS6) *100
EpsChange3  = actualEPS3 < 0 and actualEPS7  <= 0 ? na: actualEPS7  < 0 and standardEPS7  > 0 ? (actualEPS3-actualEPS7) /math.abs(actualEPS7) *100:actualEPS3   < 0 and actualEPS7  > 0 ? na:(actualEPS3-actualEPS7) /math.abs(actualEPS7) *100
EpsChange4  = actualEPS4 < 0 and actualEPS8  <= 0 ? na: actualEPS8  < 0 and standardEPS8  > 0 ? (actualEPS4-actualEPS8) /math.abs(actualEPS8) *100:actualEPS4   < 0 and actualEPS8  > 0 ? na:(actualEPS4-actualEPS8) /math.abs(actualEPS8) *100
EpsChange5  = actualEPS5 < 0 and actualEPS9  <= 0 ? na: actualEPS9  < 0 and standardEPS9  > 0 ? (actualEPS5-actualEPS9) /math.abs(actualEPS9) *100:actualEPS5   < 0 and actualEPS9  > 0 ? na:(actualEPS5-actualEPS9) /math.abs(actualEPS9) *100
EpsChange6  = actualEPS6 < 0 and actualEPS10 <= 0 ? na: actualEPS10 < 0 and standardEPS10 > 0 ? (actualEPS6-actualEPS10)/math.abs(actualEPS10)*100:actualEPS6   < 0 and actualEPS10 > 0 ? na:(actualEPS6-actualEPS10)/math.abs(actualEPS10)*100
EpsChange7  = actualEPS7 < 0 and actualEPS11 <= 0 ? na: actualEPS11 < 0 and standardEPS11 > 0 ? (actualEPS7-actualEPS11)/math.abs(actualEPS11)*100:actualEPS7   < 0 and actualEPS11 > 0 ? na:(actualEPS7-actualEPS11)/math.abs(actualEPS11)*100
// The case in which atual was - and standard was + was not taken into account, I added a condition to fix a ver low value in this case and have the '#' succesfully display
// because of the choice when fillCell.

// When EPS is negative we take the closer from 0 between standardized and reported
// We also use another variable to recognize when the calculation has been done with negative EPS (To display '#')                                                                                  // added this condition because 0.98 vs -0.16 = #712/713% not 999% APA
EpsChangeHashF = futureEPS   >= 0 ? na:futureEPS  < 0 and standardEPS3  < 0 ? na:actualEPS3  < 0 and standardEPS3  > 0 ? (futureEPS -actualEPS3) /math.abs(actualEPS3) *100:actualEPS3  <= standardEPS3  and standardEPS3 >-0.01 ? (futureEPS-standardEPS3)  /math.abs(standardEPS3) *100:(futureEPS-actualEPS3)  /math.abs(actualEPS3) *100
EpsChangeHash0 = actualEPS4  >= 0 ? na:actualEPS  < 0 and standardEPS4  < 0 ? na:actualEPS4  < 0 and standardEPS4  > 0 ? (EPS-actualEPS4)        /math.abs(actualEPS4) *100:actualEPS4  <= standardEPS4  and standardEPS4 >-0.01 ? (EPS-standardEPS4)        /math.abs(standardEPS4) *100:(EPS-actualEPS4)        /math.abs(actualEPS4) *100
EpsChangeHash1 = actualEPS5  >= 0 ? na:actualEPS1 < 0 and standardEPS5  < 0 ? na:actualEPS5  < 0 and standardEPS5  > 0 ? (actualEPS1-actualEPS5) /math.abs(actualEPS5) *100:actualEPS5  <= standardEPS5  and standardEPS5 >-0.01 ? (actualEPS1-standardEPS5) /math.abs(standardEPS5) *100:(actualEPS1-actualEPS5) /math.abs(actualEPS5) *100
EpsChangeHash2 = actualEPS6  >= 0 ? na:actualEPS2 < 0 and standardEPS6  < 0 ? na:actualEPS6  < 0 and standardEPS6  > 0 ? (actualEPS2-actualEPS6) /math.abs(actualEPS6) *100:actualEPS6  <= standardEPS6  and standardEPS6 >-0.01 ? (actualEPS2-standardEPS6) /math.abs(standardEPS6) *100:(actualEPS2-actualEPS6) /math.abs(actualEPS6) *100
EpsChangeHash3 = actualEPS7  >= 0 ? na:actualEPS3 < 0 and standardEPS7  < 0 ? na:actualEPS7  < 0 and standardEPS7  > 0 ? (actualEPS3-actualEPS7) /math.abs(actualEPS7) *100:actualEPS7  <= standardEPS7  and standardEPS7 >-0.01 ? (actualEPS3-standardEPS7) /math.abs(standardEPS7) *100:(actualEPS3-actualEPS7) /math.abs(actualEPS7) *100
EpsChangeHash4 = actualEPS8  >= 0 ? na:actualEPS4 < 0 and standardEPS8  < 0 ? na:actualEPS8  < 0 and standardEPS8  > 0 ? (actualEPS4-actualEPS8) /math.abs(actualEPS8) *100:actualEPS8  <= standardEPS8  and standardEPS8 >-0.01 ? (actualEPS4-standardEPS8) /math.abs(standardEPS8) *100:(actualEPS4-actualEPS8) /math.abs(actualEPS8) *100
EpsChangeHash5 = actualEPS9  >= 0 ? na:actualEPS5 < 0 and standardEPS9  < 0 ? na:actualEPS9  < 0 and standardEPS9  > 0 ? (actualEPS5-actualEPS9) /math.abs(actualEPS9) *100:actualEPS9  <= standardEPS9  and standardEPS9 >-0.01 ? (actualEPS5-standardEPS9) /math.abs(standardEPS9) *100:(actualEPS5-actualEPS9) /math.abs(actualEPS9) *100
EpsChangeHash6 = actualEPS10 >= 0 ? na:actualEPS6 < 0 and standardEPS10 < 0 ? na:actualEPS10 < 0 and standardEPS10 > 0 ? (actualEPS6-actualEPS10)/math.abs(actualEPS10)*100:actualEPS10 <= standardEPS10 and standardEPS10>-0.01 ? (actualEPS6-standardEPS10)/math.abs(standardEPS10)*100:(actualEPS6-actualEPS10)/math.abs(actualEPS10)*100
EpsChangeHash7 = actualEPS11 >= 0 ? na:actualEPS7 < 0 and standardEPS11 < 0 ? na:actualEPS11 < 0 and standardEPS11 > 0 ? (actualEPS7-actualEPS11)/math.abs(actualEPS11)*100:actualEPS11 <= standardEPS11 and standardEPS11>-0.01 ? (actualEPS7-standardEPS11)/math.abs(standardEPS11)*100:(actualEPS7-actualEPS11)/math.abs(actualEPS11)*100


// Due to comments I add a possibility to display the % variation even if the company is not profitable
if(i_alwaysDispP)
    EpsChangeF  := (futureEPS-actualEPS3  )/math.abs(actualEPS3) *100
    EpsChange0  := (actualEPS-actualEPS4  )/math.abs(actualEPS4) *100
    EpsChange1  := (actualEPS1-actualEPS5 )/math.abs(actualEPS5) *100
    EpsChange2  := (actualEPS2-actualEPS6 )/math.abs(actualEPS6) *100
    EpsChange3  := (actualEPS3-actualEPS7 )/math.abs(actualEPS7) *100
    EpsChange4  := (actualEPS4-actualEPS8 )/math.abs(actualEPS8) *100
    EpsChange5  := (actualEPS5-actualEPS9 )/math.abs(actualEPS9) *100
    EpsChange6  := (actualEPS6-actualEPS10)/math.abs(actualEPS10)*100
    EpsChange7  := (actualEPS7-actualEPS11)/math.abs(actualEPS11)*100
    
// EPS QoQ (To prevent me from harassment in the comments :-) ... )
EpsChangeQoQF = (futureEPS -actualEPS )/math.abs(actualEPS )*100
EpsChangeQoQ0 = (actualEPS -actualEPS1)/math.abs(actualEPS1)*100
EpsChangeQoQ1 = (actualEPS1-actualEPS2)/math.abs(actualEPS2)*100
EpsChangeQoQ2 = (actualEPS2-actualEPS3)/math.abs(actualEPS3)*100
EpsChangeQoQ3 = (actualEPS3-actualEPS4)/math.abs(actualEPS4)*100
EpsChangeQoQ4 = (actualEPS4-actualEPS5)/math.abs(actualEPS5)*100
EpsChangeQoQ5 = (actualEPS5-actualEPS6)/math.abs(actualEPS6)*100
EpsChangeQoQ6 = (actualEPS6-actualEPS7)/math.abs(actualEPS7)*100
EpsChangeQoQ7 = (actualEPS7-actualEPS8)/math.abs(actualEPS8)*100

// Sales Surprise
SalesSurprise0 = (sales  - salesEstimate )/math.abs(salesEstimate )*100
SalesSurprise1 = (sales1 - salesEstimate1)/math.abs(salesEstimate1)*100
SalesSurprise2 = (sales2 - salesEstimate2)/math.abs(salesEstimate2)*100
SalesSurprise3 = (sales3 - salesEstimate3)/math.abs(salesEstimate3)*100
SalesSurprise4 = (sales4 - salesEstimate4)/math.abs(salesEstimate4)*100
SalesSurprise5 = (sales5 - salesEstimate5)/math.abs(salesEstimate5)*100
SalesSurprise6 = (sales6 - salesEstimate6)/math.abs(salesEstimate6)*100
SalesSurprise7 = (sales7 - salesEstimate7)/math.abs(salesEstimate7)*100

// Sales QoQ
salesChangeQoQF = (futureSales-sales ) /math.abs(sales ) *100
salesChangeQoQ0 = (sales  -sales1) /math.abs(sales1) *100
salesChangeQoQ1 = (sales1 -sales2) /math.abs(sales2) *100
salesChangeQoQ2 = (sales2 -sales3) /math.abs(sales3) *100
salesChangeQoQ3 = (sales3 -sales4) /math.abs(sales4) *100
salesChangeQoQ4 = (sales4 -sales5) /math.abs(sales5) *100
salesChangeQoQ5 = (sales5 -sales6) /math.abs(sales6) *100
salesChangeQoQ6 = (sales6 -sales7) /math.abs(sales7) *100
salesChangeQoQ7 = (sales7 -sales8) /math.abs(sales8) *100


//Adapting Format of Sales 98 000 000 to 98,0 M 
futureS  = (futureSales/1000000)
Sales0M  = (sales /1000000)
Sales1M  = (sales1/1000000)
Sales2M  = (sales2/1000000)
Sales3M  = (sales3/1000000)
Sales4M  = (sales4/1000000)
Sales5M  = (sales5/1000000)
Sales6M  = (sales6/1000000)
Sales7M  = (sales7/1000000)
Sales8M  = (sales8/1000000)
Sales9M  = (sales9/1000000)
Sales10M = (sales10/1000000)
Sales11M = (sales11/1000000)

// If sales > 1000M we want it to be display in $Bil
if(sales >= 10000000000)
    futureS  := (futureSales/1000000000)
    Sales0M  := (sales /1000000000)
    Sales1M  := (sales1/1000000000)
    Sales2M  := (sales2/1000000000)
    Sales3M  := (sales3/1000000000)
    Sales4M  := (sales4/1000000000)
    Sales5M  := (sales5/1000000000)
    Sales6M  := (sales6/1000000000)
    Sales7M  := (sales7/1000000000)
    Sales8M  := (sales8/1000000000)
    Sales9M  := (sales9/1000000000)
    Sales10M := (sales10/1000000000)
    Sales11M := (sales11/1000000000)


// === TABLE FUNCTIONS === (Used for cells completion)
// Each function changes the display format in the cells
f_fillCell(_table, _column, _row, _value) =>
    _c_color = i_poscolorT
    _transp = 0
    _cellText = str.tostring(_value, '0.00')
    if(_cellText == 'NaN')
        _cellText := 'N/A'
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)

// To have one digit after coma for sales    
f_fillCell2(_table, _column, _row, _value) =>
    _c_color = i_poscolorT
    _transp = 0
    _cellText = str.tostring(_value, '0.0')
    if(_cellText == 'NaN')
        _cellText := 'N/A'
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)

// For Sales comparison    
f_fillCell2SALES(_table, _column, _row, _value, _value1) =>
    _c_color = i_poscolorT
    _transp = 0
    _cellText1 = str.tostring(_value, '0.0')
    _cellText2 = str.tostring(_value1,'0.0')
    if(_cellText1 == 'NaN')
        _cellText1 := 'N/A'
    if(_cellText2 == 'NaN')
        _cellText2 := 'N/A'
    _cellText  =  _cellText1 + ' vs ' + _cellText2
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)

// EPS comparison (Only used to compare EPS for calculation with a 'if' further)
f_fillCellEPS(_table, _column, _row, _value, _value1) =>
    _c_color = i_poscolorT
    _transp = 0
    _cellText1 = str.tostring(_value, '0.00')
    _cellText2 = str.tostring(_value1,'0.00')
    if(_cellText1 == 'NaN')
        _cellText1 := 'N/A'
    if(_cellText2 == 'NaN')
        _cellText2 := 'N/A'
    _cellText  =  _cellText1 + ' vs ' + _cellText2
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    
f_fillCellComp(_table, _column, _row, _value) =>
    _c_color = _value >= 0 ? i_poscolorT : i_negColorT
    _transp = 0
    // Recent modification made that I need to put the IBD/MarketSmith limitaton of +999% here
    _cellText = _value > 999 ? '+999%': _value < -999 ? '-999%' :_value > 0 ? '+' + str.tostring(_value, '0') + '%':str.tostring(_value, '0') + '%'
    if(_cellText == 'NaN%')
        _cellText := 'N/A'
    if(_cellText == '+0%')
        _cellText := '0%'
    if(_value == EpsChangeHash0)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash1)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash2)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash3)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash4)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash5)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash6)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    if(_value == EpsChangeHash7)
        _cellText := _value > 999 ? '#+999%': _value < -999 ? '#-999%' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '%':'#' + str.tostring(_value, '0') + '%'
    // Color for even or odd row
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=_cellText=='0%' or _cellText=='N/A'?i_RowAndColumnTextColor:_c_color,text_size=i_tableSize)

// FOR %SURPRISES
f_fillCellCompSurp(_table, _column, _row, _value) =>
    _c_color = _value >= 0 ? i_posSurp : i_negSurp
    _transp = 0
    // Recent modification made that I need to put the IBD/MarketSmith limitaton of +999% here
    _cellText = _value > 999 ? '+999%': _value < -999 ? '-999%' :_value > 0 ? '+' + str.tostring(_value, '0') + '%':str.tostring(_value, '0') + '%'
    if(_cellText == 'NaN%')
        _cellText := 'N/A'
    if(_cellText == '+0%')
        _cellText := '0%'
    if(_row == 11)
        _cellText := '-'
    // Color for even or odd row
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=_cellText=='0%' or _cellText=='N/A'?i_RowAndColumnTextColor:_c_color,text_size=i_tableSize)


//For QoQ EPS%
f_fillCellComp2(_table, _column, _row, _value) =>
    _c_color = _value >= 0 ? i_poscolorT : i_negColorT
    _transp = 0
    // Recent modification made that I need to put the IBD/MarketSmith limitaton of +999% here
    _cellText = _value > 999 ? '+999%':_value < -999 ? '-999%':_value > 0 ? '+' + str.tostring(_value, '0') + '%':str.tostring(_value, '0') + '%'
    if(_cellText == 'NaN%')
        _cellText := 'N/A'
    // Color for even or odd row
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=_cellText=='N/A'? i_RowAndColumnTextColor:_c_color,text_size=i_tableSize)
    
// Function for Date
f_array(arrayId, val) => 
    array.unshift(arrayId, val) // append vale to an array
    array.pop(arrayId)

ftdate(_table, _column, _row, _value) => 
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(table_id = _table, column = _column, row = _row, text = _value, bgcolor = myColor, text_color = i_RowAndColumnTextColor, text_size = i_tableSize)
// For Date
var date = array.new_int(datasize)
if rev
    f_array(date, time)


// For Daily Table
f_fillCellDa(_table, _column, _row, _value) =>
    _c_color = i_poscolorT
    _transp = 0
    _cellText = str.tostring(_value, '0.00') + ' |'
    if(_cellText == 'NaN')
        _cellText := 'N/A |'
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)

// To have one digit after coma for sales    
f_fillCell2Da(_table, _column, _row, _value) =>
    _c_color = i_poscolorT
    _transp = 0
    _cellText = str.tostring(_value, '0.0')  + ' |'
    if(_cellText == 'NaN |')
        _cellText := 'N/A |'
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    
f_fillCellCompDa(_table, _column, _row, _value) =>
    _c_color = _value >= 0 ? i_poscolorT : i_negColorT
    _transp = 0
    // Recent modification made that I need to put the IBD/MarketSmith limitaton of +999% here
    _cellText = _value > 999 ? '+999% |': _value < -999 ? '-999% |' :_value > 0 ? '+' + str.tostring(_value, '0') + '% |':str.tostring(_value, '0') + '% |'
    if(_cellText == 'NaN% |')
        _cellText := 'N/A |'
    if(_cellText == '+0% |')
        _cellText := '0% |'
    if(_value == EpsChangeHash0)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash1)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash2)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash3)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash4)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash5)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash6)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    if(_value == EpsChangeHash7)
        _cellText := _value > 999 ? '#+999% |': _value < -999 ? '#-999% |' : _value > 0 ? '#' +  '+' + str.tostring(_value, '0') + '% |':'#' + str.tostring(_value, '0') + '% |'
    // Color for even or odd row
    myColor = _row == 10 or _row == 8 or _row == 6 or _row == 4 ? i_resultBackgroundColorOdd:i_resultBackgroundColorEven
    if (i_tableStyle == 'HeadBand')
        myColor := i_resultBackgroundColorOdd
    table.cell(_table, _column, _row, _cellText, bgcolor=myColor, text_color=_cellText=='0% |' or _cellText=='N/A |'?i_RowAndColumnTextColor:_c_color,text_size=i_tableSize)



// Function used to master the fill of cells - Weekly Table
condRepeatSameValueAtLastLine = actualEPS==actualEPS1 and standardEPS==standardEPS1 and EPS_Estimate==EPS_Estimate[1] // here I use 'and' instead of 'or' because we want to avoid the display bug of TradingView when the 2 last lines repeat themselves
if barstate.islast and i_tableStyle == 'Table'
    table.set_frame_color (epsTableDa, color.rgb(0,0,0,100))
    table.set_border_color(epsTableDa, color.rgb(0,0,0,100))
    // EPS DISPLAY
    if(i_compare == true)
        if (i_estimates)
            f_fillCellEPS(epsTable, 1, 11, futureEPS, actualEPS3)
        f_fillCellEPS(epsTable, 1, 10, condRepeatSameValueAtLastLine ? na:EPS,condRepeatSameValueAtLastLine ? na:actualEPS4)
        f_fillCellEPS(epsTable, 1, 9, actualEPS1, actualEPS5)
        f_fillCellEPS(epsTable, 1, 8, actualEPS2, actualEPS6)
        f_fillCellEPS(epsTable, 1, 7, actualEPS3, actualEPS7)
        f_fillCellEPS(epsTable, 1, 6, actualEPS4, actualEPS8)
        if(i_moreData == false)
            f_fillCellEPS(epsTable, 1, 5, actualEPS5, actualEPS9)
            f_fillCellEPS(epsTable, 1, 4, actualEPS6, actualEPS10)
            f_fillCellEPS(epsTable, 1, 3, actualEPS7, actualEPS11)
    if(i_compare == false)
        if (i_estimates)
            f_fillCell(epsTable, 1, 11, futureEPS)
        f_fillCell(epsTable, 1, 10, condRepeatSameValueAtLastLine ? na:EPS)
        f_fillCell(epsTable, 1, 9, actualEPS1)
        f_fillCell(epsTable, 1, 8, actualEPS2)
        f_fillCell(epsTable, 1, 7, actualEPS3)
        f_fillCell(epsTable, 1, 6, actualEPS4)
        if(i_moreData == false)
            f_fillCell(epsTable, 1, 5, actualEPS5)
            f_fillCell(epsTable, 1, 4, actualEPS6)
            f_fillCell(epsTable, 1, 3, actualEPS7)
    // % CHANGE EPS
    if (i_YoY)
        if(i_moreData == false)
            f_fillCellComp(epsTable, 2, 3, i_alwaysDispP ? EpsChange7:EpsChangeHash7 > EpsChange7 ? EpsChangeHash7:EpsChange7)
            f_fillCellComp(epsTable, 2, 4, i_alwaysDispP ? EpsChange6:EpsChangeHash6 > EpsChange6 ? EpsChangeHash6:EpsChange6)
            f_fillCellComp(epsTable, 2, 5, i_alwaysDispP ? EpsChange5:EpsChangeHash5 > EpsChange5 ? EpsChangeHash5:EpsChange5)
        f_fillCellComp(epsTable, 2, 6, i_alwaysDispP ? EpsChange4:EpsChangeHash4 > EpsChange4 ? EpsChangeHash4:EpsChange4)
        f_fillCellComp(epsTable, 2, 7, i_alwaysDispP ? EpsChange3:EpsChangeHash3 > EpsChange3 ? EpsChangeHash3:EpsChange3)
        f_fillCellComp(epsTable, 2, 8, i_alwaysDispP ? EpsChange2:EpsChangeHash2 > EpsChange2 ? EpsChangeHash2:EpsChange2)
        f_fillCellComp(epsTable, 2, 9, i_alwaysDispP ? EpsChange1:EpsChangeHash1 > EpsChange1 ? EpsChangeHash1:EpsChange1)
        f_fillCellComp(epsTable, 2, 10, condRepeatSameValueAtLastLine ? na:i_alwaysDispP ? EpsChange0:EpsChangeHash0 > EpsChange0 ? EpsChangeHash0:EpsChange0)
        if (i_estimates)
            f_fillCellComp(epsTable, 2, 11, EpsChangeF)
    // % CHANGE EPS QoQ
    if(i_QoQ == true)
        if(i_moreData == false)
            f_fillCellComp2(epsTable, 3, 3, EpsChangeQoQ7)
            f_fillCellComp2(epsTable, 3, 4, EpsChangeQoQ6)
            f_fillCellComp2(epsTable, 3, 5, EpsChangeQoQ5)
        f_fillCellComp2(epsTable, 3, 6, EpsChangeQoQ4)
        f_fillCellComp2(epsTable, 3, 7, EpsChangeQoQ3)
        f_fillCellComp2(epsTable, 3, 8, EpsChangeQoQ2)
        f_fillCellComp2(epsTable, 3, 9, EpsChangeQoQ1)
        f_fillCellComp2(epsTable, 3, 10, EpsChangeQoQ0)
        if (i_estimates)
            f_fillCellComp2(epsTable, 3, 11, EpsChangeQoQF)
    // %SURPRISE EPS
    if(i_surprises)
        if(i_moreData == false)
            f_fillCellCompSurp(epsTable, 4, 3,  EpsSurprise7)
            f_fillCellCompSurp(epsTable, 4, 4,  EpsSurprise6)
            f_fillCellCompSurp(epsTable, 4, 5,  EpsSurprise5)
        f_fillCellCompSurp(epsTable, 4, 6,  EpsSurprise4)
        f_fillCellCompSurp(epsTable, 4, 7,  EpsSurprise3)
        f_fillCellCompSurp(epsTable, 4, 8,  EpsSurprise2)
        f_fillCellCompSurp(epsTable, 4, 9,  EpsSurprise1)
        f_fillCellCompSurp(epsTable, 4, 10, EpsSurprise0)
        if (i_estimates)
            f_fillCellCompSurp(epsTable, 4, 11, 0)
    
    
    //SALES DISPLAY
    if(i_compare == true)
        if (i_estimates)
            f_fillCell2SALES(epsTable, 5, 11, futureS, Sales3M)
        f_fillCell2SALES(epsTable, 5, 10, condRepeatSameValueAtLastLine ? na:recentEarn and sameSales ? na:Sales0M,condRepeatSameValueAtLastLine ? na:Sales4M)
        f_fillCell2SALES(epsTable, 5, 9, Sales1M, Sales5M)
        f_fillCell2SALES(epsTable, 5, 8, Sales2M, Sales6M)
        f_fillCell2SALES(epsTable, 5, 7, Sales3M, Sales7M)
        f_fillCell2SALES(epsTable, 5, 6, Sales4M, Sales8M)
        if(i_moreData == false)
            f_fillCell2SALES(epsTable, 5, 5, Sales5M, Sales9M )
            f_fillCell2SALES(epsTable, 5, 4, Sales6M, Sales10M)
            f_fillCell2SALES(epsTable, 5, 3, Sales7M, Sales11M)
    // SALES Normal
    if(i_compare == false)
        if (i_estimates)
            f_fillCell2(epsTable, 5,11, futureS)
        f_fillCell2(epsTable, 5, 10, condRepeatSameValueAtLastLine ? na:recentEarn and sameSales ? na:Sales0M)
        f_fillCell2(epsTable, 5, 9, Sales1M)
        f_fillCell2(epsTable, 5, 8, Sales2M)
        f_fillCell2(epsTable, 5, 7, Sales3M)
        f_fillCell2(epsTable, 5, 6, Sales4M)
        if(i_moreData == false)
            f_fillCell2(epsTable, 5, 5, Sales5M)
            f_fillCell2(epsTable, 5, 4, Sales6M)
            f_fillCell2(epsTable, 5, 3, Sales7M) 
    // % CHANGE SALES YOY
    if (i_YoY)
        if(i_moreData == false)
            f_fillCellComp(epsTable, 6, 3, salesChange7)
            f_fillCellComp(epsTable, 6, 4, salesChange6)
            f_fillCellComp(epsTable, 6, 5, salesChange5)
        f_fillCellComp(epsTable, 6, 6, salesChange4)
        f_fillCellComp(epsTable, 6, 7, salesChange3)
        f_fillCellComp(epsTable, 6, 8, salesChange2)
        f_fillCellComp(epsTable, 6, 9, salesChange1)
        f_fillCellComp(epsTable, 6, 10, condRepeatSameValueAtLastLine ? na:recentEarn and sameSales ? na:salesChange0)
        if (i_estimates)
            f_fillCellComp(epsTable, 6, 11, salesChangeF)
    if(i_QoQ == true)
        if(i_moreData == false)
            f_fillCellComp(epsTable, 7, 3, salesChangeQoQ7)
            f_fillCellComp(epsTable, 7, 4, salesChangeQoQ6)
            f_fillCellComp(epsTable, 7, 5, salesChangeQoQ5)
        f_fillCellComp(epsTable, 7, 6, salesChangeQoQ4)
        f_fillCellComp(epsTable, 7, 7, salesChangeQoQ3)
        f_fillCellComp(epsTable, 7, 8, salesChangeQoQ2)
        f_fillCellComp(epsTable, 7, 9, salesChangeQoQ1)
        f_fillCellComp(epsTable, 7, 10, condRepeatSameValueAtLastLine ? na:recentEarn and sameSales ? na:salesChangeQoQ0)
        if (i_estimates)
            f_fillCellComp(epsTable, 7, 11, salesChangeQoQF)
    // %SURPRISE SALES
    if(i_surprises)
        if(i_moreData == false)
            f_fillCellCompSurp(epsTable, 8, 3,  SalesSurprise7)
            f_fillCellCompSurp(epsTable, 8, 4,  SalesSurprise6)
            f_fillCellCompSurp(epsTable, 8, 5,  SalesSurprise5)
        f_fillCellCompSurp(epsTable, 8, 6,  SalesSurprise4)
        f_fillCellCompSurp(epsTable, 8, 7,  SalesSurprise3)
        f_fillCellCompSurp(epsTable, 8, 8,  SalesSurprise2)
        f_fillCellCompSurp(epsTable, 8, 9,  SalesSurprise1)
        f_fillCellCompSurp(epsTable, 8, 10, SalesSurprise0)
        if (i_estimates)
            f_fillCellCompSurp(epsTable, 8, 11, 0)
    // GROSS MARGIN 
    if(i_grossMargin == true)
        if(i_moreData == false)
            f_fillCellComp(epsTable, 9, 3, GM7)
            f_fillCellComp(epsTable, 9, 4, GM6)
            f_fillCellComp(epsTable, 9, 5, GM5)
        f_fillCellComp(epsTable, 9, 6, GM4)
        f_fillCellComp(epsTable, 9, 7, GM3)
        f_fillCellComp(epsTable, 9, 8, GM2)
        f_fillCellComp(epsTable, 9, 9, GM1)
        f_fillCellComp(epsTable, 9, 10, GM0)
        if (i_estimates)
            f_fillCellComp(epsTable, 9, 11, 0)
    // ROE
    if(i_ROE == true)
        if(i_moreData == false)
            f_fillCellComp(epsTable, 10, 3, ROE7)
            f_fillCellComp(epsTable, 10, 4, ROE6)
            f_fillCellComp(epsTable, 10, 5, ROE5)
        f_fillCellComp(epsTable, 10, 6, ROE4)
        f_fillCellComp(epsTable, 10, 7, ROE3)
        f_fillCellComp(epsTable, 10, 8, ROE2)
        f_fillCellComp(epsTable, 10, 9, ROE1)
        f_fillCellComp(epsTable, 10, 10, ROE0)
        if (i_estimates)
            f_fillCellComp(epsTable, 10, 11, 0)
    
    // For Date MMM-yy
    for i = 0 to datasize-blankUnderUp
        if barstate.islast
            ftdate(epsTable, 0, (datasize-i), str.format('{0, date, MMM-yy}', array.get(date, i)))
    if (i_estimates)
        ftdate(epsTable, 0, 11, str.format('{0, date, MMM-yy}', futureTime)+" est")
    
    //Headings of Weekly Table

    txt8 = 'Quarterly '
    txt9 = '     EPS($)  '
    txt6 = '      %Chg '
    txt10 = '  Sales($Mil) '
    if(sales >= 10000000000)
        txt10 := '  Sales($Bil) '
    // txt11 = '     %Chg  '
    txt12 = '   GM   '
    txt13 = '  ROE  '
    txt14 = '%Surp '
    txtQE = ' QoQ '

    // Table Heading
    table.cell(epsTable,0,0, text=txt8,  bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTable,1,0, text=txt9,  bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if (i_YoY)
        table.cell(epsTable,2,0, text=txt6,  bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if (i_QoQ)
        table.cell(epsTable,3,0, text=txtQE, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if(i_surprises)
        table.cell(epsTable,4,0, text=txt14, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTable,5,0, text=txt10, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if (i_YoY)
        table.cell(epsTable,6,0, text=txt6, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if (i_QoQ)
        table.cell(epsTable,7,0, text=txtQE, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if(i_surprises)
        table.cell(epsTable,8,0, text=txt14, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if(i_grossMargin == true)
        table.cell(epsTable,9,0, text=txt12, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    if(i_ROE == true)
        table.cell(epsTable,10,0, text=txt13, bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)



// Align Text to Right For MarketSmith like design
three = i_moreData  ? 6:3 // Begins at 3 if 8 rows and 6 if 5 rows
ten   = i_estimates ? 11:10
// Don't Aligne First Column anymore
// if (i_estimates)
//     table.cell_set_text_halign(epsTable, 0, 11, text_halign = text.align_right)
for i = three to ten // Column 0, line 1 to 9 (With two empty Lines Under heading... So 3 to 10)   
    table.cell_set_text_halign(epsTable, 1, i, text_halign = text.align_right)
    if (i_YoY)
        table.cell_set_text_halign(epsTable, 2, i, text_halign = text.align_right)
    if (i_QoQ)
        table.cell_set_text_halign(epsTable, 3, i, text_halign = text.align_right)
    if (i_surprises)
        table.cell_set_text_halign(epsTable, 4, i, text_halign = text.align_right)
    table.cell_set_text_halign(epsTable, 5, i, text_halign = text.align_right)
    if (i_YoY)
        table.cell_set_text_halign(epsTable, 6, i, text_halign = text.align_right)
    if (i_QoQ)
        table.cell_set_text_halign(epsTable, 7, i, text_halign = text.align_right)
    if(i_surprises)
        table.cell_set_text_halign(epsTable, 8, i, text_halign = text.align_right)
    if(i_grossMargin == true)
        table.cell_set_text_halign(epsTable, 9, i, text_halign = text.align_right)
    if(i_ROE == true)
        table.cell_set_text_halign(epsTable, 10, i, text_halign = text.align_right)


// Date
// if(i_moreData)
//     table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
// table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
// // Align surprises
// if(i_surprises)
//     if(i_moreData)
//         table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
//     table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
// // Align GM
// if(i_grossMargin)
//     if(i_moreData)
//         table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
//     table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
// // Align ROE
// if(i_ROE)
//     if(i_moreData)
//         table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)
//     table.cell_set_text_halign(epsTable, x,  i, text_halign = text.align_right)

// Daily Table
if barstate.islast and i_tableStyle == 'HeadBand'
    table.set_frame_color (epsTable, color.rgb(0,0,0,100))
    table.set_border_color(epsTable, color.rgb(0,0,0,100))
    // DISPLAY of the Daily Table **************************************************************************************
    // Date
    if(not i_tableBorder)
        ftdate(epsTableDa, 12, 0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 0)) + '         │')
        ftdate(epsTableDa, 8,  0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 1)) + '         │')
        ftdate(epsTableDa, 4,  0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 2)) + '         │')
        ftdate(epsTableDa, 0,  0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 3)) + '         │')
    else
        ftdate(epsTableDa, 12, 0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 0)) + '          ')
        ftdate(epsTableDa, 8,  0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 1)) + '          ')
        ftdate(epsTableDa, 4,  0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 2)) + '          ')
        ftdate(epsTableDa, 0,  0, '         Qtr Ended ' + str.format('{0, date,MMMMMMMMM dd, yyyy}', array.get(date, 3)) + '          ')
    table.cell(epsTableDa, 16, 0, text='EPS Due '+ str.format('{0, date,MM/dd}', futureTime), bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor ,text_size=i_tableSize)
    // EPS 1 
    f_fillCell(epsTableDa, 12, 1, condRepeatSameValueAtLastLine ? na:EPS)
    f_fillCell(epsTableDa, 8, 1, actualEPS1)
    f_fillCell(epsTableDa, 4, 1, actualEPS2)
    f_fillCell(epsTableDa, 0, 1, actualEPS3)
    // vs
    table.cell(epsTableDa, 13,1, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 9 ,1, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 5 ,1, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 1 ,1, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    // EPS2
    f_fillCell(epsTableDa, 14, 1, condRepeatSameValueAtLastLine ? na:actualEPS4)
    f_fillCell(epsTableDa, 10, 1, actualEPS5)
    f_fillCell(epsTableDa, 6,  1, actualEPS6)
    f_fillCell(epsTableDa, 2,  1, actualEPS7)
    // EPS%
    if(not i_tableBorder)
        f_fillCellCompDa(epsTableDa, 15, 1, condRepeatSameValueAtLastLine ? na:i_alwaysDispP ? EpsChange0:EpsChangeHash0 > EpsChange0 ? EpsChangeHash0:EpsChange0)
        f_fillCellCompDa(epsTableDa, 11, 1, i_alwaysDispP ? EpsChange1:EpsChangeHash1 > EpsChange1 ? EpsChangeHash1:EpsChange1)
        f_fillCellCompDa(epsTableDa, 7,  1, i_alwaysDispP ? EpsChange2:EpsChangeHash2 > EpsChange2 ? EpsChangeHash2:EpsChange2)
        f_fillCellCompDa(epsTableDa, 3,  1, i_alwaysDispP ? EpsChange3:EpsChangeHash3 > EpsChange3 ? EpsChangeHash3:EpsChange3)
    else
        f_fillCellComp(epsTableDa, 15, 1, condRepeatSameValueAtLastLine ? na:i_alwaysDispP ? EpsChange0:EpsChangeHash0 > EpsChange0 ? EpsChangeHash0:EpsChange0)
        f_fillCellComp(epsTableDa, 11, 1, i_alwaysDispP ? EpsChange1:EpsChangeHash1 > EpsChange1 ? EpsChangeHash1:EpsChange1)
        f_fillCellComp(epsTableDa, 7,  1, i_alwaysDispP ? EpsChange2:EpsChangeHash2 > EpsChange2 ? EpsChangeHash2:EpsChange2)
        f_fillCellComp(epsTableDa, 3,  1, i_alwaysDispP ? EpsChange3:EpsChangeHash3 > EpsChange3 ? EpsChangeHash3:EpsChange3)
    // Sales 1
    f_fillCell2(epsTableDa, 12, 2, condRepeatSameValueAtLastLine ? na:(EPSTime or EPSTime[1]) and sameSales ? na:Sales0M)
    f_fillCell2(epsTableDa, 8,  2, Sales1M)
    f_fillCell2(epsTableDa, 4,  2, Sales2M)
    f_fillCell2(epsTableDa, 0,  2, Sales3M)
    // vs
    table.cell(epsTableDa, 13, 2, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 9 , 2, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 5 , 2, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 1 , 2, text='           vs      ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    // Sales 2
    f_fillCell2(epsTableDa, 14, 2, condRepeatSameValueAtLastLine ? na:Sales4M)
    f_fillCell2(epsTableDa, 10, 2, Sales5M)
    f_fillCell2(epsTableDa, 6,  2,  Sales6M)
    f_fillCell2(epsTableDa, 2,  2,  Sales7M)
    // Sales%
    if (not i_tableBorder)
        f_fillCellCompDa(epsTableDa, 15, 2, condRepeatSameValueAtLastLine ? na:(EPSTime or EPSTime[1]) and sameSales ? na:salesChange0)
        f_fillCellCompDa(epsTableDa, 11, 2, salesChange1)
        f_fillCellCompDa(epsTableDa, 7,  2, salesChange2)
        f_fillCellCompDa(epsTableDa, 3,  2, salesChange3)
    else
        f_fillCellComp(epsTableDa, 15, 2, condRepeatSameValueAtLastLine ? na:(EPSTime or EPSTime[1]) and sameSales ? na:salesChange0)
        f_fillCellComp(epsTableDa, 11, 2, salesChange1)
        f_fillCellComp(epsTableDa, 7,  2, salesChange2)
        f_fillCellComp(epsTableDa, 3,  2, salesChange3)
    // ROE
    if (i_ROE == true)
        if(not i_tableBorder)
            f_fillCellCompDa(epsTableDa, 15, 3, ROE0) 
            f_fillCellCompDa(epsTableDa, 11, 3, ROE1)
            f_fillCellCompDa(epsTableDa, 7,  3, ROE2)
            f_fillCellCompDa(epsTableDa, 3,  3, ROE3)
        else
            f_fillCellComp(epsTableDa, 15, 3, ROE0) 
            f_fillCellComp(epsTableDa, 11, 3, ROE1)
            f_fillCellComp(epsTableDa, 7,  3, ROE2)
            f_fillCellComp(epsTableDa, 3,  3, ROE3)
    if (i_grossMargin)
        if(not i_tableBorder)
            f_fillCellCompDa(epsTableDa, 15, 3, GM0)
            f_fillCellCompDa(epsTableDa, 11, 3, GM1)
            f_fillCellCompDa(epsTableDa, 7,  3, GM2)
            f_fillCellCompDa(epsTableDa, 3,  3, GM3)
        else
            f_fillCellComp(epsTableDa, 15, 3, GM0)
            f_fillCellComp(epsTableDa, 11, 3, GM1)
            f_fillCellComp(epsTableDa, 7,  3, GM2)
            f_fillCellComp(epsTableDa, 3,  3, GM3)
    // Empty cells
    if (i_grossMargin == false and i_ROE == false)
        table.cell(epsTableDa,  3, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
        table.cell(epsTableDa,  7, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
        table.cell(epsTableDa, 11, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
        table.cell(epsTableDa, 15, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  0, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  1, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  2, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  4, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  5, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  6, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  8, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,  9, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 10, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 12, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 13, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa, 14, 3, text='', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)


    // Headings For Daily Table
    txt20 = 'Sales ($Mil)'
    if(sales >= 10000000000)
        txt20 := 'Sales ($Bil)'

    txt21 = ''
    if(i_ROE)
        txt21 := 'Return on Equity'
    if(i_grossMargin)
        txt21 := 'Gross Margin'
    
    // Data for Daily Table
    table.cell(epsTableDa,16,1, text='Earnings ($)           ', bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,16,2, text=txt20,                     bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize)
    table.cell(epsTableDa,16,3, text=txt21,                     bgcolor=i_resultBackgroundColorOdd, text_color=i_RowAndColumnTextColor,text_size=i_tableSize) 
    // // Change BG Colors of all the table
    // for i = 0 to 16
    //     for x = 0 to 3
    //         table.cell_set_bgcolor(epsTableDa, i,  x, i_resultBackgroundColorOdd)
    // Text Align
    // EPS and Sales at the left
    table.cell_set_text_halign(epsTableDa, 0,  1, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 0,  2, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 4,  1, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 4,  2, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 8,  1, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 8,  2, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 12, 1, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 12, 2, text_halign = text.align_left)
    // % figures
    table.cell_set_text_halign(epsTableDa, 3,   1, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 3,   2, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 3,   3, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 7,   1, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 7,   2, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 7,   3, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 11,  1, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 11,  2, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 11,  3, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 15,  1, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 15,  2, text_halign = text.align_right)
    table.cell_set_text_halign(epsTableDa, 15,  3, text_halign = text.align_right)
    // Earnings info
    table.cell_set_text_halign(epsTableDa, 16,  1, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 16,  2, text_halign = text.align_left)
    table.cell_set_text_halign(epsTableDa, 16,  3, text_halign = text.align_left)
    // Merge Cell
    table.merge_cells(epsTableDa, 0,  0,  3, 0)
    table.merge_cells(epsTableDa, 4,  0,  7, 0)
    table.merge_cells(epsTableDa, 8,  0, 11, 0)
    table.merge_cells(epsTableDa, 12, 0, 15, 0)



// Diplay Arrow on the graph with % variation EPS
selectEPS = ta.valuewhen(EPSTime, EpsChangeHash0, 0) > ta.valuewhen(EPSTime, EpsChange0, 0) // Time for Sales annoucement
EPSvalue   = i_ArrowQoq ? EpsChangeQoQ0:selectEPS ? ta.valuewhen(EPSTime, EpsChangeHash0, 0):ta.valuewhen(EPSTime, EpsChange0, 0)
salesValue = i_ArrowQoq ? salesChangeQoQ0:ta.valuewhen(EPSTime, salesChange0, 0) // Select the value of % sales change for the date of the arrow
//plotshape(EPSTime, style=shape.triangleup, color=color.new(color.silver, 0), location=location.bottom, size=size.tiny, text='', textcolor = color.white)
textLayout1 = i_salesOnGraph ? 'EPS & Sales':'EPS'
textLayout2 = EPSvalue > 999 ? '\n+999%':EPSvalue > 0 ? '\n+' + str.tostring(EPSvalue, '0') + '%':'\n' + str.tostring(EPSvalue, '0') + '%'
if(textLayout2 == '\nNaN%')
    textLayout2 := '\nN/A'
if(textLayout2 == '\n+0%')
    textLayout2 := '\n0%'
textLayout4 = (EPSTime or EPSTime[1]) and sameSales and barstate.islast ? 'NaN%':salesValue > 999 ? '+999%':salesValue > 0 ? '+' + str.tostring(salesValue, '0') + '%':str.tostring(salesValue, '0') + '%' // For Sales
if(textLayout4 == 'NaN%')
    textLayout4 := 'N/A'
if(textLayout4 == '+0%')
    textLayout4 := '0%'
// Here we check if we have to plot sales or not, depending on the result we display appropriate variables
if(EPSTime and i_ArrowOnGraph)
    label1 = label.new(bar_index, bar_index, xloc=xloc.bar_index, yloc=yloc.belowbar, text=textLayout1, style=label.style_triangleup, color=color.new(color.aqua,100), textcolor=i_arrowColor, size=i_arrowSize)
    if(not i_salesOnGraph)
        label2 = label.new(bar_index, low, xloc=xloc.bar_index, yloc=yloc.belowbar, text=textLayout2, style=label.style_triangleup, color=i_arrowColor,              textcolor=textLayout2=='\nN/A' or textLayout2=='\n0%' ? i_arrowColor:EPSvalue > -1 ? i_posArrowColor:i_negArrowColor, size=i_arrowSize)
    if(i_salesOnGraph)
        label2 = label.new(bar_index, low, xloc=xloc.bar_index, yloc=yloc.belowbar, text=textLayout2+' | '+textLayout4, style=label.style_triangleup, color=i_arrowColor,              textcolor=textLayout2=='\nN/A' or textLayout2=='\n0%' ? i_arrowColor:EPSvalue > -1 ? i_posArrowColor:i_negArrowColor, size=i_arrowSize)

// Test for better arrow display but now the space between arrows and text isn't fix...
// offsetArrow = ta.lowest(low*0.85, 4) // Get the Lowest low of the 4 previous bars for correct diplay even in case of earning gap up
// if(EPSTime and i_ArrowOnGraph)
//     label1    = label.new(bar_index, offsetArrow, xloc=xloc.bar_index, yloc=yloc.price, text='', style=label.style_triangleup, color=i_arrowColor, textcolor=i_arrowColor, size=i_arrowSize)
//     label1Eps = label.new(bar_index, offsetArrow*0.85, xloc=xloc.bar_index, yloc=yloc.price, text=textLayout1, style=label.style_triangleup, color=color.new(color.aqua,100), textcolor=i_arrowColor, size=i_arrowSize)
//     if(not i_salesOnGraph)
//         label2 = label.new(bar_index, offsetArrow*0.81, xloc=xloc.bar_index, yloc=yloc.price, text=textLayout2, style=label.style_triangleup, color=color.new(color.aqua,100),              textcolor=textLayout2=='\nN/A' or textLayout2=='\n0%' ? i_arrowColor:EPSvalue > -1 ? i_posArrowColor:i_negArrowColor, size=i_arrowSize)
//     if(i_salesOnGraph)
//         label2 = label.new(bar_index, offsetArrow*0.81, xloc=xloc.bar_index, yloc=yloc.price, text=textLayout2+' | '+textLayout4, style=label.style_triangleup, color=color.new(color.aqua,100),              textcolor=textLayout2=='\nN/A' or textLayout2=='\n0%' ? i_arrowColor:EPSvalue > -1 ? i_posArrowColor:i_negArrowColor, size=i_arrowSize)

Overview

Bar colors can be based either on the bar open relative to close or on the price relative to the previous bar close. It provides options to display multiple moving averages (SMA or EMA) with custom lengths and colors suited for standard charts as well as weekly timeframe analysis.

Details

Published by

klevler on GitHub

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

Moving averages, Trend

Markets

Stocks

Timeframes

M15-H1, H4 and above

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
Color Based On Previous ClosebooltrueprevClose
Candle Color Positivecolorcolor.rgb(39, 54,233,0)i_posColor
Negativecolorcolor.rgb(222,50,174,0)i_negColor
MA 1booltrueiSma10
Lenghtint10iSmaV10
ExponentialbooltrueiExp10
iCol10colorcolor.rgb(68,186,76)iCol10
MA 2booltrueiSma21
Lenghtint21iSmaV21
ExponentialbooltrueiExp21
iCol21colorcolor.rgb(240,141,240,0)iCol21
MA 3booltrueiSma50
Show all 40 settings
SettingTypeDefaultVariable
Lenghtint50iSmaV50
ExponentialboolfalseiExp50
iCol50colorcolor.rgb(255,33,33)iCol50
MA 4booltrueiSma200
Lenghtint200iSmaV200
ExponentialboolfalseiExp200
iCol200colorcolor.rgb(0,0,0,0)iCol200
SMA 1booltrueiSma10We
Lenghtint10iSmaV10We
ExponentialboolfalseiExp10We
iCol10Wecolorcolor.rgb(255,33,33)iCol10We
EMA 2booltrueiEma20We
Lenghtint20iSmaV20We
ExponentialbooltrueiExp20We
iCol20Wecolorcolor.rgb(240,141,240,0)iCol20We
SMA 3booltrueiSma30We
Lenghtint30iSmaV30We
ExponentialboolfalseiExp30We
iCol30Wecolorcolor.rgb(68,186,76)iCol30We
SMA 4booltrueiSma40We
Lenghtint40iSmaV40We
ExponentialboolfalseiExp40We
iCol40Wecolorcolor.rgb(0,0,0,0)iCol40We
Hide RS LineboolfalsehideRSLine
Hide RatingboolfalsehideRSRat
Rating OnlyboolfalseratingOnly
Comparative Symbol for LinestringSP:SPXlineTicker
Value of Comparative Symbolint4200SpxValue
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

948 stars

The Adaptive Laguerre Filter calculates a smoothed, dynamically adjusted trendline plotted directly on the main price chart. It dynamically adjusts its damping factor (alpha) based on recent price range variations and median percentile calculations over a spec

Indicator v4 TrendMoving averages
Updated 10 days ago · GPL-3.0 GitHub repository of Adaptive Laguerre Filter
330 stars

This script plots three moving averages on the price chart: a fast EMA or SMA with 10 periods, a slow EMA or SMA with 20 periods, and a trend EMA or SMA with 100 periods. It signals trend changes by drawing a white cross when the fast moving average crosses ab

Indicator v4 TrendMoving averages
Updated 2 months ago · None stated GitHub repository of 3 EMA/SMA + Cross [Alorse]
318 stars

This indicator plots four customizable moving averages directly on the main price chart using default lengths of 3, 8, 21, and 50 periods. It fills the space between adjacent averages in green or maroon depending on trend alignment. Additionally, it computes B

Indicator v5 Moving averagesTrend
Updated 2 months ago · MIT GitHub repository of Multiple Moving Averages

NVDA Trend Ribbon

by longsurf-ai
277 stars

This indicator plots three exponential moving averages and ATR volatility envelopes on the price chart. It compares the fast and slow EMAs to shade a trend ribbon and marks confirmed upward and downward crossovers with triangle labels. Settings change the thre

Indicator v6 TrendMoving averages
Updated yesterday · MIT GitHub repository of NVDA Trend Ribbon
257 stars

Donald SPX - Options Trading is an overlay indicator designed for intraday SPX analysis. It plots a 200-period Weighted Moving Average (WMA) on the price chart while evaluating multi-timeframe market structure across Daily, 15-minute, 5-minute, and 2-minute ba

Indicator v5 Moving averagesTrend Repaints
Updated 6 weeks ago · None stated GitHub repository of Donald SPX - Options Trading

60K均線

by TaichiS
219 stars

This multi-timeframe indicator calculates and plots 20-period and 60-period simple moving averages from the 60-minute timeframe directly onto the price chart. The 20-period average displays as a green line, while the 60-period average appears in blue. It serve

Indicator v4 Moving averagesTrend Repaints
Updated 5 years ago · None stated GitHub repository of 60K均線

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers