Всех категорически приветствую.
Как я уже писал, в настоящий момент разрабатываю систему под робота на основе паттерна 123. Делается это для добавления к основному роботу, который ловит развороты. Дабы работал и по тренду. Сейчас я хотел бы поделится начальными наработками, а также описать возникающие проблемы — возможно кто-то подскажет толковый путь их решения, ибо сам я в программировании чуть менее чем полный ноль.
Для начала немного теории. Что такое Price Action? Как слудет из самого название — это движение цены. Грубо говоря, определенные ценовые формации, которые используются для входа и выхода.
Одим из самых элементарных и понятных является Паттерн 123. Отчего он понятен? От того, что все движения на рынке происходят волнообразно. Существуют движения и коррекции к движению. Логично, что скорее всего после небольшой коррекции движение продолжится. Также он находит свою поддрежку и через волновую теорию. Ну да ладно… Изобразим это дело визуально, дабы любой мозг понял, о чем ему толкуют.
Допустим мы имеем начало движения. Возьмем эту точку за 0%. Движение дошло до определенного уровня и развернулось. Точку данного разворота мы возьмем за 100%. Согласно различных теорий скорее всего коррекционное движение продолжится до района 38% или 50% или 62% от первоначального диапазона. Именно в этих районах стоит входит в позицию по направлению первоначального движения. Выход осуществляется по двум целям — на 161% от первоначального движения, либо на 261%. Я думаю, рисунок дает полноценную картину сказанного.
А вот так это выглядит на реальных торгах. После нисходящего движения в начале дня, цена вошла в небольшую коррекцию. На тестировании уровня 61.8% от первоначального движения система вошла в шортовую позицию — обозначено красной стрелкой. При достижении уровня 161.8% последовал выход из позиции — обозначено зеленой стрелкой.
Раньше я часто использовал подобный метод в ручной торговле. Но я стараюсь уйти от ней. Посему условия входа/выхода необходимо формализовать и оформить в виде, понятном машине. При этом мы получаем шикарную возможность для тестирования. После определенной работы был выдан продукт. В данном случае не используются индикаторы. Однако есть оптимизируемые параметры. Правда, я думаю, что оптимизировать их вполне разумно и логично. Во-первых, это время торгов. В данном случае с 10:30 по 18:00. И это логично, ведь в первые полчаса торговой сессии мы можем получить неважнецкий сигнал, поскольку инструмент может быть нерасторгован. Во-вторых, форма свечи. Я запрещаю входы на противонаправленных свечах, открытие которых лежит в определенном диапазоне. Этот диапазон подбирается тестированием, т.е. оптимизацией. И это тоже логично.
Получил я следующий результат:
Как мне кажется, результат весьма неплох.
Но есть подводные камни. Мы ведь имеем дело с программированием. Машине нужны конкретные формализованные вещи. Так, к примеру, во время разработки системы встал вопрос — как заставить машину понять, что цена достигла уровня 161%. Если мы просто напишем нечто вроде, (Хай-Лоу)*1.61, то выхода мы не получим никогда, ибо данное выражение не станет истинным. Поскольку на каждом обновлении Хая, Хай будет меняться. Масло масленное, но вот так.
Очеивдно, что нам требуется запоминать параметры в момент входа. Я не знаю, как это реализовано в других программах теханализа, но в АмиБрокере с этим возникают проблемы. Как таковой записи я не нашел. Однако мы можем получить параметры из прошлого через такую вещь, как
ValueWhen. Здесь мы можем указать время, либо событие.
Вроде вот оно. Решение. Но не все так просто. Ведь после входа, к примеру, в лонг, может пройти еще один системный сигнал Бай. Он не будет отработан через реальную покупку, поскольку система уже в ней, однако сам по себе он пройдет и тогда ValueWhen будет уже считать в момент последнего сигнала, а к этому моменту значения Хай и Лоу могут измениться от тех, что были на момент действительной покупки.
Т.е. нам необходимо удалять лишние сигналы из системы. В АмиБрокере это делается через подобную хитрость:
Buy = ExRem(Buy,Short);
Short = ExRem(Short,Buy);
Вроде вот оно. Решение. И именно на нем построена та модель, результаты которой я представил выше. В программном виде это выглядит следующим образом:
// сигналы
Buy = (BC1 OR BC4 OR BC3) AND TM4 AND TM5 AND !BeginDay AND !anBC2;
Short = (SC1 OR SC3 OR SC4) AND TM4 AND TM5 AND !BeginDay AND !anSC2;
Buy = ExRem(Buy,Short);
Short = ExRem(Short,Buy);
H1 = ValueWhen(Buy OR Short, NewHigh, n = 1);
L1 = ValueWhen(Buy OR Short, NewLow, n = 1);
Delta = H1-L1;
D161H = L1 + Delta*1.62;
D161S = H1 — Delta*1.62;
Lout3 = Cross (H, D161H);
Sout3 = Cross (D161S, L);
Sell = Lout3 OR Lout2 OR TM;
Cover = Sout3 OR Sout2 OR TM;
Но снова НО! В данном случае сброс значение Хай/Лой для расчета расширения 161% происходит при появлении обратного сигнала — шорт после покупки либо покупка после шорта. Смотрим на код с ExRem.
Но ведь в жизни могут быть другие ситуации. К примеру, на картинке:
Система отработала первую сделку. Между 16 и 17 часами мы видим формацию для повторной покупки — цена тестирует уровень коррекции. Но сделки не происходит! Почему? Да потому, что для машины диапазон Хай/Лоу до сих пор находится там, внизу — обозначено зеленным прямоугольним. Ведь сигнала Шорт не было! И поэтому, благодаря ExRem, ситсема до сих пор хранит те значения. И по её логике цены между 16 и 17 часами не достигли необходимого уровня коррекции.
Казалось бы, ну что сложного — сбрасывать значения не только по обратной операции, но и просто по закрытию позиции. Да. Но мы попадаем в ловушку. Мы не можем прописать для ExRem Cover или Sell. Почему? Да потому что они определены ниже. А условия для них определяются после ExRem. Т.е. мы имеем замкнутый круг.
Вот здесь я и обращаюсь к товарищам с вопросом — может кто подскажет, как победить подобный расклад. Ведь, наверняка, из-за подобной ситуации мы теряем много профитных сделок. Мне предложили оформить это дело циклом и дали следующий каркас:
buy = sell = short = cover = false;
CurrentPosition[0] = 0;
Last = LastValue(BarIndex());
for (i=1 ; i < Last ; i++)
{
CurrentPosition[ i ] = CurrentPosition[ i-1 ];
if (currentPosition[ i ] == 0) // мы без позиции
{ if (условиеBuy) // проверяем условие именно на i-той свече. Например Close[i-1] > Open[i-1]
{ Buy[ i ] = true;
CurrentPosition[ i ] = Size;
}
else if (условиеShort)
{ Short[ i ] = true;
CurrentPosition[ i ] = -Size;
}
}
else if (CurrentPosition <0) // Мы в шорте
if (сработалCover)
{ Cover[ i ] = true;
CurrentPosition[ i ] = 0;
}
else if (CurrentPosition > 0) // Мы в лонге
if (сработалSell)
{ Sell[ i ] = true;
CurrentPosition[ i ] = 0;
}
}
Но, к сожалению, я вообще не могу понять, как сюда запихать мой первоначальный код. Вот такая беда.
Или оставить имеющиеся наработки, пренебрегнув возможными профитными сделками? Или убыточными...? Добавить ряд фильтров, уменьшающих текущую просадку и наслаждаться работой?
Далее. Про входе на пробое точки 2 наше соотношение прибыль/убыток в лучшем случае 1 к 1 — стоп же за точку 3? Если за точку 1, то и того хуже. При моем входе указанное соотношение уже будет иметь перевес в сторону профита.
Спасибо, интересно почитать
Ну и если уж совсем в классику, то коррекция 2-3 должна быть больше 50% 1-2, если не путаю?
На мой взгляд конечно входить по пробою точки 2 — не очень выгодно — соотношение плохое, но если избрать вариант разворота из коррекции, т.е. после коррекции ударная свеча в сторону движения, на ней и входим?
Мне интересны результаты на большой волатильности.
3% просадки при 20% дохода. Если взять 50% на погрешность, то получаем 4.5% просадки — это можно брать спокойно плечо 1 к 5, 20% просадки по депо — отключаем робота.
А заработать можно 100% в год.
Любопытно.