//======================================================================== // Ahrens Moving Average // // // // The Ahrens Moving Average is an IIR (Infinite Impulse Response), // // front-weighted moving average which can be used to filter time // // series data using a window as short as 2 periods. It provides // // superior smoothing and is less likely to be perturbed by transient // // spikes than either a simple moving average or a exponential moving // // average with the same smoothing period. // // // // This program is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // (at your option) any later version. // // // // This program is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with this program. If not, the full text of it can be found // // at http://www.gnu.org/licenses/gpl.html // //======================================================================== //------------------------------------------------------------------------ // This implementation was graciously provided by Java authority // // Michael Ernest. (Books by Michael are available on Amazon.COM) // //------------------------------------------------------------------------ package doc; import java.util.ArrayList; public class AhrensMovingAverage { public ArrayList ama(double[] icol, int period, int x_end) { ArrayList avg = new ArrayList<>(); int x_start = 0; //------------------------------------------------------- // the AMA may be used to smooth raw data or the output // of other calculations. since other calculations may // introduce significant phase lag there is no guarantee // that the input data will really start at the beginning // of the array passed to this function. this loop locates // the first actual datapoint in the input series. leading // zeros are assumed to be empty cells for (int a = 1; a < x_end; a++) { if (icol[a] != 0) { x_start = a; } } //------------------------------------------------------- // the first data point in a series may be (significantly) // divergent from the data that follows. this loop creates // a reasonably representative set of initial values to // seed the average. it uses an "expanding period" simple // moving average over the first N samples (where N equals // the period of the average) int count = 0; double total = 0; for (int a = x_start; a < x_start + period && a < x_end; a++) { count++; total += (double)icol[a]; avg.add(total / count); } //------------------------------------------------------- // once the seed values have been calculated, shift gears // and calculate the AMA for $x_start + $period through // $x_end for (int a = x_start + period; a <= x_end; a++) { double numerator = (double)icol[a] - (avg.get(a-1) + avg.get(a-period)/2); avg.set(a, avg.get(a-1) + numerator / period); } return avg; } }
Click link to download the above JAVA source code.