Индикатор CCI. Модернизация и новые возможности
Краткая история
Индикатор Индекс Товарного Канала (Commodity Channel Index) знаком каждому трейдеру. Его разработчик — Дональд Ламберт, впервые опубликовал статью об этом индикаторе в журнале Commodities (современное название – Modern Trader) в 1980 году. С тех пор этот индикатор сникал заслуженную славу, и стал весьма популярен среди трейдеров. Он входит в джентльменский набор торговой платформы MetaTrader и используется как при ручной торговле, так и в составе механических торговых систем.
Алгоритм расчета
Расчет этого индикатора довольно прост и нагляден. Индикатор показывает на сколько отклонилась цена от среднего значения по отношению к среднему абсолютному отклонению. Алгоритм расчета значений этого технического индикатора можно представить следующим образом. Пусть период индикатора составляет N отсчетов цены. Тогда:
- Рассчитываем среднее значение
- Находим среднее абсолютное отклонение
- Рассчитываем значение индикатора
В оригинальном индикаторе значение поправочного коэффициента k = 0.015. Он подобран таким образом, чтобы отклонение цены на 1.5*MAD было равно 100 единицам индикатора. Тогда отклонение на 3*MAD равно 200 единицам. (Интересное наблюдение, если деление заменить на умножение, то значение нормирующего коэффициента k будет равно 66.6)
Возможные изменения алгоритма
Заметим одну особенность этого индикатора – использование среднего абсолютного отклонения. Такой подход был полностью оправдан на заре развития вычислительной техники. Так как расчет абсолютного отклонения требовал меньше затрат вычислительных ресурсов по сравнению с расчетом более целесообразного среднеквадратичного отклонения. Современные компьютеры могут справится с операциями возведения в квадрат и извлечения корня за вполне приемлемое время. Поэтому алгоритм вычисления значений индикатора может выглядеть следующим образом.
- Находим сумму чисел:
- Находим сумму квадратов:
- Вычисляем значение индикатора:
Такой алгоритм более точен в расчетах, но и он не является совершенным. Основная проблема заключается в том, что для оценки среднего и среднеквадратичного значений требуется достаточно большое количество отсчетов цены – не меньше тридцати. Но, для трейдинга могут использоваться и короткие периоды. Например, в классическом варианте 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
TypeInd = Square
Как можно видеть, применение среднеквадратичного отклонения привело к уменьшению количества сделок и снижению больших убытков при этом.
TypeInd = Modern
Использование робастных оценок увеличило количество сделок, а число больших убытков сократилось еще больше. Это серьезный плюс для такого варианта индикатора.
Хотя во всех случаях правила открытия и закрытия позиций нуждаются в серьезной доработке.
Модификация индикатора для оценки тренда
Внимательно наблюдая за индикатором CCI (в любых его вариантах), я сделал поразительное открытие — он может принимать как положительные, так и отрицательные значения. Не знаю, тянет ли это на Нобелевскую премию, но компания MetaQuotes Ltd просто обязана учредить свою премию и наградить ею меня. Однако, шутки в сторону.
Положительные значения индикатора связаны с трендом вверх. Отрицательные — связаны с движением цены вниз. Давайте остановимся на этом моменте подробнее. Общая идея нового индикатора такая — мы будем суммировать значения индикатора CCI с момента начала тренда до его окончания. Ну и конечно же, сравнивать это движение со средними показателями. Таким образом мы сможем оценить продолжительность трендовых движений и их силу.
За основу мы возьмем версию расчетов с робастными оценками. Единственное отличие заключается в том, что мы будем накапливать сумму значений индикатора CCI после того, как он преодолеет нулевой уровень. В качестве выходных данных будет использоваться значение этой накопленной суммы. А для сравнения будут отдельно рассчитываться средние суммы для трендов вверх и вниз. Общая картинка этого индикатора получается примерно такой.
С помощью этого индикатора мы можем оценивать начало тренда, его окончание и силу. А самая простая стратегия по этому индикатору может выглядеть так - по окончании тренда, если тренд был больше среднего (индикатор пересек соответствующий уровень), то можно ожидать движения цены в противоположном направлении.
Заключение
Итак, мы увидели, что свежий взгляд на технические индикаторы может оказаться весьма полезным. Ни один индикатор не является окончательной версией - всегда есть возможность доработки и модификации под конкретные стратегии. Прикрепленные файлы:
- mCCI — индикатор с тремя версиями CCI
- EA CCI — торговый эксперт для сравнения разных версий CCI
- tCCI — индикатор, рассчитывающий накапливаемые трендовые суммы.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
...тестирую mCCI. Стандартный CCI хорош, давно мучаюсь, чтобы приспособить его к внутридневной торговле. Период 14 это много. Период 5 мало. Меньше 5, - вообще показывает ахинею. :(
mCCI со стандартным периодом (14) сразу отображает 15-минутную ситуацию очень хорошо. Необходимо просмотреть, как он себя поведет в разных ситуациях. Через неделю отпишусь. ;)
Опубликована статья Индикатор CCI. Модернизация и новые возможности:
Автор: Aleksej Poljakov
Здравствуйте, где можно скачать mCCI индикатор, хотелось протестировать его
Перейдите по ссылке на саму статью. Внизу страницы прикреплены все индикаторы