Говоря совсем просто, в нашем проекте кластер это ситуация на рынке, склонная к повтору. Изначально существует лишь 1 критерий - схожесть комбинации из 4х свечей. Если критерий совпал присваиваем нынешней ситуации кластер. Сейчас в структуру кластера добавляются и другие критерии, но об это позже.  Мы уже видели стандартную структуру по которой мы собираем комбинации. Что бы собрать кластеры, нам как минимум нужен инструмент сравнения одной комбинации с другой. У каждой свечи 4 значения, в комбинации 4 свечи. Нам надо сравнить насколько сильно отличается друг от друга набор из 16 цифр. Первый этап - подготовка комбинации к сравнению, цена варьируется от инструмента к инструменту, из-за этого было решено представить каждое из 16 значений как число от 0 до 1, где 0 минимальное значение комбинации, а 1 максимальное. Основная формула для этого этапа: Стандартизированная комбинация: Самая первая версия алгоритма просто считала % разницы между каждым значением и возвращала массив из 16 процентных значений. Затем мы считали средние отличие и все, на основе этого решали похожа комбинация или нет. Недавно алгоритм был переработан, теперь мы сравниваем каждую свечу с другой свечей по нескольким параметрам: размер свечи и верхнего нижнего хвостов, а так же расположение свечи относительно комбинации. Все это легко считается по изначальным 4м параметрам свечи. Самое главное - возможность настроить максимальное отклонение для каждого параметра отдельно. Сейчас настройки выставлены так: Иногда хвост свечи может сильно подвинуть всю комбинацию вверх или вниз и, даже если все очень похоже, положение свечей будет сильно отличаться, поэтому CBP (Clear Body Position) считается без учета верхних и нижних хвостов. По итогу сравнения мы получаем объект с параметрами и средним значением. Среднее значение будет использоваться для вычисления общего процента схожести комбинаций. Представим песочницу в которую хаотично высыпали фигуры разных цветов и форм. Наша задача собрать все фигуры в группы. Уже на этом этапе необходимо определится какие мы хотим получить группы. Например, что бы в одной группе были максимально похожие фигуры, или же что бы группы были максимально большими. Трудно сказать какой метод подходит для наших целей лучше всего, собирая максимально похожие группы, результат будет - множество небольших групп с очень похожими фигурами, с одной стороны чем больше схожесть тем лучше, с другой лучше если группа больше. Перебирая комбинации одна за другой, мы рано или поздно добавим в кластер комбинацию, а затем создадим новый кластер к которому та самая комбинация подошла бы лучше. Вот тут и необходимо решить - либо переносим комбинацию в новый кластер, либо не трогаем. Для начала делаем первый перебор по нашей импровизированной базе из JSON файлов. После определения первой комбинации для сравнения начинаем перебор для второй комбинации, внутри этого перебора мы и будем сравнивать первую комбинацию с кучей вторых комбинаций и те что похожи записывать в кластер к первой. Сет g_excluded хранит в себе все использованные комбинации и перед каждым сравнением проверяет не использовалась ли она ранее. Метод transForEx - очень простая хеш-функция, она делает из комбинации уникальную строку что бы добавить ее в сет исключенных комбинаций. Цикл while(true) может быть прерван если комбинация не найдена после всего обхода. Комбинация пропускается если исключена. Вместо пропуска комбинаций, мы можем перезаписывать ее в новый кластер, если она подходит ему больше, но об этом чуть позже. Объект d - результаты сравнения двух комбинаций, чтобы значительно уменьшить количество сравнений, мы сначала быстро проверяем цвета свечей в комбинации, и при совпадении, сравниваем уже детально. По итогу обработки всей базы у нас имеется файл со всеми кластерами. Метод сборки уже готового элемента сверху не описан и может сильно отличаться в зависимости от его применения, у нас это массив комбинаций где 0 элемент всегда тело кластера, в нем хранится вся статистика по комбинациям, хранящимся далее в массиве. Это сделано что бы можно было безболезненно оторвать тело кластера от остальных комбинаций и использовать для сравнения в реальном времени. Пример кластера: indexID это короткий пусть к комбинации в первичной базе данных, в нашем случае (f17i658) это файл 17, комбинация 658. Если мы заменяем комбинацию вместо пропуска, нам нужен этот ID. В следующей части мы детальнее посмотрим на некоторые вспомогательные функции и разберем часть проекта, которая отвечает за поиск кластера и отображение всех необходимых данных на странице.