I have a complex Pine Script v5 code that displays a screener for buy/sell signals across different timeframes and pairs.
I am concerned about its performance and resource usage, as it currently loads slowly and consumes significant memory resources.
To optimize the script, I am seeking suggestions on how to make it load faster and be more memory-efficient while maintaining its functionality and accuracy.
//@version=5
indicator("Screener", overlay = true)
import sammie123567858/Indicators/9 as indicator
import jdehorty/KernelFunctions/2 as kernels
import TradingView/ta/5 as ta
////////////
// INPUTS //
u01 = input.bool(true, title = "", group = 'Symbols', inline = 's01')
u02 = input.bool(true, title = "", group = 'Symbols', inline = 's02')
u03 = input.bool(true, title = "", group = 'Symbols', inline = 's03')
u04 = input.bool(true, title = "", group = 'Symbols', inline = 's04')
u05 = input.bool(true, title = "", group = 'Symbols', inline = 's05')
u06 = input.bool(true, title = "", group = 'Symbols', inline = 's06')
u07 = input.bool(true, title = "", group = 'Symbols', inline = 's07')
u08 = input.bool(true, title = "", group = 'Symbols', inline = 's08')
u09 = input.bool(true, title = "", group = 'Symbols', inline = 's09')
u10 = input.bool(true, title = "", group = 'Symbols', inline = 's10')
u11 = input.bool(true, title = "", group = 'Symbols', inline = 's11')
u12 = input.bool(true, title = "", group = 'Symbols', inline = 's12')
u13 = input.bool(true, title = "", group = 'Symbols', inline = 's13')
u14 = input.bool(true, title = "", group = 'Symbols', inline = 's14')
u15 = input.bool(true, title = "", group = 'Symbols', inline = 's15')
s01 = input.symbol('EURUSD', group='Symbols', inline='s01')
s02 = input.symbol('USDJPY', group='Symbols', inline='s02')
s03 = input.symbol('GBPUSD', group='Symbols', inline='s03')
s04 = input.symbol('AUDUSD', group='Symbols', inline='s04')
s05 = input.symbol('USDCHF', group='Symbols', inline='s05')
s06 = input.symbol('USDCAD', group='Symbols', inline='s06')
s07 = input.symbol('NZDUSD', group='Symbols', inline='s07')
s08 = input.symbol('GBPJPY', group='Symbols', inline='s08')
s09 = input.symbol('EURAUD', group='Symbols', inline='s09')
s10 = input.symbol('XAUUSD', group='Symbols', inline='s10')
s11 = input.symbol('EURNZD', group='Symbols', inline='s11')
s12 = input.symbol('AUDGBP', group='Symbols', inline='s12')
s13 = input.symbol('USDAUD', group='Symbols', inline='s13')
s14 = input.symbol('CADNZD', group='Symbols', inline='s14')
s15 = input.symbol('AUDJPY', group='Symbols', inline='s15')
// Display inputs
col_width = input.float(2, title = "Column Width (%)", group = 'Table Theme')
textSize = switch input.string("Auto", "Size", options = ['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], group = 'Table Theme')
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
location = switch input.string("Top Right", "Table Location",
options = ['Top Right', 'Top Center', 'Top Left', 'Middle Right', 'Middle Center', 'Middle Left', 'Bottom Right', 'Bottom Center', 'Bottom Left'], group = 'Table Theme')
"Top Right" => position.top_right
"Top Center" => position.top_center
"Top Left" => position.top_left
"Middle Right" => position.middle_right
"Middle Center" => position.middle_center
"Middle Left" => position.middle_left
"Bottom Right" => position.bottom_right
"Bottom Center" => position.bottom_center
"Bottom Left" => position.bottom_left
// timeframes
lowerTF = input.timeframe('1', 'Lower timeframe', group = 'Strategy')
higherTF = input.timeframe('5', 'Higher timeframe', group = 'Strategy')
tpRatio = input.float(1, 'TP Ratio')
//fast Kernel line inputs
float kernelFastWeight = input.float(8, "Rel Weight", 0 , 50, step = 0.2, group = "Fast AO Kernel Settings")
int kernelFastLookback = input.int(5, "Lookback",2 , 500, group = "Fast AO Kernel Settings")
int kernelFastRegressionStart = input.int(25, "Regression Start",2 , 400, group = "Fast AO Kernel Settings")
bool kernelFastSmooth = input.bool(true, "Smooth Line", inline = "Smooth", group = "Fast AO Kernel Settings")
int kernelFastSmoothPeriod = input.int(4, "",2 , 200, inline = "Smooth", group = "Fast AO Kernel Settings")
//slow Kernel line inputs
float kernelSlowWeight = input.float(3, "Rel Weight", 0 , 5, step = 0.2, group = "Slow AO Kernel Settings")
int kernelSlowLookback = input.int(34, "Lookback",2 , 500, group = "Slow AO Kernel Settings")
int kernelSlowRegressionStart = input.int(120, "Regression Start",2 , 400, group = "Slow AO Kernel Settings")
bool kernelSlowSmooth = input.bool(true, "Smooth Line", inline = "Smooth", group = "Slow AO Kernel Settings")
int kernelSlowSmoothPeriod = input.int(40, "",2 , 200, inline = "Smooth", group = "Slow AO Kernel Settings")
// rsi range shift inputs
rsiLengthInput = input.int(14, minval=1, title="RSI Length", group="RSI Settings")
rsiSourceInput = input.source(close, "Source", group="RSI Settings")
bullRangeTop = input.float(80, title="Bull Range Top", tooltip = 'the UPPER price level of the BULLISH range. Default is 80.', group="RSI Settings")
bullRangeBottom = input.float(60, title="Bull Range Bottom", tooltip = 'the LOWER price level of the BULLISH range. Default is 60.', group="RSI Settings")
bearRangeTop = input.float(40, title="Bear Range Top", tooltip = 'the UPPER price level of the BEARISH range. Default is 40.', group="RSI Settings")
bearRangeBottom = input.float(20, title="Bear Range Bottom", tooltip = 'the LOWER price level of the BEARISH range. Default is 20.', group="RSI Settings")
//////////////////
// CALCULATIONS //
// @function takes in the timeframe and returns its text equivalent
timeframeInText(string tf) =>
tf
// Get only symbol
only_symbol(s) =>
array.get(str.split(s, ":"), 1)
id_symbol(s)=>
switch s
1 => only_symbol(s01)
2 => only_symbol(s02)
3 => only_symbol(s03)
4 => only_symbol(s04)
5 => only_symbol(s05)
6 => only_symbol(s06)
7 => only_symbol(s07)
8 => only_symbol(s08)
9 => only_symbol(s09)
10 => only_symbol(s10)
11 => only_symbol(s11)
12 => only_symbol(s12)
13 => only_symbol(s13)
14 => only_symbol(s14)
15 => only_symbol(s15)
=> na
// kernel ao oscillator indicator (this will be used for the fast kernel, slow kernel & kernel ao oscillator)
kernelFast = kernels.rationalQuadratic(close, kernelFastLookback, kernelFastWeight, kernelFastRegressionStart)
if kernelFastSmooth
kernelFast := ta.sma(kernelFast, kernelFastSmoothPeriod)
kernelFastRising = ta.rising(kernelFast, 1)
kernelFastColor = kernelFastRising ? #542772 : #df4774
kernelSlow = kernels.rationalQuadratic(close, kernelSlowLookback, kernelSlowWeight, kernelSlowRegressionStart)
if kernelSlowSmooth
kernelSlow := ta.sma(kernelSlow, kernelSlowSmoothPeriod)
kernelSlowRising = ta.rising(kernelSlow, 1)
kernelSlowColor = kernelSlowRising ? #542772 : #df4774
osc = kernelFast - kernelSlow
diff = osc[1] - osc[2]
isPurple = diff <= 0 ? false : true
fastKernel() =>
kernelFastColor[1] == #542772 ? 0 : kernelFastColor[1] == #df4774 ? 1 : -1
slowKernel() =>
kernelSlowColor[1] == #542772 ? 0 : kernelSlowColor[1] == #df4774 ? 1 : -1
kernelAO() =>
isPurple[1] and osc[1] > 0 ? 0 : not isPurple[1] and osc[1] > 0 ? 1 : not isPurple[1] and osc[1] < 0 ? 2 : isPurple[1] and osc[1] < 0 ? 3 : -1
rsiRangeShift() =>
rsi = indicator.rsi(rsiSourceInput, rsiLengthInput)
bull = rsi[1] <= bullRangeTop and rsi[1] >= bullRangeBottom
bear = rsi[1] <= bearRangeTop and rsi[1] >= bearRangeBottom
neutral = rsi[1] >= bearRangeTop and rsi[1] <= bullRangeBottom
bull ? 0 : bear ? 1 : neutral ? 2 : -1
kernelAoSwing() =>
[swingHigh, swingLow] = indicator.drawSwings(osc, false)
[swingHigh, swingLow]
kernelAoSwingHigh() =>
[swingHigh, swingLow] = kernelAoSwing()
swingHigh
kernelAoSwingLow() =>
[swingHigh, swingLow] = kernelAoSwing()
swingLow
screener_func() =>
[fastKernel(), slowKernel(), kernelAO(), rsiRangeShift(), close[1], kernelAoSwingHigh(), kernelAoSwingLow(), close, high, low]
// Set Up Matrix
screenerMtx = matrix.new<float>(0, 11, na)
screenerFun(numSym, sym, flg, tf) =>
[fastK, slowK, ao, rangeShift, prevClosePrice, swingHigh, swingLow, currClosePRice, currHigh, currLow] = request.security(sym, tf, screener_func())
if flg
arr = array.from(numSym, fastK, slowK, ao, rangeShift, prevClosePrice, swingHigh, swingLow, currClosePRice, currHigh, currLow)
matrix.add_row(screenerMtx, matrix.rows(screenerMtx), arr)
// Security call
screenerFun(01, s01, u01, lowerTF), screenerFun(01, s01, u01, higherTF),
screenerFun(02, s02, u02, lowerTF), screenerFun(02, s02, u02, higherTF),
screenerFun(03, s03, u03, lowerTF), screenerFun(03, s03, u03, higherTF),
screenerFun(04, s04, u04, lowerTF), screenerFun(04, s04, u04, higherTF),
screenerFun(05, s05, u05, lowerTF), screenerFun(05, s05, u05, higherTF),
screenerFun(06, s06, u06, lowerTF), screenerFun(06, s06, u06, higherTF),
screenerFun(07, s07, u07, lowerTF), screenerFun(07, s07, u07, higherTF),
screenerFun(08, s08, u08, lowerTF), screenerFun(08, s08, u08, higherTF),
screenerFun(09, s09, u09, lowerTF), screenerFun(09, s09, u09, higherTF),
screenerFun(10, s10, u10, lowerTF), screenerFun(10, s10, u10, higherTF),
screenerFun(11, s11, u11, lowerTF), screenerFun(11, s11, u11, higherTF),
screenerFun(12, s12, u12, lowerTF), screenerFun(12, s12, u12, higherTF),
screenerFun(13, s13, u13, lowerTF), screenerFun(13, s13, u13, higherTF),
screenerFun(14, s14, u14, lowerTF), screenerFun(14, s14, u14, higherTF),
screenerFun(15, s15, u15, lowerTF), screenerFun(15, s15, u15, higherTF)
///////////
// PLOTS //
tpLineColor = color.new(#4dc251, 0)
slLineColor = color.new(color.red, 0)
lineWidth = 2
entryTime = str.format_time(time, "yyyy-MM-dd HH:mm", timezone = 'Asia/Kolkata')
trade = bool(na)
var counter = 1 //for giving new identifiers to every new trade
string msg = ''
bool check = false
var tradeMtx = matrix.new<float>(41, 5, 1)
var tbl = table.new(location, 8, 41, frame_color=#151715, frame_width=1, border_width=2, border_color=color.new(color.white, 100))
if barstate.islast
// DRAWS TABLE
table.cell(tbl, 0, 0, 'Sym', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 1, 0, '1', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 2, 0, '2', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 3, 0, '3', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 4, 0, '4', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 5, 0, 'Entry', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 6, 0, 'TP', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
table.cell(tbl, 7, 0, 'SL', width = col_width, text_halign = text.align_center, bgcolor = #000000, text_color = color.white, text_size = textSize)
if matrix.rows(screenerMtx) > 0
bool isLowerTF = true
string txt = ''
string tpSlMsg = ''
for i = 0 to matrix.rows(screenerMtx) - 1
// GETTING THAT PARTICULAR SYMBOL'S DATA
// indicator's signals
fast_kernel_signal = matrix.get(screenerMtx, i, 1)
slow_kernel_signal = matrix.get(screenerMtx, i, 2)
kernel_ao_signal = matrix.get(screenerMtx, i, 3)
kernel_ao_bearish = kernel_ao_signal == 2 or kernel_ao_signal == 3
kernel_ao_bullish = kernel_ao_signal == 0 or kernel_ao_signal == 1
range_shift_signal = matrix.get(screenerMtx, i, 4)
// indicator's colors
fast_kernel = fast_kernel_signal == 1 ? color.red : fast_kernel_signal == 0 ? color.green : #323232
slow_kernel = slow_kernel_signal == 1 ? color.red : slow_kernel_signal == 0 ? color.green : #323232
kernel_ao = kernel_ao_signal == 0 ? #028239 : kernel_ao_signal == 1 ? #00e676 : kernel_ao_signal == 2 ? #a80000 : kernel_ao_signal == 3 ? color.red : #323232
range_shift = range_shift_signal == 0 ? color.green : range_shift_signal == 1 ? color.red : range_shift_signal == 2 ? color.blue : #323232
// checking if trades are getting closed
symbol = id_symbol(matrix.get(screenerMtx, i, 0))
timeframeText = timeframeInText(isLowerTF ? lowerTF:higherTF)
isEntryOngoing = matrix.get(tradeMtx, i + 1, 0)
direction = matrix.get(tradeMtx, i + 1, 3)
currPrice = matrix.get(screenerMtx, i, 8)
currHigh = matrix.get(screenerMtx, i, 9)
currLow = matrix.get(screenerMtx, i, 10)
tradeTp = matrix.get(tradeMtx, i + 1, 1)
tradeSl = matrix.get(tradeMtx, i + 1, 2)
// checking if a sell got closed
if isEntryOngoing == 0 and direction == 1
if currPrice >= tradeSl or currHigh >= tradeSl
matrix.set(tradeMtx, i + 1, 0, 2)
table.cell_set_bgcolor(tbl, 5, i + 1, bgcolor = #323232)
table.cell_set_bgcolor(tbl, 6, i + 1, bgcolor = #323232)
table.cell(tbl, 7, i + 1, 'Closed at SL\n' + str.tostring(tradeSl), bgcolor = #c8b50a, text_color = #000000, text_size = textSize)
tpSlMsg += 'Closed Sell' + '|' + symbol + '|' + timeframeText + '|' + entryTime + '|' + ' at SL\n'
if currPrice <= tradeTp or currLow <= tradeTp
matrix.set(tradeMtx, i + 1, 0, 2)
table.cell_set_bgcolor(tbl, 5, i + 1, bgcolor = #323232)
table.cell_set_bgcolor(tbl, 7, i + 1, bgcolor = #323232)
table.cell(tbl, 6, i + 1, 'Closed at TP\n' + str.tostring(tradeTp), bgcolor = #c8b50a, text_color = #000000, text_size = textSize)
tpSlMsg += 'Closed Sell' + '|' + symbol + '|' + timeframeText + '|' + entryTime + '|' + ' at TP\n'
// checking if a buy got closed
if isEntryOngoing == 0 and direction == 0
if currPrice <= tradeSl or currLow <= tradeSl
matrix.set(tradeMtx, i + 1, 0, 2)
table.cell_set_bgcolor(tbl, 5, i + 1, bgcolor = #323232)
table.cell_set_bgcolor(tbl, 6, i + 1, bgcolor = #323232)
table.cell(tbl, 7, i + 1, 'Closed at SL\n' + str.tostring(tradeSl), bgcolor = #c8b50a, text_color = #000000, text_size = textSize)
tpSlMsg += 'Closed Buy' + '|' + symbol + '|' + timeframeText + '|' + entryTime + '|' + ' at SL\n'
if currPrice >= tradeTp or currHigh >= tradeTp
matrix.set(tradeMtx, i + 1, 0, 2)
table.cell_set_bgcolor(tbl, 5, i + 1, bgcolor = #323232)
table.cell_set_bgcolor(tbl, 7, i + 1, bgcolor = #323232)
table.cell(tbl, 6, i + 1, 'Closed at TP\n' + str.tostring(tradeTp), bgcolor = #c8b50a, text_color = #000000, text_size = textSize)
tpSlMsg += 'Closed Buy' + '|' + symbol + '|' + timeframeText + '|' + entryTime + '|' + ' at TP\n'
// plot the row
table.cell(tbl, 0, i + 1, symbol + ' ' + timeframeText, text_halign = text.align_left, bgcolor = #dcc200, text_color = #000000, text_size = textSize)
table.cell(tbl, 1, i + 1, '', bgcolor = fast_kernel)
table.cell(tbl, 2, i + 1, '', bgcolor = slow_kernel)
table.cell(tbl, 3, i + 1, '', bgcolor = kernel_ao)
table.cell(tbl, 4, i + 1, '', bgcolor = range_shift)
if matrix.get(tradeMtx, i + 1, 0) == 1 //if there is no trade in this row then colour it gray
table.cell(tbl, 5, i + 1, '', bgcolor = #323232)
table.cell(tbl, 6, i + 1, '', bgcolor = #323232)
table.cell(tbl, 7, i + 1, '', bgcolor = #323232)
isEntryOngoing := matrix.get(tradeMtx, i + 1, 0)
closePrice = matrix.get(screenerMtx, i, 5)
//this is to signal that there is no trade
if isEntryOngoing == 1 or isEntryOngoing == 2
// if there is a sell signal in this particular symbol & timeframe
if fast_kernel_signal == 1 and slow_kernel_signal == 1 and (kernel_ao_bearish or range_shift_signal == 1)
sl = matrix.get(screenerMtx, i, 6)
tp = closePrice > sl ? closePrice - ((closePrice-sl)*tpRatio) : closePrice - ((sl-closePrice)*tpRatio)
txt := txt + 'Sell' + '|' + str.tostring(closePrice) + '|' + str.tostring(tp) + '|' + str.tostring(sl) + '|' + symbol + '|' + timeframeText + '|' + entryTime + '\n'
table.cell(tbl, 5, i + 1, 'Sell \n'+str.tostring(closePrice), bgcolor = color.red, text_color = #000000, text_size = textSize)
table.cell(tbl, 6, i + 1, str.tostring(tp), bgcolor = color.red, text_color = #000000, text_size = textSize)
table.cell(tbl, 7, i + 1, str.tostring(sl), bgcolor = color.red, text_color = #000000, text_size = textSize)
matrix.set(tradeMtx, i + 1, 0, 0) //this is to signal that there is currently a trade open
matrix.set(tradeMtx, i + 1, 1, tp)
matrix.set(tradeMtx, i + 1, 2, sl)
matrix.set(tradeMtx, i + 1, 3, 1)
matrix.set(tradeMtx, i + 1, 4, counter) //assigning an identifier to this new trade
counter += 1
if isEntryOngoing == 1 or isEntryOngoing == 2 //this is to signal that there is no trade
// if there is a buy signal in this particular symbol & timeframe
if fast_kernel_signal == 0 and slow_kernel_signal == 0 and (kernel_ao_bullish or range_shift_signal == 0)
sl = matrix.get(screenerMtx, i, 7)
tp = closePrice > sl ? closePrice + ((closePrice-sl)*tpRatio) : closePrice + ((sl-closePrice)*tpRatio)
txt := txt + 'Buy' + '|' + str.tostring(closePrice) + '|' + str.tostring(tp) + '|' + str.tostring(sl) + '|' + symbol + '|' + timeframeText + '|' + entryTime + '\n'
table.cell(tbl, 5, i + 1, 'Buy \n'+str.tostring(closePrice), bgcolor = color.green, text_color = #000000, text_size = textSize)
table.cell(tbl, 6, i + 1, str.tostring(tp), bgcolor = color.green, text_color = #000000, text_size = textSize)
table.cell(tbl, 7, i + 1, str.tostring(sl), bgcolor = color.green, text_color = #000000, text_size = textSize)
matrix.set(tradeMtx, i + 1, 0, 0) //this is to signal that there is currently a trade open
matrix.set(tradeMtx, i + 1, 1, tp)
matrix.set(tradeMtx, i + 1, 2, sl)
matrix.set(tradeMtx, i + 1, 3, 0)
matrix.set(tradeMtx, i + 1, 4, counter) //assigning an identifier to this new trade
counter += 1
// changing the timeframe
isLowerTF := isLowerTF ? false:true
msg += txt
msg += tpSlMsg
if msg != ''
alert(msg, alert.freq_once_per_bar)