linear regression plot dependent on condition

Glefdar

Active member
If functions (such as "movingaverage" or "stdev") expect a constant as the length parameter, an error is returned when attempting to instead get the length parameter from a variable.

So if we want to calculate a moving average or standard deviation with a length that varies based on market conditions, it will be necessary to manually write code for movingaverage and stdev instead of using the built-in functions.
EDIT, wanted to share here that Mobius provided code in the TS Lounge that allows for variable length regression line and variable length standard deviation calculations:

Code:
# Linear Regression Channel anchored to Highest / Lowest Pivot
# Allows a floating point anchor
# Mobius
# V01.2015

def hh = highestAll(high);
def ll = lowestAll(low);
script S
    {
     input d = close;
     input n = 50;
     plot e = fold i = 0 to n
              with f
              do f + getValue(d, i);
    }
def y = close;
def x  = BarNumber();
def nan = double.nan;
def xx = if(isNaN(y[-1]) and !isNaN(y), x, xx[1]);
def hx = if(high == hh, x, hx[1]);
def lx = if(low == ll, x, lx[1]);
def MinX = Max(hx, lx);
def n = highestAll(xx - MinX);
def x1 = HighestAll(if !IsNaN(y) and IsNaN(y[-1])
                    then x
                    else nan);
def x0 = HighestAll(if GetValue(x, -n) == x1
                    then x
                    else nan);
def x_ = if GetValue(x, -n) >= x1
         then x - x0
         else x_[1];
def Ex  = S(x_, n);
def Ey  = S(y, n);
def Exy = S(x_ * y, n);
def Exsq = S(sqr(x_), n);
def b = (n * Exy - (Ex * Ey)) / (n * Exsq - (Ex * Ex));
def a = (GetValue(Ey, x - x1) - GetValue(b, x - x1) * GetValue(Ex, x - x1)) / n;
def avg = (fold i = 0 to n
           with s
           do s + getValue(y, i)) / n;
def SD = Sqrt((fold i2 = 0 to n
               with s2 = 0
               do s2 + Sqr(avg - GetValue(y, i2))) / n);
plot LRL = if x >= x0
           then a + (GetValue(b, x - x1) * x_)
           else nan;
     LRL.SetStyle(Curve.Firm);
     LRL.SetDefaultColor(Color.Cyan);
plot upper = LRL + (highestAll(SD) * .7);
     upper.SetStyle(Curve.Firm);
     upper.SetDefaultColor(Color.Yellow);
plot lower = LRL - (highestAll(SD) * .7);
     lower.SetStyle(Curve.Firm);
     lower.SetDefaultColor(Color.Yellow);
# End Code Linear Regression Line

This provided me with the template I needed. The only thing that was also important to know was that the fold function can break scripts if your chart is displaying an expansion area, and this has to be prevented by instructing the code with fold (or code accessing the fold output value) with a preliminary condition such as “def {variable} = if isNan(close) then {variable}[1} else ….” or “then double.nan else…” depending on what is needed.
 
Last edited:
Solution
@SleepyZ Wondering if you could provide your feedback here? I would love to be able to have the LRC stop painting (repainting) once a condition is met. Thanks!!!

[corrected def cond_y = if SecondsFromTime(endtime) <= 0 then x else nan;
1. This will allow you to use Mobius Time Anchored LR Channel and limit its' plot to a condition (cond_y).
2. The plot can be extended from the condition end by input extend = yes;.
3. There are some conditional examples.
4. The image on the left is with extend = no, and the right, extend = yes;. Both show the unmodified code.

Screenshot 2024-04-06 151154.png
Code:
#Mobius_Anchored_Linear_Regression_modified_End_at_Cond_y_Extended_Option
#08:35 Mobius: Here's the anchored Regression Channel I use...
Code:
script VariableStDev{
    input source = 0;
    input length = 0;
    def avg = (fold index = 0 to length with data
     do data + getvalue(source,index)) / length;
    plot variableStDev = sqrt((fold i = 0 to length with d
     do d + Sqr(GetValue(source,i) - avg)) / length);
}
plot x = VariableStDev(close,20);
plot y = VariableStDev(close,Ceil(Random() * 10));
plot z = stDev(close,20);
z.setpaintingStrategy(paintingStrategy.POINTS);
 
EDIT: I think I found a solution: https://usethinkscript.com/threads/anchored-linear-regression-lines.11141/#post-104185

I thought that I had this working but it causes the chart to break erratically. This is the code now (for comparison, the entire unmodified code from Mobius is here):

Code:
# Linear Regression Channel anchored to Highest / Lowest Pivot
# With floating point anchor
# Mobius
# V01.2015

def hh_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then highest(high,100) else hh_LRC_2[1];
def ll_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then lowest(low,100) else hh_LRC_2[1];
script S_LRC_2
    {
     input d_LRC_2 = close;
     input n_LRC_2 = 50;
     plot e_LRC_2 = fold i_LRC_2 = 0 to n_LRC_2
              with f_LRC_2
              do f_LRC_2 + getValue(d_LRC_2, i_LRC_2);
    }
def y_LRC_2 = close;
def x_LRC_2  = BarNumber();
def nan_LRC_2 = double.nan;
def xx_LRC_2 = if(isNaN(y_LRC_2[-1]) and !isNaN(y_LRC_2), x_LRC_2, xx_LRC_2[1]);
def hx_LRC_2 = if(high == hh_LRC_2, x_LRC_2, hx_LRC_2[1]);
def lx_LRC_2 = if(low == ll_LRC_2, x_LRC_2, lx_LRC_2[1]);
def MinX_LRC_2 = Max(hx_LRC_2, lx_LRC_2);
def n_LRC_2 = highestAll(xx_LRC_2 - MinX_LRC_2);
def x1_LRC_2 = HighestAll(if !IsNaN(y_LRC_2) and IsNaN(y_LRC_2[-1])
                    then x_LRC_2
                    else nan_LRC_2);
def x0_LRC_2 = HighestAll(if GetValue(x_LRC_2, -n_LRC_2) == x1_LRC_2
                    then x_LRC_2
                    else nan_LRC_2);
def x__LRC_2 = if GetValue(x_LRC_2, -n_LRC_2) >= x1_LRC_2
         then x_LRC_2 - x0_LRC_2
         else x__LRC_2[1];
def Ex_LRC_2  = S_LRC_2(x__LRC_2, n_LRC_2);
def Ey_LRC_2  = S_LRC_2(y_LRC_2, n_LRC_2);
def Exy_LRC_2 = S_LRC_2(x__LRC_2 * y_LRC_2, n_LRC_2);
def Exsq_LRC_2 = S_LRC_2(sqr(x__LRC_2), n_LRC_2);
def b_LRC_2 = (n_LRC_2 * Exy_LRC_2 - (Ex_LRC_2 * Ey_LRC_2)) / (n_LRC_2 * Exsq_LRC_2 - (Ex_LRC_2 * Ex_LRC_2));
def a_LRC_2 = (GetValue(Ey_LRC_2, x_LRC_2 - x1_LRC_2) - GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * GetValue(Ex_LRC_2, x_LRC_2 - x1_LRC_2)) / n_LRC_2;
def avg_LRC_2 = (fold i_LRC_2 = 0 to n_LRC_2
           with s_LRC_2
           do s_LRC_2 + getValue(y_LRC_2, i_LRC_2)) / n_LRC_2;
def SD_LRC_2 = if !isNan(close) then (Sqrt((fold i2_LRC_2 = 0 to n_LRC_2
               with s2_LRC_2 = 0
               do s2_LRC_2 + Sqr(avg_LRC_2 - GetValue(y_LRC_2, i2_LRC_2))) / n_LRC_2)) else double.nan;

def LRL_LRC_2_pre = if isNan(close) then double.nan else if x_LRC_2 >= x0_LRC_2
           then a_LRC_2 + (GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * x__LRC_2)
           else nan_LRC_2;

def LRL_LRC_2_countback = if isNan(LRL_LRC_2_pre) then 0 else LRL_LRC_2_countback[1]+1;
#AddChartBubble(!isNan(LRL_LRC_3_pre),LRL_LRC_3_pre,LRL_LRC_3_countback,color.white,yes);

def LRL_LRC_2_validation = if !isNan(close) then ( fold LRL_LRC_2_cross_i = 0 to LRL_LRC_2_countback
with LRL_LRC_2_cross_p
while (!isNan(z_negative_slope_sigma3) or LRL_LRC_2_validation[1]>0)
do 1+LRL_LRC_2_validation[1]) else double.nan;
#do LRL_LRC_3_cross_p + (!isNan(z_negative_slope_sigma2));

#AddChartBubble(!isNan(LRL_LRC_2_pre),LRL_LRC_2_pre,LRL_LRC_2_validation,color.white,yes);

plot LRL_LRC_2 = if barnumber()<10000 then double.nan else if LRL_LRC_2_validation>0 then (if x_LRC_2 >= x0_LRC_2
           then a_LRC_2 + (GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * x__LRC_2)
           else nan_LRC_2) else double.nan;
     LRL_LRC_2.SetStyle(Curve.Firm);
     LRL_LRC_2.AssignValueColor(color.magenta);
plot upper_LRC_2 = LRL_LRC_2 + (highestAll(SD_LRC_2) * .7);
     upper_LRC_2.SetStyle(Curve.Firm);
     upper_LRC_2.AssignValueColor(color.magenta);
plot lower_LRC_2 = LRL_LRC_2 - (highestAll(SD_LRC_2) * .7);
     lower_LRC_2.SetStyle(Curve.Firm);
     lower_LRC_2.AssignValueColor(color.magenta);
# End Code Linear Regression Line

What I changed first was these two lines:

Code:
def hh_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then highest(high,100) else hh_LRC_2[1];
def ll_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then lowest(low,100) else hh_LRC_2[1];

"z_negative_slope_sigma3" is the trigger condition I want to use for the plot (not defined in the above code excerpt, could be replaced with any condition variable). The two above variables originally were defined as "HighestAll(high)" and "LowestAll(low)".

I also added this:

Code:
def LRL_LRC_2_pre = if isNan(close) then double.nan else if x_LRC_2 >= x0_LRC_2
           then a_LRC_2 + (GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * x__LRC_2)
           else nan_LRC_2;

def LRL_LRC_2_countback = if isNan(LRL_LRC_2_pre) then 0 else LRL_LRC_2_countback[1]+1;
#AddChartBubble(!isNan(LRL_LRC_3_pre),LRL_LRC_3_pre,LRL_LRC_3_countback,color.white,yes);

def LRL_LRC_2_validation = if !isNan(close) then ( fold LRL_LRC_2_cross_i = 0 to LRL_LRC_2_countback
with LRL_LRC_2_cross_p
while (!isNan(z_negative_slope_sigma3) or LRL_LRC_2_validation[1]>0)
do 1+LRL_LRC_2_validation[1]) else double.nan;

And then changed the main plot by adding "if barnumber()<10000 then double.nan else if LRL_LRC_2_validation>0 then".

The reason for the dumb workaround with the "validation" fold loop is that the linear regression channel was still plotting even though I added "if !isNan(z_negative_slope_sigma3) within 1 bars" to the variable definition for getting the high for the regression channel (I think because the else condition just returns to the previous bar ("else hh_LRC_2[1]"), but I did that because "else double.nan" broke the script).

Although my workaround appeared to work for a while before breaking, I am in over my head trying to modify this to function as desired. I just want the linear regression channel to plot in dependence on a condition being met and I want the bar where the condition is met to be the anchor point for the high and low.

If anyone is able to figure out how to do this then it's probably easier to attempt the solution on the original code (here) not least because the variable names are less confusing (I appended "LRC_2" to all the variable names due to planning on having multiple versions of the plot painting differently while using different trigger conditions).

I think that the idea (of modifying this to plot based on a trigger condition also acting as an anchor) could be very useful because it could allow for any indicator to be complemented by a linear regression channel when the signal fires. I'm hoping someone finds this interesting enough to attempt the challenge or is willing to help with this.

I've posted a lot of questions in the forum lately but hopefully they will have value to the community by adding to the forum's searchable knowledge base 🙏
 
Last edited:
EDIT: I think I found a solution: https://usethinkscript.com/threads/anchored-linear-regression-lines.11141/#post-104185

I thought that I had this working but it causes the chart to break erratically. This is the code now (for comparison, the entire unmodified code from Mobius is here):

Code:
# Linear Regression Channel anchored to Highest / Lowest Pivot
# With floating point anchor
# Mobius
# V01.2015

def hh_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then highest(high,100) else hh_LRC_2[1];
def ll_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then lowest(low,100) else hh_LRC_2[1];
script S_LRC_2
    {
     input d_LRC_2 = close;
     input n_LRC_2 = 50;
     plot e_LRC_2 = fold i_LRC_2 = 0 to n_LRC_2
              with f_LRC_2
              do f_LRC_2 + getValue(d_LRC_2, i_LRC_2);
    }
def y_LRC_2 = close;
def x_LRC_2  = BarNumber();
def nan_LRC_2 = double.nan;
def xx_LRC_2 = if(isNaN(y_LRC_2[-1]) and !isNaN(y_LRC_2), x_LRC_2, xx_LRC_2[1]);
def hx_LRC_2 = if(high == hh_LRC_2, x_LRC_2, hx_LRC_2[1]);
def lx_LRC_2 = if(low == ll_LRC_2, x_LRC_2, lx_LRC_2[1]);
def MinX_LRC_2 = Max(hx_LRC_2, lx_LRC_2);
def n_LRC_2 = highestAll(xx_LRC_2 - MinX_LRC_2);
def x1_LRC_2 = HighestAll(if !IsNaN(y_LRC_2) and IsNaN(y_LRC_2[-1])
                    then x_LRC_2
                    else nan_LRC_2);
def x0_LRC_2 = HighestAll(if GetValue(x_LRC_2, -n_LRC_2) == x1_LRC_2
                    then x_LRC_2
                    else nan_LRC_2);
def x__LRC_2 = if GetValue(x_LRC_2, -n_LRC_2) >= x1_LRC_2
         then x_LRC_2 - x0_LRC_2
         else x__LRC_2[1];
def Ex_LRC_2  = S_LRC_2(x__LRC_2, n_LRC_2);
def Ey_LRC_2  = S_LRC_2(y_LRC_2, n_LRC_2);
def Exy_LRC_2 = S_LRC_2(x__LRC_2 * y_LRC_2, n_LRC_2);
def Exsq_LRC_2 = S_LRC_2(sqr(x__LRC_2), n_LRC_2);
def b_LRC_2 = (n_LRC_2 * Exy_LRC_2 - (Ex_LRC_2 * Ey_LRC_2)) / (n_LRC_2 * Exsq_LRC_2 - (Ex_LRC_2 * Ex_LRC_2));
def a_LRC_2 = (GetValue(Ey_LRC_2, x_LRC_2 - x1_LRC_2) - GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * GetValue(Ex_LRC_2, x_LRC_2 - x1_LRC_2)) / n_LRC_2;
def avg_LRC_2 = (fold i_LRC_2 = 0 to n_LRC_2
           with s_LRC_2
           do s_LRC_2 + getValue(y_LRC_2, i_LRC_2)) / n_LRC_2;
def SD_LRC_2 = if !isNan(close) then (Sqrt((fold i2_LRC_2 = 0 to n_LRC_2
               with s2_LRC_2 = 0
               do s2_LRC_2 + Sqr(avg_LRC_2 - GetValue(y_LRC_2, i2_LRC_2))) / n_LRC_2)) else double.nan;

def LRL_LRC_2_pre = if isNan(close) then double.nan else if x_LRC_2 >= x0_LRC_2
           then a_LRC_2 + (GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * x__LRC_2)
           else nan_LRC_2;

def LRL_LRC_2_countback = if isNan(LRL_LRC_2_pre) then 0 else LRL_LRC_2_countback[1]+1;
#AddChartBubble(!isNan(LRL_LRC_3_pre),LRL_LRC_3_pre,LRL_LRC_3_countback,color.white,yes);

def LRL_LRC_2_validation = if !isNan(close) then ( fold LRL_LRC_2_cross_i = 0 to LRL_LRC_2_countback
with LRL_LRC_2_cross_p
while (!isNan(z_negative_slope_sigma3) or LRL_LRC_2_validation[1]>0)
do 1+LRL_LRC_2_validation[1]) else double.nan;
#do LRL_LRC_3_cross_p + (!isNan(z_negative_slope_sigma2));

#AddChartBubble(!isNan(LRL_LRC_2_pre),LRL_LRC_2_pre,LRL_LRC_2_validation,color.white,yes);

plot LRL_LRC_2 = if barnumber()<10000 then double.nan else if LRL_LRC_2_validation>0 then (if x_LRC_2 >= x0_LRC_2
           then a_LRC_2 + (GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * x__LRC_2)
           else nan_LRC_2) else double.nan;
     LRL_LRC_2.SetStyle(Curve.Firm);
     LRL_LRC_2.AssignValueColor(color.magenta);
plot upper_LRC_2 = LRL_LRC_2 + (highestAll(SD_LRC_2) * .7);
     upper_LRC_2.SetStyle(Curve.Firm);
     upper_LRC_2.AssignValueColor(color.magenta);
plot lower_LRC_2 = LRL_LRC_2 - (highestAll(SD_LRC_2) * .7);
     lower_LRC_2.SetStyle(Curve.Firm);
     lower_LRC_2.AssignValueColor(color.magenta);
# End Code Linear Regression Line

What I changed first was these two lines:

Code:
def hh_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then highest(high,100) else hh_LRC_2[1];
def ll_LRC_2 = if !isNan(z_negative_slope_sigma3) within 1 bars then lowest(low,100) else hh_LRC_2[1];

"z_negative_slope_sigma3" is the trigger condition I want to use for the plot (not defined in the above code excerpt, could be replaced with any condition variable). The two above variables originally were defined as "HighestAll(high)" and "LowestAll(low)".

I also added this:

Code:
def LRL_LRC_2_pre = if isNan(close) then double.nan else if x_LRC_2 >= x0_LRC_2
           then a_LRC_2 + (GetValue(b_LRC_2, x_LRC_2 - x1_LRC_2) * x__LRC_2)
           else nan_LRC_2;

def LRL_LRC_2_countback = if isNan(LRL_LRC_2_pre) then 0 else LRL_LRC_2_countback[1]+1;
#AddChartBubble(!isNan(LRL_LRC_3_pre),LRL_LRC_3_pre,LRL_LRC_3_countback,color.white,yes);

def LRL_LRC_2_validation = if !isNan(close) then ( fold LRL_LRC_2_cross_i = 0 to LRL_LRC_2_countback
with LRL_LRC_2_cross_p
while (!isNan(z_negative_slope_sigma3) or LRL_LRC_2_validation[1]>0)
do 1+LRL_LRC_2_validation[1]) else double.nan;

And then changed the main plot by adding "if barnumber()<10000 then double.nan else if LRL_LRC_2_validation>0 then".

The reason for the dumb workaround with the "validation" fold loop is that the linear regression channel was still plotting even though I added "if !isNan(z_negative_slope_sigma3) within 1 bars" to the variable definition for getting the high for the regression channel (I think because the else condition just returns to the previous bar ("else hh_LRC_2[1]"), but I did that because "else double.nan" broke the script).

Although my workaround appeared to work for a while before breaking, I am in over my head trying to modify this to function as desired. I just want the linear regression channel to plot in dependence on a condition being met and I want the bar where the condition is met to be the anchor point for the high and low.

If anyone is able to figure out how to do this then it's probably easier to attempt the solution on the original code (here) not least because the variable names are less confusing (I appended "LRC_2" to all the variable names due to planning on having multiple versions of the plot painting differently while using different trigger conditions).

I think that the idea (of modifying this to plot based on a trigger condition also acting as an anchor) could be very useful because it could allow for any indicator to be complemented by a linear regression channel when the signal fires. I'm hoping someone finds this interesting enough to attempt the challenge or is willing to help with this.

I've posted a lot of questions in the forum lately but hopefully they will have value to the community by adding to the forum's searchable knowledge base 🙏

The problem seems to be (even with the version SleepyZ shared) that the Linear Regression Channel breaks the chart if it's not able to find any condition for plotting. So the solution I've decided to go with is to use a global color that it paints if the trigger condition isn't met within the number of bars that it's supposed to look. Then I can adjust the transparency of the global color to make it invisible. That's an acceptable workaround from my perspective. I am alright with the channel disappearing after the within x bars is exceeded, as a compromise to not have to use highestall which makes the chart run slowly.
 
The problem seems to be (even with the version SleepyZ shared) that the Linear Regression Channel breaks the chart if it's not able to find any condition for plotting. So the solution I've decided to go with is to use a global color that it paints if the trigger condition isn't met within the number of bars that it's supposed to look. Then I can adjust the transparency of the global color to make it invisible. That's an acceptable workaround from my perspective. I am alright with the channel disappearing after the within x bars is exceeded, as a compromise to not have to use highestall which makes the chart run slowly.

This may help.

The zigzag uses a moving average for pivots to minimize repainting. If there are not enough bars to compute the moving average, then the prior version's logic failed. This uses the prior pivot if the last pivot is within the moving average.

Screenshot 2023-07-10 182236.png
Code:
#Anchored_LRL_using_ZigZag_Anchor

#ZigZag Basis
#Since Priceh/Pricel are based upon a movingAverage to minimize repainting

input atrreversal = 2.0;
input ma_length   = 5;
input atr_length  = 5;
def priceh = MovingAverage(AverageType.EXPONENTIAL, high, ma_length);
def pricel = MovingAverage(AverageType.EXPONENTIAL, low , ma_length);

def EIL = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = .01, "absolute reversal" = .05, "atr length" = atr_length, "atr reversal" = atrreversal).lastL;
def EIH = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = .01, "absolute reversal" = .05, "atr length" = atr_length, "atr reversal" = atrreversal).lastH;
def lastbar    = HighestAll(if !IsNaN(close) then BarNumber() else 0);
def signalhigh = if !IsNaN(EIH) then BarNumber() else signalhigh[1];
def signallow  = if !IsNaN(EIL) then BarNumber() else signallow[1];
def lasthigh   = if (lastbar - signalhigh) >= ma_length then signalhigh else 0;
def lastlow    = if (lastbar - signallow)  >= ma_length then signallow else 0;

def cond = Max(lasthigh, lastlow);
input header_label = yes;
AddLabel(header_label, "Anchored LRL @Last Pivot " + (if cond == signalhigh then "High" else "Low"), Color.WHITE);
input test = no;
AddLabel(test, lastbar + " " + signalhigh + " " + (signallow) + " " + cond);

################
# Time Anchored Regression Channel
# Mobius
# V01.01.2016
#Modified to use zigzagHighLow as a cond anchor
#08:35 Mobius: Here's the anchored Regression Channel I use
#02.12.2019  10:49 Mobius: Just a note to the Anchored LRC. I usually change to 930 from 1800 about 11:00 EST.  I don't change to 1800 till 2000 if I still have the program up and running.  I could program it to do that automatically but am too lazy.

input y = close;
input Channel_1_Width = 0.70;
input Channel_2_Width = 1.00;
input LineWeight = 1;

script E
    {
    input y = close;
    input n = 20;
    def s = fold i = 0 to n
             with j
             do j + GetValue(y, i);
    plot D = s;
}
# Variables
def o = open;
def h = high;
def l = low;
def c = close;
def x = BarNumber();
def nan = Double.NaN;
def xx = if IsNaN(c[-1]) and !IsNaN(c) then x else xx[1];
##  code comment for line immediately above
##  thinking from left to right.. xx = 0 until the curren tbar is reached
##  at the current bar xx = x
##  beyond the current bar xx = xx[1]  the value of xx one bar back

def firstBar = if BarNumber() == cond
               then x
               else firstBar[1];
def S_y = if x == HighestAll(firstBar)
          then y
          else if x > HighestAll(firstBar)
               then S_y[1] + y
               else S_y[1];
def S_x = if x == HighestAll(firstBar)
          then 1
          else if x > HighestAll(firstBar)
               then S_x[1] + 1
               else S_x[1];
def x0_ = HighestAll(xx) - firstBar;
def x1 = HighestAll(if !IsNaN(y) and IsNaN(y[-1])
                    then x
                    else nan);
def x0 = HighestAll(if GetValue(x, -x0_) == x1
                    then x
                    else nan);
def x_ = if GetValue(x, -x0_) >= x1
         then x - x0
         else x_[1];
def Ex  = E(x_, x0_);
def Ey  = E(y, x0_);
def Exy = E(x_ * y, x0_);
def Exsq = E(Sqr(x_), x0_);
def b = (x0_ * Exy - (Ex * Ey)) / (x0_ * Exsq - (Ex * Ex));
def a = (GetValue(Ey, x - x1) - GetValue(b, x - x1) * GetValue(Ex, x - x1)) / x0_;
def LR = a + (GetValue(b, x - x1) * x_);
def r = Max(h, c[1]) - Min(l, c[1]);
def Er = E(r, x0_) / x0_;
def mean = S_y / S_x;
def SD = Sqrt((1 / S_x) * (E(Sqr(y - mean), S_x)));
# Plots
plot LRL = if x > x1 + 5 then nan else
           if x >= x0  # x is defined as barnumber()
           then LR
           else nan; # from nube



#plot LRL = if x >= x0  # x is defined as barnumber()
#           then LR
#           else nan;  # mobius original
LRL.SetStyle(Curve.FIRM);
LRL.SetLineWeight(LineWeight + 1);
LRL.AssignValueColor(if GetValue(a, x - x1) < LR
                         then Color.CYAN
                         else Color.ORANGE);
LRL.HideBubble();
LRL.HideTitle();
plot upper1 = LRL + (HighestAll(SD) * Channel_1_Width);
upper1.SetLineWeight(LineWeight);
upper1.SetDefaultColor(Color.LIGHT_GRAY);
upper1.HideBubble();
upper1.HideTitle();
plot lower1 = LRL - (HighestAll(SD) * Channel_1_Width);
lower1.SetLineWeight(LineWeight);
lower1.SetDefaultColor(Color.LIGHT_GRAY);
lower1.HideBubble();
lower1.HideTitle();
plot upper2 = LRL + (HighestAll(SD) * Channel_2_Width);
upper2.SetLineWeight(LineWeight);
upper2.SetDefaultColor(Color.LIGHT_GRAY);
upper2.HideBubble();
upper2.HideTitle();
plot lower2 = LRL - (HighestAll(SD) * Channel_2_Width);
lower2.SetLineWeight(LineWeight);
lower2.SetDefaultColor(Color.LIGHT_GRAY);
lower2.HideBubble();
lower2.HideTitle();
# End Code Time Anchored Regression Channel
#
 
This may help.

The zigzag uses a moving average for pivots to minimize repainting. If there are not enough bars to compute the moving average, then the prior version's logic failed. This uses the prior pivot if the last pivot is within the moving average.

Thanks so much for your reply. I am a little confused about how this would be used for a condition trigger based on a signal that isn't directly related to highs, lows, or moving averages across the whole chart.

For example, suppose we want to anchor the linear regression channel to the last occurrence of a long signal (painted as an up arrow) from the triple exhaustion indicator (i.e. maybe that last occurrence was one bar ago, or maybe it was 500 bars ago). And suppose we just want the linear regression channel to use the high and low from within the last 10 bars of that anchor point.

If the condition variable for that up arrow was named "triple_exhaustion_long_arrow" then would you mind giving an example of how you would recommend changing these lines?

Code:
def EIL = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = .01, "absolute reversal" = .05, "atr length" = atr_length, "atr reversal" = atrreversal).lastL;
def EIH = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = .01, "absolute reversal" = .05, "atr length" = atr_length, "atr reversal" = atrreversal).lastH;
def lastbar    = HighestAll(if !IsNaN(close) then BarNumber() else 0);
def signalhigh = if !IsNaN(EIH) then BarNumber() else signalhigh[1];
def signallow  = if !IsNaN(EIL) then BarNumber() else signallow[1];
def lasthigh   = if (lastbar - signalhigh) >= ma_length then signalhigh else 0;
def lastlow    = if (lastbar - signallow)  >= ma_length then signallow else 0;

def cond = Max(lasthigh, lastlow);
 
Thanks so much for your reply. I am a little confused about how this would be used for a condition trigger based on a signal that isn't directly related to highs, lows, or moving averages across the whole chart.

For example, suppose we want to anchor the linear regression channel to the last occurrence of a long signal (painted as an up arrow) from the triple exhaustion indicator (i.e. maybe that last occurrence was one bar ago, or maybe it was 500 bars ago). And suppose we just want the linear regression channel to use the high and low from within the last 10 bars of that anchor point.

If the condition variable for that up arrow was named "triple_exhaustion_long_arrow" then would you mind giving an example of how you would recommend changing these lines?

Code:
def EIL = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = .01, "absolute reversal" = .05, "atr length" = atr_length, "atr reversal" = atrreversal).lastL;
def EIH = ZigZagHighLow("price h" = priceh, "price l" = pricel, "percentage reversal" = .01, "absolute reversal" = .05, "atr length" = atr_length, "atr reversal" = atrreversal).lastH;
def lastbar    = HighestAll(if !IsNaN(close) then BarNumber() else 0);
def signalhigh = if !IsNaN(EIH) then BarNumber() else signalhigh[1];
def signallow  = if !IsNaN(EIL) then BarNumber() else signallow[1];
def lasthigh   = if (lastbar - signalhigh) >= ma_length then signalhigh else 0;
def lastlow    = if (lastbar - signallow)  >= ma_length then signallow else 0;

def cond = Max(lasthigh, lastlow);
[Edit to correct lastsell as the code I found for TEI had an error where both lastbuy and last sell were both coded the same.]

The anchor of the channel is based upon a barnumber() of the last condition that you want to use to define that barnumber().

Using the Triple Exhaustion Indicator (TEI), the following was added to the code below to determine which barnumber() to use to anchor the Linear Regression Channel (LRC):

Code:
def lastbuy  = highestall(if sellerRegular[1] and !sellerRegular then barnumber() else Double.NaN);
def lastsell = highestall(if buyerRegular[1]  and !buyerRegular  then barnumber() else Double.NaN);
def cond = max(lastbuy, lastsell);
#addlabel(1, lastbuy + " " + lastsell + " " + cond);

As TEI is a custom indicator, most of the code needs to be used in place of that used for the referenced ZigZag in the previous example.

Below is the full code for the TEI with LRC, There were no changes to the LRC code. The TEI replaced the ZigZag with the above code snippet to define COND.

Screenshot 2023-07-11 075215.png

Code:
#LRChannel_added_to_Triple_Exhaustion_Indicator

## Triple Exhaustion Indicator
##
##
## CREDITS
## Requested by @Chence27 from criteria listed here https://usethinkscript.com/threads/triple-exhaustion-indicator.9001/
##
##
## Removing the header Credit credits and description is not permitted, any modification needs to be shared.
##
## V 1.0 :    @cos251 - Initial release per request from www.usethinkscript.com forum thread:
##       :    https://usethinkscript.com/threads/triple-exhaustion-indicator.9001/
## V 1.1 : @chence27 - modifcations to better approximate original study
##
##
##

declare upper;

# --- Inputs
input over_bought = 80;
input over_sold = 20;
input KPeriod = 10;
input DPeriod = 10;
input priceH = high;
input priceL = low;
input priceC = close;
input averageType = AverageType.SIMPLE;
input length = 1000;
input paintBars = yes;
input showLabels = yes;


# --- Indicators - StochasticSlow / MACD / MACD StDev / DMI+/-
def SlowK = reference StochasticFull(over_bought, over_sold, KPeriod, DPeriod, priceH, priceL, priceC, 3, averageType).FullK;
def MACD = reference MACD()."Value";
def priceMean = Average(MACD, length);
def MACD_stdev =  (MACD - priceMean) / StDev(MACD, length);
def dPlus = reference DMI()."DI+";
def dMinus = reference DMI()."DI-";
# --- End Indicators

# --- Conditions
def sellerRegular = SlowK < 20 and MACD_stdev < -1 and dPlus < 15;
def sellerExtreme = SlowK < 20 and MACD_stdev < -2 and dPlus < 15;
def buyerRegular = SlowK > 80 and MACD_stdev > 1 and dMinus < 15;
def buyerExtreme = SlowK > 80 and MACD_stdev > 2 and dMinus < 15;
# --- End Conditions

# -- Price Color
AssignPriceColor( if paintBars and sellerExtreme then Color.CYAN else if buyerExtreme and paintBars then Color.MAGENTA else if paintBars and sellerRegular then Color.GREEN else if buyerRegular and paintBars then Color.RED else if paintBars then Color.GRAY else Color.Current);

# --- Arrows/Triggers
plot RegularBuy = if sellerRegular[1] and !sellerRegular then low else Double.NaN;

RegularBuy.SetPaintingStrategy(PaintingSTrategy.ARROW_UP);

RegularBuy.SetDefaultColor(Color.GREEN);


plot RegularSell = if buyerRegular[1] and !buyerRegular then high else Double.NaN;

RegularSell.SetPaintingStrategy(PaintingSTrategy.ARROW_Down);

RegularSell.SetDefaultColor(Color.RED);


# --- Labels
AddLabel(showLabels,"SellerRegular",Color.RED);
AddLabel(showLabels,"SellerExtreme",Color.MAGENTA);
AddLabel(showLabels,"BuyerRegular",Color.GREEN);
AddLabel(showLabels,"BuyerExtreme",Color.CYAN);

def lastbuy  = highestall(if sellerRegular[1] and !sellerRegular then barnumber() else Double.NaN);
def lastsell = highestall(if buyerRegular[1]  and !buyerRegular  then barnumber() else Double.NaN);
def cond = max(lastbuy, lastsell);
#addlabel(1, lastbuy + " " + lastsell + " " + cond);

# --- Labels
AddLabel(showLabels,"SellerRegular",Color.RED);
AddLabel(showLabels,"SellerExtreme",Color.MAGENTA);
AddLabel(showLabels,"BuyerRegular",Color.GREEN);
AddLabel(showLabels,"BuyerExtreme",Color.CYAN);

################
# Time Anchored Regression Channel
# Mobius
# V01.01.2016
#Modified to use zigzagHighLow as a cond anchor
#08:35 Mobius: Here's the anchored Regression Channel I use
#02.12.2019  10:49 Mobius: Just a note to the Anchored LRC. I usually change to 930 from 1800 about 11:00 EST.  I don't change to 1800 till 2000 if I still have the program up and running.  I could program it to do that automatically but am too lazy.

input y = close;
input Channel_1_Width = 0.70;
input Channel_2_Width = 1.00;
input LineWeight = 1;

script E
    {
    input y = close;
    input n = 20;
    def s = fold i = 0 to n
             with j
             do j + GetValue(y, i);
    plot D = s;
}
# Variables
def o = open;
def h = high;
def l = low;
def c = close;
def x = BarNumber();
def nan = Double.NaN;
def xx = if IsNaN(c[-1]) and !IsNaN(c) then x else xx[1];
##  code comment for line immediately above
##  thinking from left to right.. xx = 0 until the curren tbar is reached
##  at the current bar xx = x
##  beyond the current bar xx = xx[1]  the value of xx one bar back

def firstBar = if BarNumber() == cond
               then x
               else firstBar[1];
def S_y = if x == HighestAll(firstBar)
          then y
          else if x > HighestAll(firstBar)
               then S_y[1] + y
               else S_y[1];
def S_x = if x == HighestAll(firstBar)
          then 1
          else if x > HighestAll(firstBar)
               then S_x[1] + 1
               else S_x[1];
def x0_ = HighestAll(xx) - firstBar;
def x1 = HighestAll(if !IsNaN(y) and IsNaN(y[-1])
                    then x
                    else nan);
def x0 = HighestAll(if GetValue(x, -x0_) == x1
                    then x
                    else nan);
def x_ = if GetValue(x, -x0_) >= x1
         then x - x0
         else x_[1];
def Ex  = E(x_, x0_);
def Ey  = E(y, x0_);
def Exy = E(x_ * y, x0_);
def Exsq = E(Sqr(x_), x0_);
def b = (x0_ * Exy - (Ex * Ey)) / (x0_ * Exsq - (Ex * Ex));
def a = (GetValue(Ey, x - x1) - GetValue(b, x - x1) * GetValue(Ex, x - x1)) / x0_;
def LR = a + (GetValue(b, x - x1) * x_);
def r = Max(h, c[1]) - Min(l, c[1]);
def Er = E(r, x0_) / x0_;
def mean = S_y / S_x;
def SD = Sqrt((1 / S_x) * (E(Sqr(y - mean), S_x)));
# Plots
plot LRL = if x > x1 + 5 then nan else
           if x >= x0  # x is defined as barnumber()
           then LR
           else nan; # from nube



#plot LRL = if x >= x0  # x is defined as barnumber()
#           then LR
#           else nan;  # mobius original
LRL.SetStyle(Curve.FIRM);
LRL.SetLineWeight(LineWeight + 1);
LRL.AssignValueColor(if GetValue(a, x - x1) < LR
                         then Color.CYAN
                         else Color.ORANGE);
LRL.HideBubble();
LRL.HideTitle();
plot upper1 = LRL + (HighestAll(SD) * Channel_1_Width);
upper1.SetLineWeight(LineWeight);
upper1.SetDefaultColor(Color.LIGHT_GRAY);
upper1.HideBubble();
upper1.HideTitle();
plot lower1 = LRL - (HighestAll(SD) * Channel_1_Width);
lower1.SetLineWeight(LineWeight);
lower1.SetDefaultColor(Color.LIGHT_GRAY);
lower1.HideBubble();
lower1.HideTitle();
plot upper2 = LRL + (HighestAll(SD) * Channel_2_Width);
upper2.SetLineWeight(LineWeight);
upper2.SetDefaultColor(Color.LIGHT_GRAY);
upper2.HideBubble();
upper2.HideTitle();
plot lower2 = LRL - (HighestAll(SD) * Channel_2_Width);
lower2.SetLineWeight(LineWeight);
lower2.SetDefaultColor(Color.LIGHT_GRAY);
lower2.HideBubble();
lower2.HideTitle();
# End Code Time Anchored Regression Channel
#
 
Last edited:
The anchor of the channel is based upon a barnumber() of the last condition that you want to use to define that barnumber().

Using the Triple Exhaustion Indicator (TEI), the following was added to the code below to determine which barnumber() to use to anchor the Linear Regression Channel (LRC):

Code:
def lastbuy  = highestall(if sellerRegular[1] and !sellerRegular then barnumber() else Double.NaN);
def lastsell = highestall(if sellerRegular[1] and !sellerRegular then barnumber() else Double.NaN);
def cond = max(lastbuy, lastsell);
#addlabel(1, lastbuy + " " + lastsell + " " + cond);

As TEI is a custom indicator, most of the code needs to be used in place of that used for the referenced ZigZag in the previous example.

Below is the full code for the TEI with LRC, There were no changes to the LRC code. The TEI replaced the ZigZag with the above code snippet to define COND.

Thank you, this is great. Really appreciate you taking the time to explain and write it out.
 
Is there anyway to get it to draw from the last ECI pivot like mobius recommends in his ECI study?

I placed it over the ECI indicator wish it could also be somehow filtered with volume stdev

Code:
#------------------------------------------------------------------------------------
#hint: Expansion Contraction Indicator (ECI): \n ECI Identifies areas of price compression which leads to price expansion. ECI doesn't show the direction of a trend but does indicate when a trend is going to resume (price flagging) or if a change in trend polarity is happening.\n ECI plots the areas where price becomes compressed with colored and clouded bands. The indicator also leaves legacy points in areas of past compression.
# ECI is based on the FE algorithm
# Original plot style by Mobius
# Note: Default Lengths are not optimized. My personal experience has been length ranges between 8 and 13 are generally effective.
# Here's another way to look at Fractal Energy. This study plots it on the chart graph with clouded areas for the current price compression, exhaustion area and leaves colored points as a legacy plot for past areas.
# Good CSA choices with this study are:
# ECI + SuperTrend + Fractal Pivots
# ECI + SuperTrend + RSI in Laguerre Time
# ECI + SuperTrend + Standard Deviation Bands
# ECI + Linear Regression Standard Deviation Bands
# This version Modified to filter price to a normalized distribution

 

# User Inputs

input EciLength = 9; #hint EciLength: Length for calculations.

input AvgLength = 34; #hint AvgLength: Length for smoothing.

input AvgType = AverageType.SIMPLE; #hint AvgType: Average Type

input MeanValue = HL2; #hint MeanValue: Point of origen.

input DisplayPoints = yes; #hint DisplayPoints: No Points.

input OnExpansion = yes; #hint OnExpansion: Line extensions.

 

# Variables

script g {

    input data = close;

    def w = (2 * Double.Pi / 8);

    def beta = (1 - Cos(w)) / (Power(1.414, 2.0 / 4) - 1 );

    def alpha = (-beta + Sqrt(beta * beta + 2 * beta));

    def G = Power(alpha, 4) * data + 

                 4 * (1 – alpha) * G[1] – 6 * Power( 1 - alpha, 2 ) * G[2] + 

                 4 * Power( 1 - alpha, 3 ) * G[3] - Power( 1 - alpha, 4 ) * G[4];

    plot Line = G;

}

def o = g(data = open);

def h = g(data = high);

def l = g(data = low);

def c = g(data = close);

def bar = BarNumber();

def HMax = Highest(Max(h, c[1]), EciLength);

def LMax = Lowest(Min(l, c[1]), EciLength);

def TR = HMax - LMax;

def ECI = Round((Log(Sum(TrueRange(h, c, l), EciLength) / TR) /

         Log(EciLength)) / TickSize(), 0) * TickSize();

def Avg = MovingAverage(AverageType = AvgType, ECI, AvgLength);

def S1 = if ECI crosses above Avg 

         then MeanValue

         else S1[1];

def S = ECI > Avg;

def SBars = if ECI > Avg

            then bar

            else Double.NaN;

def StartBar = if ECI crosses above Avg 

               then bar

               else StartBar[1];

def LastSBar = if ECI crosses below Avg

               then bar

               else LastSBar[1];

def PP = if ECI crosses above Avg

         then MeanValue

         else PP[1];

def Mean_Limit = if bar != StartBar

                 then bar - StartBar

                 else if bar == StartBar

                      then Double.NaN

                      else Mean_Limit[1];

def SHigh = if ECI crosses above Avg

            then h

            else SHigh[1];

def SHighBar = if S and

                  h == SHigh

               then bar

               else SHighBar[1];

def SHigh_Limit = if bar == StartBar

                  then Double.NaN

                  else if bar > StartBar

                       then bar - SHighBar

                       else SHigh_Limit[1];

def SLow = if ECI crosses above Avg

           then l

           else SLow[1];

def SLowBar = if S and

                  l == SLow

              then bar

              else SLowBar[1];

def SLow_Limit = if bar == StartBar

                 then Double.NaN

                 else if bar > StartBar

                      then bar - SLowBar

                      else SLow_Limit[1];

# Internal Script Reference

script LinePlot {

    input LineLimit = 0;

    input OnExpansion = yes;

    input data = close;

    input bar = 0;

    def ThisBar = HighestAll(bar);

    def cLine = if bar == ThisBar

                then data

                else Double.NaN;

    def cond1 = CompoundValue(1, if IsNaN(data)

                                 then cond1[1] 

                                 else data, data);

    plot P = if ThisBar - LineLimit <= bar

             then HighestAll(cLine)

             else Double.NaN;

    plot ExpLine = if OnExpansion and 

                     IsNaN(data[-1]) 

                   then cond1 

                   else Double.NaN;

}

#Conditions
def sellerRegular = eci crosses below avg;
def buyerRegular = eci crosses below avg;

def lastbuy  = highestall(if sellerRegular[1] and !sellerRegular then barnumber() else Double.NaN);
def lastsell = highestall(if buyerRegular[1]  and !buyerRegular  then barnumber() else Double.NaN);
def cond = max(lastbuy, lastsell);
#addlabel(1, lastbuy + " " + lastsell + " " + cond);

# Plots

plot SD_Pivot = LinePlot(data = PP, LineLimit = Mean_Limit, OnExpansion = OnExpansion, bar = StartBar).P;

plot SD_Pivot_X = LinePlot(data = PP, LineLimit = StartBar).ExpLine;

SD_Pivot.SetDefaultColor(Color.CYAN);

SD_Pivot_X.SetDefaultColor(Color.CYAN);

plot SD_R1 = LinePlot(data = SHigh, LineLimit = SHigh_Limit, OnExpansion = OnExpansion, bar = SHighBar).P;

plot SD_R1_X = LinePlot(data = SHigh, LineLimit = SHigh_Limit).ExpLine;

SD_R1.SetDefaultColor(Color.LIGHT_GREEN);

SD_R1_X.SetDefaultColor(Color.LIGHT_GREEN);

plot SD_S1 = LinePlot(data = SLow, LineLimit = SLow_Limit, OnExpansion = OnExpansion, bar = SLowBar).P;

plot SD_S1_X = LinePlot(data = SLow, LineLimit = SLow_Limit).ExpLine;

SD_S1.SetDefaultColor(Color.LIGHT_RED);

SD_S1_X.SetDefaultColor(Color.LIGHT_RED);

plot SPlot = if S 

             then S1 #l - (2 * TickSize())

             else Double.NaN;

SPlot.SetHiding(!DisplayPoints);

SPlot.SetPaintingStrategy(PaintingStrategy.POINTS);

SPlot.SetLineWeight(1);

SPlot.SetDefaultColor(Color.YELLOW);

#addCloud(SD_pivot, SD_R1, CreateColor(50,150,75), CreateColor(50,150,70));

#addCloud(SD_S1, SD_pivot, CreateColor(175,0,50), CreateColor(175,0,50));

#addCloud(SD_pivot_X, SD_R1_X, CreateColor(50,150,75), CreateColor(50,150,70));

#addCloud(SD_S1_X, SD_pivot_X, CreateColor(175,0,50), CreateColor(175,0,50));

# Audible Alerts

#Alert(ECI crosses below Avg, "Exit", Alert.BAR, Sound.Bell);

#addverticalLine(ECI crosses above Avg, "Fire", color = Color.gray);

AddLabel(1, "ECI CHI Level = " + ECI, Color.YELLOW);

#AddVerticalLine(ECI crosses below Avg, "ECI down", color = Color.plum);
#AddVerticalLine(ECI crosses above Avg, "ECI up", color = Color.LIME);
# End Code Modified ECI

################
# Time Anchored Regression Channel
# Mobius
# V01.01.2016
#Modified to use zigzagHighLow as a cond anchor
#08:35 Mobius: Here's the anchored Regression Channel I use
#02.12.2019  10:49 Mobius: Just a note to the Anchored LRC. I usually change to 930 from 1800 about 11:00 EST.  I don't change to 1800 till 2000 if I still have the program up and running.  I could program it to do that automatically but am too lazy.

input y = close;
input Channel_1_Width = 0.70;
input Channel_2_Width = 1.00;
input LineWeight = 1;

script E
    {
    input y = close;
    input n = 20;
    def s = fold i = 0 to n
             with j
             do j + GetValue(y, i);
    plot D = s;
}
# Variables
def o = open;
def h = high;
def l = low;
def c = close;
def x = BarNumber();
def nan = Double.NaN;
def xx = if IsNaN(c[-1]) and !IsNaN(c) then x else xx[1];
##  code comment for line immediately above
##  thinking from left to right.. xx = 0 until the curren tbar is reached
##  at the current bar xx = x
##  beyond the current bar xx = xx[1]  the value of xx one bar back

def firstBar = if BarNumber() == cond
               then x
               else firstBar[1];
def S_y = if x == HighestAll(firstBar)
          then y
          else if x > HighestAll(firstBar)
               then S_y[1] + y
               else S_y[1];
def S_x = if x == HighestAll(firstBar)
          then 1
          else if x > HighestAll(firstBar)
               then S_x[1] + 1
               else S_x[1];
def x0_ = HighestAll(xx) - firstBar;
def x1 = HighestAll(if !IsNaN(y) and IsNaN(y[-1])
                    then x
                    else nan);
def x0 = HighestAll(if GetValue(x, -x0_) == x1
                    then x
                    else nan);
def x_ = if GetValue(x, -x0_) >= x1
         then x - x0
         else x_[1];
def Ex  = E(x_, x0_);
def Ey  = E(y, x0_);
def Exy = E(x_ * y, x0_);
def Exsq = E(Sqr(x_), x0_);
def b = (x0_ * Exy - (Ex * Ey)) / (x0_ * Exsq - (Ex * Ex));
def a = (GetValue(Ey, x - x1) - GetValue(b, x - x1) * GetValue(Ex, x - x1)) / x0_;
def LR = a + (GetValue(b, x - x1) * x_);
def r = Max(h, c[1]) - Min(l, c[1]);
def Er = E(r, x0_) / x0_;
def mean = S_y / S_x;
def SD = Sqrt((1 / S_x) * (E(Sqr(y - mean), S_x)));
# Plots
plot LRL = if x > x1 + 5 then nan else
           if x >= x0  # x is defined as barnumber()
           then LR
           else nan; # from nube



#plot LRL = if x >= x0  # x is defined as barnumber()
#           then LR
#           else nan;  # mobius original
LRL.SetStyle(Curve.FIRM);
LRL.SetLineWeight(LineWeight + 1);
LRL.AssignValueColor(if GetValue(a, x - x1) < LR
                         then Color.CYAN
                         else Color.ORANGE);
LRL.HideBubble();
LRL.HideTitle();
plot upper1 = LRL + (HighestAll(SD) * Channel_1_Width);
upper1.SetLineWeight(LineWeight);
upper1.SetDefaultColor(Color.LIGHT_GRAY);
upper1.HideBubble();
upper1.HideTitle();
plot lower1 = LRL - (HighestAll(SD) * Channel_1_Width);
lower1.SetLineWeight(LineWeight);
lower1.SetDefaultColor(Color.LIGHT_GRAY);
lower1.HideBubble();
lower1.HideTitle();
plot upper2 = LRL + (HighestAll(SD) * Channel_2_Width);
upper2.SetLineWeight(LineWeight);
upper2.SetDefaultColor(Color.LIGHT_GRAY);
upper2.HideBubble();
upper2.HideTitle();
plot lower2 = LRL - (HighestAll(SD) * Channel_2_Width);
lower2.SetLineWeight(LineWeight);
lower2.SetDefaultColor(Color.LIGHT_GRAY);
lower2.HideBubble();
lower2.HideTitle();
# End Code Time Anchored Regression Channel
#
 
@SleepyZ Can you alter this code so that the linear regression will anchor Premarket 4:00 and then the far right anchor stop at 2:29. I have been testing this manually and this looks very promising similar to the ORB.
1706707765744.png
 
@SleepyZ Can you alter this code so that the linear regression will anchor Premarket 4:00 and then the far right anchor stop at 2:29. I have been testing this manually and this looks very promising similar to the ORB.
View attachment 20843

At this time, you might try this on a TODAY only timeframe chart to test your idea.

The default settings are set to start the linear reg at 0400 end it at 0929 and extend it from there until 1429.

Screenshot 2024-01-31 100053.png
Code:
#
# TD Ameritrade IP Company, Inc. (c) 2008-2022
#
#
#
#Use on TODAY only TIMEFRAME

input starttime     = 0400;
input endLRtime     = 0929;
input endplottime   = 1429;
input extendtoright = yes;
input extendtoleft  = no;
def price = if secondsfromTime(endLRtime)>=0 then price[1] else close;

plot MiddleLR = if secondsFromTime(endplottime)>0 then double.nan else InertiaAll(price,  startTime = starttime, extendToLeft = extendtoleft, extendToRight = extendtoright);
def dist = HighestAll(AbsValue(MiddleLR - price));
plot UpperLR = MiddleLR + dist;
plot LowerLR = MiddleLR - dist;

MiddleLR.SetDefaultColor(GetColor(5));
UpperLR.SetDefaultColor(GetColor(5));
LowerLR.SetDefaultColor(GetColor(5));
 
@SleepyZ Thank you. This is quite telling and can be used as breakouts as well as S/R zones.
Take a look at SPY today.
Would be better if I didn't have to set chart to today.
1706805140660.png
 
Check out how accurate this Anchored LRC is for the entire day. It really helps to know when price may reverse or break and retest. Not really any different than S/R levels with the exception that the S/R moves with the slope of the channel. See images for example. @SleepyZ Is there a way to write this so that I don't have to have chart TF set to today? Curious if it is possible.

1706980281887.png

1706980292061.png

1706980302082.png

1706980309989.png

1706980316606.png


Can my request above be accomplished. Allow the anchor to work with more days than just today?
 
Last edited by a moderator:
Check out how accurate this Anchored LRC is for the entire day. It really helps to know when price may reverse or break and retest. Not really any different than S/R levels with the exception that the S/R moves with the slope of the channel. See images for example. @SleepyZ Is there a way to write this so that I don't have to have chart TF set to today? Curious if it is possible.

View attachment 20905
View attachment 20906
View attachment 20907
View attachment 20908
View attachment 20909

Can my request above be accomplished. Allow the anchor to work with more days than just today?

See the next 2 posts below
 
Last edited:
Have not found a good way yet.

This seems to work on multiple days chart timeframes for the last day's activity without having to set the chart to TODAY.

The image shows the code below at 5d2m. 1d2m and the original code's TODAY/2m only.

Screenshot 2024-02-06 100010.png
Code:
#
# TD Ameritrade IP Company, Inc. (c) 2008-2022
#
#
#


input starttime     = 0400;
input endLRtime     = 0929;
input endplottime   = 1429;
input extendtoright = yes;
input extendtoleft  = no;
def ymd = GetYYYYMMDD();
def count = if ymd != ymd[1] and !IsNaN(close) then count[1] + 1 else count[1];
def cond  = HighestAll(count) - count + 1;

def price = if cond > 1 then 0 else if cond == 1 and SecondsFromTime(endLRtime) >= 0 then price[1] else close;

def lrl = if cond > 1 then 0 else if SecondsFromTime(endplottime) > 0 then lrl[1] else InertiaAll(price,  startTime = starttime, extendToLeft = extendtoleft, extendToRight = extendtoright);
plot MiddleLR = lrl;

def dist = HighestAll(AbsValue(MiddleLR - price));
plot UpperLR = MiddleLR + dist;
plot LowerLR = MiddleLR - dist;

MiddleLR.SetDefaultColor(color.cyan);
UpperLR.SetDefaultColor(GetColor(5));
LowerLR.SetDefaultColor(GetColor(5));

MiddleLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
UpperLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
LowerLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

;
 
This seems to work on multiple days chart timeframes for the last day's activity without having to set the chart to TODAY.

The image shows the code below at 5d2m. 1d2m and the original code's TODAY/2m only.

This will allow an input lookback to pick prior day's to be selected and plot to the right edge

Screenshot 2024-02-06 102453.png
Code:
#
# TD Ameritrade IP Company, Inc. (c) 2008-2022
#
#
#

input lookback      = 1;
input starttime     = 0400;
input endLRtime     = 0929;
input endplottime   = 1959;
input extendtoright = yes;
input extendtoleft  = no;
def ymd = GetYYYYMMDD();
def count = if ymd != ymd[1] and !IsNaN(close) then count[1] + 1 else count[1];
def cond  = HighestAll(count) - count + 1;

def price = if cond > lookback then 0 else if cond <= lookback and SecondsFromTime(endLRtime) >= 0 then price[1] else close;

def lrl = if cond > lookback then 0 else if SecondsFromTime(endplottime) > 0 then lrl[1] else InertiaAll(price,  startTime = starttime, extendToLeft = extendtoleft, extendToRight = extendtoright);
plot MiddleLR = lrl;

def dist = HighestAll(AbsValue(MiddleLR - price));
plot UpperLR = MiddleLR + dist;
plot LowerLR = MiddleLR - dist;

MiddleLR.SetDefaultColor(color.cyan);
UpperLR.SetDefaultColor(GetColor(5));
LowerLR.SetDefaultColor(GetColor(5));

MiddleLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
UpperLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
LowerLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

;
 
This will allow an input lookback to pick prior day's to be selected and plot to the right edge
This has been so good that it doesn't really make sense. Not to me anyway. More ppl may be interested in this if they trade intraday.
Check out spy today.

1707248574461.png
 
This will allow an input lookback to pick prior day's to be selected and plot to the right edge
@SleepyZ Thank You!🙏 Can I get you to do one more addition to this if it is possible. Can you make the coefficient adjustable? or have two. I have noticed that some stocks work best with 1 and -1 coefficient and others work ith what you have this one set to.

**Also, just noticed that when I change the start time, It doesn't change.
1707250732348.png
 
Last edited:
@SleepyZ Thank You!🙏 Can I get you to do one more addition to this if it is possible. Can you make the coefficient adjustable? or have two. I have noticed that some stocks work best with 1 and -1 coefficient and others work ith what you have this one set to.

**Also, just noticed that when I change the start time, It doesn't change.
View attachment 20936

An optional set of Upper/Lower standdeviations channel was added.

The settings for the Linear Reg Channel are set for stocks using for the Premarket Period, inerttiall() function that I do not have TOS code available to modify. The inertiaall function requires a starttime for it to work. So if you change the starttime, I am relying at this time for the function to do it correctly, but when I do change the starttime, all it seems to mostly do is truncate the lines.

If you are using this on SPY, you might want to use the settings in the image. Otherwise you will have to change the settings to hopefully make this work.

At this time, I would not recommend using this for more than the Premarket Period or adjusting the Premarket Period by changing the ending time to cover a different period from the starttime.

Screenshot 2024-02-06 144044.png

Code:
#
# TD Ameritrade IP Company, Inc. (c) 2008-2022
#
#An optional set of Upper/Lower standdeviations channel was added.

#The settings for the Linear Reg Channel are set for stocks using for the Premarket Period, inerttiall(0 function that I do not have TOS code available. The inertiaall function requires a starttime for it to work. So if you change the starttime, I am relying at this time for the function to do it correctly, but when I do change the starttime, all it seems to mostly do is truncate the lines.

#If you are using this SPY, you might want to use the settings in the image. Otherwise you will have to change the settings to hopefully make this work.  See https://usethinkscript.com/threads/linear-regression-plot-dependent-on-condition.16025/post-137758

#At this time, I would not recommend using this for more than the Premarket Period or adjusting the Premarket Period by changing the ending time to cpver a different period from the starttime.
#

input lookback      = 1;
input pricetype     = close;
input starttime     = 0400;
input endLRtime     = 0929;
input endplottime   = 1959;
input extendtoright = yes;
input extendtoleft  = no;
def ymd = GetYYYYMMDD();
def count = if ymd != ymd[1] and !IsNaN(close) then count[1] + 1 else count[1];
def cond  = HighestAll(count) - count + 1;

def price = if cond > lookback or secondsfromTime(starttime)<0 then 0 else if cond <= lookback and SecondsFromTime(endLRtime) >= 0 then price[1] else pricetype;

def lrl = if cond > lookback then 0 else if SecondsFromTime(endplottime) >= 0 then lrl[1] else if SecondsFromTime(starttime) >= 0 then InertiaAll(price,  startTime = starttime, extendToLeft = extendtoleft, extendToRight = extendtoright) else lrl[1];
plot MiddleLR = lrl;


#Distance

input showDistance = yes;

def dist = if !showDistance then double.nan else HighestAll(AbsValue(MiddleLR - price));

plot UpperLR = MiddleLR + dist;
plot LowerLR = MiddleLR - dist;

MiddleLR.SetDefaultColor(Color.CYAN);
UpperLR.SetDefaultColor(GetColor(5));
LowerLR.SetDefaultColor(GetColor(5));

MiddleLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
UpperLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
LowerLR.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

#Deviations

input showDeviations = yes;
input deviation1 = 1.0;

def stdDeviation = if !showDeviations then double.nan else StDevAll(pricetype, extendtoright=extendtoright);

plot UpperDev = MiddleLR + stdDeviation * deviation1 ;
plot LowerDev = MiddleLR - stdDeviation * deviation1 ;

UpperDev.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
LowerDev.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);

UpperDev.SetDefaultColor(color.yellow);
LowerDev.SetDefaultColor(color.yellow);
;
 
Last edited:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
295 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top