Calculate formulas using visible bars in chart

Hi,
The code below creates a linear regression trendline and two bands at 95% and 5% of the frequency distribution of the Price-Trendline difference. The line are plottable in the chart.
It works well in explorer and and dates can be changed in the date from/to in the anaysis window.

When I plot the lines in the chart, all the calulations apply to the historical time series. Is there is a short way to apply the calculation only to what I can see on the chart ?

I have read On Balance Volume Indicator - Use only the visible bars but not sure does the job I'm looking for.
It would require to modify all the formulas to
only_visible = any_indicator - FirstVisibleValue( any_indicator );

Is this the only way?
Any help would be welcome.

BI=BarIndex(); x = Cum(1);
logC=log(Close); DateN=DateNum();
pds = LastValue( x ); 
a = LastValue( LinRegIntercept( logC, pds) );
b = LastValue( LinRegSlope( logC, pds ) );
y = a + b *  x ; 
trendline= exp(y);
diff=(c-trendline)/trendline; //
Per95= EndValue( Percentile(diff,pds,95));
Per05= EndValue( Percentile(diff,pds,05));
Band95=trendline*(1+Per95);
Band05=trendline*(1+Per05);
Plot(C, "Close", colorBlack, styleline );
Plot( trendline, "TrendLine", colorBlue, styleDashed);
Plot( Band95,  "95%", colorRed, styleDashed );
Plot( band05, "5%", colorRed,styleDashed );
// ==============
Filter= (Status("actionEx"));
//AddColumn(DateNum(), "date Num",1.0);
AddColumn(c,"Close",1.3);
AddColumn(trendline,"Trend Line",1.3);
AddColumn(Band95, "95%",1.3);
AddColumn(Band05, "05%",1.3);
//other
AddColumn(x,"x",1.0);
AddColumn(pds,"Periods",1.0);
AddColumn(a,"Inter",1.3);
AddColumn(b,"Slope",1.3);
AddColumn(diff,"Diff",1.3);
AddColumn(Band95, "Band95",1.3);
AddColumn(Band05, "Band05",1.3);


@jbenfeld
easy way use SetBarsRequired() at end of your code...
but if you want .....

only_visible = any_indicator - FirstVisibleValue( any_indicator ); 
x = Cum(1) - FirstVisibleValue(Cum(1));
2 Likes

Use ...VisibleBarValue functions.
Note: In analysis there is not any visible bar range so i.e. if in analysis you want same (intraday) data output of visible chart you have to store values in chart to make them ready for output in analysis. Each scroll will automatically prepare chart's updated visible data range for analysis. For that and for easier static var handling I have used new static variable declaration feature of AB 6.21 to 6.30 dev. cycle. See lines 8, 9 as well as lines 35-41.

/// output of linear reg line of visible chart area
/// mod. by fxshrat for fixed output requested by jbenfeld
/// @link http://forum.amibroker.com/t/calculate-formulas-using-visible-bars-in-chart/4907/2
/// first apply in chart then in analysis
/// check periodicity setting of analysis!
Version(6.28);// latest beta required as of March 2018

#pragma enable_static_decl(vislinreg)
static _pds, _a, _b, _x, _diff, _Band05, _Band95, _trendline;

bi = BarIndex();
fvb = FirstVisibleValue(bi);
x = bi - fvb + 1;
pds = x;
 
array = log(C);

a = LastVisibleValue(LinRegSlope(array, pds));
b = LastVisibleValue(LinRegIntercept(array, pds));
y = a * x + b;
trendline = exp(y);

diff = ( C - trendline ) / trendline; 
Per95 = LastVisibleValue( Percentile( diff, pds, 95 ) );
Per05 = LastVisibleValue( Percentile( diff, pds, 5 ) );
Band95 = trendline * ( 1 + Per95 );
Band05 = trendline * ( 1 + Per05 );

Plot(C, "Close", colorBlack, styleline );
Plot( trendline, "TrendLine", colorBlue, styleDashed);
Plot( Band95,  "95%", colorRed, styleDashed );
Plot( band05, "5%", colorRed,styleDashed );

// storing visible chart vars to static vars with help of dynamic vars
if( Status("action") == actionIndicator ) {
	varstr = "a,b,x,diff,pds,trendline,Band95,Band05";
	for( i = 0; i < StrCount(varstr, ",")+1; i++ ) { 
		varextr = StrExtract(varstr, i);
		VarSet( "_" + varextr, VarGet(varextr)); 
	}
}

Filter = _x > 0 AND _x > Ref(_x, -1);
AddTextColumn( Interval(2), "Interval", 1 );
AddColumn(DateNum(), "date Num",1.0);
AddColumn(C,"Close",1.3);
AddColumn(_trendline,"Trend Line",1.3);
AddColumn(_Band95, "95%",1.3);
AddColumn(_Band05, "05%",1.3);
//other
AddColumn(_x,"x",1.0);
AddColumn(_pds,"Periods",1.0);
AddColumn(_a,"Inter",1.5);
AddColumn(_b,"Slope",1.3);
AddColumn(_diff,"Diff",1.3);
//AddColumn(_Band95, "Band95",1.3);
//AddColumn(_Band05, "Band05",1.3);

003121

003216

1 Like

Got a mail regarding previous code returning syntax error.
Filter variable just had a space missing after AND operator.
That's all. So it is easy to fix. Anyway here is code update.

/// output of linear reg line of visible chart area
/// mod. by fxshrat for fixed output requested by jbenfeld
/// @link http://forum.amibroker.com/t/calculate-formulas-using-visible-bars-in-chart/4907/3
/// first apply in chart then in analysis
/// check periodicity setting of analysis!
Version(6.28);// latest beta required as of March 2018

#pragma enable_static_decl(vislinreg)
static _pds, _a, _b, _x, _diff, _Band05, _Band95, _trendline;

if( Status("action") == actionIndicator ) {	

	bi = BarIndex();
	fvb = FirstVisibleValue(bi);
	x = bi - fvb + 1;
	pds = LastVisibleValue(x);	
	
	array = log(C);

	a = LastVisibleValue(LinRegSlope(array, pds));
	b = LastVisibleValue(LinRegIntercept(array, pds));
	y = a * x + b;
	trendline = exp(y);

	diff = ( C - trendline ) / trendline; 
	Per95 = LastVisibleValue( Percentile( diff, pds, 95 ) );
	Per05 = LastVisibleValue( Percentile( diff, pds, 5 ) );
	Band95 = trendline * ( 1 + Per95 );
	Band05 = trendline * ( 1 + Per05 );

	Plot(C, "Close", colorBlack, styleline );
	Plot( trendline, "TrendLine", colorBlue, styleDashed);
	Plot( Band95,  "95%", colorRed, styleDashed );
	Plot( band05, "5%", colorRed,styleDashed );

	// storing visible chart vars to static vars with help of dynamic vars
	varstr = "a,b,x,diff,pds,trendline,Band95,Band05";
	for( i = 0; i < StrCount(varstr, ",")+1; i++ ) { 
		varextr = StrExtract(varstr, i);
		VarSet( "_" + varextr, VarGet(varextr)); 
	}
}

Filter = _x > 0 AND _x > Ref(_x, -1);
AddTextColumn( Interval(2), "Interval", 1 );
AddColumn(DateNum(), "date Num",1.0);
AddColumn(C,"Close",1.3);
AddColumn(_trendline,"Trend Line",1.3);
AddColumn(_Band95, "95%",1.3);
AddColumn(_Band05, "05%",1.3);
//other
AddColumn(_x,"x",1.0);
AddColumn(_pds,"Periods",1.0);
AddColumn(_a,"Inter",1.5);
AddColumn(_b,"Slope",1.3);
AddColumn(_diff,"Diff",1.3);
//AddColumn(_Band95, "Band95",1.3);
//AddColumn(_Band05, "Band05",1.3);
2 Likes

Thanks Fx,
much apprecitated
I reached a similar conclusion. The code below works well with both charting and exploration. With exploration there is an option to show either debug values or ready to export into excel mode, just the lines.

I have to admit that your code is much clearer and elegant. But I also guess you know by now that I am not really a good programmer.

Wanted to give some credit to http://www.amibroker.com/kb/2014/10/10/how-to-draw-regression-channel-programatically/ also

Just wanted to clarify that the bands 95-05 moves because are based on the frequency distribution of the "errors" and not on Standard deviation or standard error and they are more narrow than SE or SD.

LogC = log(Close);
xx = Cum(1);
firstx= FirstVisibleValue(xx);
lastx = LastVisibleValue(xx);
pds = lastx - firstx +1 ;
// linear regression values
a = LastVisibleValue( LinRegIntercept( LogC, pds ));
b = LastVisibleValue( LinRegSlope( LogC, pds )) ;
x = xx - firstx +1 ;
// linear regression equation
y = a + b * x ;
trendline=exp(y); // trendline in nominal values
diff=(c-trendline)/trendline; // error in %
Per95= LastVisibleValue( Percentile(diff,pds,95));
Per05= LastVisibleValue( Percentile(diff,pds, 05));
Band95=trendline*(1+Per95); Band05=trendline*(1+Per05);
// Charting
Plot( Close, "Close", colorDefault);
Plot( trendline, "LinReg", colorblue, styleDashed );
Plot( band95, "95%", colorred, styleDashed );
Plot( band05, "05%", colorred, styleDashed );
// ===== Explorer =========
Filter= Status("action") == actionExplore;
ExcelReady=ParamToggle("Excel Ready?","NO|YES",0);
{  logC=log(Close); 
xx = Cum(1);
fbr = Status( "FirstBarInRange" ); 
lbr = Status( "LastBarInRange" );
firstx= LastValue(ValueWhen (fbr==1,xx,1));
lastx= LastValue(ValueWhen (lbr==1,xx,1));
pds = lastx - firstx +1 ;
// linear regression values
a = LastValue( LinRegIntercept( logC, pds) );
b = LastValue( LinRegSlope( logC, pds ) );
x= xx - firstx +1 ;
R2= LastValue(Correlation(xx,logc,pds-1)^2); // to be finished
// linear regression equation
y = a + b * x;
trendline= exp(y);
diff=(c-trendline)/trendline; //
Per95= EndValue( Percentile(diff,pds,95));
Per05= EndValue( Percentile(diff,pds,05));
Band95=trendline*(1+Per95);
Band05=trendline*(1+Per05);
if (ExcelReady==1)
{
AddColumn(c,"Close",1.2);
AddColumn(trendline,"Trend Line",1.2);
AddColumn(Band95, "95%",1.2);
AddColumn(Band05, "5%",1.2);
}
if (ExcelReady==0)
{
AddColumn(c,"Close",1.2);
AddColumn(trendline,"Trend Line",1.2);
AddColumn(Band95, "95%",1.2);
AddColumn(Band05, "5%",1.2);
AddColumn(R2,"R2",1.2);
AddColumn(x,"x",1.0);
AddColumn(a,"Inter(a)",1.3);
AddColumn(b,"Slope(b)",1.3);
AddColumn(diff,"Diff",1.3);
AddColumn(firstx,"firstx",1.0);
AddColumn(lastx,"lastx",1.0);
AddColumn(pds,"Periods",1.0);}
}
1 Like