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 ); }
