English 中文 Español Deutsch 日本語 Português Türkçe
Оптимальный подход к разработке и анализу торговых систем

Оптимальный подход к разработке и анализу торговых систем

MetaTrader 5Торговые системы | 23 октября 2020, 09:24
3 760 67
Evgeniy Ilin
Evgeniy Ilin

Введение

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

Моя философия

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

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

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

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

Бывало, я писал советников по 2000-3000 строк кода и толку от него не было, а бывало писал рабочий код 20-50 строк и, как ни странно, оно сразу работало по всей истории и еще и мультивалютно ). Качество ваших знаний о рынке на самом деле решает все. Талантливый кодер не тот, кто пишет скайнет и тот вообще не работает, а тот кто знает, что писать и нужно ли это вообще в системе.

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

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

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

Выбросьте все это из головы и начинайте думать, что же двигает цену. Также необходимым условием того, чтобы у вас был шанс что-то найти, это знание математики и умение ее применять, умение анализировать результаты, вычленять рабочие моменты и понимать их физику. Все это достигается только практикой + теорией. В итоге все будет зависеть от количества написанных и протестированных вами торговых систем. Не нужно сгонять чужой код, пишите сами с нуля. Если кто-то думает, что он вот сейчас возьмет и закодит мега грааль и будет стричь капусту, то он ошибается. Я так думал на протяжении нескольких лет. Думать — не значит знать.


Сигналы,  советники, индикаторы

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

Сигналы

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

Ниже приведу пример плохого сигнала и хорошего:

Безопасный сигнал:

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

Следующий сигнал:

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

Советники

Никто и никогда не будет выкладывать стабильный и прибыльный советник в Маркет без того соображения, что продажа данного советника принесет гораздо больше, чем просто тихое его использование автором. Либо возможен второй вариант: автор сам не уверен в системе и не хочет рисковать, вкладывая большие средства в свой депозит, он торгует по минимуму с минимальными рисками. Для того чтобы покупка советника окупилась, вам потребуется большой депозит, скажем, купив на год советника, который предположительно принесет 200 долларов со 100 начальных, и при этом заплатив за него 200 долларов, то вы ничего не получите даже при условии, что советник сохранит работоспособность.

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

Сначала покажу общую таблицу тестирования советника на последних 10 годах истории основных валютных пар:


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

Вот один из вариантов в таблице:


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

Индикаторы

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

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

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

Здесь я тоже приведу пример своего индикатора:


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

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

Математика оптимального поиска

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

  • Ps=Ps(L)

Где "L" — количество строк рабочего кода. Иначе говоря, вероятность того, что первые показатели текущей создаваемой системы окажутся в приемлемом диапазоне, напрямую зависит от количества написанного нами кода. Многим может показаться, что чем больше строк, то тем лучше система, на самом деле это не всегда так. При этом необходимо понимать что:

  • T=K*L

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

  • E= Ps/T
  • E --> Max

Иначе говоря, мы должны добиваться максимума показателя "E" всеми возможными способами. Основные 2 способа — это повысить качество своих знаний о рынке и найти оптимальный размер кода прототипа. После того, как мы определились с размером прототипа и естественно, учитывая текущие ваши знания о рынке и способность их применять, все это дает определенный "E0". Некий показатель вашей эффективности на текущий момент. Также получается некое среднее время разработки которое уходит на 1 систему.

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

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

  • Pa=Сумм(m0...m...n)[C(n,m)*Pow(Ps ,m)*Pow(1-Ps ,n-m)]
  • m0 - минимальное количество удовлетворительных прототипов
  • Pa — вероятность того, что в результате разработки мы получим хотя-бы "m0" или больше из "n" циклов разработки.
  • n — максимально доступное количество циклов поиска рабочих прототипов

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

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

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

  • Pf= Сумм(1...m...n)[C(n,m)*Pow(Po,m)*Pow(1-Po,n-m)]
  • Po — вероятность того, что в результате итерации мы получим приемлемый результат
  • n — максимально доступное количество циклов поиска

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

  • Ef= Pf/m
  • Ef--> Max

На данном этапе важно соблюдать баланс между правками и тестированием, важно чувствовать как влияет тот или иной параметр на итоговый результат и есть ли смысл в дальнейшем тестировании. Процесс тестирования и доработок всегда занимает примерно одно и то же время, поэтому "m" здесь — количество тестов которое, вы должны определять самостоятельно путем интуиции или опыта. Нет конкретных установок или рекомендации. Можно, конечно, придерживаться и классической схемы, когда вы берете "n" циклов и по итогу смотрите, но во многих случаях можно сократить количество этих итераций и, например, отбросить систему уже на начальном этапе, либо наоборот — сделать вывод о ее прекрасной работоспособности и гибкости. Я всегда стараюсь придерживаться именно этого подхода, ведь он экономит время, ведь время это самое ценное, что есть у нас. На основе предыдущих выводов можно создать более полный и общий показатель эффективности вашей разработки, принимая во внимание, что в среднем вы используете "m" тестов вместо полных "n":

  • ET= ( Ps*Pf)/(TSumm)
  • TSumm = T + m*Tm
  • Tm — среднее время цикла(тестирования-модификации-оптимизации)

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

Но также мы знаем, что на каждый найденный вариант требуется время на разработку прототипа "T" и на процессы доработки "m*Tm". Чем больше вероятность успеха, отнесенная к одному полному циклу разработки, тем эффективнее наш подход. Во многом итоговое время зависит именно от времени тестирования. Изначально я делал тиковых роботов, но всем советую делать только такие прототипы, которые работают по барам. Во-первых, вы в несколько раз ускорите свои тесты, во-вторых уйдете от тиков и не будете тратить время на тесты с реальными тиками, а это, поверьте мне, очень большое ускорение вашей разработки. Далее мы разберем какие критерии можно предъявлять стратегии и какие из них стоит брать в расчет.

Основные показатели стратегии

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

  • Математическое ожидание
  • Профит фактор
  • Абсолютная просадка
  • Относительная просадка
  • Максимальная просадка
  • Фактор восстановления
  • Процент прибыльных сделок

Математическое ожидание

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

  • M_Points=( Сумм(1,n)(PrPoints[i]) - Сумм(1,n)(LsPoints[i]) )/n
  • M=( Сумм(1,n)(Pr[i]) - Сумм(1,n)(Ls[i]) )/n

Где:

  • PrPoints[i] — если i-я сделка прибыльна, то это величина ее прибыли в пунктах
  • LsPoints[i] — если i-я сделка убыточна, то это величина ее убытка в пунктах
  • Pr[i] — если i-я сделка прибыльна, то это величина ее прибыли в валюте депозита
  • Ls[i] — если i-я сделка убыточна, то это величина ее убытка в валюте депозита
  • n — количество сделок

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

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

  • PrPoints[i]=PrPoints_0[i] - (SpreadOpen[i]/2 + SpreadClose[i]/2) - (OrderComission[i]/OrderLots[i])/TickValue + (OrderSwap[i]/OrderLots[i])/TickValue
  • Pr[i]=Pr_0[i] - (SpreadOpen[i]/2 + SpreadClose[i]/2)*OrderLots[i])*TickValue - OrderComission[i] + OrderSwap[i]

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

Профит фактор

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

  • PrFactor = Сумм(1,n)(Pr[i]) / Сумм(1,n)(Ls[i])

Как видно из формулы, если знаменатель данной формулы обращается в ноль, то профит фактор посчитать невозможно, ну или формально можно принять что это предел при знаменателе, стремящемся к нулю с положительной части аргумента. Предел равен плюс бесконечности, то есть если нет убыточных сделок, этот показатель обращается в бесконечность, а если нет прибыльных сделок, то этот показатель обращается в "0". Получается что диапазон значений этой величины [0,+бесконечность]. Средним значением тут является число 1, все что больше, то прибыльное, что меньше — то убыточное.

Дальше по важности идут 2 параметра, по сути они отражают одно и то же, но немного по-другому. Оба этих параметра, на мой взгляд, отражают одну и ту же величину, просто немного по-разному.

Максимальная просадка

Максимальная просадка — это максимальная разница между двумя соседними максимумом и минимум средств, если считать, что сначала достигнут максимум, а потом прибыль пошла на спад вплоть до следующего минимума. Если обозначить цены массива вершин PriceExtremum[i], то максимальная просадка будет:

  • MaximumDrawdown = MaxOf( PriceExtremum[i+1]- PriceExtremum[i] )

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

Фактор восстановления

Практически идентичная величина предыдущей за тем малым исключением, что прибыль присутствует в формуле:

  • RecoveryFactor = TotalProfit/MaximumDrawdown

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

Процент выигрышных сделок

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

  • WinPercent= (100*NProfit)/(NProfit + NLoss)

Абсолютная просадка

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

  • AbsoluteDrawdown= StartBalance - MinimumBalance
Относительная просадка

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

  • 100*AbsoluteDrawdown/EndProfit

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

Остальные параметры стратегии

Так же существуют некоторые менее важные параметры стратегии, но не стоит их недооценивать

  • Максимальный выигрыш
  • Максимальный проигрыш
  • Средний выигрыш
  • Средний проигрыш
  • Максимальная череда выигрышных сделок
  • Максимальная череда проигрышных сделок
  • Средняя череда выигрышных сделок
  • Средняя череда проигрышных сделок

Максимальный выигрыш

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

Максимальный проигрыш

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

Средний выигрыш

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

  • MiddleProfit= Сумм(Pr[i])/n;

Средний проигрыш

Аналогично среднему выигрышу, только используя убыточные сделки:

  • MiddleLoss= Сумм(Ls[i])/n;

Максимальная череда выигрышных сделок

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

Максимальная череда проигрышных сделок

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

Средняя череда выигрышных сделок

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

  • MiddleWins= Сумм(Wins[i])/n

где Wins[i] — длина конкретной полуволны. Если разделить весь график баланса на возрастающие и падающие участки и выделить только возрастающие, и сосчитать в них количество сегментов(или сделок что то же самое), при этом еще сосчитать количество таких полуволн(возрастающих), что будет "n", то можно будет посчитать сам показатель, который ни что иное как среднее арифметическое определенных полуволн.

Средняя череда проигрышных сделок

Аналогичный показатель за тем лишь отличием, что считаются отрицательные полуволны:

  • MiddleLosses= Сумм(Loss[i])/n

Мои дополнения

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

  • Фактор линейности

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

  • LinearFactor = MaxDeviation/EndBalance
  • MaxDeviaton = Max(MathAbs(Balance[i]-AverageLine))
  • AverageLine=StartBalance+K*i
  • K=(EndBalance-StartBalance)/n
  • n - количество сделок в тесте

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

Кое что можно изобразить на рисунке ниже для понимания:


На какие показатели стоит ориентироваться при тестировании или обзоре системы

На мой взгляд есть всего несколько основных показателей системы которые стоит брать в расчет:

  • Математическое ожидание в пунктах
  • Профит фактор либо его эквивалент
  • Максимальная просадка
  • Максимальная череда проигрышных сделок
  • Фактор линейности

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

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

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

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

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

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

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

Баланс и эквити

Этот вопрос очень важно рассмотреть новичкам, в особенности тем, кто не видит между этими величинами разницы. Эквити— это текущая незафиксированная прибыль, а баланс — текущая зафиксированная прибыль. Разница в том, что в основном все смотрят на линию баланса, но никак не на эквити, потому что она более яркая и привлекает к себе внимания. Строго говоря, в хороших торговых системах эквити максимально близко находится к линии баланса. Это говорит о том что в стратегии не используется никаких мухлежных трюков типа сетки или мартингейла, пирамидинга. Я, конечно, не говорю, что эти приемы не работают, но без хорошего сигнала это лишь бутафория, будем честными. Подтверждения моих слов можно найти в предыдущих статьях. В тестере стратегий MetaTrader 5 и на сайте MQL5 линия баланса отображается темно синим. Линия эквити отображается зеленым. Чем ближе линия эквити к линии баланса, тем безопаснее стратегия, конечно, при условии того, что обе линии идут вверх. 

Показатели реальной торговой системы и ее жизнеспособность

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

Моя практика показывает, что система, способная торговать прибыльно по всей истории, будет иметь примерно 5-50 пунктов математического ожидания, при профит факторе лежащем в диапазоне 1.05-3.0. Я очень люблю таймфрейм M5, так как все рабочие системы, что я создавал работали именно на этом таймфрейме, и при желании можно было их запустить на M1. Это тоже очень хороший график, наверное из за того, что это самые маленькие бары и на единицу времени они содержат больше информации ( High[i],Low[i],Close[i],Open[i] ). Данные точки баров — это сохраненные реальные тики по сути, и чем меньше период графика тем больше в нем сохранено реальных тиков внутри свечей. При тестировании системы в тестере для многих систем это будет иметь важнейшее значение, если, конечно, вы не тестируете по реальным тикам.

Лично я никогда не тестирую по реальным тикам, потому что уже давно взял на вооружение одну концепцию. Все мои советники работают по закрытию бара, и мне нет надобности беспокоиться об искусственной генерации тиков, ведь закрытие бара — это всегда реальный тик. Если оценивать в среднем, то средний профит-фактор найденных мной систем был в районе 1.2, а математическое ожидание около 15 пунктов. Все потому, что я использовал довольно низкие таймфреймы. Намного сложнее найти что-то рабочее на высоких таймфреймах. Математическое ожидание вы поднимете, но профит фактор вряд ли.

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

Как правильно тестировать систему

Лично я для теста и своих и чужих систем, хотя, конечно, в 99 процентах я тестирую именно свои системы, использую следующий подход:

Для первого теста всегда выбирается последний год, если считать от текущей даты, ну или чуть больше, не сильно разница. Если тест мне нравится, я беру еще несколько участков. Важно понимать, что для комплексного анализа нужно брать участок не меньше чем 10 лет. А лучше 20.

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

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

Добившись наилучших показателей, можно приступать к тестированию системы на демо счете. Если система показывает приемлемый результат на демо счете, тогда можно пробовать ее на реальном. Опять же, еще один плюс работы советника по барам, это то, что результат на демо вообще не будет отличаться от результата на реале, но, конечно, при условии адекватного брокера. Лично я рекомендую Alp***. Буковки сами дорисуете. Исторические данные данного брокера без искажений. Еще не советую тестировать тиковые роботы, там нет никаких гарантий. Только те советники что работают по закрытиям либо открытиям баров.

Параметры баров

Для того чтобы правильно понимать котировку, я считаю, что необходимо рассмотреть, что такое бар или свеча и какие данные в них содержатся, и какую информацию можно получить исходя из вида самого бара или свечи. Бар или свеча — это отрезок тиковой истории фиксированной длины, в котором не сохраняются все тики, но сохраняется стартовый тик, конечный тик, максимальный тик и минимальный тик, а так же время открытия бара, изменяемое в datetime. Данная величина представляет собой количество секунд прошедших с 1 января 1970 года. Внутри бара есть 6 величин:

  • Close[]
  • Open[]
  • Low[]
  • High[]
  • Time[]
  • Volume[]

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


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

Пишем и тестируем простой советник на объемах

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

Начнем с уже до боли всем известных библиотек для работы с позициями:

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
CPositionInfo  m_position=CPositionInfo();// trade position object
CTrade         m_trade=CTrade();          // trading object

Нужны они в первую очередь для упрощения кода. Что и как работает там, объяснять не буду, информации полно на сайте.

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

enum MODE_CALCULATE
   {
   MODE_1=0,
   MODE_2=1,
   MODE_3=2,
   MODE_4=3
   };

Это делается с тем расчетом, что режимов будет несколько для того, чтобы определить самую действенную формулу рынка. Изначально должны быть какие-то общие представления о том, какую физику мы хотим эксплуатировать, но ведь мы не знаем, какая формула будет максимально действенной для нашего случая. В данном роботе я создал 4 варианта такой формулы и мы будем смотреть, какой из вариантов лучше всего описывает рынок. Слишком много режимов плодить тоже не нужно, так как если есть какая-то правда в нашем предположении, то мы ее увидим непременно. Я обычно делаю не более 4 режимов.

Далее определим входные параметры и что зачем нужно:

input MODE_CALCULATE MODEE=MODE_1;//Mode
input int TradeHour=0;//Start Trading Hour
input int TradeMinute=1;//Start Trading Minute
input int TradeHourEnd=23;//End Trading Hour
input int TradeMinuteEnd=59;//End Trading Minute

input bool bWriteValuesE=false;//Log
input int CandlesE=50;//Bars To Analyse
input int Signal=200;//Signal Power
input int PercentE=52;//Percent Signals To One Side

input bool bInvert=false;//Trade Invert

input int SLE=3000;//Stop Loss Points
input int TPE=3000;//Take Profit Points
input double Lot=0.01;//Lot

input int MagicF=15670867;//Magic

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

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

Для того чтобы быстро и удобно вычислять значения предопределенных массивов нужно ввести следующие функции:

MqlTick LastTick;//последний тик

double High[];
double Low[];
double Close[];
double Open[];
datetime Time[];
long Volume[];

void DimensionAllMQL5Values()//подготовка массивов
   {
   ArrayResize(Time,CandlesE,0);
   ArrayResize(High,CandlesE,0);
   ArrayResize(Close,CandlesE,0);
   ArrayResize(Open,CandlesE,0);   
   ArrayResize(Low,CandlesE,0);
   ArrayResize(Volume,CandlesE,0);
   }

void CalcAllMQL5Values()//пересчет массивов
   {
   ArraySetAsSeries(High,false);                        
   ArraySetAsSeries(Low,false);                              
   ArraySetAsSeries(Close,false);                        
   ArraySetAsSeries(Open,false);                                 
   ArraySetAsSeries(Time,false); 
   ArraySetAsSeries(Volume,false);                                   
   CopyHigh(_Symbol,_Period,0,CandlesE,High);
   CopyLow(_Symbol,_Period,0,CandlesE,Low);
   CopyClose(_Symbol,_Period,0,CandlesE,Close);
   CopyOpen(_Symbol,_Period,0,CandlesE,Open);
   CopyTime(_Symbol,_Period,0,CandlesE,Time);
   CopyTickVolume(_Symbol,_Period,0,CandlesE,Volume);
   ArraySetAsSeries(High,true);                        
   ArraySetAsSeries(Low,true);
   ArraySetAsSeries(Close,true);                        
   ArraySetAsSeries(Open,true);                                 
   ArraySetAsSeries(Time,true);
   ArraySetAsSeries(Volume,true);
   }

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

Основные переменные и логику я поместил в static class:

class TickBox
   {
   public:
   static int BarsUp;
   static int BarsDown;
   static double PowerUp;
   static double PowerDown;
   static double PercentUp;
   static double PercentDown;
   static double PercentPowerUp;
   static double PercentPowerDown;

   static void CalculateAll(MODE_CALCULATE MODE0)//посчитаем все необходимые параметры
      {
      BarsUp=0;
      BarsDown=0;
      PercentUp=0.0;
      PercentDown=0.0;
      PowerUp=0.0;
      PowerDown=0.0;
      if ( MODE0 == MODE_1 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            }
         }
         
      if ( MODE0 == MODE_2 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(MathAbs(Open[i] - Close[i])/_Point)*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(MathAbs(Open[i] - Close[i])/-_Point)*Volume[i];
               } 
            }
         }
         
      if ( MODE0 == MODE_3 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/_Point)*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/_Point)*Volume[i];
               } 
            }
         }
         
      if ( MODE0 == MODE_4 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            }
         }
         
      if ( BarsUp > 0 && BarsDown > 0 )
         {
         PercentUp=(double(BarsUp)/double(BarsUp+BarsDown))*100.0;
         PercentDown=(double(BarsDown)/double(BarsUp+BarsDown))*100.0;
         PercentPowerUp=(double(PowerUp)/double(PowerUp+PowerDown))*100.0;
         PercentPowerDown=(double(PowerDown)/double(PowerUp+PowerDown))*100.0;
         }         
      }
   };
   int TickBox::BarsUp=0;
   int TickBox::BarsDown=0;
   double TickBox::PowerUp=0;
   double TickBox::PowerDown=0;   
   double TickBox::PercentUp=0;
   double TickBox::PercentDown=0;
   double TickBox::PercentPowerUp=0;
   double TickBox::PercentPowerDown=0;

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

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

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

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

Далее опишем главную функцию, в которой будем открывать и закрывать позиции:

void Trade()
   {
   SymbolInfoTick(Symbol(),LastTick);
   MqlDateTime tm;
   TimeToStruct(LastTick.time,tm);
   int MinuteEquivalent=tm.hour*60+tm.min;
   int BorderMinuteStartTrade=HourCorrect(TradeHour)*60+MinuteCorrect(TradeMinute);
   int BorderMinuteEndTrade=HourCorrect(TradeHourEnd)*60+MinuteCorrect(TradeMinuteEnd);
   if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= 1.0 && TickBox::PercentPowerUp >= 50.0 )
      {
      if ( !bInvert ) ClosePosition(POSITION_TYPE_BUY);
      else ClosePosition(POSITION_TYPE_SELL);
      }
      
   if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= 1.0 && TickBox::PercentPowerDown >= 50.0 )
      {
      if ( !bInvert ) ClosePosition(POSITION_TYPE_SELL);
      else ClosePosition(POSITION_TYPE_BUY);
      }
      
     if ( BorderMinuteStartTrade > BorderMinuteEndTrade )
        {
        if ( PositionsTotal() == 0 && !(MinuteEquivalent>=BorderMinuteEndTrade && MinuteEquivalent<= BorderMinuteStartTrade) )
           {
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerUp >= PercentE )
              {
              if ( !bInvert ) m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              else m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              }
      
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerDown >= PercentE )
              {
              if ( !bInvert ) m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              else m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              }
           }        
        }
     if ( PositionsTotal() == 0 && BorderMinuteStartTrade <= BorderMinuteEndTrade )
        {
        if ( MinuteEquivalent>=BorderMinuteStartTrade && MinuteEquivalent<= BorderMinuteEndTrade )
           {
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerUp >= PercentE )
              {
              if ( !bInvert ) m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              else m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              }
      
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerDown >= PercentE )
              {
              if ( !bInvert ) m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              else m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              }
           }        
        }
   }

Открываем по силе сигнала и его качеству измеренному в процентах. Закрываем, если есть хотя бы минимальный намек на смену сигнала.

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

void ClosePosition(ENUM_POSITION_TYPE Direction)//закрыть позицию по символу
   {
   bool ord;
   ord=PositionSelect(Symbol());
   if ( ord && int(PositionGetInteger(POSITION_MAGIC)) == MagicF  && Direction == ENUM_POSITION_TYPE(PositionGetInteger(POSITION_TYPE)) )
      {
      if(m_position.SelectByIndex(0)) m_trade.PositionClose(m_position.Ticket());          
      }
   }

Далее опишем основные события и функцию для работы по барам:

int OnInit()
  {
  m_trade.SetExpertMagicNumber(MagicF);//установим магик для позиций
  DimensionAllMQL5Values();//подготовим предопределенные массивы
  return(INIT_SUCCEEDED);
  }

datetime Time0;
datetime TimeX[1];
bool bNewBar()
   {
   CopyTime(_Symbol,_Period,0,1,TimeX);
   if ( Time0 < TimeX[0] )
      {
      if (Time0 != 0)
         {
         Time0=TimeX[0];
         return true;
         }
      else
         {
         Time0=TimeX[0];
         return false;
         }
      }
   else return false;
   }

void OnTick()
  {
  if ( bNewBar())//работаем по барам
     {
     CalcAllMQL5Values();
     TickBox::CalculateAll(MODEE);
     if (bWriteValuesE)
        {
        Print("% Sit in buy = ",TickBox::PercentUp);
        Print("% Sit in sell = ",TickBox::PercentDown);
        Print("Signal = ",MathAbs(TickBox::BarsDown-TickBox::BarsUp));
        Print("% Resistance = ",TickBox::PercentPowerUp);
        Print("% Support = ",TickBox::PercentPowerDown);        
        Print("***************************************************************************");
        }
     Trade();
     } 
  }

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

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

Тестируем советник

В данном разделе протестируем наш советник и попытаемся найти рабочие моменты, если они вообще присутствуют. Начнем с теста по последнему году. Возьмем пару EURUSD M5. Перебирая режимы работы и тестируя 10 лет истории, используя еще и разные временные коридоры, я нашел следующий приемлемый результат. Сет, с которым тестировался советник, будет приложен к статье. Следуя собственным правилам анализа систем, я попеременно менял как режимы работы, так и промежуток серверного времени для торговли, и в результате, примерно за 30-60 минут, нашел следующие параметры.

Ниже будет тест на последнем годе:


Далее я тестировал первый год в 10-летнем промежутке:

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

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

Как видно, и здесь есть признаки глобальной закономерности и нам лишь остается протестировать весь промежуток и посмотреть, как это выглядит в глобальном масштабе:


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

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

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

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

Заключение

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

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

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

Я никогда не понимал людей которые здесь варятся годами и вешают тысячу индикаторов на график и пытаются что-то там увидеть, это путь в никуда. Сначала нужно определить, вы настроены на результат или просто как хобби этим заниматься, я считаю, что есть гораздо более интересные хобби, чем годами смотреть на унылую котировку. Форекс — это черная дыра, и если в ней застрять, то можно никогда не вернуться.

Прикрепленные файлы |
VAI_EURUSD_M5.set (1.28 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (67)
Denis Kirichenko
Denis Kirichenko | 8 нояб. 2020 в 23:13
AMK_robot:

Респект и спасибо автору. Прочитал с пользой и удовольствием. Не надо придираться к коду - это иллюстрация некой идеи...

Забавно читать такое на программерском форуме...

Evgeniy Ilin
Evgeniy Ilin | 9 нояб. 2020 в 10:56
AMK_robot:

Респект и спасибо автору. Прочитал с пользой и удовольствием. Не надо придираться к коду - это иллюстрация некой идеи.

Мне осталось не ясно с каким плечом вы тестировали ваш впечатляющий и загадочный код? Прекрасный результат. Надеюсь что в дальнейшем будут подробности.

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

Evgeniy Ilin
Evgeniy Ilin | 9 нояб. 2020 в 11:03
Denis Kirichenko:

Забавно читать такое на программерском форуме...

Меня больше удивило "прекрасный результат" ))). Код ***с ним DDD. Ну и такое бывает ). Что обидно мало кто понял вообще о чем статья. Может я слишком поверил в заинтересованность аудитории

Vladimir Gulakov
Vladimir Gulakov | 27 июл. 2021 в 17:46
Теоретически все правильно. Только на практике получается, что теоретически правильные системы результат почти не дают. Это не моя сугубо точка зрения. Эти выводы выходят из анализа методов торговли успешных трейдеров с долгоиграющими стратегиями. Мои сигналы просто разделяются по степени риска. Чем больше риск, тем больше вероятности просадки, но тем больше и доход. .... 
Danylo Hukov
Danylo Hukov | 22 мая 2022 в 11:28
  • LinearFactor = MaxDeviation/EndBalance
  • MaxDeviaton = Max(MathAbs(Balance[i]-AverageLine))
  • AverageLine=StartBalance+K*i
  • K=(EndBalance-StartBalance)/n
  • n - количество сделок в тесте

Спасибо автору. Я, как и многие, наибольшее внимание всегда уделял именно именно линейности роста прибыли. Использую для оптимизации в таком виде, правда без дополнительных классов и прочих усложнений(не умею такое). Считаю баланс и заполняю массив в OnTradeTransaction() после каждой сделки DEAL_ENTRY_OUT, а в OnTester() сравниваю с идеальной линией.  Работает за 1 прогон. Добавил возможность переключения пользовательского критерия. Использую еще вариант  среднего значения отклонения от идеальной линии баланса и вариант отклонения экуаити от идеальной линии баланса. Согласен с тем, что "ровность кривой" ))) дает наибольшее представление о работоспособности системы в будущем по сравнению с остальными критериями, но естественно - не на 100%.

Ну и там же в OnTester()  откидываю ненужные варианты , такие как "мало сделок" и "маленькое матожидание" обнулением показателя LinearFactor , соответственно оптимизатор такие гены тоже не использует и сосредотачивается на "более правильных" результатах.

Ещё раз спасибо.

Практическое применение нейросетей в трейдинге. Python (Часть I) Практическое применение нейросетей в трейдинге. Python (Часть I)
В данной статье мы поэтапно разберем вариант реализации торговой системы на основе программирования глубоких нейронных сетей на Python. Для этого мы используем библиотеку машинного обучения TensorFlow, разработанной компанией Google. А для описания нейронных сетей используем библиотеку Keras.
Работа с таймсериями в библиотеке DoEasy (Часть 55): Класс-коллекция индикаторов Работа с таймсериями в библиотеке DoEasy (Часть 55): Класс-коллекция индикаторов
В статье продолжим развитие классов объектов-индикаторов и их коллекции. Создадим для каждого объекта-индикатора его описание и скорректируем класс-коллекцию для безошибочного хранения и получения объектов-индикаторов из списка-коллекции.
Примеры анализа графиков с использованием Секвенты Демарка и уровней Мюррея-Ганна Примеры анализа графиков с использованием Секвенты Демарка и уровней Мюррея-Ганна
Секвента Томаса Демарка отлично покаызвает изменения баланса в движении цены. Особенно хорошо это видно, если сочетать её сигналы с индикатором уровней, например, с уровнями Мюррея. Статья именно о таких сочетаниях. Текст рассчитан скорее на новичков в торговле, и тех, у кого всё ещё не получается найти свой "Грааль", хотя я и показываю некоторые особенности построения уровней, которых на других форумах не встречал. Так что, возможно, местами будет полезно и продвинутым пользователям.. Ну, а гуру приглашаю к диалогу и критике...
Набор инструментов для ручной разметки графиков и торговли (Часть II). Рисование разметки Набор инструментов для ручной разметки графиков и торговли (Часть II). Рисование разметки
Статья продолжает цикл, в котором я показываю, как создавал удобную для меня библиотеку для ручной разметки графиков с помощью сочетаний клавиш. Разметка происходит прямыми линиями и их комбинациями. В этой части рассказано непосредственно о самом рисовании с помощью функций, описанных в первой части. Библиотеку можно подключить к любому эксперту или индикатору, существенно облегчив себе задачи разметки. Данное решение НЕ ИСПОЛЬЗУЕТ внешних dll, все команды реализованы с помощью встроенных средств языка MQL.