Dennis, I was forced towards programming a DLL because I had a critical algorithm that required a triple nested loop structure. I tried is as an array structure in AFL (it is possible) and as a loop structure in AFL. In the end I moved towards a C++ DLL and I don't recall the precise speed enhancement, but it was very significant. If I say it was greater than x20 faster I am guessing, but it was of a similar order.
You an develop a DLL easily with the right structure surrounding it. TJ has made that as easy as possible. You can download a free C++ compiler. E-mail directly if you want some pointers. --- In [email protected], Dennis Brown <se...@...> wrote: > > Hello, > > I spent a good deal of effort creating a very useful smooth moving average > filter that was also fast. It is based on the John Ehlers Adaptive Laguerre > Filter. I started with some code from "Mich" in the AB library a couple of > years ago. > > http://www.amibroker.com/library/detail.php?id=772&hilite=PLOT > > The general problem with this adaptive filter is that is uses a loop within a > loop for each bar. The time to execute is the number of bars times the > look-back period. This made long periods impractically slow. > > I came up with a feedback method that worked well in a single loop. The > speed became a normal linear function of the number of bars to process. > > This filter is excellent for de-trending. It is also very smooth. I use it > as the basis of many indicators. I would not trade without it. Because the > Periods input to the function can also be an array, it can be further adapted > with inputs like volume. This makes some indicators even better. > > However, since I use it so often I would like it to run even faster. There > are two different ways that could happen: > > 1. Convert the algorithm to run with array operations instead of a loop. I > don't know how to do that with this algorithm. Perhaps someone with more > experience with doing everything in arrays can look at this code and render > an opinion on if it can be done (or even post the method). > > 2. Convert the inner loop of the algorithm into a DLL plugin. The guts of > the loop is fairly straight forward and should not be hard to code in C++, > but it is beyond my current level of development expertise. It would take me > some time to do that myself. I am also in the process of converting to 64 > bit W7. > > In any case, I am posting the AFL code for my prized filter for all to use. > Hopefully someone will improve it with one of the above means and share it > with me. > > Best regards, > Dennis > > //================================================================ > //AdaptiveLaGuerre function Last Updated 8/5/2010 by Dennis Brown > //================================================================ > // Smooth Adaptive Moving Average Filter, by Dennis Brown 9/6/2007 > // Laguerre Filter section, by John Ehlers > // Adaptive coeficient filter algorithm, by Dennis Brown > // This adaptive filter runs orders of magnitudes faster than the original > Ehlers version. > // The speed of the original slowed geometrically by the feedback lookback > bars. > // There is no looking back in this version, so speed is linear to number > of bars. > // > // decay is the decay time for historical error feedback significance --99 is > a good starting number > // smooth is smoothing factor of the error feedback signal --0.8 is a good > starting number > // gain is a number (or array for additional adaptive inputs) that sets the > base filtering --1 is a good number > // Periods is an array of periods for the filter that is translated to a gain > array. > //================================================================ > > function ALF( array, decay, smooth, gain ) > { > global g_FirstBar, g_LastBar; // global bar range to apply all loops > due to lack of full control over SBR > lastResult = lastL0 = lastL1 = lastL2 = lastL3 = array[g_FirstBar]; > lastErrorFactor = 0.5; > HH = 0.1; > LL = 0; > > for ( i = g_FirstBar; i <= g_LastBar; i++ ) > { > //following error > error = abs( array[i] - lastResult ); > //recent highest error (decays over time) > if ( error > HH ) { HH = error; } > else { HH *= decay; } > //recent lowest error (decays over time) > if ( error < LL ) { LL = error; } > else { LL *= decay; } > //get ema of error position in range of error > if ( HH != LL ) { errorFactor = smooth * lastErrorFactor + (1 - > smooth) * ((error - LL) / (HH - LL)); } > else { errorFactor = 1; } // for x/0 case > lastErrorFactor = errorFactor ; > // LaGuerre Filter > G = errorFactor * gain[i]; > L0 = G * array[i] + (1 - G) * lastL0; > L1 = -(1 - G) * L0 + lastL0 + (1 - G) * lastL1; > lastL0 = L0; > L2 = -(1 - G) * L1 + lastL1 + (1 - G) * lastL2; > lastL1 = L1; > L3 = -(1 - G) * L2 + lastL2 + (1 - G) * lastL3; > lastL2 = L2; > lastL3 = L3; > result[i] = lastResult = (L0 + 2 * L1 + 2 * L2 + L3) / 6; > } > return result; > } > > function ALFilter( PriceArray, Periods ) > { > gain = (1 / ((Periods / 2) ^.6666) + 2 / (Periods / 2)) / 2; // > translate Periods to the non-linear gain term > decay = 0.99; // error decay factor > smooth = 0.8; // error smoothing factor > return ALF( PriceArray, decay, smooth, gain ); > } >
