Linear Regression among swing High

Hi All,

I am calculating the swing High by the following code:

Hnbar = 30;
PHigh = Ref(H, -Hnbar) > Ref(HHV(H,Hnbar-1),-1) AND Ref(H, -Hnbar) > Ref(HHV(H,Hnbar-1),-1-Hnbar);

Then I can address the value and location of the last four Highs by:

last_PHigh1_H = ValueWhen(PHigh, H, 1);
last_PHigh2_H = ValueWhen(PHigh, H, 2);
last_PHigh3_H = ValueWhen(PHigh, H, 3);
last_PHigh4_H = ValueWhen(PHigh, H, 4);

xx = BarIndex()

last_PHigh1_loc = ValueWhen(PHigh, xx, 1);
last_PHigh2_loc = ValueWhen(PHigh, xx, 2);
last_PHigh3_loc = ValueWhen(PHigh, xx, 3);
last_PHigh4_loc = ValueWhen(PHigh, xx, 4);

What I want to calculate now is the linear regression among the last four High points. I know I have the build-in function Lineareq(), but I just don't know how to combine them together. Anyone here can kindly give me a hand?

Thanks!

i wrote some code that i put in the library that uses the pivots only, see:
https://www.amibroker.com/members/library/detail.php?id=1527

so taking some from that code you could calculate the best linear fit through the last 4 pivots as follows:

order = 1; // linear

Hnbar = 30;
pHigh = H == HHV( H, Hnbar ) AND Ref( HHV( H, Hnbar ), Hnbar ) < H;

last_PHigh1_H = LastValue( ValueWhen( PHigh, H, 1 ) );
last_PHigh2_H = LastValue( ValueWhen( PHigh, H, 2 ) );
last_PHigh3_H = LastValue( ValueWhen( PHigh, H, 3 ) );
last_PHigh4_H = LastValue( ValueWhen( PHigh, H, 4 ) );

xx = BarIndex();

last_PHigh1_loc = LastValue( ValueWhen( PHigh, xx, 1 ) );
last_PHigh2_loc = LastValue( ValueWhen( PHigh, xx, 2 ) );
last_PHigh3_loc = LastValue( ValueWhen( PHigh, xx, 3 ) );
last_PHigh4_loc = LastValue( ValueWhen( PHigh, xx, 4 ) );

function calculateCoefficients( xVal, yVal, bars, av )
{
    local i, j;

    xx = Matrix( bars + 1, order + 1, 1 );

    for( i = 0; i <= bars; i++ )
    {
        for( j = 1; j <= order; j++ )
        {
            xx[i][j] = ( xVal[i] - av ) ^ j;
        }
    }

    yy = Matrix( bars + 1, 1, 0 );

    for( i = 0; i <= bars; i++ )
    {
        yy[i][0] = yVal[ i ];

    }

    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;

    return aa;
}

xvalue = yvalue = Null;
xvalue[0] = last_PHigh4_loc;
xvalue[1] = last_PHigh3_loc;
xvalue[2] = last_PHigh2_loc;
xvalue[3] = last_PHigh1_loc;

yvalue[0] = last_PHigh4_H;
yvalue[1] = last_PHigh3_H;
yvalue[2] = last_PHigh2_H;
yvalue[3] = last_PHigh1_H;

// average index of range examined. Used to make the process of fitting more accurate (numerically)
avgx = ( xvalue[3] + xvalue[0] ) / 2;

aa = calculateCoefficients( xvalue, yvalue, 3 , avgx );

// calculate the linear fit
lsft = lsftExt = Null;

for( k = xvalue[0]; k <= xvalue[3]; k++ )
{
    lsft[k] = aa[0][0];

    for( s = 1; s <= order; s++ )
    {
        lsft[k] += aa[s][0] * ( k - avgx ) ^ s;
    }
}

SetChartOptions( 0, chartShowDates );
SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
PlotShapes( shapeSmallCircle*PHigh, ColorRGB( 250, 0, 0 ), 0, H, 10 );

Plot( lsft, "", colorAqua, styleLine, Null, Null, 0, 0, 4 );
5 Likes

@empottasch

I have removed a few loops

E.g. from

function calculateCoefficients( xVal, yVal, bars, av )
{
    local i, j;

    xx = Matrix( bars + 1, order + 1, 1 );
    for( i = 0; i <= bars; i++ )
    {
        for( j = 1; j <= order; j++ )
        {
            xx[i][j] = ( xVal[i] - av ) ^ j;
        }
    }

    yy = Matrix( bars + 1, 1, 0 );
    for( i = 0; i <= bars; i++ )
    {
        yy[i][0] = yVal[ i ];
    }

    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;
    return aa;
}

to

function calculateCoefficients( xVal, yVal, bars, av )
{
    local j, aa, xx, yy, xxt;
    xx = Matrix( bars + 1, order + 1, 1 );
	for( j = 1; j <= order; j++ )
        xx = MxSetBlock(xx, 0, bars, j, j, (xVal - av)^j);

    yy = Matrix( bars + 1, 1, 0 );
    yy = MxSetBlock(yy, 0, bars, 0, 0, yVal);

    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;
    return aa;
}

And from

lsft = lsftExt = Null;
for( k = xvalue[0]; k <= xvalue[3]; k++ )
{
    lsft[k] = aa[0][0];
    for( s = 1; s <= order; s++ )
    {
        lsft[k] += aa[s][0] * ( k - avgx ) ^ s;
    }
}

to

lsft = aa[0][0]; 
bi_adj = IIf(bi>= xvalue[0] AND bi <= xvalue[3], bi-avgx, Null);
for( s = 1; s <= order; s++ )
	lsft += aa[s][0] * bi_adj^s;

As well as from

last_PHigh1_H = LastValue( ValueWhen( PHigh, H, 1 ) );
last_PHigh2_H = LastValue( ValueWhen( PHigh, H, 2 ) );
last_PHigh3_H = LastValue( ValueWhen( PHigh, H, 3 ) );
last_PHigh4_H = LastValue( ValueWhen( PHigh, H, 4 ) );

xx = BarIndex();

last_PHigh1_loc = LastValue( ValueWhen( PHigh, xx, 1 ) );
last_PHigh2_loc = LastValue( ValueWhen( PHigh, xx, 2 ) );
last_PHigh3_loc = LastValue( ValueWhen( PHigh, xx, 3 ) );
last_PHigh4_loc = LastValue( ValueWhen( PHigh, xx, 4 ) );

xvalue = yvalue = Null;
xvalue[0] = last_PHigh4_loc;
xvalue[1] = last_PHigh3_loc;
xvalue[2] = last_PHigh2_loc;
xvalue[3] = last_PHigh1_loc;

yvalue[0] = last_PHigh4_H;
yvalue[1] = last_PHigh3_H;
yvalue[2] = last_PHigh2_H;
yvalue[3] = last_PHigh1_H;

to

xvalue = yvalue = Null;
for ( i = 0; i <= 3; i++ ) {
	xvalue[i] = LastValue(ValueWhen(PHigh, xx, 4-i));
	yvalue[i] = LastValue(ValueWhen(PHigh, H, 4-i));
}

All together:

/// @link https://forum.amibroker.com/t/linear-regression-among-swing-high/22681/2
/// by empottasch and fxshrat@gmail.com
order = 1; // linear
Hnbar = 30;
pHigh = H == HHV( H, Hnbar ) AND Ref( HHV( H, Hnbar ), Hnbar ) < H;
bi = BarIndex();

function calculateCoefficients( xVal, yVal, bars, av )
{
    local j, aa, xx, yy, xxt;
    xx = Matrix( bars + 1, order + 1, 1 );
	for( j = 1; j <= order; j++ )
        xx = MxSetBlock(xx, 0, bars, j, j, (xVal - av)^j);

    yy = Matrix( bars + 1, 1, 0 );
    yy = MxSetBlock(yy, 0, bars, 0, 0, yVal);

    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;
    return aa;
}

n = 3;
if ( BarCount > n ) {
	xvalue = yvalue = Null;
	for ( i = 0; i <= n; i++ ) {
		xvalue[i] = LastValue(ValueWhen(PHigh, bi, n+1-i));
		yvalue[i] = LastValue(ValueWhen(PHigh, H, n+1-i));
	}

	// average index of range examined. Used to make the process of fitting more accurate (numerically)
	avgx = ( xvalue[n] + xvalue[0] ) / 2;
	aa = calculateCoefficients( xvalue, yvalue, n, avgx );

	// calculate the linear fit
	lsft = aa[0][0]; 
	bi_adj = IIf(bi>= xvalue[0] AND bi <= xvalue[n], bi-avgx, Null);
	for( s = 1; s <= order; s++ )
		lsft += aa[s][0] * bi_adj^s;

	SetChartOptions( 0, chartShowDates );
	SetChartBkColor( ColorRGB( 0, 0, 0 ) );
	Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
	PlotShapes( shapeSmallCircle*PHigh, ColorRGB( 250, 0, 0 ), 0, H, 10 );
	Plot( lsft, "", colorAqua, styleLine, Null, Null, 0, 0, 4 );
}
8 Likes

just added the extension using Fx's coding approach

/// @link https://forum.amibroker.com/t/linear-regression-among-swing-high/22681/2
/// by empottasch and fxshrat@gmail.com
order = Param( "Polynomial order", 1, 1, 3, 1 );
Hnbar = 30;
pHigh = H == HHV( H, Hnbar ) AND Ref( HHV( H, Hnbar ), Hnbar ) < H;
bi = BarIndex();

function calculateCoefficients( xVal, yVal, bars, av )
{
    local j, aa, xx, yy, xxt;
    xx = Matrix( bars + 1, order + 1, 1 );
	for( j = 1; j <= order; j++ )
        xx = MxSetBlock(xx, 0, bars, j, j, (xVal - av)^j);

    yy = Matrix( bars + 1, 1, 0 );
    yy = MxSetBlock(yy, 0, bars, 0, 0, yVal);

    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;
    return aa;
}

n = 3;
if ( BarCount > n ) {
	xvalue = yvalue = Null;
	for ( i = 0; i <= n; i++ ) {
		xvalue[i] = LastValue(ValueWhen(PHigh, bi, n+1-i));
		yvalue[i] = LastValue(ValueWhen(PHigh, H, n+1-i));
	}

	// average index of range makes fitting more accurate (numerically)
	avgx = ( xvalue[n] + xvalue[0] ) / 2;
	aa = calculateCoefficients( xvalue, yvalue, n, avgx );

	// calculate the fit
	lsft = aa[0][0]; 
	bi_adj = IIf(bi>= xvalue[0] AND bi <= xvalue[n], bi-avgx, Null);
	for( s = 1; s <= order; s++ )
		lsft += aa[s][0] * bi_adj^s;
		
	// calculate the fit extension
	lsftExt = aa[0][0]; 
	bi_adj = IIf(bi > xvalue[n] AND bi < BarCount, bi-avgx, Null);
	for( s = 1; s <= order; s++ )
		lsftExt += aa[s][0] * bi_adj^s;		

	SetChartOptions( 0, chartShowDates );
	SetChartBkColor( ColorRGB( 0, 0, 0 ) );
	Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
	PlotShapes( shapeSmallCircle*PHigh, ColorRGB( 250, 0, 0 ), 0, H, 10 );
	Plot( lsft, "", colorAqua, styleLine |styleNoRescale, Null, Null, 0, 0, 2 );
	Plot( lsftExt, "", colorAqua, styleLine | styleNoRescale | styleDots | styleNoLine, Null, Null, 0, 0, 1 );
}
5 Likes

Ed,

I have added line for lows in addition and have put all into one loop (includes extensions).

// calculate the linear fit
lsft = aa[0][0]; 
cond1 = bi>= xvalue[0] AND bi <= xvalue[n];
cond2 = bi > xvalue[n] AND bi < BarCount;
bi_adj = IIf(cond1 OR cond2, bi-avgx, Null);
for ( s = 1; s <= order; s++ ) 
	lsft += aa[s][0] * bi_adj^s;

/// @link https://forum.amibroker.com/t/linear-regression-among-swing-high/22681/2
/// by AmiBroker.com, empottasch and fxshrat@gmail.com
order = 1; // linear
Hnbar = 30;
Lnbar = 30;
n = 3;

function calculateCoefficients( xVal, yVal, bars, av ) {
    local j, aa, xx, yy, xxt;
    xx = Matrix( bars + 1, order + 1, 1 );
	for( j = 1; j <= order; j++ )
        xx = MxSetBlock(xx, 0, bars, j, j, (xVal - av)^j);
        
    yy = Matrix( bars + 1, 1, 0 );
    yy = MxSetBlock(yy, 0, bars, 0, 0, yVal);

    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;
    return aa;
}

bi = BarIndex();
p1 = H == HHV(H, Hnbar) AND Ref(HHV(H, Hnbar), Hnbar) < H;
p2 = L == LLV(L, Lnbar) AND Ref(LLV(L, Lnbar), Lnbar) > L;
arr1 = H; arr2 = L;

SetChartOptions( 0, chartShowDates );
SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
PlotShapes( shapeSmallCircle*P1, ColorRGB( 250, 0, 0 ), 0, H, 10 );
PlotShapes( shapeSmallCircle*P2, ColorRGB( 250, 0, 0 ), 0, L, 10 );

if ( BarCount > n ) {
	style2 = styleLine | styleNoRescale | styleDots | styleNoLine;
	for ( k = 1; k <= 2; k++ ) { // Peaks and throughs	
		xvalue = yvalue = Null;	
		for ( i = 0; i <= n; i++ ) {
			xvalue[i] = LastValue(ValueWhen(VarGet("P"+k), bi, n+1-i));
			yvalue[i] = LastValue(ValueWhen(VarGet("P"+k), VarGet("arr"+k), n+1-i));			
		}
		// average index of range examined. Used to make the process of fitting more accurate (numerically)
		avgx = (xvalue[n] + xvalue[0]) / 2;
		aa = calculateCoefficients(xvalue, yvalue, n, avgx);

		// calculate the linear fit
		lsft = aa[0][0]; 
		cond1 = bi>= xvalue[0] AND bi <= xvalue[n];
		cond2 = bi > xvalue[n] AND bi < BarCount;
		bi_adj = IIf(cond1 OR cond2, bi-avgx, Null);
		for ( s = 1; s <= order; s++ ) 
			lsft += aa[s][0] * bi_adj^s;

		color = IIf(k==1, colorAqua, colorViolet);
		Plot(IIf(cond1, lsft, Null), "", color, styleLine, Null, Null, 0, 0, 4 );
		Plot(IIf(cond2, lsft, Null), "", color, style2, Null, Null, 0, 0, 1 );
	}
}

14

5 Likes

Thanks Ed and FX's reply. Now this version is calculating the regression line of the "last" four pivots. What if I would like to obtain the value of "lsft" of each bar? what I am trying to do is:

First, declare the variables by using similar loops:

for ( k = 1; k <= 2; k++ )
{
	for ( i = 0; i <= n; i++ ) 
	{
		//xvalue[i] = LastValue(ValueWhen(VarGet("P"+k), bi, n+1-i));
		//yvalue[i] = LastValue(ValueWhen(VarGet("P"+k), VarGet("arr"+k), n+1-i));		
		
		VarSet("P"+k+"_"+n+"th_bi", (ValueWhen(VarGet("P"+k), bi, n+1-i)));
		VarSet("P"+k+"_"+n+"th_arr"+k, ValueWhen(VarGet("P"+k), VarGet("arr"+k), n+1-i));
	}
}

Then, I call these two variables in every bar by using [j]:

			xvalue[i] = VarGet("P"+k+"_"+n+"th_bi"+"["+j+"]");
			yvalue[i] = VarGet("P"+k+"_"+n+"th_arr"+k+"["+j+"]");

Then, calculate the avgx for each bar:

for( j = n; j < BarCount; j++ ) 
{ 
	if ( BarCount > n ) 
	{
		for ( k = 1; k <= 2; k++ ) 
		{ // Peaks and throughs	
			
			for ( i = 0; i <= n; i++ ) 
			{
				//xvalue[i] = LastValue(ValueWhen(VarGet("P"+k), bi, n+1-i));
				//yvalue[i] = LastValue(ValueWhen(VarGet("P"+k), VarGet("arr"+k), n+1-i));		
				
				xvalue[i] = VarGet("P"+k+"_"+n+"th_bi"+"["+j+"]");
				yvalue[i] = VarGet("P"+k+"_"+n+"th_arr"+k+"["+j+"]");
				
					
			}
			// average index of range examined. Used to make the process of fitting more accurate (numerically)
			avgx[j] = (xvalue[n] + xvalue[0]) / 2;
		}
	}	
}

Then I am not sure the next step. The function "calculateCoefficients(xvalue, yvalue, n, avgx)" is dealing with input in the format of array with 4 element( in this case). It really confuses me. May I have some hints from you Gents?

Thanks a lot!

oh, i understood you wanted to only use price at the pivot points. If you want to use all data you just use the regular Amibroker functions. Lots of examples out there. I also made a couple of AFL. Just google for "Amibroker LinRegIntercept LinRegSlope LinearReg" you will find a bunch of code.

here is 1 for you:

2 Likes

@wtchung, Change to

for ( i = 0; i <= n; i++ ) {
         xvalue[i] = SelectedValue(ValueWhen(VarGet("P"+k), bi, n+1-i));
         yvalue[i] = SelectedValue(ValueWhen(VarGet("P"+k), VarGet("arr"+k), n+1-i));         
}
3 Likes

Thanks for your quick reply!
You didn't misunderstand my question - I do really want to only use the price at the pivot points, and so your solution is perfectly solving my problem. I want to obtain the regression line for, say in this example, for last 4 pivot points for every single bar. I studied your "using fractals for trendlines" and I believe the concept is very similar, but just replacing the trendlines by the regression line.

So I believe I can only calculate the regression line by using for-loop for each bar. But I have not yet got a solution to call your function "calculateCoefficients" in the for-loop. In the for-loop, I can calculate each element by using array[i]. But your function's input, i.e xvalue and yvalue, are forth dimension array. So any idea I can combine them together? Or do I miss anything? should I go for completely different diection?

Thanks again.

The original function code is by AmiBroker.com.
Take a look at example 3 (that's why I added addtional credit to amibroker.com in upper code!):

// Part of EXAMPLE 3 of MxSolve documention of AmiBroker.com
// https://www.amibroker.com/guide/afl/mxsolve.html
yy = Matrix( length + 1, 1, 0 );
xx = Matrix( length + 1, order + 1, 1 );

yy = MxSetBlock( yy, 0, length, 0, 0, Ref( C, fvb ) );

x = BarIndex() - length/2;

for( j = 1; j <= order; j++ )
{
     xx = MxSetBlock( xx, 0, length, j, j, x ^ j );
}

xxt = MxTranspose( xx );
aa = MxSolve( xxt @ xx, xxt ) @ yy;

?

No, xvalue and yvalue in upper code are 1-dimensional arrays.

1 Like

Thanks FX. You are right, they are 1 dimension array, i wanted to say they store 4 elements.
I go through the reply from Empottasch and you again, and sorry that I didn't study them details enough. I think the file provided by Empottasch in the library is already doing what I am looking for.
Programming is a really special talent and I hope I can always translate my idea into code like all of you.

Thanks again.

You do not need Barcount loop.


FYI, I have added code for multi lines to AFL library.
http://www.amibroker.com/members/library/detail.php?id=1547
Keep in mind... you are not allowed to share to non-members. Also commercial use is prohibited.

Example output:

15


Note: You may have to add SetBarsRequired() function.

See also:
http://www.amibroker.com/kb/2008/07/03/quickafl/

6 Likes

Thanks @ fxshrat and empottasch

I have been playing with the idea of having one byte of peaks (or throughs) and then finding of the 8 peaks, the combination of peaks that are as much as possible on the same line. So that would need to loop through the 255 combinations of peaks and choose the best fit and omit some peaks that are lower than the resistance line. Thanks for posting these wonderfull codes, it will really help if I have time to test that idea.

Thanks a lot! Don't worry, I fully respect this community and I will not do anything to harm it.

and since we now have the wonderful new python plugin by Kuba and Tomasz we can now avoid all the math and let the calculations be done by Python. I am playing around with it to get familiar with the plugin and Python.

If you did not install the plugin yet the instructions are posted here:

best go through the entire thread and make sure you install Python through the link given by Tomasz in 1 of the posts (version 3.8).

then if every thing is setup, you installed Python, installed the Amipy plugin, installed numpy then the only additional thing to run my code is to do type in the CMD window:
pip install scipy

the python code I stored in a file called PolyfitForAB.py and you need to make sure you store it in a location that corresponds to the link you use in the AFL file.

import AmiPy
from numpy.polynomial import polynomial as poly
from scipy import interpolate

def polyfitInput( x, y, cnt, order, xnew ):
    xarr = x[0:int(cnt)]
    yarr = y[0:int(cnt)]
    coefs = poly.polyfit(xarr, yarr, int(order))
    ynew = poly.polyval(xnew, coefs)
    return ynew

def splineInput( x, y, cnt, xnew ):
    xarr = x[0:int(cnt)]
    yarr = y[0:int(cnt)]
    tck = interpolate.splrep(xarr, yarr, k=3)
    ynew = interpolate.splev(xnew, tck, der=0)
    return ynew

this then is the AFL file

PyLoadFromFile( "polyfit using Python", "C:\\Users\\win 10\\AppData\\Local\\Programs\\Python\\Python38\\mypython\\PolyfitForAB.py" );

rightstrength = Param( "Right Strength", 30, 2, 50, 1 );
leftstrength = Param( "Left Strength", 30, 2, 50, 1 );
extend = Param( "Extend (bars)", 150, 1, 500, 1 );
order = Param( "Polynomial Order", 1, 1, 10, 1 );
nn = Param( "Number of Pivots", 4, 2, 30, 1 );
ftype = ParamToggle( "Fit Type", "Spline(needs min. 4 points)|Polynomial", 1 );

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
Lx = LastValue( bi );

pk = H == HHV( H, leftstrength ) AND Ref( HHV( H, rightstrength ), rightstrength ) < H;
pk AND Lx - ValueWhen( pk, bi ) > rightStrength;
tr = L == LLV( L, leftstrength ) AND Ref( LLV( L, rightstrength ), rightstrength ) > L;
tr AND Lx - ValueWhen( tr, bi ) > rightStrength;

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 0 );

// tops
lastIndex = LastValue( SelectedValue( ValueWhen( pk, bi ) ) );

// fill x array, y array and xnew array
xarr = yarr = xnew = cnt = 0;
firstIndex = LastValue( SelectedValue( ValueWhen( pk, bi, nn ) ) );

for( i = firstIndex; i <= lvb; i++ )
{
    xnew[i] = bi[i]; // index where interpolated values will be stored

    if( pk[i] AND i <= lastIndex )
    {
        // points used to calculate the polynomial
        xarr[cnt] = bi[i];
        yarr[cnt] = H[i];
        cnt = cnt + 1;
    }
}

if( ftype )
{
    ynew = PyEvalFunction( "polyfit using Python", "polyfitInput", xarr, yarr, cnt, order, xnew );
    ynew = IIf( bi >= firstIndex, ynew, Null );
    ynew = IIf( bi >= lastIndex + extend, Null, ynew );
    Plot( IIf( bi <= lastIndex, ynew, Null ), "", colorAqua, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( IIf( bi > lastIndex + rightStrength, ynew, Null ), "", colorAqua, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( IIf( bi >= lastIndex AND bi <= lastIndex + rightStrength, ynew, Null ), "", colorLightGrey, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( bi == lastIndex, "", colorAqua, styleHistogram | styleDashed | styleOwnScale | styleNoLabel, 0, 1, 0, -1, 1 );
    pivs = Flip( firstIndex == bi, lastIndex + 1 == bi );
    PlotShapes( IIf( pivs, shapeCircle, shapeSmallCircle ) * pk, ColorRGB( 250, 0, 0 ), 0, H, 10 );
}
else
    if( !ftype AND cnt > 3 ) // number of pivots should be greater than 3
    {
        ynew = PyEvalFunction( "polyfit using Python", "splineInput", xarr, yarr, cnt, xnew );
        ynew = IIf( bi >= firstIndex, ynew, Null );
        ynew = IIf( bi >= lastIndex + extend, Null, ynew );
        Plot( IIf( bi <= lastIndex, ynew, Null ), "", colorAqua, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( IIf( bi > lastIndex + rightStrength, ynew, Null ), "", colorAqua, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( IIf( bi >= lastIndex AND bi <= lastIndex + rightStrength, ynew, Null ), "", colorLightGrey, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( bi == lastIndex, "", colorAqua, styleHistogram | styleDashed | styleOwnScale | styleNoLabel, 0, 1, 0, -1, 1 );
        pivs = Flip( firstIndex == bi, lastIndex + 1 == bi );
        PlotShapes( IIf( pivs, shapeCircle, shapeSmallCircle ) * pk, ColorRGB( 250, 0, 0 ), 0, H, 10 );
    }

// bottoms
lastIndex = LastValue( SelectedValue( ValueWhen( tr, bi ) ) );

// fill x array, y array and xnew array
xarr = yarr = xnew = cnt = 0;
firstIndex = LastValue( SelectedValue( ValueWhen( tr, bi, nn ) ) );

for( i = firstIndex; i <= lvb; i++ )
{
    xnew[i] = bi[i]; // index where interpolated values will be stored

    if( tr[i] AND i <= lastIndex )
    {
        // points used to calculate the polynomial
        xarr[cnt] = bi[i];
        yarr[cnt] = L[i];
        cnt = cnt + 1;
    }
}

if( ftype )
{
    ynew = PyEvalFunction( "polyfit using Python", "polyfitInput", xarr, yarr, cnt, order, xnew );
    ynew = IIf( bi >= firstIndex, ynew, Null );
    ynew = IIf( bi >= lastIndex + extend, Null, ynew );
    Plot( IIf( bi <= lastIndex, ynew, Null ), "", colorViolet, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( IIf( bi > lastIndex + rightStrength, ynew, Null ), "", colorViolet, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( IIf( bi >= lastIndex AND bi <= lastIndex + rightStrength, ynew, Null ), "", colorLightGrey, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( bi == lastIndex, "", colorViolet, styleHistogram | styleDashed | styleOwnScale | styleNoLabel, 0, 1, 0, -1, 1 );
    pivs = Flip( firstIndex == bi, lastIndex + 1 == bi );
    PlotShapes( IIf( pivs, shapeCircle, shapeSmallCircle ) * tr, ColorRGB( 0, 250, 0 ), 0, L, -10 );
}
else
    if( !ftype AND cnt > 3 ) // number of pivots should be greater than 3
    {
        ynew = PyEvalFunction( "polyfit using Python", "splineInput", xarr, yarr, cnt, xnew );
        ynew = IIf( bi >= firstIndex, ynew, Null );
        ynew = IIf( bi >= lastIndex + extend, Null, ynew );
        Plot( IIf( bi <= lastIndex, ynew, Null ), "", colorViolet, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( IIf( bi > lastIndex + rightStrength, ynew, Null ), "", colorViolet, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( IIf( bi >= lastIndex AND bi <= lastIndex + rightStrength, ynew, Null ), "", colorLightGrey, styleDashed | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( bi == lastIndex, "", colorViolet, styleHistogram | styleDashed | styleOwnScale | styleNoLabel, 0, 1, 0, -1, 1 );
        pivs = Flip( firstIndex == bi, lastIndex + 1 == bi );
        PlotShapes( IIf( pivs, shapeCircle, shapeSmallCircle ) * tr, ColorRGB( 0, 250, 0 ), 0, L, -10 );
    }
2 Likes