← Назад

ADX, DiPlus, DiMinus

Обнаружил, что способ расчета DiPlus, DiMinus и, как следствие, ADX, не совпадает с описываемым тут а также со значениями из как минимум 2 программ теханализа (WLD, AlfaDirect). После моего фикса считает правильно.

Единственным исправлением было использование параметров по умолчанию у AverageTrueRange при расчете DiPart. (+удаление неиспользуемого DmTrueRange) Было:

protected DiPart()
{
    _averageTrueRange = new AverageTrueRange(new ExponentialMovingAverage(), new DmTrueRange());
    _movingAverage = new WilderMovingAverage();
}

Стало:

protected DiPart()
{
    _averageTrueRange = new AverageTrueRange();
    _movingAverage = new WilderMovingAverage();
}

в связи с чем у меня вопрос: Это вообще баг или расчет +-DI/ADX намеренно выполняется с использованием нестандартных параметров? Если это не баг, то каким образом коммитить фикс? Как отдельный индикатор?

Комментарии (1)

Вход или Создать аккаунт, Войдите или зарегистрируйтесь, чтобы оставить комментарий

OvcharenkoVI
OvcharenkoVI

Мне самому нужна была формула для ADX, когда искал - нашел кучу вариаций, после чего написал в тех поддержку Альфы, они прислали мне код, правда он был не на C#, но смысл я понял.

Прикладываю класс индюка DiPart. Реализован не через Length indicator, а просто как класс. Полностью совпадает с альфой.

Получить Di+ можно свойством Dlpp, Di- свойством Dlmm.

Методом Process Добавляем готовую свечку(не через CandleIndicatorValue, а просто candle),

Также добавлен метод UpDate, чтобы индюк мог меняться внутри свечи(также добавляем туда candle). Также считает верно.

[h]public class ADX
    {
        public decimal Length;

        private decimal dH;

        private decimal dL;

        private decimal DXp;

        private decimal DXm;

        private decimal TR;

        private decimal TRPpast;

        private decimal Dlp;

        private decimal Dlm;

        public decimal Dlpp;

        public decimal DLmm;

        private Candle _prevCandle;

        private List<decimal> list = new List<decimal>(); 

        public void Process(Candle candle)
        {
            if(_prevCandle == null)
            {
                _prevCandle = candle;

                return;
            }

            dH = candle.HighPrice - _prevCandle.HighPrice;

            dL = _prevCandle.LowPrice - candle.LowPrice;

            DXp = dH > 0 ? dH : 0;

            DXm = dL > 0 ? dL : 0;

            if(DXp == DXm)
            {
                DXm = 0;
                DXp = 0;
            }
            else
            {
                if (DXp > DXm)
                    DXm = 0;

                if (DXm > DXp)
                    DXp = 0;
            }

            list.Add(Math.Abs(candle.HighPrice - candle.LowPrice));
            list.Add(Math.Abs(candle.HighPrice - _prevCandle.ClosePrice));
            list.Add(Math.Abs(candle.LowPrice - _prevCandle.ClosePrice));

            _prevCandle = candle;

            TR = list.Max();

            list.Clear();

            TR = TRPpast - TRPpast/Length + TR/Length;

            TRPpast = TR;

            if(TR == 0)
            {
                DXp = 0;
                DXm = 0;
                Dlp = Dlp - Dlp/Length + DXp/Length;
                Dlm = Dlm - Dlm/Length + DXm/Length;
            }
            else
            {
                Dlp = Dlp - Dlp/Length + DXp/Length;
                Dlm = Dlm - Dlm/Length + DXm/Length;
                Dlpp = Dlp/TR*100;
                DLmm = Dlm/TR*100;
            }
        }

        public void UpDate(Candle candle)
        {
            dH = candle.HighPrice - _prevCandle.HighPrice;

            dL = _prevCandle.LowPrice - candle.LowPrice;

            DXp = dH > 0 ? dH : 0;

            DXm = dL > 0 ? dL : 0;

            if (DXp == DXm)
            {
                DXm = 0;
                DXp = 0;
            }
            else
            {
                if (DXp > DXm)
                    DXm = 0;

                if (DXm > DXp)
                    DXp = 0;
            }

            list.Add(Math.Abs(candle.HighPrice - candle.LowPrice));
            list.Add(Math.Abs(candle.HighPrice - _prevCandle.ClosePrice));
            list.Add(Math.Abs(candle.LowPrice - _prevCandle.ClosePrice));

            TR = list.Max();

            list.Clear();

            TR = TRPpast - TRPpast / Length + TR / Length;

            if (TR == 0)
            {
                DXp = 0;
                DXm = 0;
                var dlp = Dlp - Dlp / Length + DXp / Length;
                var dlm = Dlm - Dlm / Length + DXm / Length;
            }
            else
            {
                var dlp = Dlp - Dlp / Length + DXp / Length;
                var dlm = Dlm - Dlm / Length + DXm / Length;
                Dlpp = dlp / TR * 100;
                DLmm = dlm / TR * 100;
            }
        }
[/h]
}
Кот Матроскин