Overall Statistics
namespace QuantConnect.Algorithm.CSharp
{
    public class DynamicMultidimensionalReplicator : QCAlgorithm
    {

		private AdaptiveFilter _adf;
		
        public override void Initialize()
        {
            SetStartDate(2018, 8, 18);  //Set Start Date
            SetCash(100000);             //Set Strategy Cash
            
            AddForex("EURUSD", Resolution.Daily);
            
            _adf = new AdaptiveFilter(10);


        }

        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// Slice object keyed by symbol containing the stock data
        public override void OnData(Slice data)
        {
            // if (!Portfolio.Invested)
            // {
            //    SetHoldings(_spy, 1);
            //    Debug("Purchased Stock");
            //}
            
            var bar = data["EURUSD"];
            
            if (bar == null)
            	return;
            
            _adf.Update(bar);
            Log($"Price: {bar.Close} :: ADF: {_adf}");
        }

    }
    
    public class AdaptiveFilter : BarIndicator, IIndicatorWarmUpPeriodProvider
    {
        
        private readonly double _k;
        private readonly int _period;
        
        /// <summary>
        /// Required period, in data points, for the indicator to be ready and fully initialized.
        /// </summary>
        public int WarmUpPeriod => _period;
             
        private  IBaseDataBar _previousInput;

       

        //+------------------------------------------------------------------+
        //| Custom indicator default constructor. DO NOT REMOVE              |
        //+------------------------------------------------------------------+

        

        /// <summary>
        ///Initializes a new instance of the  Adaptive Filter indicator using the specified name, period and smoothing factor
        /// </summary>
        /// <param name="name">The name of this indicator</param>
        /// <param name="period">Number of bars</param>
        /// <param name="smoothingFactor">NThe smoothing factor /param>
        public AdaptiveFilter(string name, int period, decimal smoothingFactor)
        : base("name")
        {

            _k = (double)smoothingFactor;
            _period = period;

        }

        /// <summary>
        ///Initializes a new instance of the  Adaptive Filter indicator using the specified name and  period 
        /// </summary>
        /// <param name="name">The name of this indicator</param>
        /// <param name="period">Number of bars</param>
        public AdaptiveFilter(string name, int period)
        : base("name")
        {

            _k = 1;
        }
            
        /// <summary>
        /// Initializes a new instance of the  Adaptive Filter indicator using the default name and specified period
        /// </summary>
        /// <param name="period">The smoothing period used to smooth the true range values</param>
        public AdaptiveFilter(int period)
        : this($"ADF({period})", period)
        {
        }
        
        
        /// <summary>
        /// Gets a flag indicating when this indicator is ready and fully initialized
        /// </summary>
        public override bool IsReady => _previousInput != null;

       

        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            if (!IsReady)
            {
                _previousInput = input;
                return 0m;
            }

            var _speed = 0m;
            var iValue = (input.High + input.Low + 2 * input.Close) / 4;

        
            var _value = (_previousInput.High + _previousInput.Low + 2 * _previousInput.Close) / 4;
            
            var _delta = iValue -_value;
            var _error = _value + (_delta * (decimal)Math.Sqrt(_k / 100));
            _speed +=  _delta * (decimal)_k / 100;
            _value = _error + _speed;

            _previousInput = input;
            
            return _value;
        }
        /// <summary>
        /// Resets this indicator to its initial state
        /// </summary>
        public override void Reset()
        {
            _previousInput = null;
            base.Reset();
        }
    }
}