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

//@version=5
import PineCoders/LibraryStopwatch/1 as sw
// @description This library allows you to reduce the number of request.security calls to 1 per symbol per timeframe.
library("ReduceSecurityCalls")
nonRepaintingSecurity(sym, tf, expr) => request.security(sym, tf, expr[barstate.isrealtime ? 1 : 0])[barstate.isrealtime ? 0 : 1]
ifSecurity(sym, tf, expr) => request.security(sym, tf, expr)
// @function Parsedata function, should be used inside request.security call. Optimise your calls using timeframe.change when htf data parsing! Supports up to 5 expressions (results of expressions must be float or int)
// @param mat_outs Matrix to be used as outputs, first value is newest 
// @param o Please use parametres in the order they specified (o should be 1st, h should be 2nd etc..)  
// @returns outs array, due to weird limitations do not try to matrix_out = matrix.copy(ParseSource)
export ParseSource(series float o = na, series float h = na, series float l = na, series float c = na, series float custom = na, int length) =>//, matrix<float> mat_outs) =>
	mat_outs = matrix.new<float>()
	int count = 0
    if length < 1
    	runtime.error('length to parse should be >= 1 (current candle counts as 1)')
	//if barstate.isfirst
	while matrix.columns(mat_outs)<length
		matrix.add_col(mat_outs,0)
	while matrix.rows(mat_outs)<5
		matrix.add_row(mat_outs,0)
	
	count += na(o) 		? 0 : 1
	count += na(h) 		? 0 : 1
	count += na(l) 		? 0 : 1
	count += na(c) 		? 0 : 1
	count += na(custom) ? 0 : 1
    
	for i=0 to length-1
	    if count >=  1
			matrix.set(mat_outs, 0, i,  o[i])
	    if count >=  2
			matrix.set(mat_outs, 1, i,  h[i])
	    if count >=  3
			matrix.set(mat_outs, 2, i,  l[i])
	    if count >=  4
			matrix.set(mat_outs, 3, i,  c[i])
	    if count ==  5
			matrix.set(mat_outs, 4, i,  custom[i])
	mat_outs

inp_l = input.int(defval = 5, title = 'length')
inp_tf =input.timeframe(defval = '1D', title = 'TF')
inp_sym =input.symbol(defval = 'BYBIT:BTCUSDT.P',title = 'symbol')

var mat_parsed = matrix.new<float>(5, inp_l, 0)


if barstate.isfirst or timeframe.change(inp_tf)
	mat_parsed :=ifSecurity(syminfo.tickerid, inp_tf, ParseSource(o=open, h= high, l=low, c=close, custom =ta.tr(true), length =inp_l))//,  mat_outs = mat_parsed))


[timePerBarInMs, totalTimeInMs, barsTimed, barsNotTimed] = sw.stopwatchStats()
msElapsed = sw.stopwatch()
res = array.size(matrix.row(mat_parsed, int(math.random(0,5))))

if barstate.islast
    var table t = table.new(position.middle_right, 1, 1)
    var txt = str.tostring(timePerBarInMs, "ms/bar: #.######\n") +
              str.tostring(totalTimeInMs, "Total time (ms): #,###.######\n") + 
              str.tostring(barsTimed + barsNotTimed, "Bars analyzed: #\n") +
             
			  str.tostring(mat_parsed)+'\n Symbol: ' +
			  
              inp_sym + '\n TF: ' +
			  inp_tf +'\n data length: ' +
			  str.tostring(res)
              //res2
    table.cell(t, 0, 0, txt, bgcolor = color.yellow, text_halign = text.align_right)

