Example #1
0
        // AVERAGE DIRECTIONAL INDEX
        public static IEnumerable <AdxResult> GetAdx(IEnumerable <Quote> history, int lookbackPeriod = 14)
        {
            // clean quotes
            history = Cleaners.PrepareHistory(history);

            // check exceptions
            int qtyHistory = history.Count();
            int minHistory = 2 * lookbackPeriod + 1;

            if (qtyHistory < minHistory)
            {
                throw new BadHistoryException("Insufficient history provided for ADX.  " +
                                              string.Format("You provided {0} periods of history when {1} is required.  "
                                                            + "Since this uses a smoothing technique, "
                                                            + "we recommend you use at least 250 data points prior to the intended "
                                                            + "usage date for maximum precision.", qtyHistory, minHistory));
            }

            // initialize results and working variables
            IEnumerable <AtrResult> atrResults = GetAtr(history, lookbackPeriod); // uses True Range value
            List <AdxResult>        results    = new List <AdxResult>();

            decimal prevHigh = 0;
            decimal prevLow  = 0;
            decimal prevTrs  = 0; // smoothed
            decimal prevPdm  = 0;
            decimal prevMdm  = 0;
            decimal prevAdx  = 0;

            decimal sumTr  = 0;
            decimal sumPdm = 0;
            decimal sumMdm = 0;
            decimal sumDx  = 0;

            // roll through history
            foreach (Quote h in history)
            {
                AdxResult result = new AdxResult
                {
                    Index = (int)h.Index,
                    Date  = h.Date
                };

                // skip first period
                if (h.Index == 1)
                {
                    results.Add(result);
                    prevHigh = h.High;
                    prevLow  = h.Low;
                    continue;
                }

                decimal tr   = (decimal)atrResults.Where(x => x.Index == h.Index).FirstOrDefault().Tr;
                decimal pdm1 = (h.High - prevHigh) > (prevLow - h.Low) ? Math.Max(h.High - prevHigh, 0) : 0;
                decimal mdm1 = (prevLow - h.Low) > (h.High - prevHigh) ? Math.Max(prevLow - h.Low, 0) : 0;

                prevHigh = h.High;
                prevLow  = h.Low;

                // initialization period
                if (h.Index <= lookbackPeriod + 1)
                {
                    sumTr  += tr;
                    sumPdm += pdm1;
                    sumMdm += mdm1;
                }

                // skip DM initialization period
                if (h.Index <= lookbackPeriod)
                {
                    results.Add(result);
                    continue;
                }


                // smoothed true range and directional movement
                decimal trs;
                decimal pdm;
                decimal mdm;

                if (h.Index == lookbackPeriod + 1)
                {
                    trs = sumTr / lookbackPeriod;
                    pdm = sumPdm / lookbackPeriod;
                    mdm = sumMdm / lookbackPeriod;
                }
                else
                {
                    trs = prevTrs - (prevTrs / lookbackPeriod) + tr;
                    pdm = prevPdm - (prevPdm / lookbackPeriod) + pdm1;
                    mdm = prevMdm - (prevMdm / lookbackPeriod) + mdm1;
                }

                prevTrs = trs;
                prevPdm = pdm;
                prevMdm = mdm;


                // directional increments
                decimal pdi = 100 * pdm / trs;
                decimal mdi = 100 * mdm / trs;
                decimal dx  = 100 * Math.Abs(pdi - mdi) / (pdi + mdi);

                result.Pdi = pdi;
                result.Mdi = mdi;


                // calculate ADX
                decimal adx;

                if (h.Index > 2 * lookbackPeriod)
                {
                    adx        = (prevAdx * (lookbackPeriod - 1) + dx) / lookbackPeriod;
                    result.Adx = adx;
                    prevAdx    = adx;
                }

                // initial ADX
                else if (h.Index == 2 * lookbackPeriod)
                {
                    sumDx     += dx;
                    adx        = sumDx / lookbackPeriod;
                    result.Adx = adx;
                    prevAdx    = adx;
                }

                // ADX initialization period
                else
                {
                    sumDx += dx;
                }

                results.Add(result);
            }

            return(results);
        }
Example #2
0
        // AVERAGE DIRECTIONAL INDEX
        public static IEnumerable <AdxResult> GetAdx <TQuote>(
            IEnumerable <TQuote> history,
            int lookbackPeriod = 14)
            where TQuote : IQuote
        {
            // clean quotes
            List <TQuote> historyList = history.Sort();

            // verify parameters
            ValidateAdx(history, lookbackPeriod);

            // initialize results and working variables
            List <AdxResult> results    = new List <AdxResult>();
            List <AtrResult> atrResults = GetAtr(history, lookbackPeriod).ToList(); // uses True Range value

            decimal prevHigh = 0;
            decimal prevLow  = 0;
            decimal prevTrs  = 0; // smoothed
            decimal prevPdm  = 0;
            decimal prevMdm  = 0;
            decimal prevAdx  = 0;

            decimal sumTr  = 0;
            decimal sumPdm = 0;
            decimal sumMdm = 0;
            decimal sumDx  = 0;

            // roll through history
            for (int i = 0; i < historyList.Count; i++)
            {
                TQuote h     = historyList[i];
                int    index = i + 1;

                AdxResult result = new AdxResult
                {
                    Date = h.Date
                };

                // skip first period
                if (index == 1)
                {
                    results.Add(result);
                    prevHigh = h.High;
                    prevLow  = h.Low;
                    continue;
                }

                decimal tr   = (decimal)atrResults[i].Tr;
                decimal pdm1 = (h.High - prevHigh) > (prevLow - h.Low) ? Math.Max(h.High - prevHigh, 0) : 0;
                decimal mdm1 = (prevLow - h.Low) > (h.High - prevHigh) ? Math.Max(prevLow - h.Low, 0) : 0;

                prevHigh = h.High;
                prevLow  = h.Low;

                // initialization period
                if (index <= lookbackPeriod + 1)
                {
                    sumTr  += tr;
                    sumPdm += pdm1;
                    sumMdm += mdm1;
                }

                // skip DM initialization period
                if (index <= lookbackPeriod)
                {
                    results.Add(result);
                    continue;
                }


                // smoothed true range and directional movement
                decimal trs;
                decimal pdm;
                decimal mdm;

                if (index == lookbackPeriod + 1)
                {
                    trs = sumTr;
                    pdm = sumPdm;
                    mdm = sumMdm;
                }
                else
                {
                    trs = prevTrs - (prevTrs / lookbackPeriod) + tr;
                    pdm = prevPdm - (prevPdm / lookbackPeriod) + pdm1;
                    mdm = prevMdm - (prevMdm / lookbackPeriod) + mdm1;
                }

                prevTrs = trs;
                prevPdm = pdm;
                prevMdm = mdm;


                // directional increments
                decimal pdi = 100 * pdm / trs;
                decimal mdi = 100 * mdm / trs;
                decimal dx  = 100 * Math.Abs(pdi - mdi) / (pdi + mdi);

                result.Pdi = pdi;
                result.Mdi = mdi;


                // calculate ADX
                decimal adx;

                if (index > 2 * lookbackPeriod)
                {
                    adx        = (prevAdx * (lookbackPeriod - 1) + dx) / lookbackPeriod;
                    result.Adx = adx;
                    prevAdx    = adx;
                }

                // initial ADX
                else if (index == 2 * lookbackPeriod)
                {
                    sumDx     += dx;
                    adx        = sumDx / lookbackPeriod;
                    result.Adx = adx;
                    prevAdx    = adx;
                }

                // ADX initialization period
                else
                {
                    sumDx += dx;
                }

                results.Add(result);
            }

            return(results);
        }
Example #3
0
        // AVERAGE DIRECTIONAL INDEX
        public static IEnumerable <AdxResult> GetAdx(IEnumerable <Quote> history, int lookbackPeriod = 14)
        {
            // clean quotes
            history = Cleaners.PrepareHistory(history);

            // verify parameters
            ValidateAdx(history, lookbackPeriod);

            // initialize results and working variables
            IEnumerable <AtrResult> atrResults = GetAtr(history, lookbackPeriod); // uses True Range value
            List <AdxResult>        results    = new List <AdxResult>();

            decimal prevHigh = 0;
            decimal prevLow  = 0;
            decimal prevTrs  = 0; // smoothed
            decimal prevPdm  = 0;
            decimal prevMdm  = 0;
            decimal prevAdx  = 0;

            decimal sumTr  = 0;
            decimal sumPdm = 0;
            decimal sumMdm = 0;
            decimal sumDx  = 0;

            // roll through history
            foreach (Quote h in history)
            {
                AdxResult result = new AdxResult
                {
                    Index = (int)h.Index,
                    Date  = h.Date
                };

                // skip first period
                if (h.Index == 1)
                {
                    results.Add(result);
                    prevHigh = h.High;
                    prevLow  = h.Low;
                    continue;
                }

                decimal tr   = (decimal)atrResults.Where(x => x.Index == h.Index).FirstOrDefault().Tr;
                decimal pdm1 = (h.High - prevHigh) > (prevLow - h.Low) ? Math.Max(h.High - prevHigh, 0) : 0;
                decimal mdm1 = (prevLow - h.Low) > (h.High - prevHigh) ? Math.Max(prevLow - h.Low, 0) : 0;

                prevHigh = h.High;
                prevLow  = h.Low;

                // initialization period
                if (h.Index <= lookbackPeriod + 1)
                {
                    sumTr  += tr;
                    sumPdm += pdm1;
                    sumMdm += mdm1;
                }

                // skip DM initialization period
                if (h.Index <= lookbackPeriod)
                {
                    results.Add(result);
                    continue;
                }


                // smoothed true range and directional movement
                decimal trs;
                decimal pdm;
                decimal mdm;

                if (h.Index == lookbackPeriod + 1)
                {
                    trs = sumTr / lookbackPeriod;
                    pdm = sumPdm / lookbackPeriod;
                    mdm = sumMdm / lookbackPeriod;
                }
                else
                {
                    trs = prevTrs - (prevTrs / lookbackPeriod) + tr;
                    pdm = prevPdm - (prevPdm / lookbackPeriod) + pdm1;
                    mdm = prevMdm - (prevMdm / lookbackPeriod) + mdm1;
                }

                prevTrs = trs;
                prevPdm = pdm;
                prevMdm = mdm;


                // directional increments
                decimal pdi = 100 * pdm / trs;
                decimal mdi = 100 * mdm / trs;
                decimal dx  = 100 * Math.Abs(pdi - mdi) / (pdi + mdi);

                result.Pdi = pdi;
                result.Mdi = mdi;


                // calculate ADX
                decimal adx;

                if (h.Index > 2 * lookbackPeriod)
                {
                    adx        = (prevAdx * (lookbackPeriod - 1) + dx) / lookbackPeriod;
                    result.Adx = adx;
                    prevAdx    = adx;
                }

                // initial ADX
                else if (h.Index == 2 * lookbackPeriod)
                {
                    sumDx     += dx;
                    adx        = sumDx / lookbackPeriod;
                    result.Adx = adx;
                    prevAdx    = adx;
                }

                // ADX initialization period
                else
                {
                    sumDx += dx;
                }

                results.Add(result);
            }

            return(results);
        }