English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
preview
Индикатор CCI. Модернизация и новые возможности

Индикатор CCI. Модернизация и новые возможности

MetaTrader 5Примеры | 6 июля 2022, 08:56
1 687 3
Aleksej Poljakov
Aleksej Poljakov

Краткая история

Индикатор Индекс Товарного Канала (Commodity Channel Index) знаком каждому трейдеру. Его разработчик — Дональд Ламберт, впервые опубликовал статью об этом индикаторе в журнале Commodities (современное название – Modern Trader) в 1980 году. С тех пор этот индикатор сникал заслуженную славу, и стал весьма популярен среди трейдеров. Он входит в джентльменский набор торговой платформы MetaTrader и используется как при ручной торговле, так и в составе механических торговых систем.


Алгоритм расчета

Расчет этого индикатора довольно прост и нагляден. Индикатор показывает на сколько отклонилась цена от среднего значения по отношению к среднему абсолютному отклонению. Алгоритм расчета значений этого технического индикатора можно представить следующим образом. Пусть период индикатора составляет N отсчетов цены. Тогда:

  • Рассчитываем среднее значение 

mean

  • Находим среднее абсолютное отклонение

MAD

  • Рассчитываем значение индикатора

CCI

В оригинальном индикаторе значение поправочного коэффициента k = 0.015. Он подобран таким образом, чтобы отклонение цены на 1.5*MAD было равно 100 единицам индикатора. Тогда отклонение на 3*MAD равно 200 единицам. (Интересное наблюдение, если деление заменить на умножение, то значение нормирующего коэффициента k будет равно 66.6)


Возможные изменения алгоритма

Заметим одну особенность этого индикатора – использование среднего абсолютного отклонения. Такой подход был полностью оправдан на заре развития вычислительной техники. Так как расчет абсолютного отклонения требовал меньше затрат вычислительных ресурсов по сравнению с расчетом более целесообразного среднеквадратичного отклонения. Современные компьютеры могут справится с операциями возведения в квадрат и извлечения корня за вполне приемлемое время. Поэтому алгоритм вычисления значений индикатора может выглядеть следующим образом.

  • Находим сумму чисел:

sumS

  • Находим сумму квадратов:

sumQ

  • Вычисляем значение индикатора:

CCI

Такой алгоритм более точен в расчетах, но и он не является совершенным. Основная проблема заключается в том, что для оценки среднего и среднеквадратичного значений требуется достаточно большое количество отсчетов цены – не меньше тридцати. Но, для трейдинга могут использоваться и короткие периоды. Например, в классическом варианте CCI рекомендуется период в 14 отсчетов.

В таких ситуациях могут помочь робастные методы статистики. Они позволяют получить достаточно устойчивые и надежные оценки параметров, даже в очень экстремальных ситуациях, которыми так богат финансовый рынок.

 Давайте, рассмотрим, как работают робастные методы, и сравним их с классическими вариантами. Для примера возьмем временной ряд из трех значений: p[0] = 1, p[1] = 3, p[2] = 8.

Тогда классический подход сводится к следующим расчетам:

  • Среднее (1 + 3 + 8) / 3 = 4
  • Абсолютное отклонение (abs(1 – 4) + abs(3 – 4) + abs(8 – 4)) /3 = 2.67
  • Нижняя и верхняя границы канала 1.33 – 6.67 

Теперь, произведем расчет с использованием среднеквадратичного отклонения:

  • Среднее (1 + 3 + 8) / 3 = 4
  • Стандартное отклонение sqrt(((1 – 4)^2 + (3 – 4)^2 + (8 – 4)^2) / 3) = 2.94
  • Нижняя и верхняя границы канала 1.06 – 6.94

Робастные оценки более затратны в вычислениях. Для оценки среднего будем использовать метод Тейла – Сена. Для этого нужно сначала найти все полусуммы из попарно взятых значений временного ряда. Количество этих пар можно получить по формуле: num=(N*(N-1)) / 2.

И тогда устойчивое среднее будет равно медиане этих полусумм. Чтобы найти медиану нужно сначала отсортировать массив по возрастанию. Тогда медиана будет соответствовать значению, оказавшемуся в центре массива. Чтобы найти значение медианы нам потребуется индекс центрального элемента – если размер массива равен нечетному числу. Или двух центральных элементов – если размер массива четное число. Тогда медиана будет равна среднему значению от этих двух элементов.

Формулы для вычисления индексов в обеих случаях (size – число элементов в массиве):

  • size нечетное число

Index = size / 2

  • size четное число

Index1 = size / 2 – 1; Index2 = size / 2

Для нашего примера это будет выглядеть так:

hs1 = (1 + 3) / 2 = 2

hs2 = (1 + 8) / 2 = 4.5

hs3 = (3 + 8) / 2 = 5.5

сортировка 2, 4.5, 5.5

  • Среднее = 4.5

Теперь перейдем к оценке отклонения. Для этого нужно найти медиану между абсолютными значениями исходного временного ряда и его средней.

d1 = abs(1 – 4,5) = 3.5

d2 = abs(3 – 4,5) = 1.5

d3 = abs(8 – 4,5) = 3.5

сортировка 3.5, 1.5, 3.5

  • Отклонение = 3.5
  • Нижняя и верхняя границы канала 1 – 8


Сравнение классической и модернизированных версий индикатора

Самое время сравнить все эти подходы. При обычных расчетах минимальное и максимальное значения нашего временного ряда вышли за пределы среднее значение +/- отклонение. А при робастной оценке все значения исходного ряда укладываются в эти границы. Разница в трех подходах очевидна, но только на выдуманном нами примере. Теперь посмотрим, как поведут себя разные способы расчета на реальных данных. Реализуем все три алгоритма в виде отдельного индикатора. Заодно, познакомимся с особенностями расчета каждого варианта.

Внешний вид индикатора во многом зависит от двух переменных — используемой ценовой константы и его периода. В языке MQL5 ценовую константу можно задать при определении свойств индикатора.

#property indicator_applied_price PRICE_TYPICAL

А для версии языка MQL4 мы будем использовать отдельную функцию.

Период индикатора показывает количество отсчетов цены, которое используется при расчетах.

input ushort iPeriod=14;//период индикатора

Значение этой переменной должно быть не меньше трех. Вообще, нужно помнить, что при небольших периодах индикатора есть вероятность получить не совсем корректные — очень большие — значения.

Расчет классической версии CCI на каждом i-ом баре производится следующим образом. Сначала найдем значение выборочной средней.

double mean=0;                //выборочная средняя
for(int j=0; j<iPeriod; j++)
   {
    mean=mean+price[i+j];     //суммируем значения цены
   }
mean=mean/iPeriod;            //выборочная средняя за период

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

double mad=0;                          //среднее абсолютное отклонение
for(int j=0; j<iPeriod; j++)
   {
    mad=mad+MathAbs(price[i+j]-mean);  //суммируем абсолютные значения разностей
   }

Если значение среднего абсолютного отклонения будет больше ноля, то значение индикатора будет равно:

res=(price[i]-mean)*iPeriod/mad;

Вариант индикатора с использованием среднеквадратичного отклонения рассчитывается так. Сначала нужно найти суммы цен и их квадратов.

double sumS=0,//сумма цен
       sumQ=0;//сумма квадратов цен
for(int j=0; j<iPeriod; j++)
   {
    sumS=sumS+price[i+j];
    sumQ=sumQ+price[i+j]*price[i+j];
   }

Теперь нужно найти знаменатель, необходимый для расчета значения индикатора.

double denom=MathSqrt(iPeriod*sumQ-sumS*sumS);

Если значение знаменателя больше ноля, то результат будет равен:

res=(iPeriod*price[i]-sumS)/denom;

И, наконец, рассмотрим расчеты с помощью робастных методов. Сначала нам нужно подготовить два массива, в которых мы будем хранить значения промежуточных результатов. В одном массиве мы будем сохранять значения полусумм, а в другом — абсолютных разностей.

double halfsums[],diff[];

Сначала подготовим для дальнейшего использования массив halfsums. Для этого установим его размер.

int size=iPeriod*(iPeriod-1)/2; //размер массива halfsums
ArrayResize(halfsums,size);     //устанавливаем размер массива

Теперь найдем индексы центральных элементов массива. Для универсальности мы будем использовать два индекса. Если значение size нечетно, то эти индексы будут совпадать друг с другом, и отличаться в противном случае.

indx10=size/2;
indx11=indx10;
if(MathMod(size,2)==0)
   indx11=indx10-1;

После этого нужно подготовить массив diff. Его размер совпадает с периодом индикатора. А индексы элементов как и в предыдущем случае.

ArrayResize(diff,iPeriod);
indx20=iPeriod/2;
indx21=indx20;
if(MathMod(iPeriod,2)==0)
   indx21=indx20-1;

Теперь можно приступать к вычислению значений индикатора. Для заполнения массива с полусуммами нам потребуется дополнительный счетчик.

int cnt=0; //счетчик элементов массива
for(int j=iPeriod-2; j>=0; j--)
   {
    for(int k=iPeriod-1; k>j; k--)
       {
        halfsums[cnt]=(price[i+j]+price[i+k])/2; //значение полусуммы
        cnt++;                                   //увеличиваем счетчик
       }
   }

После заполнения массива его нужно отсортировать, а в качестве оценки среднего использовать значения из центра массива.

ArraySort(halfsums);                               //сортируем массив
double mean=(halfsums[indx10]+halfsums[indx11])/2; //робастное среднее

На следующем этапе найдем робастную оценку стандартного отклонения.

for(int j=0; j<iPeriod; j++)
   {
    diff[j]=MathAbs(price[i+j]-mean);
   }
    
ArraySort(diff);
double sd=(diff[indx20]+diff[indx21])/2; //робастное стандартное отклонение

Если стандартное отклонение больше ноля, то значение индикатора будет равно:

res=(price[i]-mean)/sd;

Теперь мы можем сравнить поведение разных вариантов индикатора между собой. В некоторых случаях индикаторы выглядят очень похоже.


Но также встречаются участки, где разница между индикаторами довольно ощутима.



Небольшой эксперт для сравнения индикаторов

Визуальные сравнения субъективны и могут привести к неверным выводам. Нам же необходимы более надежные основания для выводов. Чтобы оценить все варианты индикатора, давайте напишем простого эксперта. Зададим ему одни и те же правила открытия и закрытия позиций, и сравним результаты. Будем использовать следующие правила — пересечение заданного уровня открывает позицию в одном направлении и закрывает позиции противоположного направления (если таковые имеются).

Параметры эксперта:

  • TypeInd - тип индикатора (Classical, Square, Modern)
  • iPeriod - период индикатора
  • iPrice - цена индикатора
  • Level - уровень, пересечение которого будет отслеживаться. Его значение в 150 соответствует уровню 100 в классическом CCI.

Для ускорения тестирования алгоритм расчета индикатора перенесен внутрь эксперта. Значения индикатора рассчитываются при открытии нового бара. Открытие позиции Buy происходит если значение индикатора пересекает отрицательное значение уровня снизу вверх. В это же время происходит закрытие позиций Sell. Открытие позиций Sell (и закрытие Buy) осуществляется, если значение индикатора пересекает положительное значение уровня сверху вниз.

Параметры тестирования:

валютная пара EURUSD

таймфрейм H1

временной интервал – 2021 год

iPeriod = 14

iPrice = PRICE_TYPICAL

Level = 150

Варианты кривой баланса для всех трех случаев представлены ниже.

TypeInd = Classical

tester1

TypeInd = Square

tester2

Как можно видеть, применение среднеквадратичного отклонения привело к уменьшению количества сделок и снижению больших убытков при этом.

TypeInd = Modern

tester3

Использование робастных оценок увеличило количество сделок, а число больших убытков сократилось еще больше. Это серьезный плюс для такого варианта индикатора.

Хотя во всех случаях правила открытия и закрытия позиций нуждаются в серьезной доработке.


    Модификация индикатора для оценки тренда

    Внимательно наблюдая за индикатором CCI (в любых его вариантах), я сделал поразительное открытие — он может принимать как положительные, так и отрицательные значения. Не знаю, тянет ли это на Нобелевскую премию, но компания MetaQuotes Ltd просто обязана учредить свою премию и наградить ею меня. Однако, шутки в сторону.

    Положительные значения индикатора связаны с трендом вверх. Отрицательные — связаны с движением цены вниз. Давайте остановимся на этом моменте подробнее. Общая идея нового индикатора такая — мы будем суммировать значения индикатора CCI с момента начала тренда до его окончания. Ну и конечно же, сравнивать это движение со средними показателями. Таким образом мы сможем оценить продолжительность трендовых движений и их силу.

    За основу мы возьмем версию расчетов с робастными оценками. Единственное отличие заключается в том, что мы будем накапливать сумму значений индикатора CCI после того, как он преодолеет нулевой уровень. В качестве выходных данных будет использоваться значение этой накопленной суммы. А для сравнения будут отдельно рассчитываться средние суммы для трендов вверх и вниз. Общая картинка этого индикатора получается примерно такой.


    С помощью этого индикатора мы можем оценивать начало тренда, его окончание и силу. А самая простая стратегия по этому индикатору может выглядеть так - по окончании тренда, если тренд был больше среднего (индикатор пересек соответствующий уровень), то можно ожидать движения цены в противоположном направлении.

    Заключение

    Итак, мы увидели, что свежий взгляд на технические индикаторы может оказаться весьма полезным. Ни один индикатор не является окончательной версией - всегда есть возможность доработки и модификации под конкретные стратегии. Прикрепленные файлы:

    • mCCI — индикатор с тремя версиями CCI
    • EA CCI — торговый эксперт для сравнения разных версий CCI
    • tCCI — индикатор, рассчитывающий накапливаемые трендовые суммы.

    Прикрепленные файлы |
    mCCI.mq5 (3.84 KB)
    EA_CCI.mq5 (7.46 KB)
    tCCI.mq5 (4.55 KB)
    mCCI.mq4 (5.25 KB)
    EA_CCI.mq4 (6.26 KB)
    tCCI.mq4 (4.54 KB)
    Последние комментарии | Перейти к обсуждению на форуме трейдеров (3)
    Begemotik
    Begemotik | 7 июл. 2022 в 12:49

    ...тестирую mCCI. Стандартный CCI хорош, давно мучаюсь, чтобы приспособить его к внутридневной торговле. Период 14 это много. Период 5 мало. Меньше 5, - вообще показывает ахинею. :(

    mCCI со стандартным периодом (14) сразу отображает 15-минутную ситуацию очень хорошо. Необходимо просмотреть, как он себя поведет в разных ситуациях. Через неделю отпишусь. ;)

    Lenar Mansurov
    Lenar Mansurov | 9 сент. 2022 в 18:22
    Здравствуйте, где можно скачать mCCI индикатор, хотелось протестировать его
    Aleksej Poljakov
    Aleksej Poljakov | 9 сент. 2022 в 18:33
    Lenar Mansurov #:
    Здравствуйте, где можно скачать mCCI индикатор, хотелось протестировать его

    Перейдите по ссылке на саму статью. Внизу страницы прикреплены все индикаторы

    Разработка торгового советника с нуля (Часть 14): Добавляем Volume at Price (II) Разработка торгового советника с нуля (Часть 14): Добавляем Volume at Price (II)
    Сегодня мы добавим несколько ресурсов в наш советник. Эта интересная статья может натолкнуть вас на новые идеи и методы представления информации и в то же время исправить мелкие недочеты в ваших проектах.
    Нейросети — это просто (Часть 19): Ассоциативные правила средствами MQL5 Нейросети — это просто (Часть 19): Ассоциативные правила средствами MQL5
    Продолжаем тему поиска ассоциативных правил. В предыдущей статье мы рассмотрели теоретические аспекты данного типа задач. В этой статье я продемонстрирую реализацию метода FP-Growth средствами MQL5. А также мы протестируем нашу реализацию на реальных данных.
    Разработка торгового советника с нуля (Часть 15): Доступ к данным в Интернете (I) Разработка торгового советника с нуля (Часть 15): Доступ к данным в Интернете (I)
    Как получить доступ к данным в Интернете в MetaTrader 5. В Интернете у нас есть различные сайты и места, с огромным количеством информации, доступной для тех, кто знает, где искать и как лучше всего использовать эту информацию.
    Видео: Простая автоматизированная торговля – Как создать простой торговый советник с помощью MQL5 Видео: Простая автоматизированная торговля – Как создать простой торговый советник с помощью MQL5
    Большинство слушателей моих курсов считали, что язык MQL5 сложен для понимания. Кроме того, они искали простые способы автоматизации некоторых процессов. В этой статье вы узнаете как сходу начать работать в MQL5 даже без навыков программирования и даже если в прошлом у вас уже были неудачные попытки освоить эту тему.