I have developed the Bullcharts indicator listed below which characterises current support and resistance price levels relative to the prices which have been most statistically probable over a given period. This indicator calculates a histogram of the incidence of Close prices within 25 equal bands between the minimum and maximum prices of a period which is considered representative and within each price band decays the significance of the older data.
Except for new listings which go on to trend strongly and consistently for most shares a histogram of the incidence of price levels, ranked in order of their incidence, will be skewed with a long tail of prices which occur infrequently and a number of bands with the more frequent price levels (approximately Weibull).
Other support and resistance indicators employ an exponential moving average to calculate the current representative support and resistance price levels. Those available in the Bullchart library use 280 bars as a basis, the most recent three peaks and troughs of the zigzag function and a 25 bar exponential moving average as standard.
I advocate that this proposed statistical method is a more accurate hypothetical model than a support and resistance formulation using an exponential moving average as a basis because it calculates the most statistically probable price levels but decays the significance of historical prices with a time weighted average. This formulation employs significant volume spikes or changes in cumulative volume to determine the timing in changes of support and resistance levels. Over the last few months I have found this method to be more responsive than an EMA support or resistance indicator.
Some purists may criticise this formulation for a number of reasons including;
a) either method of calculating the timing of changing between indicator support or resistance price levels involves an element of subjectivity (the sensitivity of the zigzag function), and;
b) the subjectivity of deciding the incidence cutoff between the long tail of improbable price level bands and the higher probability bands, and;
c) throughout this indicator the support and resistance levels displayed change when additional data is received, the support and resistance levels calculated for the next bar are, at least, infinitesimally different from that calculated for the current bar.
Unfortunately the Achilles heel of this indicator is that while Bullcharts can calculate it, it takes a long time to evaluate the Bullchart’s standard lowest and highest (LLV and HHV) functions. The time taken is heavily dependent on the number of bars, WHA is quick but 30 years of BHP is slow (15 minutes or more). I recently brought a fairly modern Windows 10 Professional computer and I have not thought of a way to expedite this indicator because I will not be able to markedly improve the computer’s clock speed of 4.2GHz in the near future.
The limits on number of parameters and memory size of a Metastock exploration are such that I have not thought of a way that this could be readily done in Metastock. I would appreciate it if anyone can inform me of a software which has a statistical method such as this formulated successfully.
Having written this indicator I have subsequently tried to find an academic basis for what I believe is elementary statistics. I assert that with the exception of the Weis/Wyckoff treatment of cumulative volume I wrote this Bullcharts indicator independently. Googling the terms “support resist probab statist” returns a number of academic articles on memory effect including those by Garzarelli et al and De Angelis et al but I did not find anything as pragmatic as that below. In part due to the speed of the Bullchart’s lowest and highest functions and the Metastock exploration number of parameters and memory size issues I infer that this statistical method is not readily available.
I first discussed with Bullsystems the response duration of the Lowest and Highest functions in early October and I believe we are agreed that this is an issue with these standard Bullcharts functions. If you are interested please take the time to explore the potential of the indicator below. As a workaround I have split this indicator into two parts. The first part can still take around five minutes to display the representative period (number of bars for analysis) and the corresponding minimum and maximum prices. I then manually enter these three numbers for the second part to calculate the time weighted average and display the support and resistance level indicators. Ultimately my objective is to find a way to automate calculation of this indicator and display it in under 60 seconds without human interference.
I seek your support and ask that you trial this indicator in Bullcharts, if you have a licence, as I would appreciate confirmation as to whether anyone else obtains faster results with a different operating system. Further if anyone is interested I would appreciate feedback from anyone who successfully codes it in a different software (eg AmiBroker or NinjaTrader or ?).
I accept no responsibility nor liability for any use of this indicator, in particular, noting the concerns above and its response time.
{************************************************************************The indicator below, down to the next line of asterisks, should be saved in Custom Indicators as “S&R Representative min max price” or similar. When inserted in a chart it should display two numbers in the top and bottom right corners of the Price chart by default }
{Determine repesentative minimum and maximum price of current data}
ScopeMax:= lastvalue(highestbars(C,min(lastvalue(barnumber)-2,1300)));
ScopeMin:= lastvalue(lowestbars(C,min(lastvalue(barnumber)-2,1300)));
range:= if(lastvalue(barnumber)>1300, lastvalue(highest(c,1300)-lowest(c,1300)), lastvalue(highest(c,75)-lowest(c,75)));
mean:= if(lastvalue(barnumber)>1300, if(range=0, 0, abs(((0.5*(lastvalue(highest(c,1300)+lowest(c,1300))))-lastvalue(ma(C,1300)))/range)),
abs(((0.5*(lastvalue(highest(c,75)+lowest(c,75))))-lastvalue(ma(C,75)))/range));
infinity:= if(ScopeMax+ScopeMin>2250, 1300, 100+1200*htan((ScopeMax+ScopeMin)/40));
scope:= int(if(lastvalue(barssince(ma(V,10,s)=0))>0,min(1300,min(
infinity + (0.5*mean*(min(1300,lastvalue(barssince(ma(V,10,s)=0)))-infinity)),lastvalue(barssince(ma(V,10,s)=0)))),
infinity + (0.5*mean*(1300-infinity)) ));
timescale:= lastvalue(barnumber);
dataset:= if(timescale>scope+1,timescale-scope,1);
CDS:= valuewhen(1,if(barnumber>dataset,1,0),C);
closelo:= lastvalue(lowest(CDS,scope));
closehi:= lastvalue(highest(CDS,scope));
[linestyle=text; target=price; textalign=top,right]
if(barnumber=lastvalue(barnumber), closehi, undefined);
c;
[linestyle=text; target=price; textalign=bottom,right]
if(barnumber=lastvalue(barnumber), closelo, undefined);
c;
{***************this line is not required as Bullchart code************}
{The code above will display indicator lines but I hide them by making them the same colour as the background}
{************************************************************************The indicator below, down to the next line of asterisks, should be saved in Custom Indicators as “S&R Representative duration” or similar. When inserted in a chart it should display two numbers in the upper right corner of the Volume chart by default }
boxend:= lastvalue(barnumber);
[linestyle=text; target=volume; textalign=top, right]
if(barnumber=lastvalue(barnumber), boxend, undefined);
V;
{Determine repesentative set of current data}
ScopeMax:= lastvalue(highestbars(C,min(lastvalue(barnumber)-2,1300)));
ScopeMin:= lastvalue(lowestbars(C,min(lastvalue(barnumber)-2,1300)));
range:= if(lastvalue(barnumber)>1300, lastvalue(highest(c,1300)-lowest(c,1300)), lastvalue(highest(c,75)-lowest(c,75)));
mean:= if(lastvalue(barnumber)>1300, if(range=0, 0, abs(((0.5*(lastvalue(highest(c,1300)+lowest(c,1300))))-lastvalue(ma(C,1300)))/range)),
abs(((0.5*(lastvalue(highest(c,75)+lowest(c,75))))-lastvalue(ma(C,75)))/range));
infinity:= if(ScopeMax+ScopeMin>2250, 1300, 100+1200*htan((ScopeMax+ScopeMin)/40));
scope:= int(if(lastvalue(barssince(ma(V,10,s)=0))>0,min(1300,min(
infinity + (0.5*mean*(min(1300,lastvalue(barssince(ma(V,10,s)=0)))-infinity)),lastvalue(barssince(ma(V,10,s)=0)))),
infinity + (0.5*mean*(1300-infinity)) ));
[linestyle=text; target=volume; textalign=top, left]
if(barnumber=lastvalue(barnumber), scope, undefined);
V;
{***************this line is not required as Bullchart code************}
{************************************************************************The indicator below should be saved in Custom Indicators as “S&R Manual” or similar. When inserted in a chart it should display support and resistance levels on the price chart by default }
{Determine repesentative set of current data}
ScopeMax:= if(lastvalue(barnumber)<520,lastvalue(barnumber),lastvalue(highestbars(C,1300)));
ScopeMin:= if(lastvalue(barnumber)<520,lastvalue(barnumber),lastvalue(lowestbars(C,1300)));
mean:= 0.5*(highest(C,if(barnumber<1300,barnumber,1300))+lowest(C,if(barnumber<1300,barnumber,1300)));
average:= abs(ma(C,1300,s)-mean)/mean;
infinity:= if(ScopeMax+ScopeMin>2250, 1300, 100+1200*htan((ScopeMax+ScopeMin)/40));
scope:= input("Enter the analysis PERIOD");
timescale:= lastvalue(barnumber);
dataset:= if(timescale>scope+1,timescale-scope,1);
CDS:= valuewhen(1,if(barnumber>dataset,1,0),C);
VDS:= valuewhen(1,if(barnumber>dataset,1,0),V);
cutoff:=0.02;
{Significant Volume Peaks}
oracle:= if(C>hist(C,1), VDS/ma(VDS,40,e), if(c<hist(c,1), -1*VDS/ma(VDS,40,e), 0));
verticalrise:= lastvalue(cum(oracle));
factored:= cum(oracle) - (barnumber*verticalrise/timescale);
ScaleMin:= lastvalue(lowest(factored));
ScaleMax:= lastvalue(highest(factored));
sensitivity:= abs(ScaleMax - ScaleMin)/25;
{Significant Cumulative Volume changes}
[citation="Weis / Wyckoff"]
priceapprox:=zigzag(If(Outside() AND Ref(H,-1)>Ref(H,-2),H,If(Outside() AND Ref(L,-1)<Ref(L,-2),L,If((Outside() OR Inside()) AND C>O,H,If((Outside() OR Inside()) AND O>C,L,If(H>Ref(H,-1),H,If(L<Ref(L,-1),L,If(Ref(H,-1)>Ref(H,-2),H,If(Ref(L,-1)<Ref(L,-2),L,C)))))))), lastvalue((100*atr(14)/c)+0.8*abs(highest(c,100)-lowest(c,100))/3.00) ,%);
posivolume:= if(priceapprox>hist(priceapprox,1), previous+v, 0);
negivolume:= if(priceapprox<hist(priceapprox,1), previous-v, 0);
cumvolume:= posivolume+negivolume;
temphi:= input("Enter the MAXIMUM price");
templo:= input("Enter the MINIMUM price");
closelo:= min(templo, temphi);
gap:= abs(temphi - templo);
Band00:= sum(if(CDS>=closelo+(0.00*gap),if(CDS<closelo+(0.04*gap), CDS*(barnumber-scope),0), 0));
Band01:= sum(if(CDS>=closelo+(0.04*gap),if(CDS<closelo+(0.08*gap), CDS*(barnumber-scope),0), 0));
Band02:= sum(if(CDS>=closelo+(0.08*gap),if(CDS<closelo+(0.12*gap), CDS*(barnumber-scope),0), 0));
Band03:= sum(if(CDS>=closelo+(0.12*gap),if(CDS<closelo+(0.16*gap), CDS*(barnumber-scope),0), 0));
Band04:= sum(if(CDS>=closelo+(0.16*gap),if(CDS<closelo+(0.20*gap), CDS*(barnumber-scope),0), 0));
Band05:= sum(if(CDS>=closelo+(0.20*gap),if(CDS<closelo+(0.24*gap), CDS*(barnumber-scope),0), 0));
Band06:= sum(if(CDS>=closelo+(0.24*gap),if(CDS<closelo+(0.28*gap), CDS*(barnumber-scope),0), 0));
Band07:= sum(if(CDS>=closelo+(0.28*gap),if(CDS<closelo+(0.32*gap), CDS*(barnumber-scope),0), 0));
Band08:= sum(if(CDS>=closelo+(0.32*gap),if(CDS<closelo+(0.36*gap), CDS*(barnumber-scope),0), 0));
Band09:= sum(if(CDS>=closelo+(0.36*gap),if(CDS<closelo+(0.40*gap), CDS*(barnumber-scope),0), 0));
Band10:= sum(if(CDS>=closelo+(0.40*gap),if(CDS<closelo+(0.44*gap), CDS*(barnumber-scope),0), 0));
Band11:= sum(if(CDS>=closelo+(0.44*gap),if(CDS<closelo+(0.48*gap), CDS*(barnumber-scope),0), 0));
Band12:= sum(if(CDS>=closelo+(0.48*gap),if(CDS<closelo+(0.52*gap), CDS*(barnumber-scope),0), 0));
Band13:= sum(if(CDS>=closelo+(0.52*gap),if(CDS<closelo+(0.56*gap), CDS*(barnumber-scope),0), 0));
Band14:= sum(if(CDS>=closelo+(0.56*gap),if(CDS<closelo+(0.60*gap), CDS*(barnumber-scope),0), 0));
Band15:= sum(if(CDS>=closelo+(0.60*gap),if(CDS<closelo+(0.64*gap), CDS*(barnumber-scope),0), 0));
Band16:= sum(if(CDS>=closelo+(0.64*gap),if(CDS<closelo+(0.68*gap), CDS*(barnumber-scope),0), 0));
Band17:= sum(if(CDS>=closelo+(0.68*gap),if(CDS<closelo+(0.72*gap), CDS*(barnumber-scope),0), 0));
Band18:= sum(if(CDS>=closelo+(0.72*gap),if(CDS<closelo+(0.76*gap), CDS*(barnumber-scope),0), 0));
Band19:= sum(if(CDS>=closelo+(0.76*gap),if(CDS<closelo+(0.80*gap), CDS*(barnumber-scope),0), 0));
Band20:= sum(if(CDS>=closelo+(0.80*gap),if(CDS<closelo+(0.84*gap), CDS*(barnumber-scope),0), 0));
Band21:= sum(if(CDS>=closelo+(0.84*gap),if(CDS<closelo+(0.88*gap), CDS*(barnumber-scope),0), 0));
Band22:= sum(if(CDS>=closelo+(0.88*gap),if(CDS<closelo+(0.92*gap), CDS*(barnumber-scope),0), 0));
Band23:= sum(if(CDS>=closelo+(0.92*gap),if(CDS<closelo+(0.96*gap), CDS*(barnumber-scope),0), 0));
Band24:= sum(if(CDS>=closelo+(0.96*gap),if(CDS<closelo+(1.00*gap), CDS*(barnumber-scope),0), 0));
Count00:= sum(if(CDS>=closelo+(0.00*gap),if(CDS<closelo+(0.04*gap), barnumber-scope,0), 0));
Count01:= sum(if(CDS>=closelo+(0.04*gap),if(CDS<closelo+(0.08*gap), barnumber-scope,0), 0));
Count02:= sum(if(CDS>=closelo+(0.08*gap),if(CDS<closelo+(0.12*gap), barnumber-scope,0), 0));
Count03:= sum(if(CDS>=closelo+(0.12*gap),if(CDS<closelo+(0.16*gap), barnumber-scope,0), 0));
Count04:= sum(if(CDS>=closelo+(0.16*gap),if(CDS<closelo+(0.20*gap), barnumber-scope,0), 0));
Count05:= sum(if(CDS>=closelo+(0.20*gap),if(CDS<closelo+(0.24*gap), barnumber-scope,0), 0));
Count06:= sum(if(CDS>=closelo+(0.24*gap),if(CDS<closelo+(0.28*gap), barnumber-scope,0), 0));
Count07:= sum(if(CDS>=closelo+(0.28*gap),if(CDS<closelo+(0.32*gap), barnumber-scope,0), 0));
Count08:= sum(if(CDS>=closelo+(0.32*gap),if(CDS<closelo+(0.36*gap), barnumber-scope,0), 0));
Count09:= sum(if(CDS>=closelo+(0.36*gap),if(CDS<closelo+(0.40*gap), barnumber-scope,0), 0));
Count10:= sum(if(CDS>=closelo+(0.40*gap),if(CDS<closelo+(0.44*gap), barnumber-scope,0), 0));
Count11:= sum(if(CDS>=closelo+(0.44*gap),if(CDS<closelo+(0.48*gap), barnumber-scope,0), 0));
Count12:= sum(if(CDS>=closelo+(0.48*gap),if(CDS<closelo+(0.52*gap), barnumber-scope,0), 0));
Count13:= sum(if(CDS>=closelo+(0.52*gap),if(CDS<closelo+(0.56*gap), barnumber-scope,0), 0));
Count14:= sum(if(CDS>=closelo+(0.56*gap),if(CDS<closelo+(0.60*gap), barnumber-scope,0), 0));
Count15:= sum(if(CDS>=closelo+(0.60*gap),if(CDS<closelo+(0.64*gap), barnumber-scope,0), 0));
Count16:= sum(if(CDS>=closelo+(0.64*gap),if(CDS<closelo+(0.68*gap), barnumber-scope,0), 0));
Count17:= sum(if(CDS>=closelo+(0.68*gap),if(CDS<closelo+(0.72*gap), barnumber-scope,0), 0));
Count18:= sum(if(CDS>=closelo+(0.72*gap),if(CDS<closelo+(0.76*gap), barnumber-scope,0), 0));
Count19:= sum(if(CDS>=closelo+(0.76*gap),if(CDS<closelo+(0.80*gap), barnumber-scope,0), 0));
Count20:= sum(if(CDS>=closelo+(0.80*gap),if(CDS<closelo+(0.84*gap), barnumber-scope,0), 0));
Count21:= sum(if(CDS>=closelo+(0.84*gap),if(CDS<closelo+(0.88*gap), barnumber-scope,0), 0));
Count22:= sum(if(CDS>=closelo+(0.88*gap),if(CDS<closelo+(0.92*gap), barnumber-scope,0), 0));
Count23:= sum(if(CDS>=closelo+(0.92*gap),if(CDS<closelo+(0.96*gap), barnumber-scope,0), 0));
Count24:= sum(if(CDS>=closelo+(0.96*gap),if(CDS<closelo+(1.00*gap), barnumber-scope,0), 0));
total:= lastvalue(Count00 + Count01 + Count02 + Count03 + Count04 + Count05 + Count06 + Count07 + Count08 + Count09 +
Count10 + Count11 + Count12 + Count13 + Count14 + Count15 + Count16 + Count17 + Count18 + Count19 +
Count20 + Count21 + Count22 + Count23 + Count24);
PriceLevel:= max(
if(Count00>hist(Count00,1), if(lastvalue(Count00)/total<cutoff, 0, lastvalue(Band00)/lastvalue(Count00)), 0),
if(Count01>hist(Count01,1), if(lastvalue(Count01)/total<cutoff, 0, lastvalue(Band01)/lastvalue(Count01)), 0),
if(Count02>hist(Count02,1), if(lastvalue(Count02)/total<cutoff, 0, lastvalue(Band02)/lastvalue(Count02)), 0),
if(Count03>hist(Count03,1), if(lastvalue(Count03)/total<cutoff, 0, lastvalue(Band03)/lastvalue(Count03)), 0),
if(Count04>hist(Count04,1), if(lastvalue(Count04)/total<cutoff, 0, lastvalue(Band04)/lastvalue(Count04)), 0),
if(Count05>hist(Count05,1), if(lastvalue(Count05)/total<cutoff, 0, lastvalue(Band05)/lastvalue(Count05)), 0),
if(Count06>hist(Count06,1), if(lastvalue(Count06)/total<cutoff, 0, lastvalue(Band06)/lastvalue(Count06)), 0),
if(Count07>hist(Count07,1), if(lastvalue(Count07)/total<cutoff, 0, lastvalue(Band07)/lastvalue(Count07)), 0),
if(Count08>hist(Count08,1), if(lastvalue(Count08)/total<cutoff, 0, lastvalue(Band08)/lastvalue(Count08)), 0),
if(Count09>hist(Count09,1), if(lastvalue(Count09)/total<cutoff, 0, lastvalue(Band09)/lastvalue(Count09)), 0),
if(Count10>hist(Count10,1), if(lastvalue(Count10)/total<cutoff, 0, lastvalue(Band10)/lastvalue(Count10)), 0),
if(Count11>hist(Count11,1), if(lastvalue(Count11)/total<cutoff, 0, lastvalue(Band11)/lastvalue(Count11)), 0),
if(Count12>hist(Count12,1), if(lastvalue(Count12)/total<cutoff, 0, lastvalue(Band12)/lastvalue(Count12)), 0),
if(Count13>hist(Count13,1), if(lastvalue(Count13)/total<cutoff, 0, lastvalue(Band13)/lastvalue(Count13)), 0),
if(Count14>hist(Count14,1), if(lastvalue(Count14)/total<cutoff, 0, lastvalue(Band14)/lastvalue(Count14)), 0),
if(Count15>hist(Count15,1), if(lastvalue(Count15)/total<cutoff, 0, lastvalue(Band15)/lastvalue(Count15)), 0),
if(Count16>hist(Count16,1), if(lastvalue(Count16)/total<cutoff, 0, lastvalue(Band16)/lastvalue(Count16)), 0),
if(Count17>hist(Count17,1), if(lastvalue(Count17)/total<cutoff, 0, lastvalue(Band17)/lastvalue(Count17)), 0),
if(Count18>hist(Count18,1), if(lastvalue(Count18)/total<cutoff, 0, lastvalue(Band18)/lastvalue(Count18)), 0),
if(Count19>hist(Count19,1), if(lastvalue(Count19)/total<cutoff, 0, lastvalue(Band19)/lastvalue(Count19)), 0),
if(Count20>hist(Count20,1), if(lastvalue(Count20)/total<cutoff, 0, lastvalue(Band20)/lastvalue(Count20)), 0),
if(Count21>hist(Count21,1), if(lastvalue(Count21)/total<cutoff, 0, lastvalue(Band21)/lastvalue(Count21)), 0),
if(Count22>hist(Count22,1), if(lastvalue(Count22)/total<cutoff, 0, lastvalue(Band22)/lastvalue(Count22)), 0),
if(Count23>hist(Count23,1), if(lastvalue(Count23)/total<cutoff, 0, lastvalue(Band23)/lastvalue(Count23)), 0),
if(Count24>hist(Count24,1), if(lastvalue(Count24)/total<cutoff, 0, lastvalue(Band24)/lastvalue(Count24)), 0));
interim:=if(PriceLevel=0,1,0);
Normalised:= if(interim=1, previous + PriceLevel, PriceLevel);
{Resistance Level calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Red]
valuewhen(1,if(barnumber>dataset, if(peakbars(1,zigzag(factored,sensitivity,points),20)=0,1,0),0), Normalised);
{Support Level Calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Dark Green]
valuewhen(1,if(barnumber>dataset, if(troughbars(1,zigzag(factored,sensitivity,points),20)=0,1,0),0), Normalised);
{Resistance Level calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Orange]
valuewhen(1,if(barnumber>dataset, if(peakbars(1,zigzag(cumvolume, 5, percent),20)=0,1,0),0), Normalised);
{Support Level Calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Orchid]
valuewhen(1,if(barnumber>dataset, if(troughbars(1,zigzag(cumvolume, 5, percent),20)=0,1,0),0), Normalised);
Except for new listings which go on to trend strongly and consistently for most shares a histogram of the incidence of price levels, ranked in order of their incidence, will be skewed with a long tail of prices which occur infrequently and a number of bands with the more frequent price levels (approximately Weibull).
Other support and resistance indicators employ an exponential moving average to calculate the current representative support and resistance price levels. Those available in the Bullchart library use 280 bars as a basis, the most recent three peaks and troughs of the zigzag function and a 25 bar exponential moving average as standard.
I advocate that this proposed statistical method is a more accurate hypothetical model than a support and resistance formulation using an exponential moving average as a basis because it calculates the most statistically probable price levels but decays the significance of historical prices with a time weighted average. This formulation employs significant volume spikes or changes in cumulative volume to determine the timing in changes of support and resistance levels. Over the last few months I have found this method to be more responsive than an EMA support or resistance indicator.
Some purists may criticise this formulation for a number of reasons including;
a) either method of calculating the timing of changing between indicator support or resistance price levels involves an element of subjectivity (the sensitivity of the zigzag function), and;
b) the subjectivity of deciding the incidence cutoff between the long tail of improbable price level bands and the higher probability bands, and;
c) throughout this indicator the support and resistance levels displayed change when additional data is received, the support and resistance levels calculated for the next bar are, at least, infinitesimally different from that calculated for the current bar.
Unfortunately the Achilles heel of this indicator is that while Bullcharts can calculate it, it takes a long time to evaluate the Bullchart’s standard lowest and highest (LLV and HHV) functions. The time taken is heavily dependent on the number of bars, WHA is quick but 30 years of BHP is slow (15 minutes or more). I recently brought a fairly modern Windows 10 Professional computer and I have not thought of a way to expedite this indicator because I will not be able to markedly improve the computer’s clock speed of 4.2GHz in the near future.
The limits on number of parameters and memory size of a Metastock exploration are such that I have not thought of a way that this could be readily done in Metastock. I would appreciate it if anyone can inform me of a software which has a statistical method such as this formulated successfully.
Having written this indicator I have subsequently tried to find an academic basis for what I believe is elementary statistics. I assert that with the exception of the Weis/Wyckoff treatment of cumulative volume I wrote this Bullcharts indicator independently. Googling the terms “support resist probab statist” returns a number of academic articles on memory effect including those by Garzarelli et al and De Angelis et al but I did not find anything as pragmatic as that below. In part due to the speed of the Bullchart’s lowest and highest functions and the Metastock exploration number of parameters and memory size issues I infer that this statistical method is not readily available.
I first discussed with Bullsystems the response duration of the Lowest and Highest functions in early October and I believe we are agreed that this is an issue with these standard Bullcharts functions. If you are interested please take the time to explore the potential of the indicator below. As a workaround I have split this indicator into two parts. The first part can still take around five minutes to display the representative period (number of bars for analysis) and the corresponding minimum and maximum prices. I then manually enter these three numbers for the second part to calculate the time weighted average and display the support and resistance level indicators. Ultimately my objective is to find a way to automate calculation of this indicator and display it in under 60 seconds without human interference.
I seek your support and ask that you trial this indicator in Bullcharts, if you have a licence, as I would appreciate confirmation as to whether anyone else obtains faster results with a different operating system. Further if anyone is interested I would appreciate feedback from anyone who successfully codes it in a different software (eg AmiBroker or NinjaTrader or ?).
I accept no responsibility nor liability for any use of this indicator, in particular, noting the concerns above and its response time.
{************************************************************************The indicator below, down to the next line of asterisks, should be saved in Custom Indicators as “S&R Representative min max price” or similar. When inserted in a chart it should display two numbers in the top and bottom right corners of the Price chart by default }
{Determine repesentative minimum and maximum price of current data}
ScopeMax:= lastvalue(highestbars(C,min(lastvalue(barnumber)-2,1300)));
ScopeMin:= lastvalue(lowestbars(C,min(lastvalue(barnumber)-2,1300)));
range:= if(lastvalue(barnumber)>1300, lastvalue(highest(c,1300)-lowest(c,1300)), lastvalue(highest(c,75)-lowest(c,75)));
mean:= if(lastvalue(barnumber)>1300, if(range=0, 0, abs(((0.5*(lastvalue(highest(c,1300)+lowest(c,1300))))-lastvalue(ma(C,1300)))/range)),
abs(((0.5*(lastvalue(highest(c,75)+lowest(c,75))))-lastvalue(ma(C,75)))/range));
infinity:= if(ScopeMax+ScopeMin>2250, 1300, 100+1200*htan((ScopeMax+ScopeMin)/40));
scope:= int(if(lastvalue(barssince(ma(V,10,s)=0))>0,min(1300,min(
infinity + (0.5*mean*(min(1300,lastvalue(barssince(ma(V,10,s)=0)))-infinity)),lastvalue(barssince(ma(V,10,s)=0)))),
infinity + (0.5*mean*(1300-infinity)) ));
timescale:= lastvalue(barnumber);
dataset:= if(timescale>scope+1,timescale-scope,1);
CDS:= valuewhen(1,if(barnumber>dataset,1,0),C);
closelo:= lastvalue(lowest(CDS,scope));
closehi:= lastvalue(highest(CDS,scope));
[linestyle=text; target=price; textalign=top,right]
if(barnumber=lastvalue(barnumber), closehi, undefined);
c;
[linestyle=text; target=price; textalign=bottom,right]
if(barnumber=lastvalue(barnumber), closelo, undefined);
c;
{***************this line is not required as Bullchart code************}
{The code above will display indicator lines but I hide them by making them the same colour as the background}
{************************************************************************The indicator below, down to the next line of asterisks, should be saved in Custom Indicators as “S&R Representative duration” or similar. When inserted in a chart it should display two numbers in the upper right corner of the Volume chart by default }
boxend:= lastvalue(barnumber);
[linestyle=text; target=volume; textalign=top, right]
if(barnumber=lastvalue(barnumber), boxend, undefined);
V;
{Determine repesentative set of current data}
ScopeMax:= lastvalue(highestbars(C,min(lastvalue(barnumber)-2,1300)));
ScopeMin:= lastvalue(lowestbars(C,min(lastvalue(barnumber)-2,1300)));
range:= if(lastvalue(barnumber)>1300, lastvalue(highest(c,1300)-lowest(c,1300)), lastvalue(highest(c,75)-lowest(c,75)));
mean:= if(lastvalue(barnumber)>1300, if(range=0, 0, abs(((0.5*(lastvalue(highest(c,1300)+lowest(c,1300))))-lastvalue(ma(C,1300)))/range)),
abs(((0.5*(lastvalue(highest(c,75)+lowest(c,75))))-lastvalue(ma(C,75)))/range));
infinity:= if(ScopeMax+ScopeMin>2250, 1300, 100+1200*htan((ScopeMax+ScopeMin)/40));
scope:= int(if(lastvalue(barssince(ma(V,10,s)=0))>0,min(1300,min(
infinity + (0.5*mean*(min(1300,lastvalue(barssince(ma(V,10,s)=0)))-infinity)),lastvalue(barssince(ma(V,10,s)=0)))),
infinity + (0.5*mean*(1300-infinity)) ));
[linestyle=text; target=volume; textalign=top, left]
if(barnumber=lastvalue(barnumber), scope, undefined);
V;
{***************this line is not required as Bullchart code************}
{************************************************************************The indicator below should be saved in Custom Indicators as “S&R Manual” or similar. When inserted in a chart it should display support and resistance levels on the price chart by default }
{Determine repesentative set of current data}
ScopeMax:= if(lastvalue(barnumber)<520,lastvalue(barnumber),lastvalue(highestbars(C,1300)));
ScopeMin:= if(lastvalue(barnumber)<520,lastvalue(barnumber),lastvalue(lowestbars(C,1300)));
mean:= 0.5*(highest(C,if(barnumber<1300,barnumber,1300))+lowest(C,if(barnumber<1300,barnumber,1300)));
average:= abs(ma(C,1300,s)-mean)/mean;
infinity:= if(ScopeMax+ScopeMin>2250, 1300, 100+1200*htan((ScopeMax+ScopeMin)/40));
scope:= input("Enter the analysis PERIOD");
timescale:= lastvalue(barnumber);
dataset:= if(timescale>scope+1,timescale-scope,1);
CDS:= valuewhen(1,if(barnumber>dataset,1,0),C);
VDS:= valuewhen(1,if(barnumber>dataset,1,0),V);
cutoff:=0.02;
{Significant Volume Peaks}
oracle:= if(C>hist(C,1), VDS/ma(VDS,40,e), if(c<hist(c,1), -1*VDS/ma(VDS,40,e), 0));
verticalrise:= lastvalue(cum(oracle));
factored:= cum(oracle) - (barnumber*verticalrise/timescale);
ScaleMin:= lastvalue(lowest(factored));
ScaleMax:= lastvalue(highest(factored));
sensitivity:= abs(ScaleMax - ScaleMin)/25;
{Significant Cumulative Volume changes}
[citation="Weis / Wyckoff"]
priceapprox:=zigzag(If(Outside() AND Ref(H,-1)>Ref(H,-2),H,If(Outside() AND Ref(L,-1)<Ref(L,-2),L,If((Outside() OR Inside()) AND C>O,H,If((Outside() OR Inside()) AND O>C,L,If(H>Ref(H,-1),H,If(L<Ref(L,-1),L,If(Ref(H,-1)>Ref(H,-2),H,If(Ref(L,-1)<Ref(L,-2),L,C)))))))), lastvalue((100*atr(14)/c)+0.8*abs(highest(c,100)-lowest(c,100))/3.00) ,%);
posivolume:= if(priceapprox>hist(priceapprox,1), previous+v, 0);
negivolume:= if(priceapprox<hist(priceapprox,1), previous-v, 0);
cumvolume:= posivolume+negivolume;
temphi:= input("Enter the MAXIMUM price");
templo:= input("Enter the MINIMUM price");
closelo:= min(templo, temphi);
gap:= abs(temphi - templo);
Band00:= sum(if(CDS>=closelo+(0.00*gap),if(CDS<closelo+(0.04*gap), CDS*(barnumber-scope),0), 0));
Band01:= sum(if(CDS>=closelo+(0.04*gap),if(CDS<closelo+(0.08*gap), CDS*(barnumber-scope),0), 0));
Band02:= sum(if(CDS>=closelo+(0.08*gap),if(CDS<closelo+(0.12*gap), CDS*(barnumber-scope),0), 0));
Band03:= sum(if(CDS>=closelo+(0.12*gap),if(CDS<closelo+(0.16*gap), CDS*(barnumber-scope),0), 0));
Band04:= sum(if(CDS>=closelo+(0.16*gap),if(CDS<closelo+(0.20*gap), CDS*(barnumber-scope),0), 0));
Band05:= sum(if(CDS>=closelo+(0.20*gap),if(CDS<closelo+(0.24*gap), CDS*(barnumber-scope),0), 0));
Band06:= sum(if(CDS>=closelo+(0.24*gap),if(CDS<closelo+(0.28*gap), CDS*(barnumber-scope),0), 0));
Band07:= sum(if(CDS>=closelo+(0.28*gap),if(CDS<closelo+(0.32*gap), CDS*(barnumber-scope),0), 0));
Band08:= sum(if(CDS>=closelo+(0.32*gap),if(CDS<closelo+(0.36*gap), CDS*(barnumber-scope),0), 0));
Band09:= sum(if(CDS>=closelo+(0.36*gap),if(CDS<closelo+(0.40*gap), CDS*(barnumber-scope),0), 0));
Band10:= sum(if(CDS>=closelo+(0.40*gap),if(CDS<closelo+(0.44*gap), CDS*(barnumber-scope),0), 0));
Band11:= sum(if(CDS>=closelo+(0.44*gap),if(CDS<closelo+(0.48*gap), CDS*(barnumber-scope),0), 0));
Band12:= sum(if(CDS>=closelo+(0.48*gap),if(CDS<closelo+(0.52*gap), CDS*(barnumber-scope),0), 0));
Band13:= sum(if(CDS>=closelo+(0.52*gap),if(CDS<closelo+(0.56*gap), CDS*(barnumber-scope),0), 0));
Band14:= sum(if(CDS>=closelo+(0.56*gap),if(CDS<closelo+(0.60*gap), CDS*(barnumber-scope),0), 0));
Band15:= sum(if(CDS>=closelo+(0.60*gap),if(CDS<closelo+(0.64*gap), CDS*(barnumber-scope),0), 0));
Band16:= sum(if(CDS>=closelo+(0.64*gap),if(CDS<closelo+(0.68*gap), CDS*(barnumber-scope),0), 0));
Band17:= sum(if(CDS>=closelo+(0.68*gap),if(CDS<closelo+(0.72*gap), CDS*(barnumber-scope),0), 0));
Band18:= sum(if(CDS>=closelo+(0.72*gap),if(CDS<closelo+(0.76*gap), CDS*(barnumber-scope),0), 0));
Band19:= sum(if(CDS>=closelo+(0.76*gap),if(CDS<closelo+(0.80*gap), CDS*(barnumber-scope),0), 0));
Band20:= sum(if(CDS>=closelo+(0.80*gap),if(CDS<closelo+(0.84*gap), CDS*(barnumber-scope),0), 0));
Band21:= sum(if(CDS>=closelo+(0.84*gap),if(CDS<closelo+(0.88*gap), CDS*(barnumber-scope),0), 0));
Band22:= sum(if(CDS>=closelo+(0.88*gap),if(CDS<closelo+(0.92*gap), CDS*(barnumber-scope),0), 0));
Band23:= sum(if(CDS>=closelo+(0.92*gap),if(CDS<closelo+(0.96*gap), CDS*(barnumber-scope),0), 0));
Band24:= sum(if(CDS>=closelo+(0.96*gap),if(CDS<closelo+(1.00*gap), CDS*(barnumber-scope),0), 0));
Count00:= sum(if(CDS>=closelo+(0.00*gap),if(CDS<closelo+(0.04*gap), barnumber-scope,0), 0));
Count01:= sum(if(CDS>=closelo+(0.04*gap),if(CDS<closelo+(0.08*gap), barnumber-scope,0), 0));
Count02:= sum(if(CDS>=closelo+(0.08*gap),if(CDS<closelo+(0.12*gap), barnumber-scope,0), 0));
Count03:= sum(if(CDS>=closelo+(0.12*gap),if(CDS<closelo+(0.16*gap), barnumber-scope,0), 0));
Count04:= sum(if(CDS>=closelo+(0.16*gap),if(CDS<closelo+(0.20*gap), barnumber-scope,0), 0));
Count05:= sum(if(CDS>=closelo+(0.20*gap),if(CDS<closelo+(0.24*gap), barnumber-scope,0), 0));
Count06:= sum(if(CDS>=closelo+(0.24*gap),if(CDS<closelo+(0.28*gap), barnumber-scope,0), 0));
Count07:= sum(if(CDS>=closelo+(0.28*gap),if(CDS<closelo+(0.32*gap), barnumber-scope,0), 0));
Count08:= sum(if(CDS>=closelo+(0.32*gap),if(CDS<closelo+(0.36*gap), barnumber-scope,0), 0));
Count09:= sum(if(CDS>=closelo+(0.36*gap),if(CDS<closelo+(0.40*gap), barnumber-scope,0), 0));
Count10:= sum(if(CDS>=closelo+(0.40*gap),if(CDS<closelo+(0.44*gap), barnumber-scope,0), 0));
Count11:= sum(if(CDS>=closelo+(0.44*gap),if(CDS<closelo+(0.48*gap), barnumber-scope,0), 0));
Count12:= sum(if(CDS>=closelo+(0.48*gap),if(CDS<closelo+(0.52*gap), barnumber-scope,0), 0));
Count13:= sum(if(CDS>=closelo+(0.52*gap),if(CDS<closelo+(0.56*gap), barnumber-scope,0), 0));
Count14:= sum(if(CDS>=closelo+(0.56*gap),if(CDS<closelo+(0.60*gap), barnumber-scope,0), 0));
Count15:= sum(if(CDS>=closelo+(0.60*gap),if(CDS<closelo+(0.64*gap), barnumber-scope,0), 0));
Count16:= sum(if(CDS>=closelo+(0.64*gap),if(CDS<closelo+(0.68*gap), barnumber-scope,0), 0));
Count17:= sum(if(CDS>=closelo+(0.68*gap),if(CDS<closelo+(0.72*gap), barnumber-scope,0), 0));
Count18:= sum(if(CDS>=closelo+(0.72*gap),if(CDS<closelo+(0.76*gap), barnumber-scope,0), 0));
Count19:= sum(if(CDS>=closelo+(0.76*gap),if(CDS<closelo+(0.80*gap), barnumber-scope,0), 0));
Count20:= sum(if(CDS>=closelo+(0.80*gap),if(CDS<closelo+(0.84*gap), barnumber-scope,0), 0));
Count21:= sum(if(CDS>=closelo+(0.84*gap),if(CDS<closelo+(0.88*gap), barnumber-scope,0), 0));
Count22:= sum(if(CDS>=closelo+(0.88*gap),if(CDS<closelo+(0.92*gap), barnumber-scope,0), 0));
Count23:= sum(if(CDS>=closelo+(0.92*gap),if(CDS<closelo+(0.96*gap), barnumber-scope,0), 0));
Count24:= sum(if(CDS>=closelo+(0.96*gap),if(CDS<closelo+(1.00*gap), barnumber-scope,0), 0));
total:= lastvalue(Count00 + Count01 + Count02 + Count03 + Count04 + Count05 + Count06 + Count07 + Count08 + Count09 +
Count10 + Count11 + Count12 + Count13 + Count14 + Count15 + Count16 + Count17 + Count18 + Count19 +
Count20 + Count21 + Count22 + Count23 + Count24);
PriceLevel:= max(
if(Count00>hist(Count00,1), if(lastvalue(Count00)/total<cutoff, 0, lastvalue(Band00)/lastvalue(Count00)), 0),
if(Count01>hist(Count01,1), if(lastvalue(Count01)/total<cutoff, 0, lastvalue(Band01)/lastvalue(Count01)), 0),
if(Count02>hist(Count02,1), if(lastvalue(Count02)/total<cutoff, 0, lastvalue(Band02)/lastvalue(Count02)), 0),
if(Count03>hist(Count03,1), if(lastvalue(Count03)/total<cutoff, 0, lastvalue(Band03)/lastvalue(Count03)), 0),
if(Count04>hist(Count04,1), if(lastvalue(Count04)/total<cutoff, 0, lastvalue(Band04)/lastvalue(Count04)), 0),
if(Count05>hist(Count05,1), if(lastvalue(Count05)/total<cutoff, 0, lastvalue(Band05)/lastvalue(Count05)), 0),
if(Count06>hist(Count06,1), if(lastvalue(Count06)/total<cutoff, 0, lastvalue(Band06)/lastvalue(Count06)), 0),
if(Count07>hist(Count07,1), if(lastvalue(Count07)/total<cutoff, 0, lastvalue(Band07)/lastvalue(Count07)), 0),
if(Count08>hist(Count08,1), if(lastvalue(Count08)/total<cutoff, 0, lastvalue(Band08)/lastvalue(Count08)), 0),
if(Count09>hist(Count09,1), if(lastvalue(Count09)/total<cutoff, 0, lastvalue(Band09)/lastvalue(Count09)), 0),
if(Count10>hist(Count10,1), if(lastvalue(Count10)/total<cutoff, 0, lastvalue(Band10)/lastvalue(Count10)), 0),
if(Count11>hist(Count11,1), if(lastvalue(Count11)/total<cutoff, 0, lastvalue(Band11)/lastvalue(Count11)), 0),
if(Count12>hist(Count12,1), if(lastvalue(Count12)/total<cutoff, 0, lastvalue(Band12)/lastvalue(Count12)), 0),
if(Count13>hist(Count13,1), if(lastvalue(Count13)/total<cutoff, 0, lastvalue(Band13)/lastvalue(Count13)), 0),
if(Count14>hist(Count14,1), if(lastvalue(Count14)/total<cutoff, 0, lastvalue(Band14)/lastvalue(Count14)), 0),
if(Count15>hist(Count15,1), if(lastvalue(Count15)/total<cutoff, 0, lastvalue(Band15)/lastvalue(Count15)), 0),
if(Count16>hist(Count16,1), if(lastvalue(Count16)/total<cutoff, 0, lastvalue(Band16)/lastvalue(Count16)), 0),
if(Count17>hist(Count17,1), if(lastvalue(Count17)/total<cutoff, 0, lastvalue(Band17)/lastvalue(Count17)), 0),
if(Count18>hist(Count18,1), if(lastvalue(Count18)/total<cutoff, 0, lastvalue(Band18)/lastvalue(Count18)), 0),
if(Count19>hist(Count19,1), if(lastvalue(Count19)/total<cutoff, 0, lastvalue(Band19)/lastvalue(Count19)), 0),
if(Count20>hist(Count20,1), if(lastvalue(Count20)/total<cutoff, 0, lastvalue(Band20)/lastvalue(Count20)), 0),
if(Count21>hist(Count21,1), if(lastvalue(Count21)/total<cutoff, 0, lastvalue(Band21)/lastvalue(Count21)), 0),
if(Count22>hist(Count22,1), if(lastvalue(Count22)/total<cutoff, 0, lastvalue(Band22)/lastvalue(Count22)), 0),
if(Count23>hist(Count23,1), if(lastvalue(Count23)/total<cutoff, 0, lastvalue(Band23)/lastvalue(Count23)), 0),
if(Count24>hist(Count24,1), if(lastvalue(Count24)/total<cutoff, 0, lastvalue(Band24)/lastvalue(Count24)), 0));
interim:=if(PriceLevel=0,1,0);
Normalised:= if(interim=1, previous + PriceLevel, PriceLevel);
{Resistance Level calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Red]
valuewhen(1,if(barnumber>dataset, if(peakbars(1,zigzag(factored,sensitivity,points),20)=0,1,0),0), Normalised);
{Support Level Calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Dark Green]
valuewhen(1,if(barnumber>dataset, if(troughbars(1,zigzag(factored,sensitivity,points),20)=0,1,0),0), Normalised);
{Resistance Level calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Orange]
valuewhen(1,if(barnumber>dataset, if(peakbars(1,zigzag(cumvolume, 5, percent),20)=0,1,0),0), Normalised);
{Support Level Calculation}
[target=price; width=2; linestyle=dash; transparency=75; color=Orchid]
valuewhen(1,if(barnumber>dataset, if(troughbars(1,zigzag(cumvolume, 5, percent),20)=0,1,0),0), Normalised);