Самоадаптирующийся алгоритм (Часть III): Отказываемся от оптимизации

Maxim Romanov | 28 декабря, 2020

Введение

Перед началом изучения данной статьи рекомендую ознакомиться со второй статьей серии "Разработка самоадаптирующегося алгоритма (Часть II): Повышение эффективности". Методика из текущей статьи будет существенно отличаться от всего рассмотренного ранее, но для понимания проблемы знакомство с предыдущими статьями серии будет полезным.

Анализ недостатков

Как и в прошлый раз, начну с анализа недостатков предыдущей успешной версии. В процессе анализа были выявлены следующие недостатки:

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

Алгоритм должен быть полностью самоадаптирующийся, поэтому разрабатываться будет под валютный и под биржевой рынок. Для него не должно быть разницы, по каким инструментам торговать. Это важно потому, что должно быть четкое представление, чем одни рынки отличаются от других. А если такое представление есть, то воплотить его в алгоритме имеет смысл. В этот раз я перешел на платформу MetaTrader 5, потому что она имеет более функциональный тестер стратегий и доступна для работы не только с FOREX инструментами, но и с биржевыми.

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

Преобразование свечного графика в другой вид

В новой версии я отказался от использования свечей из-за их нестабильных параметров. Точнее, свечи будут использоваться, но таймфрейма M1 и только потому, что переход на обработку тиков приводит к значительному увеличению потребления ресурсов. В идеале лучше обрабатывать тики.

Анализировать буду блоки размером N пунктов. Это блоки, похожие на ренко, но построенные немного по другому алгоритму. Я уже писал про блоковые графики и их преимущества при анализе в статье "Что такое тренды и какова структура рынков — трендовая или флэтовая".

Block

Рисунок 1. Вид блокового графика

На рисунке 1 показано, как выглядят блоки, которые я буду анализировать. Снизу показан общий вид блокового графика, а сверху показано, как выглядят блоки на графике цены. Блоки строятся в прошлое и в будущее от зафиксированного времени. На рисунке зафиксированное время показано желтой вертикальной полосой. Это нулевая точка, от которой блоки строятся в прошлое и в будущее, алгоритм построения получается зеркальный. То, что блоки строятся в прошлое и будущее, будет важно при дальнейшей разработке.

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

Модель рынка

Базовая закономерность будет похожа на ту, что я использовал в предыдущих алгоритмах, а именно: локальное отклонение числа падающих блоков от числа растущих блоков и последующий возврат к некоторому равновесию. Закономерность статистическая, поэтому начать нужно с анализа статистических характеристик блоковых графиков. Для этого я разработал специальный индикатор Max_distribution, который подробно рассматривался в статье "Что такое тренды и какова структура рынков — трендовая или флэтовая".

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

Основным режимом работы индикатора является измерение количества блоков, которое проходит цена по вертикали за N шагов.

blocks vertically

Рисунок 2. Пример измерения числа блоков по вертикали за 24 шага

На рисунке 2 показан пример. Измеряется, сколько блоков по вертикали цена прошла за N шагов. Так набирается нужное число выборок (например, 100) и потом находится среднее значение. Подобный анализ проводится для блоков разного размера.

distribution

Рисунок 3. Средняя амплитуда для разного размера блоков

На рисунке 3 показан пример распределения средней амплитуды в блоках по вертикали за 24 шага. Каждый столбец гистограммы — это значение средней амплитуды для своего размера блока. Число выборок = 1000. Слева измерения для самого маленького размера блоков, справа для самого большого. Для размера блоков 0.00015 за 24 шага и 1000 выборок цена проходит в среднем 5.9 блока по вертикали. Для размера блока 0.00967 за те же 24 шага и 1000 выборок цена проходит по вертикали в среднем 4,2 блока.

Красной линией показано эталонное значение, которое было бы, если бы ценовой ряд был случайным блужданием. Для 24 шагов — это значение 3.868 блока по вертикали. Эталонное значение рассчитывается методом комбинаторики и наглядно можно представить таблицей на рисунке 4.

probability table

Рисунок 4. Расчет эталона для 24 шагов

На рисунке 4 показан расчет эталонного значения числа блоков по вертикали, которое в среднем пройдет цена за 24 шага, если будет случайным блужданием. В последнем столбце это значение переведено в степень. Можно сказать, что средняя амплитуда случайного блуждания стремится к значению 24^0.4526. Для каждого числа шагов можно пересчитать эталон. Таблицу прикрепил к статье в формате .xlsx.

Я провел исследования на разных торговых инструментах: это было около 35 валютных пар, более 100 акций, 10 криптовалют и около 10 сырьевых инструментов. Серьезных отклонений нет, в целом картина примерно похожа на всех инструментах. Средняя амплитуда колеблется от 7 на быстро растущих криптовалютах до 3.8 на валютных парах. Некоторые низко ликвидные акции могут опускаться даже ниже значения 3.8.

Получено значение средней амплитуды за 24 шага или за какое-то другое число шагов, но что это значит? Представим график в виде синусоиды, преобразованной в блоковый вид, как на рисунке 5.

Sinus

Рисунок 5. Синусоида в блоковом виде

Пусть размер блоков будет такой, что в половине периода синусоиды будет 24 шага. Тогда период будет 48 шагов. Если измерить среднюю амплитуду за 25 выборок по 24 шага, то получим среднюю амплитуду 10.33 блока за 24 шага. С увеличением числа выборок средняя амплитуда будет стремиться к 12, или к числу шагов, деленное на 2. Ценовой ряд не синусоида, но на синусоиде удобно торговать. Теперь, если при измерении средней амплитуды мы будем получать значение больше 12, значит размер блоков недостаточно большой, и 24 блока не укладываются в половину периода. Но значение меньше 12 будет говорить о двух причинах: блоки слишком большие или трендовое движение на ценовом ряде не такое линейное, как на синусоиде. Сейчас не рассматриваем трендовый наклон, это будет дальше.

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

distribution2

Рисунок 6. зависимость средней амплитуды от величины блока для синусоиды

На рисунке 6 видно, что с блоками малого размера цена проходит по вертикали за 24 шага 24 блока. Но с увеличением размера блока за 24 шага цена проходит все меньшее число блоков и затем, когда размер блока становится сопоставим с амплитудой колебаний, число блоков по вертикали падает до нуля. На графике рисунка 3 такой картины не наблюдалось, там максимальное значение было 5.9 и стремилось к эталону, 3.868. Значит, ценовой ряд можно представить как синусоиду, но зашумленную, всегда имеющую на некоторых масштабах некоторую трендовую составляющую. Другими словами, на рынке всегда должен быть масштаб, на котором сейчас флэт (вероятность разворота выше вероятности продолжения тенденции) и масштаб, на котором сейчас тренд (вероятность продолжения выше вероятности разворота).

Почему я принял именно такое определение тренда и флэта, можно прочитать в одной из предыдущих моих статей "Что такое тренды и какова структура рынков — трендовая или флэтовая".

При помощи индикатора Max_distribution я измерил среднее число блоков по вертикали для разных торговых инструментов не только за 24 шага, но и для других значений числа шагов. Пример показан на рисунке 7.

multysample

Рисунок 7. Зависимость средней амплитуды от числа шагов в выборке

На рисунке 7 белыми столбцами показана измеренная амплитуда движения для значений числа шагов от 10 до 120, с шагом 2 и 1000 выборок для каждого измерения. Красными линиями показано эталонное значение для данного числа шагов. Как видно, с увеличением числа шагов существенных отклонений от основной тенденции не наблюдается. Общая форма кривой измеренных значений похожа на форму кривой для эталона. Измерения были сделаны для GBPUSD, но я проводил исследования и для остальных инструментов. Существует много торговых инструментов, у которых значения гистограмм выше эталона, но общая тенденция сохраняется и ее можно описать нелинейным уравнением.

Известно, что стабильных простых закономерностей на рынке быть не может. Значит, масштабы, на которых сейчас тренд и степень тренда, постоянно меняются. При этом масштабы с флэтом тоже становятся трендовыми.

Возьму среднюю амплитуду для 24 шагов с рисунка 7, это значение 3.86. Предположу, что по аналогии с синусоидой движение будет состоять из трендовой и флэтовой части. Тогда можно рассчитать, какая будет трендовая часть для такой средней амплитуды. Для этого 3.86*2=7.72 блока по вертикали за 24 шага округлю в большую сторону до 8, потому что блоки могут быть только целыми. Если попадем на трендовый участок, то цена проходит 8 блоков по вертикали за 24 шага. Да, цена может пройти и 24 блока по вертикали за 24 шага, ничего ей не мешает, но дальше станет ясно, почему это не важно.

Получилось, что на трендовом участке цена пройдет за 24 шага 8 блоков по вертикали. Значит будет движение, у которого блоков одного направления будет 16, блоков другого направления будет 8. Так же известно, что за трендовой частью должна следовать флэтовая часть, чтобы средняя амплитуда оставалась стабильной (а она достаточно стабильна на большом числе выборок). Но рынок не синусоида, и как видно из рисунка 7, с увеличением числа шагов число блоков по вертикали увеличивается. Поэтому буду считать, что отклонение от среднего, возникшее на меньшем числе шагов, совершит возврат к среднему значению на большем числе шагов.

По графику на рисунке 7 посмотрим, сколько в среднем должна проходить цена за 26, 28, 30, 32, 34 шагов:

26 шагов = 3.98; 28 шагов = 4.11; 30 шагов = 4.2; 32 шага = 4.36.

За 24 шага цена уже прошла 8 блоков по вертикали, но за 28 шагов в среднем должна пройти 4.1 блока по вертикали, округляем до целого = 4. Значит, в ближайшее 4 шага возможен откат от предыдущего движения 4 блока. Рынок не настолько предсказуем и маловероятно, что события будут развиваться по данному сценарию. Из того же графика на рисунке 7 можно узнать, что 8 блоков по вертикали цена проходит в среднем за 116 шагов.

rollback 1

rollback 2

Рисунок 8. Возможные варианты развития событий

На рисунке 8 показаны 2 варианта развития событий. Это 2 крайних варианта, они маловероятны и показаны для визуализации. Вероятнее всего, события будут развиваться по одному из промежуточных сценариев. Но сейчас важно, что известно, сколько цена в среднем должна проходить за каждое число шагов. Видно, что чем более резкий откат, тем он глубже, но чем более пологий откат, тем меньшая глубина отката.

В конечном итоге, амплитуда движений будет стремиться к своему среднему значению. Для 24 шагов — это 3.8 блока по вертикали, а для 116 шагов — это 8 блоков по вертикали.

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

rollback

Рисунок 9. Пример трендового движения и глубины отката

На рисунке 9 показано, как это выглядит на реальном графике. Видно, что слева было резкое движение и резкий откат, при этом глубина отката оказалась более 60%. Справа было более плавное движение и продолжительный откат, что привело к откату на 30%. Так получилось потому, что на правом рисунке цена прошла большее число шагов, и за время формирования движения его амплитуда увеличилась.

Причины такого поведения можно объяснить не только тем, что у ценового ряда есть средняя амплитуда и он ее придерживается, но и тем, что резкие движения вызваны резким притоков/оттоком капитала в актив на суммы, значительно превышающие текущую ликвидность. После того, как позиция на большую сумму открыта, ее нужно закрыть. При этом неважно, кому принадлежал объем средств — одному участнику или несколькими. Если сразу же закрыть позицию на всю сумму, то цена вернется на первоначальный уровень, то есть откат будет 100%. Но если позиция будет закрываться постепенно, учитывая приходящую ликвидность, то большая сумма вызовет меньшее движение. Чем быстрее игрок выходит из позиции, тем сильнее будет откат от движения, которое он создал своим капиталом.

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

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

Отслеживание тренда

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

Робот будет анализировать число падающих и растущих блоков. Если он находит существенное отклонение числа растущих блоков от нормального значения, то генерирует сигнал для серии Sell позиций. Для падающих аналогично, только отклонение падающих блоков генерирует сигнал серии Buy.

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

Пороговый процент для начала и завершения серии

Так как для анализа используется диапазон блоков (например, 24-34), то брать фиксированный пороговый процент для каждого числа блоков — неверное решение. Вероятность появления комбинации из 24 блоков с 75% перевесом преобладающих блоков не равна вероятности появления такой комбинации для 34 блоков. Нужно чтобы вероятность появления комбинаций была одинаковая, значит, пороговый процент нужно использовать динамический, который зависит от вероятности появления данной комбинации.

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

probability table

Рисунок 10. Таблица вероятностей 

На рисунке 10 показана таблица, через которую пересчитывается вероятность попадания в диапазон в процент для открытия.  В таблице принято, что все 100% движений попадут в диапазон от 0 до 16 блоков по вертикали за 16 шагов. Вероятность попадания в диапазон 2.1% (для таблицы на рисунке 10) означает, что только 2.1% всех движений пройдет по вертикали за 16 шагов от 10 до 16 блоков. В настройках задаем вероятность попадания в диапазон, например, 2.2, и алгоритм по таблице ищет ближайшее значение меньше или равно 2.2, потом берет процент, соответствующий этому значению, в данном случае это 81.25%. Так для каждого числа блоков будет свой пороговый процент. Таблицу прикрепил к статье в формате .xlsx.

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

Пороговый процент для закрытия тоже рассчитывается через вероятность попадания в диапазон. Но вероятность попадания в диапазон имеет обратную шкалу. Это непринципиальный момент, просто я так сделал. В таблице для расчета процента закрытия выделен отдельный столбец. Предположим, что я хочу закрыть позиции, когда значение станет больше или равно 75. Тогда находится ближайшее значение больше 75. Для 16 блоков это 78.9, что соответствует пороговому проценту закрытия = 62.5%. 

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

На предполагаемую точку закрытия в прибыли устанавливается take profit для всех позиций в серии. Так реализован алгоритм контроля величины отката в зависимости от текущего состояния рынка. Чем больше блоков в выборке образовалось после начала серии (трендового движения), тем меньше получается величина отката.

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

Разработана методика порогового процента, и можно ответить на вопрос (не используя оптимизацию): какой пороговый процент использовать. Для этого разработана формула:

%open

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

Процент закрытия тоже можно рассчитать заранее на основе показаний индикатора.

%close;

Выглядит формула для расчета процента закрытия аналогично, только используется другой коэффициент умножения Kc. Его лучше сделать равным 1, но возможность коррекции нужно предусмотреть.

Исходя из анализа средней амплитуды, равной 3.8, можно установить пороговый процент открытия для 24 блоков, равный 66,67%, для остальных значений пересчитать через таблицу вероятностей.

Отслеживание тренда

Как я писал выше, рынок не имеет стабильных закономерностей и стабильной амплитуды колебаний. А анализировать степень тренда на фиксированном числе блоков с фиксированным размером решение сомнительное. Окно для анализа должно быть динамическим и корректироваться в реальном времени. Пусть число блоков для анализа задается диапазоном от 24 до 28. 

Сразу отвечу на необходимый вопрос, почему окно анализа именно 24-28 блоков. Эти значения выбраны на основе средней амплитуды = 3.8 и зависят от порогового процента открытия/закрытия. При таком числе блоков после сигнала на начало серии мы получим 4 блока прибыли. Чем больше блоков в окне для анализа, тем точнее будет работать алгоритм. Принципиальной разницы нет, сколько блоков прибыли получать: 4 или 10, если размер блока будет пропорционально изменен. Но так как позиции будут открываться на каждом новом блоке, то их число будет расти с увеличением точности работы, а это не очень хорошо отразится на результатах. 

Далее нужно определить минимальный размер блока, который имеет смысл анализировать. Блоки строятся по сформированным минутным свечам. Минимальная частота дискретизации получается 1 минута. Нельзя делать блоки слишком маленькие, потому что тогда они начнут строиться внутри свечи, и такой анализ не будет иметь смысла. Поэтому минимальный размер блоков будет определяться на основе размера свечей. Для этого можно использовать индикатор ATR за большой период, например, 1440 минут (сутки) или выше, и умножать его значение на коэффициент. Коэффициент от 2 до 5 должен быть приемлемым, но зависит от особенностей торгового инструмента.

Если размер свечей сильно неравномерен, то лучше использовать коэффициент больше. Второй критерий — это комиссии и спред. Прибыль, полученная за 4 блока, должна быть значительно больше комиссий, которые мы заплатим. Чем меньше размер блока, тем чаще будут сигналы на начало серии и тем больше прибыли можно заработать. Тут нужно соблюсти баланс. В итоге минимальный размер блока зависит от размера свечей и от комиссий. Есть четкие критерии выбора минимального размера блока.

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

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

Робот будет анализировать блоки с минимальным размером, но, когда найдет маленький трендовый участок с процентом перевеса выше порогового, должен определить максимальный масштаб на присутствие тренда. Для этого нужно просканировать участок большего размера. Так как число блоков для анализа фиксированное, то нужно увеличить сам размер блоков и посмотреть, что происходит на большем размере блоков. Минимальный размер блоков я назвал TF1 по аналогии с таймфреймом. Это синтетический блоковый таймфрейм. Блоки большего размера будут получены через коэффициент умножения, KTF, например, он будет 1.1.

1. Сигнал на начало серии

Нужно ввести понятие базового таймфрейма (далее везде, где речь идет про таймфреймы, имеются ввиду блоковые таймфреймы). Базовый таймфрейм это тот, на котором найден сигнал на начала серии.

Алгоритм должен создать несколько дополнительных блоковых таймфреймов и проверить наличие сигнала начала серии на высших таймфреймах. 

Для коэффициента KTF=1.1 достаточно просмотреть ближайшие 5 таймфреймов, так размер блока самого большего таймфрейма будет в 1.6 раза больше минимального. Если на одном из высших таймфреймов найден сигнал на начало серии, то алгоритм перейдет на этот таймфрейм и сделает его базовым. После того, как найден новый базовый таймфрейм, нужно опять создать 5 таймфреймов большего размера и повторить процедуру сканирования. Так будет найден максимальный таймфрейм с перевесом выше порогового.


work

Анимация 1.

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

На этом моменте становится важным использование диапазона числа блоков вместо фиксированного значения. В примере сигнал ищется для диапазона 24-28 блоков. Приоритетной считается выборка с большим числом блоков. Если сигнал найден и на 24 блоках, и на 28 блоках, то базовой выборкой становятся 28 блоков. На дополнительных таймфреймах аналогично: сигнал ищется в диапазоне 24-28 блоков. Приоритетным считается таймфрейм с большим размером блока, и внутри этого таймфрейма приоритет отдается выборке с большим числом блоков.

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

size error

Рисунок 11. Погрешность построения блоков

На рисунке 11 показано, что 10 блоков большего размера могут охватывать меньше данных, чем 10 блоков меньшего размера. Для того, чтобы минимизировать этот эффект, и используется диапазон числа блоков для анализа 24-28. Робот может перейти на больший базовый таймфрейм и увеличить число блоков в выборке. Затем ему будет легче перейти на еще больший таймфрейм с меньшим числом блоков в выборке.

Отвечаю на вопрос: почему именно KTF = 1.1? Чем меньше коэффициент умножения, тем точнее будет работать алгоритм, но тем больше таймфреймов нужно просматривать одновременно. Для того, чтобы размер блока увеличился в 1.6 раза относительно базового таймфрейма, нужно просматривать всего 5 таймфреймов. Если сделать KTF = 1.05, то придется просматривать уже 10 таймфреймов, а это дополнительная вычислительная нагрузка. Но чем меньше коэффициент умножения, тем точнее работает.

2. Задержка открытия позиций

Найден сигнал на начало серии, но если сейчас начать открывать позиции, то результат будет сомнительный, слабая самоадаптация. Цена может продолжить движение в том же направлении и скорее всего так и сделает. Нужно убедиться, что найден максимальный масштаб, и тренд закончился. Для этого нужно чтобы на следующем таймфрейме от базового отсутствовал сигнал на начало серии, и чтобы алгоритм не мог повысить базовый таймфрейм. Сигнал начала серии на высшем таймфрейме сейчас отсутствует, но блоки большего таймфрейма охватывают больший диапазон данных, и уходят в прошлое относительно начала тренда.

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

а) Задержка по трендовому участку

Блоки высшего таймфрейма, как правило, уходят в историю глубже, чем блоки базового. Значит, нужно ждать до тех пор, пока 24-28 блока высшего таймфрейма не поместятся в тот же исторический диапазон, что и 24-28 блоков базового таймфрейма. Проверять нужно на каждой новой свече.

delay a

Рисунок 12. Задержка открытия позиций для перехода на высший таймфрейм

На рисунке 12 показано, что нужно было подождать 2 минуты, чтобы блоки большего размера вместились во временной диапазон, который занимали блоки меньшего размера. Если идет задержка и во время задержки на одном из высших таймфремов (их просматривается одновременно несколько) обнаружен сигнал на начало серии, то базовый таймфрейм повышается, и задержка повторяется. Если после окончания задержки алгоритм не смог перейти на высший таймфрейм, то найден максимальный трендовый масштаб, можно открывать позицию.

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

б) Задержка на основе статистических характеристик инструмента

Цель данного метода аналогична той, что преследовалась в пункте (а). Нужно, чтобы блоки высшего таймфрейма охватывали тот же трендовый участок, что и блоки базового таймфрейма.

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

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

formula dalay;

Пример: пусть mbn=24; %open=75; BSB=0.00064; Bsd= 0.0007. Тогда Vb=18. Значит, из 24 блоков 18 должно быть одного направления. Считаем, сколько пунктов цена прошла за 18 блоков на базовом таймфрейме. Для этого 18*BSB = 0.01152, рассчитываем сколько цена должна пройти за 18 блоков высшего таймфрейма. Для этого 18*Bsd = 0.0126, находим сколько пунктов не хватает, чтобы были сформированы все блоки высшего таймфрема. Для этого 0.0126-0.01152=0.00108, и делим полученное значение на размер блока высшего таймфрейма. Nd=0.00108/0.0007=1.54. Получилось, что 1.54 блока не хватает для того, чтобы перейти на высший таймфрейм.

Полученное значение справедливо, если цена движется строго вертикально, но она не движется строго вертикально, и из 24 блоков только 18 одного направления и 6 другого. Поэтому 1.5 блока нужно пересчитать в правильное число блоков для данного торгового инструмента, так получится значение Nbd = 3. Значит реально, учитывая характеристики трендового движения данного торгового инструмента, нужно подождать формирования трех блоков высшего таймфрейма.

Но просто так ждать, пока пройдет нужное число блоков задержки (3 из примера), неэффективно. Ждать имеет смысл, только если цена идет в направлении найденного тренда и переход на высший таймфрейм возможен. Нужно взять минимальное число блоков Nd, умножить на размер блока Bsd и отложить нужное число пунктов от цены закрытия блока базового таймфрейма в сторону тренда. Это будет контрольная точка, до которой должна дойти цена, чтобы был возможен переход на высший таймфрейм. Теперь после закрытия каждого нового блока высшего таймфрейма нужно проверять, хватит ли оставшихся блоков, чтобы цена достигла установленной контрольной точки. 

Например: Nbd = 3 блока, тренд падающий. Рассчитали контрольную точку, она на расстоянии 1.54 блока вниз от цены закрытия блока базового таймфрейма. Сформировался падающий блок высшего таймфрейма, потом сформировался растущий блок и остался 1 блок задержки. Ждать дальше смысла нет, потому что если сформируется еще 1 блок задержки, то он уже не пересечет контрольную точку. Стало известно, что продолжать задержку смысла нет, переход на высший таймфрейм не состоится, можно открывать позицию. 

Как это работает, показано на анимации 2.

work 2

Анимация 2.

Для примера я взял синусоиду. Пока рабочая версия не умеет определять статистические характеристики торгового инструмента, и я задал процент открытия и закрытия вручную. В следующих версиях это будет реализовано, и алгоритм сам будет определять характеристики торгового инструмента. Размер блоков и момент открытия позиции он определяет сам.

Видно, что тест начинается с блоков маленького размера, и далее алгоритм, отслеживая тренд, увеличивает размер блоков. После того, как максимальный размер тренда определен, происходит открытие позиции. Далее рассчитывается откат от этого тренда. Для синусоиды откат 100%, поэтому рассчитывается точка закрытия и устанавливается take profit. Я выбрал синусоиду для визуализации и упрощения понимания процесса работы. Видно, что алгоритм использует почти всю амплитуду синусоиды для получения прибыли, кроме небольшого участка 2 блока в начале нового трендового участка.

3. Сопровождение серии

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

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

Заключение

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

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

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

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

Предыдущие статьи на эту тему

Разработка самоадаптирующегося алгоритма (часть I): поиск базовой закономерности
Разработка самоадаптирующегося алгоритма (часть II): повышение эффективности