Search code examples
pine-scriptpine-script-v5

Use of boolean variable in function not working


I used what descibred in question Conditionally assign a series or na to a variable and in particular what answered by user rumpypumpydumpy

I need to call request.security (in 'tuple mode') only when a condition is met.

I made a function to return the tuple, in particular to return a 'NA-tuple' ([na, na, ..., na]) based on cited condition. The function receives a boolean parameter: if this parameter is 'true' the tuple contains the values I want collect from the higher timeframe, a NA-tuple otherwise.

The boolean parameter is generated with the following code: "My65_AvailFlag = barstate.islast and (My65TFInSec >= MyCurrTFInSec)", that is, I want request.security to return meaningful values only when the last bar is reached and when the chart timeframe is lower than the request.security timeframe ('65' minutes in the example).

The code doesn't work: if the chart timeframe is, as an example, '130' minutes (in general, greater than '65' minutes), values from the lower TF are requested and returned. The code works if I force 'false' inside the call to the function.

The table (only 1 row) in the bottom-right of the chart shows that the variable is 'false', but time is collected. Forcing to false the call to function, time is not collected.

For sure I'm wrong somewhere in the code, but don't understand where. Thanks for any advice / support.

Following an example of code:

//@version=5
indicator(title="ZZ_MyMiscInfo_V01", shorttitle="ZZ_MyMiscInfo_V01", overlay=true)


//Functions - BEGIN
MyFunc_GetSecurity(paramFlag) =>
    locTime = paramFlag ? time : int(na)
    locOpen = paramFlag ? open : float(na)
    locHigh = paramFlag ? high : float(na)
    locLow = paramFlag ? low : float(na)
    locClose = paramFlag ? close : float(na)
    locHigh1 = paramFlag ? high[1] : float(na)
    locLow1 = paramFlag ? low[1] : float(na)

    [locTime, locOpen, locHigh, locLow, locClose, locHigh1, locLow1]
//Functions - END


//Information about last bar candle of 'monitored' TimeFrames (TFs) is only available for higher TFs than the chart one
var MyCurrTFInSec = timeframe.in_seconds(timeframe.period)
var My65TFInSec = timeframe.in_seconds('65')

My65_AvailFlag = barstate.islast and (My65TFInSec >= MyCurrTFInSec)

//Information about last (and before last) candle is requested (only for higher TFs than the chart one)
[My65_OTime, My65_O, My65_H, My65_L, My65_C, My65_H1, My65_L1] = request.security(syminfo.tickerid, '65', expression=MyFunc_GetSecurity(My65_AvailFlag))


//Debug in Data-Window - BEGIN
plotchar(My65_AvailFlag, "My65_AvailFlag", "", location=location.top)
//Debug in Data-Window - END


var MyTable = table(na)

//Table with collected information
if barstate.islast
    //Table initialization
    if not na(MyTable)
        table.delete(MyTable)
        MyTable := table(na)
    
    MyTable := table.new('bottom_right', columns=1, rows=1, border_width=1)
    
    table.cell(MyTable, 0, 0, ("65-min ( " + str.tostring(My65TFInSec) + " - " + str.tostring(My65_AvailFlag) + " ) " + (na(My65_OTime) ? "_NA_" : str.format_time(My65_OTime, "YYYY-MM-dd HH:mm", syminfo.timezone))), text_color=color.white, bgcolor=color.blue, text_size=size.small, width=0, height=0)

Solution

  • Couple things you need to understand about current behaviour of request. function first:

    1. Function will allways request data for each bar on the chart no matter the conditions used.
    2. The expression parameter "sucks in" all the variables/functions/dependencies that passed to it, and evaluates it in context of other charts data.
    var MyCurrTFInSec = timeframe.in_seconds(timeframe.period)
    
    ... 
    
    My65_AvailFlag = barstate.islast and (My65TFInSec >= MyCurrTFInSec)
    
    [My65_OTime, My65_O, My65_H, My65_L, My65_C, My65_H1, My65_L1] = request.security(syminfo.tickerid, '65', expression=MyFunc_GetSecurity(My65_AvailFlag))
    
    

    here MyFunc_GetSecurity(My65_AvailFlag) calculates in 65 min charts context! Thus, My65_AvailFlag will be true, because My65TFInSec == MyCurrTFInSec (because in timeframe.in_seconds(timeframe.period) the timeframe.period is not charts period, but security period, which is 65 min).

    So, from the (1) and (2) the solution might be:

    request values from security, and if condition is not met, reassign them to na:

    //@version=5
    indicator(title="ZZ_MyMiscInfo_V01", shorttitle="ZZ_MyMiscInfo_V01", overlay=true)
    
    MyFunc_GetSecurity() =>
        [time, open, high, low, close, high[1], low[1]]
    
    var MyCurrTFInSec = timeframe.in_seconds(timeframe.period)
    var My65TFInSec = timeframe.in_seconds('65')
    
    My65_AvailFlag = barstate.islast and (My65TFInSec >=  timeframe.in_seconds("1D"))
    
    [My65_OTime, My65_O, My65_H, My65_L, My65_C, My65_H1, My65_L1] = request.security(syminfo.tickerid, '65', expression = MyFunc_GetSecurity())
    
    if not My65_AvailFlag
        My65_OTime:=na 
        My65_O:=na 
        My65_H:=na 
        My65_L:=na
        My65_C:=na
        My65_H1:=na
        My65_L1:=na
    
    plotchar(My65_AvailFlag, "My65_AvailFlag", "", location=location.top)
    
    var MyTable = table(na)
    
    if barstate.islast
        if not na(MyTable)
            table.delete(MyTable)
            MyTable := table(na)
        MyTable := table.new('bottom_right', columns=1, rows=1, border_width=1)
        table.cell(MyTable, 0, 0, ("65-min ( " + str.tostring(My65TFInSec) + " - " + str.tostring(My65_AvailFlag) + " ) " + (na(My65_OTime) ? "_NA_" : str.format_time(My65_OTime, "YYYY-MM-dd HH:mm", syminfo.timezone))), text_color=color.white, bgcolor=color.blue, text_size=size.small, width=0, height=0)