Coding The Multinomial Retrogression Projection Model

Female Software Engineer Coding on Computer

// This source code is subject to the terms of the Mozilla Public License 2.0
// © Yaseen Khalil
// @version=5

//Define as indicator, overlay on chart, assign maximum line count to 500

indicator(“Multinomial Retrogression Projection (MRP)”, overlay = true, max_lines_count = 500)

//------------------------------------ SETTINGS ------------------------------------
//User inputs to define the length or period, the projection, and the degree of the multinomial retrogression

length      = input.int(100, minval = 0)

extrapolate = input.int(10, minval = 0)

degree      = input.int(3, ‘Polynomial Degree’, minval = 0, maxval = 8)

src         = input(close)

lock        = input(false, ‘Lock Forecast’)

//Style to define the color and width of the MRP line

up_css = input.color(#0cb51a, ‘Upward Color’, group = ‘Style’)

dn_css = input.color(#ff1100, ‘Downward Color’, group = ‘Style’)

ex_css = input.color(#ff5d00, ‘Extrapolation Color’, group = ‘Style’)

width  = input(1, ‘Width’, group = ‘Style’)

//------------------------------------ Fill lines array ------------------------------------
//Create a new array, type line

var lines = array.new_line(0)

//Check if current bar is first bar in the barset. Repeat as new bar is set.

if barstate.isfirst

    for i = -extrapolate to length-1

        array.push(lines, line.new(na, na, na, na))

//------------------------------------ Design matrix & partially solve system ----------------------------
//Set n to the current bar index

n = bar_index

//Assign variables to new matrix object, type float

var design   = matrix.new<float>(0, 0)

var response = matrix.new<float>(0, 0)

//Check if current bar is first bar in barset. Develop loop that iterates through each degree, starting   //from 0 up to the specified degree.                                                                                                                                            //Initialize a new array named 'column' to store floating-point values, will be initially empty.                        //Create loop through each element in the range from 0 to the length of the array minus 1.

if barstate.isfirst

    for i = 0 to degree

        column = array.new_float(0)

        //Push the result of raising j to the power of i to the 'column' array.

        for j = 0 to length-1

            array.push(column, math.pow(j,i))

        //Add the 'column' array as a new column to the 'design' matrix.

        matrix.add_col(design, i, column)

//calculate the inverse of the product of the changed position of the 'design' matrix and the 'design' matrix itself and assigns it to variable 'a'.                                                                                                                               //Then calculate the product of 'a' and the changed position of the 'design' matrix and assigns it to variable 'b

var a = matrix.inv(matrix.mult(matrix.transpose(design), design))

var b = matrix.mult(a, matrix.transpose(design))

//-------------Get response matrix and compute rolling polynomial retrogression ----------------
//Now we initialize the variables 'pass', 'coefficients', 'x', and 'forecast' with default values

var pass = 1

var matrix<float> coefficients = na

var x = -extrapolate

var float forecast = na

//Check if the current bar state is the last one. Check if 'pass' is true. If yes, initialize an array 'price' to store float values.

if barstate.islast

    if pass

        prices = array.new_float(0)

 //Loop through each element in the 'src' array and add each element of 'src' array to the 'prices' array.

        for i = 0 to length-1

            array.push(prices, src[i])

//Add the 'prices' array as a new column to the 'response' matrix at index 0 and calculate coefficients by multiplying matrix 'b' with matrix 'response'

        matrix.add_col(response, 0, prices)

        coefficients := matrix.mult(b, response)

//Initialize 'y1' variable as 'na' and 'idx' as 0

        float y1 = na

        idx = 0

 //Loop through -extrapolate to length-1.

        for i = -extrapolate to length-1

            y2 = 0.

    //Calculate 'y2' using multinomial retrogression based on 'i' and 'coefficients'

            for j = 0 to degree

                y2 += math.pow(i, j)*matrix.get(coefficients, j, 0)

            if idx == 0

                forecast := y2

   //Here we set the line attributes
  //Set 'css' variable based on the comparison of 'y2' and 'y1'
  //Then Update line positions, colors, and width

            css = y2 < y1 ? up_css : dn_css

            get_line = array.get(lines, idx)

            line.set_xy1(get_line, n – i + 1, y1)

            line.set_xy2(get_line, n – i, y2)

            line.set_color(get_line, i <= 0 ? ex_css : css)

            line.set_width(get_line, width)

   //Update 'y1' with 'y2' value and increment 'idx' by 1

            y1 := y2

            idx += 1

 //Set 'pass' to 0 if 'lock' is true    

        if lock

            pass := 0

//Reset 'y2' and reduce 'x' if 'pass' is false

    else

        y2 = 0.

        x -= 1

//Now, we calculate the forecast for extrapolation or projection - 'y2' for extrapolation based on 'x' and 'coefficients'

        for j = 0 to degree

            y2 += math.pow(x, j)*matrix.get(coefficients, j, 0)

        forecast := y2

//Finally, we plot the forecasted values if 'pass' is 0, otherwise plot 'na'

plot(pass == 0 ? forecast : na, ‘Extrapolation’

  , color     = ex_css

  , offset    = extrapolate

  , linewidth = width)

Download and see more projects at my GitHub page.

Now, let’s check out how well it back tests!

Powerful Closures: Leaving a Lasting Impression

Concluding your blog post isn’t just about wrapping things up – it’s your final opportunity to leave a strong impact. Summarize the key takeaways from your post, reinforcing your main points. If relevant, provide actionable solutions or thought-provoking questions to keep readers thinking beyond the post. Encourage engagement by inviting comments, questions, or sharing. A well-crafted conclusion should linger in your readers’ minds, inspiring them to explore further or apply what they’ve learned.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top