JS_Riddler
JS_Riddler

Reputation: 1580

Get daily close values of the last N days, regardless of chart's timeframe

I'm not able to figure out how to grab the last 200-days of close values, for example.

I believe the core issue is that the security function returns a series indexed by the chart's current timeframe, and not by the resolution itself. I cannot find any option to alter this behavior.

Eg:

sec = security("SPY", "D", close)
// this will return the close 100 bars ago, not days ago!
sec[100]

In this example, I'm trying to plot the 10-day moving average, regardless of the chart's timeframe:

//@version=4
study(title='Test', overlay=false, max_labels_count=500) 

// get the daily close for asset and benchmark
sec = security("SPY", "D", close)
lookback = 10

get_daily_closes(sec, lookback) =>
    // populate array with "lookback" number of values
    // unfortunatley, sec[i] will not be the value i days ago, but the value i bars ago.
    var arr_daily_closes = array.new_float()
    array.clear(arr_daily_closes)
    for i = 0 to lookback-1
        array.push(arr_daily_closes, sec[i])
    arr_daily_closes
    
get_arr_avg(arr) =>
    // compute the average of the entire array
    var float sum = 0.0
    sum := 0
    var length = array.size(arr)
    for i = 0 to length-1
        sum := sum + array.get(arr, i)
    sum/length
    
arr_daily_closes = get_daily_closes(sec, lookback)
nday_avg = get_arr_avg(arr_daily_closes)
plot(nday_avg, color=color.red)

This will only work as intended if the chart's timeframe is set to Daily. Otherwise, it will plot the 10-bar moving average, and not 10-day moving average.

I also don't understand why I need to call array.clear() and sum := 0 within those functions. It seems as though those variables should be created only each time I call the function... but I suppose that's a separate question.

Upvotes: 0

Views: 2143

Answers (1)

rumpypumpydumpy
rumpypumpydumpy

Reputation: 3833

Functions, both custom and built in can be used within the context of a security call.

sec = security("SPY", "D", sma(close, 10))

If you require the values in an array for another purpose you can do this :

var int lookback = 10

daily_close_ts = security(syminfo.tickerid, "D", time_close)

var int min_in_ms = 60000

last_bar_ts = daily_close_ts - timeframe.multiplier * min_in_ms

var float[] daily_closes = array.new_float(lookback)

if barstate.isconfirmed and timeframe.isintraday and time == last_bar_ts
    array.unshift(daily_closes, close)
    array.pop(daily_closes)
    
l = label.new(x = bar_index, y = close, style = label.style_label_left, text = tostring(daily_closes))
label.delete(l[1])

daily_sma = array.avg(daily_closes)
plot(daily_sma)

You need to keep in mind though, that depending on your intraday timeframe and the length of lookback, it may exceed the number of daily values that are available. We can only access those values that exist within the historical range of the chart's timeframe. If the lookback exceeds what is available, you'll end up with an array that is partially still populated with na values.

Alternatively you can also approach it this way, however it will only obtain the day's close on the first bar of the next new day, rather than on the closing of the last intraday bar of the day.

var int lookback = 10

daily_close = security(syminfo.tickerid, "D", close)


var float[] daily_closes = array.new_float(lookback)

if change(time("D")) != 0
    array.unshift(daily_closes, daily_close)
    array.pop(daily_closes)

l = label.new(x = bar_index, y = close, style = label.style_label_left, text = tostring(daily_closes))
label.delete(l[1])

daily_sma = array.avg(daily_closes)
plot(daily_sma)

If you declare your array or variable with the var keyword then it isn't reinitialized each bar, but maintains it's state from the previous bar. Since your functions will be called every bar, on the first bar they are created in the scope of the function and still exist within that scope when the function is called on subsequent bars. If you do want them to be reset each bar execution then you just declare them without the var keyword.

Upvotes: 1

Related Questions