// Optimal Tracking Filter published by John Ehlers // Based on a Kalman Filter (Dr. R. E. Kalman, 1960) // and Kalatas Tracking Index (Paul. R. Kalata, 1984) function OptimalTrackingSeries( Period: integer ): integer; begin var Bar: integer; var sName: string; var Value: float; var opttrack: integer; // Series //var period: integer; // EMA period var lambda, alpha: float; var value1, value2, value3: float; var smooth_constant, smooth_constant1: float; var value1_old, value2_old, value3_old: float; var Start: integer; sName := 'OptimalTracking(' + IntToStr( Period ) +')'; Result := FindNamedSeries( sName ); if Result >= 0 then Exit; opttrack := CreateNamedSeries( sName ); // Init local variables //period:= 4; // should be >= 4, not much influence on result lambda := 0; alpha := 0; Start := 1; // we look back one bar value1_old := 0; value2_old := 0; value3_old := PriceAverage(Start-1); // EMA coefficients smooth_constant1 := Exp(-1.0 / period); // Time constant smooth_constant := 1.0 - smooth_constant1; for Bar := Start to BarCount -1 do begin // EMA of maneuverability uncertainty (bar to bar variation of #Average) value1 := smooth_constant * (PriceAverage(Bar) - PriceAverage(Bar-1)) + smooth_constant1 * Value1_old; value1_old := value1; // EMA of Measurement uncertainty (high-low Range) value2 := smooth_constant * ((PriceHigh(Bar) - PriceLow(Bar)) / 2.0) + smooth_constant1 * value2_old; value2_old := value2; // Tracking Index if value2 <> 0 then lambda := abs(value1 / value2); // alpha for alpha filter alpha := ( -lambda * lambda + Sqrt(lambda*lambda*lambda*lambda + 16*lambda*lambda)) / 8.0; value3 := alpha * PriceAverage(Bar) + (1.0 - alpha) * value3_old; value3_old := value3; SetSeriesValue(Bar, opttrack, value3); end; Result := opttrack; end; function OptimalTracking( Bar, Period: integer ): float; begin Result := GetSeriesValue( Bar, OptimalTrackingSeries( Period ) ); end;