Cleaner Screeners Library
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=5

// © kaigouthro
// Thanks @ PineCoders , and the Group members for setting the bar high.


// @description # Screener Panel.
// > This indicator displays a panel with a list of symbols and their indications.
// > It can be used as a screener for multiple timess and symbols
// > in any timeframe and with any indication in any combination.
// ### Features
// > - Multiple timeframes
// > - Multiple symbols
// > - Multiple indications per group
// > - Vertical or horizontal layouts
// > - Acceepts External Inputs
// > - Customizable colors with 170 presets included (dark and light)
// > - Customizable icons
// > - Customizable text size and font
// > - Customizable cell size width and height
// > - Customizable frame width and border width
// > - Customizable position
// > - Customizable strong and weak values
// > - Accepts any indicator as input
// > - Only 4 functions to call, easy to use
// ### Usage
//
// `local setup for methods on our script`
// ```
// 
// import kaigouthro/cleanscreen/2
// method Screener  ( cleanscreen.panel      p , string _name                       ) => cleanscreens.Screener  ( p,  _name) 
// method Indicator ( cleanscreen.screener   s , string _tf, string name, float val ) => cleanscreens.Indicator ( s , _tf, name, val) 
// method display   ( cleanscreen.panel      p                                      ) => cleanscreens.display   ( p ) 
// 
// // Initialize the panel with 
// _paneel   = cleanscreens.init()  
// // Add groupd with 
// _screener  = _paneel.Screener("Group Name")  
// // Add indicartors to screeener groups with 
// _screener.Indication( "Indicator Name", _source)
//
// Update the panel with
// _paneel.display(_paneel)
//
//```
library("cleanscreens",true)

____z()=>
    /////////////////////////////////////////////////////////////////////////////////
    _o  = '         █▀ █▀▀ █▀█ █▀▀ █▀▀ █▄░█ █▀▀ █▀█   █░░ █ █▄▄              '
    _o := '         ▄█ █▄▄ █▀▄ ██▄ ██▄ █░▀█ ██▄ █▀▄   █▄▄ █ █▄█              '
    /////////////////////////////////////////////////////////////////////////////////


import TradingView/TechnicalRating/1 as techrate
import kaigouthro/theme_presets/2
import kaigouthro/theme_engine/1 as thm
import kaigouthro/calc/6
import kaigouthro/font/5
import kaigouthro/hsvColor/15 as h
import kaigouthro/ColorArray/7 as ca
import kaigouthro/SizeAndPlace/2 as ssp


// @type single indication for a symbol screener
// @field name         name of the indication
// @field icon         icon name
// @field rating       rating
// @field value        value
// @field col          color of the indication
// @field tf           timeframe
// @field avg          average value
// @field tooltip      tooltip text
// @field normalized   color value
// @field init         init
export type indication
    string name     = ''
    string icon     = ''
    string rating   = ''
    float  value    = 0
    color  col      = color.gray
    string tf       = timeframe.period
    string tooltip  = ''
    float  normalized   = 0
    bool   init     = false

// @type  single   symbol screener
// @field ticker   ticker name
// @field icon     icon name
// @field rating   rating
// @field value    value
// @field bg       background color
// @field fg       foreground color
// @field items    list of indications
// @field init     init
export type screener
    string        ticker  = ''
    string        icon    = ''
    string        rating  = ''
    float         value   = 0.
    color         bg      = #000000
    color         fg      = #000000
    indication    [] items
    bool          init    = false

// @type screener configuration
// @field strong       strong value
// @field weak         weak value
// @field theme        theme name
// @field vert         vertical layout
// @field cellwidth    cell width
// @field cellheight   cell height
// @field textsize     text size
// @field font         font index
// @field framewidth   frame width
// @field borders      border width
// @field position     position
export type config
    float         strong      = 50
    float         weak        = 20
    string        theme       = 'dark'
    bool          vert        = true
    float         cellwidth   = 0.
    float         cellheight  = 0.
    string        textsize    = size.small
    int           font        = 1
    int           framewidth  = 1
    int           borders     = 1
    string        position    = position.bottom_center

// @type screener Icons
// @field buy         buy icon
// @field sell        sell icon
// @field strong      strong icon
export type icons
    string        buy
    string        sell
    string        strong

// @type screener panel object
// @field items        list of symbols
// @field table        table object
// @field config       config object
// @field thm.theme    theme object
// @field icons        icons object
export type panel
    screener[]       items
    table            table
    config           config
    thm.theme        theme
    icons            icons


// helper functions
method  icon(panel panel, string _str )  =>
    strong        = panel.icons.strong
    buy           = panel.icons.buy
    sell          = panel.icons.sell
    icon = ''
    if str.contains(_str, 'Strong')
        icon += strong
        icon += switch
            str.contains(_str, 'Buy'   ) => buy
            str.contains(_str, 'Sell'  ) => sell
    else
        if str.contains(_str, '*')
            icon += strong
        icon += switch
            str.contains(_str, 'Buy'   ) => buy
            str.contains(_str, 'Sell'  ) => sell

//@function get the rating of the indication
//@param panel      panel       panel object
//@param value      float       value
method rate(panel p,float value) =>
    _strong  = p.config.strong/100
    _weak    = p.config.weak/100
    thin = p.config.cellwidth < math.min(10, (100/array.size(p.items))) or (not p.config.vert)
    out  = switch
        value >   _strong => thin ? '*B*' : 'Strong Buy'
        value < - _strong => thin ? '*S*' : 'Strong Sell'
        value >   _weak   => thin ? 'B'   : 'Buy'
        value < - _weak   => thin ? 'S'   : 'Sell'
        => "   "

method rate(panel p,indication i) =>
    i.rating := rate(p,i.value)
    i.rating := icon(p,i.rating)

method getTotal(indication[] items, _count)=>
    sum = 0.
    den = 0.
    for [i,item] in items
        sum += item.normalized
        den += 1
    sum/den

method cell(panel p    , _col , _row     ,_string     , _width     , _height  ,_textcolor  , _hAlign    , _vAlign  ,_textSize   , _cellcolor , _tip     ) =>
    _table = p.table
    table.cell(_table  , _col , _row     ,_string     , _width     , _height  ,_textcolor  , _hAlign    , _vAlign  ,_textSize   , _cellcolor , _tip     )

export method decorate(panel p,thm.varient t)=>
    table.set_bgcolor       (p.table, t.accent)
    table.set_frame_color   (p.table, t.bg)
    table.set_border_color  (p.table, t.bg)
    table.set_frame_width   (p.table, p.config.framewidth)
    table.set_border_width  (p.table, p.config.borders)
    table.set_position      (p.table, p.config.position)

method col              ( panel p, float _source, color[] _colsin)  =>
    _th = p.config.weak/100, _thmax = math.min(0.99,math.max(_th*1.01,p.config.strong/100))
    _cols  = _colsin
    _s3a   =   _cols.get(0),  _s2a   =   _cols.get(1)
    _s1a   =   _cols.get(2),  _s1b   =   _cols.get(3)
    _s2b   =   _cols.get(4),  _s3b   =   _cols.get(5)
    _1     =   math.max(0.01,math.min(_th,_thmax * 0.99 ))
    _2     =   math.min(0.99,math.max(_1*1.01 ,_thmax   ))
    _3     =   1.01
    src    =  _source
    hc3    =  h.hsv_gradient( src ,  _2 ,   _3 , _s2b  , _s3b  )
    lc3    =  h.hsv_gradient( src , -_2 , - _3 , _s2a  , _s3a  )
    hc2    =  h.hsv_gradient( src ,  _1 ,   _2 , _s1b  ,  hc3  )
    lc2    =  h.hsv_gradient( src , -_1 , - _2 , _s1a  ,  lc3  )
    hc1    =  h.hsv_gradient( src ,  0  ,   _1 , lc2   ,  hc2  )
    lc1    =  h.hsv_gradient( src , -_1 ,   0  , lc2   ,  hc2  )
    out    =  h.hsv_gradient( src , -_1 ,   _1 , lc1   ,  hc1  )

//@function  Normalizer to retrieve a value between -1 and 1 for consistent coloring
//@param float value: value to normalize
method norm_value (float value)=>
    varip min = float (value)
    varip max = float (value)
    varip out = 0.
    min := math.min(value,nz(min,value))
    max := math.max(value,nz(max,value))
    out := (value - min) / (max - min) * 2 - 1



/// EXPORTS


// @function # Panel init
// > init a panel for all the screens
// ### Example:
// ```
// 
// import kaigouthro/cleanscreen/2
// method Screener  ( cleanscreen.panel      p , string _name                       ) => cleanscreens.Screener  ( p,  _name) 
// method Indicator ( cleanscreen.screener   s , string _tf, string name, float val ) => cleanscreens.Indicator ( s , _tf, name, val) 
// method display   ( cleanscreen.panel      p                                      ) => cleanscreens.display   ( p ) 
// 
//
// // Theme names for the theme input a botom (place here)
// string  GRP1 = "Settings"
// // init panel with theme and location
// var loc      = input.int(9, ' Table loc (1-9)', 1, 9)
// var _panel    = init(input.string(SILK, 'Theme Choice', options = [APATHY,APPRENTICE,ASHES,ATELIER_CAVE,ATELIER_DUNE,ATELIER_ESTUARY,ATELIER_FOREST,ATELIER_HEATH,ATELIER_LAKESIDE,ATELIER_PLATEAU,ATELIER_SAVANNA,ATELIER_SEASIDE,ATELIER_SULPHURPOOL,ATLAS,AYU,AYU_MIRAGE,BESPIN,BLACK_METAL,BLACK_METAL_BATHORY,BLACK_METAL_BURZUM,BLACK_METAL_FUNERAL,BLACK_METAL_GORGOROTH,BLACK_METAL_IMMORTAL,BLACK_METAL_KHOLD,BLACK_METAL_MARDUK,BLACK_METAL_MAYHEM,BLACK_METAL_NILE,BLACK_METAL_VENOM,BLUE_FOREST,BLUEISH,BREWER,BRIGHT,BROGRAMMER,BRUSH_TREES,CATPPUCCIN,CHALK,CIRCUS,CLASSIC,CLRS,CODESCHOOL,CUPCAKE,CUPERTINO,DA_ONE_BLACK,DA_ONE_GRAY,DA_ONE_OCEAN,DA_ONE_PAPER,DA_ONE_SEA,DA_ONE_WHITE,DANQING,DARCULA,DARK_VIOLET,DARKMOSS,DARKTOOTH,DECAF,DIRTYSEA,DRACULA,EDGE,EIGHTIES,EMBERS,EMIL,EQUILIBRIUM,EQUILIBRIUM_GRAY,ESPRESSO,EVA,EVERFOREST,FLAT,FRAMER,FRUIT_SODA,GIGAVOLT,GITHUB,GOOGLE,GOTHAM,GRAYSCALE,GREEN_SCREEN,GRUBER,GRUVBOX_HARD,GRUVBOX_MEDIUM,GRUVBOX_PALE,GRUVBOX_SOFT,GRUVBOX_MATERIAL_HARD,GRUVBOX_MATERIAL_MEDIUM,GRUVBOX_MATERIAL_SOFT,HARDCORE,HARMONIC16,HEETCH,HELIOS,HOPSCOTCH,HORIZON,HORIZON_TERMINAL,HUMANOID,IA,ICY,IR_BLACK,ISOTOPE,KANAGAWA,KATY,KIMBER,LIME,LONDON_TUBE,MACINTOSH,MARRAKESH,MATERIA,MATERIAL,MATERIALDARKER,MATERIAL_PALENIGHT,MATERIAL_VIVID,MELLOW_PURPLE,MOCHA,MONOKAI,NEBULA,NORD,NOVA,OCEAN,OCEANICNEXT,ONEDARK,OUTRUN,PANDORA,PAPERCOLOR,PARAISO,PASQUE,PHD,PICO,PINKY,POP,PORPLE,PRIMER,PURPLEDREAM,QUALIA,RAILSCASTS,REBECCA,ROSE_PINE,ROSE_PINE_DAWN,ROSE_PINE_MOON,SAGELIGHT,SAKURA,SANDCASTLE,SETI_UI,SHADES_OF_PURPLE,SHADESMEAR,SHAPESHIFTER,SILK,SNAZZY,SOLAR_FLARE,SOLARIZED,SPACEDUCK,SPACEMACS,STELLA,STILL_ALIVE,SUMMERCAMP,SUMMERFRUIT,SYNTH_MIDNIGHT_TERMINAL,TANGO,TENDER,TOKYO_CITY,TOKYO_CITY_TERMINAL,TOKYO_NIGHT,TOKYO_NIGHT_STORM,TOKYO_NIGHT_TERMINAL,TOKYO_NIGHT_TERMINAL_STORM,TOKYODARK,TOKYODARK_TERMINAL,TOMORROW,TOMORROW_NIGHT,TOMORROW_NIGHT_EIGHTIES,TWILIGHT,UNIKITTY,UNIKITTY_REVERSIBLE,UWUNICORN,VICE,VULCAN,WINDOWS_10,WINDOWS_95,WINDOWS_HIGH_CONTRAST,WINDOWS_NT,WOODLAND,XCODE_DUSK]),
//                   loc)
// var tfInput  = input.timeframe("",  "Higher timeframe",         group = GRP1)
// if barstate.isfirst  
//        panel.config.theme      := input.string           ( 'light'   , "Theme Variewnt" , options=['light' , 'dark']             , inline='ic'    , group='Icons' )
//        panel.config.cellwidth  := input.float            ( 7.5       , 'cellwidth'      , step=0.5         , inline = "Cellsize" , group=GRP1     )
//        panel.config.cellheight := input.float            ( 7.5       , 'cellheight'     , step=0.5         , inline = "Cellsize" , group=GRP1     )
//        panel.config.textsize   := input.string           ( size.auto , 'Textsize'       , options=[size.auto, size.small, size.normal, size.large, size.huge] , inline = "set" , group=GRP1    )
//        panel.config.font       := input.int              ( 15        , 'Font'           , 1                , 17                  , inline = "set" , group=GRP1    )
//        panel.config.framewidth := input.int              ( 10        , 'Framewidth'     , 0                , 20                  , inline = "set" , group=GRP1    )
//        panel.config.borders    := input.int              ( 1         , 'Borders'        , -1               , 10                  , inline = "set" , group=GRP1    )
//        panel.config.vert       := input.bool             ( true      , 'vert'           ) //int            ( 1                   , 'Borders'      , -1            , 10          )
//        // Icons
//        panel.icons.strong      := input.string('💸', 'Strong ✼', inline='ic', group='Icons')
//        panel.icons.buy         := input.string('💰', 'Buy  ⇡', inline='ic', group='Icons')
//        panel.icons.sell        := input.string('🔥', 'Sell ⇣', inline='ic', group='Icons')
//
// // Add groupd with                              _screener  = _paneel.Screener("Group Name")  
// // Add indicartors to screeener groups with     _screener.Indication( "Indicator Name", _source)
// // Update the panel with                        _paneel.display(_paneel)
//
//  var string APATHY = "Apathy", var string APPRENTICE = "Apprentice", var string ASHES = "Ashes", var string ATELIER_CAVE = "Atelier Cave", var string ATELIER_DUNE = "Atelier Dune", var string ATELIER_ESTUARY = "Atelier Estuary", var string ATELIER_FOREST = "Atelier Forest", var string ATELIER_HEATH = "Atelier Heath", var string ATELIER_LAKESIDE = "Atelier Lakeside", var string ATELIER_PLATEAU = "Atelier Plateau", var string ATELIER_SAVANNA = "Atelier Savanna", var string ATELIER_SEASIDE = "Atelier Seaside", var string ATELIER_SULPHURPOOL = "Atelier Sulphurpool", var string ATLAS = "Atlas", var string AYU = "Ayu", var string AYU_MIRAGE = "Ayu Mirage", var string BESPIN = "Bespin", var string BLACK_METAL = "Black Metal", var string BLACK_METAL_BATHORY = "Black Metal (bathory)", var string BLACK_METAL_BURZUM = "Black Metal (burzum)", var string BLACK_METAL_FUNERAL = "Black Metal (dark Funeral)", var string BLACK_METAL_GORGOROTH = "Black Metal (gorgoroth)", var string BLACK_METAL_IMMORTAL = "Black Metal (immortal)", var string BLACK_METAL_KHOLD = "Black Metal (khold)", var string BLACK_METAL_MARDUK = "Black Metal (marduk)", var string BLACK_METAL_MAYHEM = "Black Metal (mayhem)", var string BLACK_METAL_NILE = "Black Metal (nile)", var string BLACK_METAL_VENOM = "Black Metal (venom)", var string BLUE_FOREST = "Blue Forest", var string BLUEISH = "Blueish", var string BREWER = "Brewer", var string BRIGHT = "Bright", var string BROGRAMMER = "Brogrammer", var string BRUSH_TREES = "Brush Trees", var string CATPPUCCIN = "Catppuccin", var string CHALK = "Chalk", var string CIRCUS = "Circus", var string CLASSIC = "Classic", var string CLRS = "Colors", var string CODESCHOOL = "Codeschool", var string CUPCAKE = "Cupcake", var string CUPERTINO = "Cupertino", var string DA_ONE_BLACK = "Da One Black", var string DA_ONE_GRAY = "Da One Gray", var string DA_ONE_OCEAN = "Da One Ocean", var string DA_ONE_PAPER = "Da One Paper", var string DA_ONE_SEA = "Da One Sea", var string DA_ONE_WHITE = "Da One White", var string DANQING = "Danqing", var string DARCULA = "Darcula", var string DARK_VIOLET = "Dark Violet", var string DARKMOSS = "Darkmoss", var string DARKTOOTH = "Darktooth", var string DECAF = "Decaf", var string DIRTYSEA = "Dirtysea", var string DRACULA = "Dracula", var string EDGE = "Edge", var string EIGHTIES = "Eighties", var string EMBERS = "Embers", var string EMIL = "Emil", var string EQUILIBRIUM = "Equilibrium", var string EQUILIBRIUM_GRAY = "Equilibrium Gray", var string ESPRESSO = "Espresso", var string EVA = "Eva", var string EVERFOREST = "Everforest", var string FLAT = "Flat", var string FRAMER = "Framer", var string FRUIT_SODA = "Fruit Soda", var string GIGAVOLT = "Gigavolt", var string GITHUB = "Github", var string GOOGLE = "Google", var string GOTHAM = "Gotham", var string GRAYSCALE = "Grayscale", var string GREEN_SCREEN = "Green Screen", var string GRUBER = "Gruber", var string GRUVBOX_HARD = "Gruvbox Dark, Hard", var string GRUVBOX_MEDIUM = "Gruvbox Dark, Medium", var string GRUVBOX_PALE = "Gruvbox Dark, Pale", var string GRUVBOX_SOFT = "Gruvbox Dark, Soft", var string GRUVBOX_MATERIAL_HARD = "Gruvbox Material Dark, Hard", var string GRUVBOX_MATERIAL_MEDIUM = "Gruvbox Material Dark, Medium", var string GRUVBOX_MATERIAL_SOFT = "Gruvbox Material Dark, Soft", var string HARDCORE = "Hardcore", var string HARMONIC16 = "Harmonic16", var string HEETCH = "Heetch", var string HELIOS = "Helios", var string HOPSCOTCH = "Hopscotch", var string HORIZON = "Horizon", var string HORIZON_TERMINAL = "Horizon Terminal", var string HUMANOID = "Humanoid", var string IA = "Ia", var string ICY = "Icy", var string IR_BLACK = "Ir Black", var string ISOTOPE = "Isotope", var string KANAGAWA = "Kanagawa", var string KATY = "Katy", var string KIMBER = "Kimber", var string LIME = "Lime", var string LONDON_TUBE = "London Tube", var string MACINTOSH = "Macintosh", var string MARRAKESH = "Marrakesh", var string MATERIA = "Materia", var string MATERIAL = "Material", var string MATERIALDARKER = "Material Darker", var string MATERIAL_PALENIGHT = "Material Palenight", var string MATERIAL_VIVID = "Material Vivid", var string MELLOW_PURPLE = "Mellow Purple", var string MOCHA = "Mocha", var string MONOKAI = "Monokai", var string NEBULA = "Nebula", var string NORD = "Nord", var string NOVA = "Nova", var string OCEAN = "Ocean", var string OCEANICNEXT = "Oceanicnext", var string ONEDARK = "Onedark", var string OUTRUN = "Outrun", var string PANDORA = "Pandora", var string PAPERCOLOR = "Papercolor", var string PARAISO = "Paraiso", var string PASQUE = "Pasque", var string PHD = "Phd", var string PICO = "Pico", var string PINKY = "Pinky", var string POP = "Pop", var string PORPLE = "Porple", var string PRIMER = "Primer", var string PURPLEDREAM = "Purpledream", var string QUALIA = "Qualia", var string RAILSCASTS = "Railscasts", var string REBECCA = "Rebecca", var string ROSE_PINE = "Rosé Pine", var string ROSE_PINE_DAWN = "Rosé Pine Dawn", var string ROSE_PINE_MOON = "Rosé Pine Moon", var string SAGELIGHT = "Sagelight", var string SAKURA = "Sakura", var string SANDCASTLE = "Sandcastle", var string SETI_UI = "Seti Ui", var string SHADES_OF_PURPLE = "Shades Of Purple", var string SHADESMEAR = "Shadesmear", var string SHAPESHIFTER = "Shapeshifter", var string SILK = "Silk", var string SNAZZY = "Snazzy", var string SOLAR_FLARE = "Solar Flare", var string SOLARIZED = "Solarized", var string SPACEDUCK = "Spaceduck", var string SPACEMACS = "Spacemacs", var string STELLA = "Stella", var string STILL_ALIVE = "Still Alive", var string SUMMERCAMP = "Summercamp", var string SUMMERFRUIT = "Summerfruit", var string SYNTH_MIDNIGHT_TERMINAL = "Synth Midnight Terminal", var string TANGO = "Tango", var string TENDER = "Tender", var string TOKYO_CITY = "Tokyo City", var string TOKYO_CITY_TERMINAL = "Tokyo City Terminal", var string TOKYO_NIGHT = "Tokyo Night", var string TOKYO_NIGHT_STORM = "Tokyo Night Storm", var string TOKYO_NIGHT_TERMINAL = "Tokyo Night Terminal", var string TOKYO_NIGHT_TERMINAL_STORM = "Tokyo Night Terminal Storm", var string TOKYODARK = "Tokyodark", var string TOKYODARK_TERMINAL = "Tokyodark Terminal", var string TOMORROW = "Tomorrow", var string TOMORROW_NIGHT = "Tomorrow Night", var string TOMORROW_NIGHT_EIGHTIES = "Tomorrow Night Eighties", var string TWILIGHT = "Twilight", var string UNIKITTY = "Unikitty", var string UNIKITTY_REVERSIBLE = "Unikitty Reversible", var string UWUNICORN = "Uwunicorn", var string VICE = "Vice", var string VULCAN = "Vulcan", var string WINDOWS_10 = "Windows 10", var string WINDOWS_95 = "Windows 95", var string WINDOWS_HIGH_CONTRAST = "Windows High Contrast", var string WINDOWS_NT = "Windows Nt", var string WOODLAND = "Woodland", var string XCODE_DUSK = "Xcode Dusk"
//
//
// ```
//@param _themein string:  Theme Preset Name
//@param loc int :
// 1 = left top,
// 2 = middle top,
// 3 = right top,
// 4 = left middle,
// 5 = middle middle,
// 6 = right middle,
// 7 = left bottom,
// 8 = middle bottom,
// 9 = right bottom
//
//@returns panel
export        init ( string _themein, int loc) =>
    var _screens    = array.new<screener>()
    var _names      = array.new<string>()
    var _tf         = array.new<string>()
    var _table      = table.new(ssp.table_posittion(loc),80,80)
    var _config     = config.new(50,10,'dark',true)
    var _theme      = theme_presets.getTheme(_themein)
    var _icons      = icons.new('','','')
    var _panel      = panel.new(_screens,_table,_config,_theme,_icons)
    _panel

//@function # Screener - Create a new screener
// ### Example:
// ```
// cleanscreen.Screeneer(panel, 'Crpyto Screeners')
// ```
//@param panel p:  Panel Object
//@param string _name:  Name of the Screener
export method Screener  ( panel p, string _name) =>
    var _icon   = ''
    var _rating = ''
    var _value  = 0.
    var _bg     = #ffffff
    var _fg     = #ffffff
    var _screen = screener.new(_name,_icon,_rating,_value,_bg,_fg,array.new<indication>())
    switch _screen.init
        false =>
            if  p.items.includes(_screen) == false
                p.items.push(_screen)
            else
                _screen.init:=true
                _screen
    _screen

//@function # Indicator - Create a new Indicator
// ### Example:
// ```
// cleanscreen.Inidcator('1h', 'RSI', ta.rsi(close, 14))
// ```
//@param screener s:  Screener Object
//@param string _tf:  Timeframe
//@param string name:  Name of the Indicator
//@param float val:  Value of the Indicator
export method Indicator ( screener s , string _tf, string name, float val) =>
    var _name      = name
    var _icon      = ''
    var _rating    = ''
    var _value     = 0.
    var _color     = #000000
    var tmf        = _tf
    var _indicator = indication.new(_name,_icon,_rating,_value,_color, tmf, '', 0)
    switch _indicator.init
        false =>
            if not s.items.includes(_indicator)
                s.items.push(_indicator)
            else
                _indicator.init := true
    _indicator.value:= val
    _indicator.normalized := nz(norm_value(_indicator.value))
    _indicator


//@function # Display - Display the Panel
// ### Example:
// ```
//
// cleanscreen.display(panel)
//
// ```
//@param panel p:  Panel Object
export method display   ( panel p ) =>
    var _colsize            = p.items.size() - 1
    var color   _nocol      = color.new(color.black,100)
    var color   _bg         = na ,  var color  _fg       = na
    var string  _string     = na ,  var float  _value    = na
    var string  _tip        = na ,  theme                = p.theme
    var _theme  = p.config.theme == 'dark' ? theme.dark : theme.light
    var _cols   = ca.makeGradient(6,array.from(theme.red,theme.orange,theme.yellow,theme.green,theme.aqua,theme.blue))
    if barstate.islastconfirmedhistory
        p.decorate(_theme)
    for _x              = 0 to array.size(p.items)-1
        symbol          = array.get(p.items,_x)
        symbol.value   := getTotal(symbol.items, array.size(symbol.items))
        symbol.bg      := p.col (symbol.value,_cols)
        symbol.fg      := p.col (symbol.value,_cols)
        symbol.rating  := p.rate(symbol.value      )
        symbol.icon    := p.icon(symbol.rating     )
        _rowsize        = array.size(symbol.items)
        _hAlign         = text.align_left
        _vAlign         = text.align_center
        _textSize       = p.config.textsize
        for _y          = 0  to _rowsize + 1
            _width      = p.config.cellwidth
            _height     = p.config.cellheight
            _col        = p.config.vert ? _x : _y
            _row        = p.config.vert ? _y : _x
            switch _y
                0  =>
                    _string := font.uni(str.replace(symbol.ticker,syminfo.prefix(symbol.ticker)+':',''),p.config.font)
                    _fg     := col (p, symbol.value,_cols)
                    _bg     := p.theme.dark.bg
                    _tip    := str.tostring(symbol.value)
                    _height /= 2
                    _width  *= p.config.vert ? 1 :1.5
                1  =>
                    _string := icon(p, symbol.rating)  + ' ' + symbol.rating
                    _bg     := p.theme.dark.accent
                    _fg     := _fg
                    _height /= 2
                =>
                    _ind    =  array.get(symbol.items,_y-2)
                    rate(p,_ind)
                    _string := str.format(' {1, number, percent}  -  {0}',
                                          _ind.icon, _ind.normalized)
                    _tip    := str.format("Indicator: {0}\nTimeframe: {1}\nValue: {2}",
                                           _ind.name, _ind.tf, _ind.value)
                    _bg     :=  col (p, _ind.normalized, _cols)
                    _fg     :=  h.tripswitch(_bg,.25,#ffffff,#000000)
                    _hAlign :=  text.align_right

            _string := font.uni(_string,p.config.font)

            cell( p           , _col       , _row     ,
                  _string     , _width     , _height  ,
                  _fg         , _hAlign    , _vAlign  ,
                  _textSize   , _bg        , _tip     )





___q()=>
    /////////////////////////////////////////////////////////////////////////
    _o  = '          █▀▄ █▀▀ █▀▄▀█ █▀█   ░░▄▀   ▀█▀ █▀▀ █▀ ▀█▀                '
    _o := '          █▄▀ ██▄ █░▀░█ █▄█   ▄▀░░   ░█░ ██▄ ▄█ ░█░                '
    ///////////////////////////////////////////////////////////////////////////



// ————— Inputs

// Theme names for the theme input
var string  APATHY                         = "Apathy", var string  APPRENTICE                     = "Apprentice", var string  ASHES                          = "Ashes", var string  ATELIER_CAVE                   = "Atelier Cave", var string  ATELIER_DUNE                   = "Atelier Dune", var string  ATELIER_ESTUARY                = "Atelier Estuary", var string  ATELIER_FOREST                 = "Atelier Forest", var string  ATELIER_HEATH                  = "Atelier Heath", var string  ATELIER_LAKESIDE               = "Atelier Lakeside", var string  ATELIER_PLATEAU                = "Atelier Plateau", var string  ATELIER_SAVANNA                = "Atelier Savanna", var string  ATELIER_SEASIDE                = "Atelier Seaside", var string  ATELIER_SULPHURPOOL            = "Atelier Sulphurpool", var string  ATLAS                          = "Atlas", var string  AYU                            = "Ayu", var string  AYU_MIRAGE                     = "Ayu Mirage", var string  BESPIN                         = "Bespin", var string  BLACK_METAL                    = "Black Metal", var string  BLACK_METAL_BATHORY            = "Black Metal (bathory)", var string  BLACK_METAL_BURZUM             = "Black Metal (burzum)", var string  BLACK_METAL_FUNERAL            = "Black Metal (dark Funeral)", var string  BLACK_METAL_GORGOROTH          = "Black Metal (gorgoroth)", var string  BLACK_METAL_IMMORTAL           = "Black Metal (immortal)", var string  BLACK_METAL_KHOLD              = "Black Metal (khold)", var string  BLACK_METAL_MARDUK             = "Black Metal (marduk)", var string  BLACK_METAL_MAYHEM             = "Black Metal (mayhem)", var string  BLACK_METAL_NILE               = "Black Metal (nile)", var string  BLACK_METAL_VENOM              = "Black Metal (venom)", var string  BLUE_FOREST                    = "Blue Forest", var string  BLUEISH                        = "Blueish", var string  BREWER                         = "Brewer", var string  BRIGHT                         = "Bright", var string  BROGRAMMER                     = "Brogrammer", var string  BRUSH_TREES                    = "Brush Trees", var string  CATPPUCCIN                     = "Catppuccin", var string  CHALK                          = "Chalk", var string  CIRCUS                         = "Circus", var string  CLASSIC                        = "Classic", var string  CLRS                           = "Colors", var string  CODESCHOOL                     = "Codeschool", var string  CUPCAKE                        = "Cupcake", var string  CUPERTINO                      = "Cupertino", var string  DA_ONE_BLACK                   = "Da One Black", var string  DA_ONE_GRAY                    = "Da One Gray", var string  DA_ONE_OCEAN                   = "Da One Ocean", var string  DA_ONE_PAPER                   = "Da One Paper", var string  DA_ONE_SEA                     = "Da One Sea", var string  DA_ONE_WHITE                   = "Da One White", var string  DANQING                        = "Danqing", var string  DARCULA                        = "Darcula", var string  DARK_VIOLET                    = "Dark Violet", var string  DARKMOSS                       = "Darkmoss", var string  DARKTOOTH                      = "Darktooth", var string  DECAF                          = "Decaf", var string  DIRTYSEA                       = "Dirtysea", var string  DRACULA                        = "Dracula", var string  EDGE                           = "Edge", var string  EIGHTIES                       = "Eighties", var string  EMBERS                         = "Embers", var string  EMIL                           = "Emil", var string  EQUILIBRIUM                    = "Equilibrium", var string  EQUILIBRIUM_GRAY               = "Equilibrium Gray", var string  ESPRESSO                       = "Espresso", var string  EVA                            = "Eva", var string  EVERFOREST                     = "Everforest", var string  FLAT                           = "Flat", var string  FRAMER                         = "Framer", var string  FRUIT_SODA                     = "Fruit Soda", var string  GIGAVOLT                       = "Gigavolt", var string  GITHUB                         = "Github", var string  GOOGLE                         = "Google", var string  GOTHAM                         = "Gotham", var string  GRAYSCALE                      = "Grayscale", var string  GREEN_SCREEN                   = "Green Screen", var string  GRUBER                         = "Gruber", var string  GRUVBOX_HARD                   = "Gruvbox Dark, Hard", var string  GRUVBOX_MEDIUM                 = "Gruvbox Dark, Medium", var string  GRUVBOX_PALE                   = "Gruvbox Dark, Pale", var string  GRUVBOX_SOFT                   = "Gruvbox Dark, Soft", var string  GRUVBOX_MATERIAL_HARD          = "Gruvbox Material Dark, Hard", var string  GRUVBOX_MATERIAL_MEDIUM        = "Gruvbox Material Dark, Medium", var string  GRUVBOX_MATERIAL_SOFT          = "Gruvbox Material Dark, Soft", var string  HARDCORE                       = "Hardcore", var string  HARMONIC16                     = "Harmonic16", var string  HEETCH                         = "Heetch", var string  HELIOS                         = "Helios", var string  HOPSCOTCH                      = "Hopscotch", var string  HORIZON                        = "Horizon", var string  HORIZON_TERMINAL               = "Horizon Terminal", var string  HUMANOID                       = "Humanoid", var string  IA                             = "Ia", var string  ICY                            = "Icy", var string  IR_BLACK                       = "Ir Black", var string  ISOTOPE                        = "Isotope", var string  KANAGAWA                       = "Kanagawa", var string  KATY                           = "Katy", var string  KIMBER                         = "Kimber", var string  LIME                           = "Lime", var string  LONDON_TUBE                    = "London Tube", var string  MACINTOSH                      = "Macintosh", var string  MARRAKESH                      = "Marrakesh", var string  MATERIA                        = "Materia", var string  MATERIAL                       = "Material", var string  MATERIALDARKER                 = "Material Darker", var string  MATERIAL_PALENIGHT             = "Material Palenight", var string  MATERIAL_VIVID                 = "Material Vivid", var string  MELLOW_PURPLE                  = "Mellow Purple", var string  MOCHA                          = "Mocha", var string  MONOKAI                        = "Monokai", var string  NEBULA                         = "Nebula", var string  NORD                           = "Nord", var string  NOVA                           = "Nova", var string  OCEAN                          = "Ocean", var string  OCEANICNEXT                    = "Oceanicnext", var string  ONEDARK                        = "Onedark", var string  OUTRUN                         = "Outrun", var string  PANDORA                        = "Pandora", var string  PAPERCOLOR                     = "Papercolor", var string  PARAISO                        = "Paraiso", var string  PASQUE                         = "Pasque", var string  PHD                            = "Phd", var string  PICO                           = "Pico", var string  PINKY                          = "Pinky", var string  POP                            = "Pop", var string  PORPLE                         = "Porple", var string  PRIMER                         = "Primer", var string  PURPLEDREAM                    = "Purpledream", var string  QUALIA                         = "Qualia", var string  RAILSCASTS                     = "Railscasts", var string  REBECCA                        = "Rebecca", var string  ROSE_PINE                      = "Rosé Pine", var string  ROSE_PINE_DAWN                 = "Rosé Pine Dawn", var string  ROSE_PINE_MOON                 = "Rosé Pine Moon", var string  SAGELIGHT                      = "Sagelight", var string  SAKURA                         = "Sakura", var string  SANDCASTLE                     = "Sandcastle", var string  SETI_UI                        = "Seti Ui", var string  SHADES_OF_PURPLE               = "Shades Of Purple", var string  SHADESMEAR                     = "Shadesmear", var string  SHAPESHIFTER                   = "Shapeshifter", var string  SILK                           = "Silk", var string  SNAZZY                         = "Snazzy", var string  SOLAR_FLARE                    = "Solar Flare", var string  SOLARIZED                      = "Solarized", var string  SPACEDUCK                      = "Spaceduck", var string  SPACEMACS                      = "Spacemacs", var string  STELLA                         = "Stella", var string  STILL_ALIVE                    = "Still Alive", var string  SUMMERCAMP                     = "Summercamp", var string  SUMMERFRUIT                    = "Summerfruit", var string  SYNTH_MIDNIGHT_TERMINAL        = "Synth Midnight Terminal", var string  TANGO                          = "Tango", var string  TENDER                         = "Tender", var string  TOKYO_CITY                     = "Tokyo City", var string  TOKYO_CITY_TERMINAL            = "Tokyo City Terminal", var string  TOKYO_NIGHT                    = "Tokyo Night", var string  TOKYO_NIGHT_STORM              = "Tokyo Night Storm", var string  TOKYO_NIGHT_TERMINAL           = "Tokyo Night Terminal", var string  TOKYO_NIGHT_TERMINAL_STORM     = "Tokyo Night Terminal Storm", var string  TOKYODARK                      = "Tokyodark", var string  TOKYODARK_TERMINAL             = "Tokyodark Terminal", var string  TOMORROW                       = "Tomorrow", var string  TOMORROW_NIGHT                 = "Tomorrow Night", var string  TOMORROW_NIGHT_EIGHTIES        = "Tomorrow Night Eighties", var string  TWILIGHT                       = "Twilight", var string  UNIKITTY                       = "Unikitty", var string  UNIKITTY_REVERSIBLE            = "Unikitty Reversible", var string  UWUNICORN                      = "Uwunicorn", var string  VICE                           = "Vice", var string  VULCAN                         = "Vulcan", var string  WINDOWS_10                     = "Windows 10", var string  WINDOWS_95                     = "Windows 95", var string  WINDOWS_HIGH_CONTRAST          = "Windows High Contrast", var string  WINDOWS_NT                     = "Windows Nt", var string  WOODLAND                       = "Woodland", var string  XCODE_DUSK                     = "Xcode Dusk"


string  GRP1 = "Settings"

// init panel with theme and location
var loc      = input.int(9, ' Table loc (1-9)', 1, 9)
var panel    = init(input.string(SILK, 'Theme Choice', options = [APATHY,APPRENTICE,ASHES,ATELIER_CAVE,ATELIER_DUNE,ATELIER_ESTUARY,ATELIER_FOREST,ATELIER_HEATH,ATELIER_LAKESIDE,ATELIER_PLATEAU,ATELIER_SAVANNA,ATELIER_SEASIDE,ATELIER_SULPHURPOOL,ATLAS,AYU,AYU_MIRAGE,BESPIN,BLACK_METAL,BLACK_METAL_BATHORY,BLACK_METAL_BURZUM,BLACK_METAL_FUNERAL,BLACK_METAL_GORGOROTH,BLACK_METAL_IMMORTAL,BLACK_METAL_KHOLD,BLACK_METAL_MARDUK,BLACK_METAL_MAYHEM,BLACK_METAL_NILE,BLACK_METAL_VENOM,BLUE_FOREST,BLUEISH,BREWER,BRIGHT,BROGRAMMER,BRUSH_TREES,CATPPUCCIN,CHALK,CIRCUS,CLASSIC,CLRS,CODESCHOOL,CUPCAKE,CUPERTINO,DA_ONE_BLACK,DA_ONE_GRAY,DA_ONE_OCEAN,DA_ONE_PAPER,DA_ONE_SEA,DA_ONE_WHITE,DANQING,DARCULA,DARK_VIOLET,DARKMOSS,DARKTOOTH,DECAF,DIRTYSEA,DRACULA,EDGE,EIGHTIES,EMBERS,EMIL,EQUILIBRIUM,EQUILIBRIUM_GRAY,ESPRESSO,EVA,EVERFOREST,FLAT,FRAMER,FRUIT_SODA,GIGAVOLT,GITHUB,GOOGLE,GOTHAM,GRAYSCALE,GREEN_SCREEN,GRUBER,GRUVBOX_HARD,GRUVBOX_MEDIUM,GRUVBOX_PALE,GRUVBOX_SOFT,GRUVBOX_MATERIAL_HARD,GRUVBOX_MATERIAL_MEDIUM,GRUVBOX_MATERIAL_SOFT,HARDCORE,HARMONIC16,HEETCH,HELIOS,HOPSCOTCH,HORIZON,HORIZON_TERMINAL,HUMANOID,IA,ICY,IR_BLACK,ISOTOPE,KANAGAWA,KATY,KIMBER,LIME,LONDON_TUBE,MACINTOSH,MARRAKESH,MATERIA,MATERIAL,MATERIALDARKER,MATERIAL_PALENIGHT,MATERIAL_VIVID,MELLOW_PURPLE,MOCHA,MONOKAI,NEBULA,NORD,NOVA,OCEAN,OCEANICNEXT,ONEDARK,OUTRUN,PANDORA,PAPERCOLOR,PARAISO,PASQUE,PHD,PICO,PINKY,POP,PORPLE,PRIMER,PURPLEDREAM,QUALIA,RAILSCASTS,REBECCA,ROSE_PINE,ROSE_PINE_DAWN,ROSE_PINE_MOON,SAGELIGHT,SAKURA,SANDCASTLE,SETI_UI,SHADES_OF_PURPLE,SHADESMEAR,SHAPESHIFTER,SILK,SNAZZY,SOLAR_FLARE,SOLARIZED,SPACEDUCK,SPACEMACS,STELLA,STILL_ALIVE,SUMMERCAMP,SUMMERFRUIT,SYNTH_MIDNIGHT_TERMINAL,TANGO,TENDER,TOKYO_CITY,TOKYO_CITY_TERMINAL,TOKYO_NIGHT,TOKYO_NIGHT_STORM,TOKYO_NIGHT_TERMINAL,TOKYO_NIGHT_TERMINAL_STORM,TOKYODARK,TOKYODARK_TERMINAL,TOMORROW,TOMORROW_NIGHT,TOMORROW_NIGHT_EIGHTIES,TWILIGHT,UNIKITTY,UNIKITTY_REVERSIBLE,UWUNICORN,VICE,VULCAN,WINDOWS_10,WINDOWS_95,WINDOWS_HIGH_CONTRAST,WINDOWS_NT,WOODLAND,XCODE_DUSK]),
                  loc)

var tfInput  = input.timeframe("",  "Higher timeframe",         group = GRP1)

if barstate.isfirst  
    panel.config.theme      := input.string           ( 'light'   , "Theme Variewnt" , options=['light' , 'dark']             , inline='ic'    , group='Icons' )
    panel.config.cellwidth  := input.float            ( 7.5       , 'cellwidth'      , step=0.5         , inline = "Cellsize" , group=GRP1     )
    panel.config.cellheight := input.float            ( 7.5       , 'cellheight'     , step=0.5         , inline = "Cellsize" , group=GRP1     )
    panel.config.textsize   := input.string           ( size.auto , 'Textsize'       , options=[size.auto, size.small, size.normal, size.large, size.huge] , inline = "set" , group=GRP1    )
    panel.config.font       := input.int              ( 15        , 'Font'           , 1                , 17                  , inline = "set" , group=GRP1    )
    panel.config.framewidth := input.int              ( 10        , 'Framewidth'     , 0                , 20                  , inline = "set" , group=GRP1    )
    panel.config.borders    := input.int              ( 1         , 'Borders'        , -1               , 10                  , inline = "set" , group=GRP1    )
    panel.config.vert       := input.bool             ( true      , 'vert'           ) //int            ( 1                   , 'Borders'      , -1            , 10          )
    panel.config.position   := ssp.table_posittion(loc)

    // Icons
    panel.icons.strong      := input.string('💸', 'Strong ✼', inline='ic', group='Icons')
    panel.icons.buy         := input.string('💰', 'Buy  ⇡', inline='ic', group='Icons')
    panel.icons.sell        := input.string('🔥', 'Sell ⇣', inline='ic', group='Icons')


// Inputs
var _001 = input.symbol('CELOUSDTPERP', group='symbols')
var _002 = input.symbol('MTLUSDTPERP', group='symbols')
var _003 = input.symbol('CVCUSDTPERP', group='symbols')

// Using Pineecoders technical Indicators, and 3 basic buil ins:
method getvals(screener s, simple string ticker, _tf) =>

    [ratingTotal, ratingOther, ratingMa]                  = request.security(ticker, tfInput, techrate.calcRatingAll(), ignore_invalid_symbol = true)

    // update screener indicators
    s.Indicator(_tf, 'Total', ratingTotal)
    s.Indicator(_tf, 'Other', ratingOther)
    s.Indicator(_tf, 'MAs  ', ratingMa)


    // calculating to have maimum off 1,low of -1
    
    
    

    // update screener indicators
    s.Indicator(_tf, 'RSI', request.security(ticker, _tf, ta.rsi(close,7)))
    s.Indicator(_tf, 'mom', request.security(ticker, _tf, ta.mom(close,7)))
    s.Indicator(_tf, 'atr', request.security(ticker, _tf, ta.atr(20)))

// Initialize
var _Screener_01 = Screener(panel, _001)
var _Screener_02 = Screener(panel, _001)
var _Screener_03 = Screener(panel, _001)

// Get values for different timeframes
getvals(_Screener_01, _001, '15')
getvals(_Screener_02, _001, '60')
getvals(_Screener_03, _001, '1440')


// Three tickers on same timeframe, wors wihou  var as well
_Screener_01a = Screener(panel, _001)
_Screener_02a = Screener(panel, _002)
_Screener_03a = Screener(panel, _003)

// Get values for different ticers
getvals(_Screener_01a, _001, timeframe.period)
getvals(_Screener_02a, _002, timeframe.period)
getvals(_Screener_03a, _003, timeframe.period)


// Display!
if bar_index + 2                                      >= last_bar_index
    panel.display()


