pine-scriptnormalizationnanormalize

Can't normalize my custom index to start at 0% y-intercept


I'm trying to normalize my script plot of the Mag7 index to start at the y-intercept, so that it lines up with the NASDAQ composite index (IXIC). The bespoke index consists of prices and total outstanding shares for the Mag 7. The normalizing divisor should be assigned bar_c_init on the first run, which is the initial Mag 7 index value. Then the initial value (of 1) and the subsequent normalized values should be multiplied by the initial IXIC value to start at the same point on the main chart. However, as you can see from the attached image and initial log values, the global IXIC initial value I assign is way off from the IXIC value on the plots and even what I log immediately after assigning the global value. What is going on?

// redbulleconomy - notes: improved RaenonX NQ 7 Index script to update % change based on window timeframe
// attribution to RaenonX for original script

//@version=5
indicator("NQ 7 Dynamic", overlay = true)


candle_up = #26a699
candle_down = #ef5350


var float factor = na // This will hold the first value of your index
var bool isFactorSet = false 
log.warning('isFactorSet {0}', isFactorSet)
var float nq_initial = na
var float[] bar_c_history = array.new_float()

[msft_o, msft_h, msft_l, msft_c] = request.security(ticker.new("NASDAQ", "MSFT", session.extended), timeframe.period, [open, high, low, close])
[msft_h_d, msft_l_d, msft_c_d] = request.security(ticker.new("NASDAQ", "MSFT", session.extended), "D", [high, low, close])
msft_shares = request.financial("NASDAQ:MSFT", "TOTAL_SHARES_OUTSTANDING", "FQ")

[aapl_o, aapl_h, aapl_l, aapl_c] = request.security(ticker.new("NASDAQ", "AAPL", session.extended), timeframe.period, [open, high, low, close])
[aapl_h_d, aapl_l_d, aapl_c_d] = request.security(ticker.new("NASDAQ", "AAPL", session.extended), "D", [high, low, close])
aapl_shares = request.financial("NASDAQ:AAPL", "TOTAL_SHARES_OUTSTANDING", "FQ")
log.info('apple close {0}', aapl_c)

[goog_o, goog_h, goog_l, goog_c] = request.security(ticker.new("NASDAQ", "GOOG", session.extended), timeframe.period, [open, high, low, close])
[goog_h_d, goog_l_d, goog_c_d] = request.security(ticker.new("NASDAQ", "GOOG", session.extended), "D", [high, low, close])
goog_shares = request.financial("NASDAQ:GOOG", "TOTAL_SHARES_OUTSTANDING", "FQ")

[nvda_o, nvda_h, nvda_l, nvda_c] = request.security(ticker.new("NASDAQ", "NVDA", session.extended), timeframe.period, [open, high, low, close])
[nvda_h_d, nvda_l_d, nvda_c_d] = request.security(ticker.new("NASDAQ", "NVDA", session.extended), "D", [high, low, close])
nvda_shares = request.financial("NASDAQ:NVDA", "TOTAL_SHARES_OUTSTANDING", "FQ")

[tsla_o, tsla_h, tsla_l, tsla_c] = request.security(ticker.new("NASDAQ", "TSLA", session.extended), timeframe.period, [open, high, low, close])
[tsla_h_d, tsla_l_d, tsla_c_d] = request.security(ticker.new("NASDAQ", "TSLA", session.extended), "D", [high, low, close])
tsla_shares = request.financial("NASDAQ:TSLA", "TOTAL_SHARES_OUTSTANDING", "FQ")

[amzn_o, amzn_h, amzn_l, amzn_c] = request.security(ticker.new("NASDAQ", "AMZN", session.extended), timeframe.period, [open, high, low, close])
[amzn_h_d, amzn_l_d, amzn_c_d] = request.security(ticker.new("NASDAQ", "AMZN", session.extended), "D", [high, low, close])
amzn_shares = request.financial("NASDAQ:AMZN", "TOTAL_SHARES_OUTSTANDING", "FQ")

[meta_o, meta_h, meta_l, meta_c] = request.security(ticker.new("NASDAQ", "META", session.extended), timeframe.period, [open, high, low, close])
[meta_h_d, meta_l_d, meta_c_d] = request.security(ticker.new("NASDAQ", "META", session.extended), "D", [high, low, close])
meta_shares = request.financial("NASDAQ:META", "TOTAL_SHARES_OUTSTANDING", "FQ")

nq_init = request.security(ticker.new("NASDAQ","IXIC",session.extended),timeframe.period, close)
log.warning("Current bar time: {0}-{1}-{2} {3}:{4} UTC", year(time), month(time), dayofmonth(time), hour(time), minute(time))
log.warning("IXIC index value: {0}", nq_init)

if na(nq_initial) and not na(nq_init) // or if barstate.isfirst
    nq_initial := nq_init

bar_c_init = aapl_c * aapl_shares + msft_c * msft_shares + goog_c * goog_shares + nvda_c * nvda_shares + tsla_c * tsla_shares + meta_c * meta_shares + amzn_c * amzn_shares

if not isFactorSet and not na(bar_c_init)
    factor := bar_c_init
    isFactorSet := true

// if na(factor)
//     factor := input.float(750241000, title = "Divisor")

log.warning('bar_c init {0}', bar_c_init)
log.warning("factor {0}", factor)
log.warning("nq initial {0}", nq_initial)

bar_o = (((aapl_o * aapl_shares + msft_o * msft_shares + goog_o * goog_shares + nvda_o * nvda_shares + tsla_o * tsla_shares + meta_o * meta_shares + amzn_o * amzn_shares)) / factor) * nq_initial
bar_h = ((aapl_h * aapl_shares + msft_h * msft_shares + goog_h * goog_shares + nvda_h * nvda_shares + tsla_h * tsla_shares + meta_h * meta_shares + amzn_h * amzn_shares)) / factor * nq_initial
bar_l = ((aapl_l * aapl_shares + msft_l * msft_shares + goog_l * goog_shares + nvda_l * nvda_shares + tsla_l * tsla_shares + meta_l * meta_shares + amzn_l * amzn_shares)) / factor * nq_initial
bar_c = (((aapl_c * aapl_shares + msft_c * msft_shares + goog_c * goog_shares + nvda_c * nvda_shares + tsla_c * tsla_shares + meta_c * meta_shares + amzn_c * amzn_shares)) / factor) * nq_initial

bar_c_prev = (((aapl_c_d[1] * aapl_shares + msft_c_d[1] * msft_shares + goog_c_d[1] * goog_shares + nvda_c_d[1] * nvda_shares + tsla_c_d[1] * tsla_shares + meta_c_d[1] * meta_shares + amzn_c_d[1] * amzn_shares)) / bar_c_init) * nq_initial

bar_color = bar_c > bar_o ? candle_up : candle_down

plotcandle(
     bar_o, bar_h, bar_l, bar_c,
     title = "NQ 7 Index", color = bar_color, wickcolor = bar_color, bordercolor = bar_color, format = 'percent')

Initial log values:

[2024-02-20T16:46:00.000-00:00]: isFactorSet true
[2024-02-20T16:46:00.000-00:00]: Current bar time: 2,024-2-20 11:46 UTC
[2024-02-20T16:46:00.000-00:00]: IXIC index value: 15,589.749
[2024-02-20T16:46:00.000-00:00]: bar_c init 11,667,709,725,440
[2024-02-20T16:46:00.000-00:00]: factor 11,423,353,265,270
[2024-02-20T16:46:00.000-00:00]: nq initial 14,147.935

Note that "IXIC index value" (nq_init) should be identical to the global "nq initial" (nq_initial), but it is not.

Again in the code we have:

nq_init = request.security(ticker.new("NASDAQ","IXIC",session.extended),timeframe.period, close)

if na(nq_initial) and not na(nq_init) 
// or we can do if barstate.isfirst w/same result
    nq_initial := nq_init

It just doesn't make sense. Appreciate any help and insight!

Update: it looks like the initial bar is off-screen (20,000 bars to the left) and being set as the global nq_initial value. However, the logs only correspond to what's visible. Also, the main security on the chart shows the correct return when y-axis is set to percentage, so there has to be a way to do this based on what's visible in the window.

IXIC index and bespoke Mag 7 Index


Solution

  • The issue was resolved mostly by using the recent feature chart.left_visible_bar_time like so:

    if (time == chart.left_visible_bar_time)
        nq_initial := nq_comp
        bar_c_init := aapl_c * aapl_shares + msft_c * msft_shares + goog_c * goog_shares + nvda_c * nvda_shares + tsla_c * tsla_shares + meta_c * meta_shares + amzn_c * amzn_shares // the factor