PureBytes Links
Trading Reference Links
|
Larry -
Good first attempt. I thought I'd tackle this for two reasons. First, you did a fair amount of work before asking. But, second, I had been about to write an article for a web site about array processing and happened upon your post. If you don't mind, I'd like to use a variation of it as an example for that. There are several great teaching points in the performance issue that you ran into.
There are two classes of issues in your AFL - an algorithm/math issue and a looping issue. Let's deal with the major one first.
As you might suspect the inner loop is the problem. If you assume approx. 400 x 1 minute bars per day, then on average for each bar, you will execute the inner (j) loop 200 times. This has to go !
Here's the original code for reference -
// now the hard part...calculate the variance... // a separate calc from the start of each day - note it requires the vwap from above // also note, we calculate starting at the first bar in the new day to today to the curent bar Variance = 0;
for ( j = newdayindex; j < i; j++ ) { AvgPrice = ( O[j] + H[j] + L[j] + C[j] ) / 4; Variance += ( Volume[j] / totVolume ) * ( Avgprice - Vwap2temp ) * ( Avgprice - Vwap2temp ); }
The way to get rid of it may not be what you expect, though. You are calculating a variance at each bar by restarting the calculation from the first bar of the day. At first glance, it probably appeared that this was required because of the volume weighting.
With some fairly straightforward algebraic manipulation, the formula can be converted into a "running" variance calculation. I'll just show the result, and you can work through it. Replace the code above with -
variance = ( prevvar * prevtotvol / totvolume ) + ( Volume[i] / totvolume ) * ( Avgprice - Vwap2temp ) * ( Avgprice - Vwap2temp );
prevtotvol = totvolume; prevvar = Variance;
Finally, to support this code, there are two areas of initialization. I did it this way to minimize changes to your original code. Insert the following code in two places -
prevtotvol = 0; prevvar = 0;
Put it once above the outer (i) loop before the for( i=0; i<Barcount; i++). Then, put it in the newday initialization found in the if ( newday[i] == True) block.
This should yield a improvement of over two orders of magnitude. Actually, a little more could be wrung out as you have a few calculations that could be streamlined. I didn't post the entire code, because the endgame is really an AFL with NO LOOPS that uses purely array processing. That will yield about an additional minimum 2x improvement at the smaller intervals (5000 bars) that you are probably using, but much greater as bars increase. As importantly, it is only 7 or 8 lines of code in total. I'll show you that next and later.
-- BruceR
--- In amibroker@xxxxxxxxxxxxxxx, "shakerlr" <ljr500@xxx> wrote: > > I just created the following code to calculate the VWAP + std deviation bands, but have found that it is extrememly slow. I posted the original code to the amibroker study site and was wondering if anyone has any suggestions to speed it up for display on 1 minute charts. > > Also, I noticed that if I DO NOT USE: > SetBarsRequired( 1000, 0 ); > > The bands show up incorrect...(sometimes expanding/shrinkking as I scroll on the 1 minute chart) > > Note that I have about 100000 bars in my stock/ticker being studied...so that may be the reason it is slow... > > ---- > /// VWAP code that also plots standard deviations...if you want a 3rd...it > should be fairly simple to add > // > // NOTE: the code is SLOOOOWWWW...can someone help speed it up? > // I tried my best, but can't really do much with the two for-loops... > // > // LarryJR > > > SetBarsRequired( 1000, 0 ); > > // this stores true/false based on a new day... > newday=Day() != Ref(Day(), -1); > > SumPriceVolume=0; > totVolume=0; > Vwap2=0; > stddev=0; > newdayindex=0; > Variance =0; > > // we must use a loop here because we need to save the vwap for each bar to > calc the variance later > for( i= 0; i < BarCount; i++ ) > { > // only want to reset our values at the start of a new day > if (newday[i]==True) > { > SumPriceVolume=0; > totVolume=0; > newdayindex=i; // this is the index at the start of a new day > Variance=0; > //Vwap2=0; > } > AvgPrice=(O[i] + H[i] + L[i] + C[i])/4; > > // Sum of Volume*price for each bar > sumPriceVolume += AvgPrice * (Volume[i]); > > // running total of volume each bar > totVolume += (Volume[i]); > > if (totVolume[i] >0) > { > Vwap2[i]=Sumpricevolume / totVolume ; > Vwap2temp=Vwap2[i]; > } > > // now the hard part...calculate the variance... > // a separate calc from the start of each day - note it requires the vwap from > above > // also note, we calculate starting at the first bar in the new day to today > to the curent bar > Variance=0; > for (j=newdayindex; j < i; j++) > { > AvgPrice=(O[j] + H[j] + L[j] + C[j])/4; > Variance += (Volume[j]/totVolume) * > (Avgprice-Vwap2temp)*(Avgprice-Vwap2temp); > } > stddev_1_pos[i]=Vwap2temp + sqrt(Variance); > stddev_1_neg[i]=Vwap2temp - sqrt(Variance); > > stddev_2_pos[i]=Vwap2temp + 2*sqrt(Variance); > stddev_2_neg[i]=Vwap2temp - 2*sqrt(Variance); > } > Plot (Vwap2,"VWAP2",colorDarkGrey, styleLine); > Plot (stddev_1_pos,"VWAP_std+1",colorGrey50, styleDashed); > Plot (stddev_1_neg,"VWAP_std-1",colorGrey50, styleDashed); > Plot (stddev_2_pos,"VWAP_std+2",colorGrey40, styleDashed); > Plot (stddev_2_neg,"VWAP_std-2",colorGrey40, styleDashed); >
__._,_.___
**** IMPORTANT PLEASE READ ****
This group is for the discussion between users only.
This is *NOT* technical support channel.
TO GET TECHNICAL SUPPORT send an e-mail directly to
SUPPORT {at} amibroker.com
TO SUBMIT SUGGESTIONS please use FEEDBACK CENTER at
http://www.amibroker.com/feedback/
(submissions sent via other channels won't be considered)
For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
http://www.amibroker.com/devlog/
__,_._,___
|