| / | Статьи |
Cтатьи
Тестер
Мой первый "грааль"
Авторизуйтесь или зарегистрируйтесь , чтобы добавить новую статью
|
|
Мой первый "грааль" [ en | cn ]".. не программируется искусство, не выводятся два чувства поэзии. Таланты не выращиваются квадратно-гнездовым способом. Они рождаются. Они национальные богатства - как залежи радия, сентябрь в Сигулде или целебный источник .." (А.А.Вознесенский)
В современной среде программистов слово "грааль" имеет ироничный оттенок - под этим подразумевается невозможность создания "универсальной" программы на все случаи жизни, а в случае программирования на языке MQL4 - невозможность создания эксперта, показывающего фантастический результат в реальной торговле. На самом деле валютный рынок являет собой отражение сложного конгломерата явлений - экономических и производственных отношений, характеров людей, политических событий. А кроме того, что более важно, он не поддаётся простой формализации. Опытные трейдеры советуют входить в рынок только в том в случае, если одновременно присутствует не менее трёх-пяти признаков, указывающих на возможную тенденцию. Вместе с тем, выявленные на сегодняшний день закономерности не могут в полной мере служить фундаментальной основой для прогнозирования рынка с большой вероятностью успеха. Подтверждением тому - противоречивые прогнозы ведущих аналитиков именитых банков и финансовых организаций. У всех без исключения аналитиков очень хорошо получается объяснять уже случившиеся события и одновременно с этим мало кто из них может показать серию действительно уверенных прогнозов. Будем справедливы: эти люди делают то, что могут, у большинства из них за плечами немалый опыт трейдера и знания, которым могут позавидовать многие из нас. Однако же будем называть вещи своими именами: практически все они нередко ошибаются. Они могут делать важный вид, пользоваться той или иной популярностью, иногда сколачивать целые состояния (о всевозможных "гуру" очень хорошо написано в книге А.Элдера "Как играть и выигрывать на бирже") но факт остаётся фактом - опытные аналитики нередко ошибаются. Каковы же при этих обстоятельствах шансы начинающего программиста, осваивающего первые шаги в торговле на рынке Forex ? Попробуем проследить путь, который проходит начинающий исследователь в поисках "грааля".
1. Из чего состоит "грааль".
1.1. Формальная стратегия. В подавляющем большинстве случаев начинающий программист не ставит перед собой задачу в короткий срок создать сверхприбыльную торговую стратегию. Подогреваемый мыслью о крупных и быстрых заработках на валютном рынке, он, тем не менее, обычно понимает, что для получения хотя бы немного прибыльного эксперта необходимо задаться чёткими критериями, по которым будут осуществляться торговые операции. Для поиска хороших критериев наш герой открывает клиентский терминал MetaTrader 4 и смотрит на график EURUSD в минутном масштабе. Очень легко заметить, что курс валют изменяется волнами: вверх - вниз, вверх - вниз. Герой решает зарабатывать на этих волнах. Но для того, чтобы "поймать" волну, нужно как-то определить, что подъём уже кончился и вот уже начинается спуск. Если критерием направления выбрать простое движение курса, то из этого ничего не выйдет, потому что черные и белые свечи часто сменяют друг друга, причём амплитуда этого мелкого дребезжания зачастую находится в пределах спреда или близко к тому. Кроме того, хотелось бы открыться на вершине волны, а не на склоне. И волны, к сожалению, имеют разную высоту. Немного поразмыслив, наш герой определяет следующие критерии:
Рис.1. Торговые критерии к эксперту Грааль_1. Жизнь подчас готовит нам удивительный, неожиданный опыт. Всего за 3 дня новоиспечённый программист создал свой первый "грааль". extern int TP=100; extern int SL=100; extern int lim=1; extern int prodvig=3; extern double Prots= 10; int total, bb=0,ss=0; double max,min,lmax,lmin,Lot; int start(){ total=OrdersTotal(); if (total==0){bb=0;ss=0;} if (max<Bid) max=Bid;if (min>Ask) min=Ask; if (((max-Bid)>=lim*Point)&&(Bid>lmax )) { for (int i=total;i>=0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY) {OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE); bb=0;}} Strateg(1); } if (((Ask-min)>=lim*Point)&&(lmin>Ask )) { for (i=total;i>=0;i--) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL) {OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);ss=0;}} Strateg(2);}return;} void Strateg (int vv) {if (vv==1 && ss==0) {OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red); ss=1;} if (vv==2 && bb==0) {OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);bb=1;} lmax=Ask+prodvig*Point; lmin=Bid-prodvig*Point; return; } double Lots(){ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1); double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); if (Lot==0 ) Lot=Min_Lot; return(Lot); }
Что получилось, то получилось. Не будем судить строго - это ведь первый опыт начинающего программиста, у которого ещё не сложился свой стиль. И будем относиться уважительно, потому что этот эксперт работает и показывает действительно фантастический результат. Давайте представим код в удобочитаемом виде и попробуем разобраться, что здесь к чему. После некоторого редактирования этот же эксперт может выглядеть так:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Грааль_1.mq4. // Используется в качестве примера в статье "Мой первый Грааль". // Сергей Ковалёв, Днепропетровск, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/. //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int TP = 100; // ТэйкПрофит ордера extern int SL = 100; // СтопЛосс ордера extern int lim= 1; // Дистанция возврата курса extern int prodvig=3; // Дистанция продвижения курса extern double Prots= 10; // Процент от свободных средств //-------------------------------------------------------------------------------------------- int total, // Количество лотов bb=0, // 1 = факт налиия ордера Buy ss=0; // 1 = факт налиия ордера Sell //-------------------------------------------------------------------------------------------- double max, // Максимальная цена на горке (абс) min, // Минимальная цена во впадине(абс) lmax, // Пороговая цена, после преодоления // которой рассматриваем продажу(абс) lmin, // То же для покупки Lot; // Количество лотов //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Количество лотов if (total==0) // Если ордеров нет, .. { bb=0; // .. то нет баёв ss=0; // .. то нет селов } if (max<Bid) max=Bid; // Считаем максим цену на горке if (min>Ask) min=Ask; // Считаем миним цену во впадине //------------------------------------------------------------- Цена разворачивается вниз ---- if (((max-Bid)>=lim*Point)&&(Bid>lmax )) // Разворот на высовком уровне { for (int i=total;i>=0;i--) // По всем ордерам { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_BUY) { OrderClose(OrderTicket(),OrderLots(),Bid,3,CLR_NONE);// Закрываем бай bb=0; // Баёв больше нет } } Strateg(1); // Открывающая функция } //------------------------------------------------------------ Цена разворачивается вверх ---- if (((Ask-min)>=lim*Point)&&(lmin>Ask )) // Разворот глубоко внизу { for (i=total;i>=0;i--) // По всем ордерам { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true && OrderType()==OP_SELL) { OrderClose(OrderTicket(),OrderLots(),Ask,3,CLR_NONE);// Закрываем селл ss=0; // Селлов больше нет } } Strateg(2); // Открывающая функция } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Strateg (int vv) // Открывающая функция { //============================================================================================ if (vv==1 && ss==0) // Селловая ситуация и селлов нет { OrderSend(Symbol(),OP_SELL,Lots(),Bid,3,Bid+SL*Point,Bid-TP*Point,"",0,0,Red);// Откр ss=1; // Теперь есть селл } //-------------------------------------------------------------------------------------------- if (vv==2 && bb==0) // Баёвая ситуация и баёв нет { OrderSend(Symbol(),OP_BUY, Lots(),Ask,3,Ask-SL*Point,Ask+TP*Point,"",0,0,Blue);// Откр bb=1; // Теперь есть бай } //-------------------------------------------------------------------------------------------- lmax=Ask+prodvig*Point; // Переопределяем новые пороговые .. lmin=Bid-prodvig*Point; // .. уровни для откр и закр //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // Вычисление лотов { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Вычисляем колич. лотов double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Минимально допустимая стоим. лотов if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /* В целом содержание советника вполне понятно. В верхней части до функции start() собраны переменные. В функции start() сначала вычисляется текущее положение курса на склоне горки (впадины), а после осуществляется анализ ситуации на срабатывание торговых критериев. И если критерии срабатывают, то производится закрытие уже отработавших ордеров. В эксперте используются также 2 функции - Strateg() для открытия новых ордеров и Lots() для определения количества лотов. Для учёта уже открытых ордеров используются переменные ss и bb. Очень важным инструментом из состава клиентского терминала MetaTrader 4 является тестер стратегий. Наш герой произвёл тщательное тестирование с целью оптимизации параметров и одним из лучших результатов получил такой. Рис. 2. Классический "грааль". Результат получен при тестировании эксперта Грааль_1.mq4 на истории с марта 2005 по июнь 2006 года в масштабе М1 EURUSD на торговых условиях демо-сервера компании MetaQuotes Software Corp.
Легко представить себе радость программиста, собственными руками сотворившего это произведение искусства. Новенький, вполне осязаемый - вот он, сверкающий гранями совершенства, с профитом, достигающим поднебесья, его первый "грааль"! И он легко пришёл к выводу - "Только я!" Какая бы то ни было формальная стратегия совсем не обязательно должна заканчиваться созданием "грааля", но в данном случае получилось именно так. Рассмотрим более подробно, что именно привело к такому результату.
1.2. Прогрессивное вложение средств. Наш герой не остановился на достигнутом и решил попробовать предельно увеличить стоимость ордеров. Он довёл стоимость ордеров при тестировании до 70% (значение extern-переменной Prots=70) от суммы свободных средств, но результат показал неэффективность такого подхода:
Рис. 3. Агрессивное инвестирование средств может привести к неоправданным потерям.
Рассмотрим более подробно причины такого результата.
1.2.1. Геометрическая прогрессия. Обратим внимание на технологию расчёта стоимости ордеров. В соответствии с представленным кодом стоимость ордеров наращивается пропорционально сумме свободных денежных средств: Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Вычисляем колич. лотов double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Минимально допустимая стоим. лотов if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах Этот алгоритм являет собой геометрическую прогрессию. Переменная Prots (процент) позволяет регулировать стоимость ордера в зависимости от текущего количества свободных средств. Такой способ вычисления стоимости ордеров является не вполне корректным, т.к. не учитывает маржинальные требования при работе с конкретным дилером. Вместе с тем, представленный фрагмент кода позволяет решить основную задачу - пропорционального вложения средств. Таким образом, стоимость каждого последующего ордера будет пропорционально зависеть от достигнутых результатов: после каждой прибыльной операции стоимость будет повышаться, а после убыточной - понижаться. В представленном коде эксперта Грааль_1.mq4 стоимость ордера составляет 10% от свободных средств. Сама по себе прогрессия вовсе не является атрибутом "грааля". По этой технологии может быть построен любой другой эксперт из разряда нормальных. Однако, для более удобного рассмотрения состава "грааля" геометрическую прогрессию следует полностью исключить и ориентироваться на результаты тестирования, проведенного при постоянной минимальной стоимости ордеров (равной 0,1 лота, если это возможно). В этом случае мы можем легко судить о количестве заработанных пунктов.
Установим значение переменной Prots равным 0 и в соответствии с этим кодом if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах проведём тестирование при постоянной стоимости ордеров. В этом случае результат будет таким: Рис. 4. Результаты тестирования эксперта Грааль_1.mq4 при постоянной стоимости лотов. Исключение прогрессивной стоимости ордеров наглядно показывает истинный характер изменения кривой баланса - наличие резких скачков, глубоких просадок и прочее. 1.2.2. Агрессивное реинвестирование. Например, вполне приемлемым отношением прибыли и убытка можно считать отношение 3 : 1. То есть, на 100 последовательно открытых и закрытых ордеров должно приходиться 75 прибыльных и 25 убыточных. Вместе с тем, никогда нельзя сказать наперёд как будут распределены убыточные ордера среди прибыльных. Это распределение в значительной степени носит случайный характер.
А. Идеальным случаем последовательности Прибылей и Убытков является равномерное их распределение на протяжении всей торговой истории:
П П П У П П П У П П П У П П П У П П П У П П П У П П П У ...
Однако, нет никакой гарантии, что в реальной торговле распределение всегда будет идеальным. Как раз наоборот, существует большая вероятность, что рано или поздно встретится случай с длинной серией последовательных убытков.
П П П П П П П П П П П П П П П УУУУУ П П П У П П П У ...
К чему может привести эта закономерная случайность? Ответ на этот вопрос зависит от качества торговой стратегии, которой придерживается трейдер. Одно дело, если трейдер ведёт осмотрительную торговлю, соблюдая разумные меры предосторожности, а именно - суммарная стоимость его ордеров не превышает 10-15%; и совсем другое дело, если трейдер допускает агрессивное реинвестирование, а именно вкладывает в торговлю большую долю своего депозита, причём не один раз, а всякий раз после получения очередной прибыли. В случае агрессивного реинвестирования история торгового счёта будет развиваться непредсказуемо. Какой-нибудь редкий "везунчик" может быть и ускользнёт от неприятностей. Но в ряде случаев негативный результат неизбежен. Для иллюстрации возможных сценариев работы эксперта Грааль_1.mq4 проанализируем два варианта инвестиций при прочих равных условиях (один и тот же исторический период, одинаковые настраиваемые параметры).
Обратите внимание на отчёт по результатам тестирования: максимальное количество непрерывных проигрышей (серия убыточных ордеров) для эксперта Грааль_1.mq4 составляет всего 10. В течение всего тестируемого периода были и другие убыточные серии, но каждая из них содержала не более 10-и убыточных ордеров. Эти серии убытков не оказали заметного влияния на общий результат торговли в первом варианте и сыграли роковую роль во втором. Он сделал вывод, что торговля, допускающая агрессивное реинвестирование, является самообманом и рано или поздно приводит к полному разорению. Каждый трейдер сам решает на какой высоте установить планку. В соответствии с принятым решением не заставят себя ждать и результаты.
Покрутив свой "грааль" так и эдак, ещё раз убедившись, что все работает, наш герой открыл реальный счёт и начал "зарабатывать". После нескольких успешно открытых и закрытых ордеров выяснилось, что сумма баланса на реальном счёте расти не собирается, а почему-то неуклонно снижается. Более того, в конце торгового дня сотрудники дилингового центра отключили для его реального счёта возможность использования советников. Наш герой был очень раздосадован. Он стал выяснять причину такой несправедливости у дилеров, но при этом гневно отвергал любые объяснения. Он недоумевал, какие ещё могут быть "технические ограничения" и причём тут "проскальзывание"?! В результате такого первого опыта реальной торговли наш герой пришёл к выводу, что это "плохой ДЦ", что его просто обманули и разорвал свой договор с дилинговым центром.
1.3. Ошибки. Редактор Meta Editor постоянно свидетельствовал об отсутствии ошибок, Рис. 5. Отсутствие ошибок при компиляции.
но они, тем не менее, были. 1.3.1. Отступление от формальной стратегии.
Между чёрным и белым нет чёткой границы. Все промежуточные состояния можно охарактеризовать лишь степенью черноты или белизны. Но обычно бывает понятно, что конкретный цвет ближе к белому, чем к чёрному, или наоборот.. В данном случае "чисто белая" исходная идея была настолько "запачкана" новыми значениями переменных, что стала чернее сажи и утратила какую бы то ни было силу. Можно сказать, что по этой причине случайно и получился "грааль".
1.3.2. Некорректное программирование.
Обратите внимание на то, как в переменных ss и bb ведётся учет ордеров. Такой способ учёта ордеров является некорректным. Ордер учитывается как уже открытый на этапе формирования торгового приказа. В этот момент ещё нельзя сказать наверняка будет ли открыт ордер. Чтобы точно ответить на этот вопрос, необходимо дождаться ответа сервера и проанализировать наличие ордера по факту его присутствия в терминале. Для реальной торговли код в этой части следовало бы переписать, хотя представленный вариант и будет работать в большинстве случаев, в том числе в тестере стратегий (см. статью Учёт ордеров в большой программе ). 1.4. Технические ограничения.
Если для моделирования истории бара большого масштаба уточнением является баровая история меньшего масштаба, то в отношении минутного бара такого уточнения не существует, потому что тиковая история в клиентском терминале MetaTrader 4 не сохраняется и не используется. (см. Strategy Tester: режимы моделирования при тестировании).
Главное отличие любой модели, принятой при тестировании, от реальной торговли заключается в отсутствии при тестировании проскальзывания и рекотирования (предоставление дилером другой цены, отличной от содержащейся в торговом приказе трейдера). Разные дилинговые центры работают с разными источниками котировок (рассматривается ниже). Чем большие и частые отклонения курсов наблюдаются на трафике, тем больше вероятность, что в ряде случаев дилер предложит трейдеру новую цену для исполнения торгового приказа. С другой стороны, чем более "приглаженным" выглядит трафик, тем меньше вероятность получения реквота (requote), но и тем меньше простора для работы советника, торгующего часто, но с малыми целями. Наш герой протестировал Грааль_1 на минутной истории другого дилингового центра (при том же спреде) и воочию убедился, что результат во многом зависит от вида трафика. ![]() Рис. 6. Результат тестирования эксперта Грааль_1.mq4 на истории с 4 апреля 2006 по 26 июля 2006 года в масштабе М1 валютного инструмента EURUSD на торговых условиях демо-сервера Интеграл-банка при постоянной стоимости ордеров. Наличие глубоких просадок, неустойчивое развитие прибыли свидетельствует о балансировании советника на грани убытка. Как правило, разница курсов при рекотировании составляет 1-2 пункта (хотя бывает и гораздо больше на быстром рынке). Это явление не может оказать существенного влияния на успешность работы советника, у которого матожидание выигрыша значительно выше, например, 10 - 15. Но советник, у которого матожидание выигрыша мало, в особенности советник, имеющий матожидание менее 2, не может всерьёз рассчитывать на общий успех, потому что он находится в большой зависимости от характера поставляемых котировок и связанного с этим рекотирования. Будет или не будет выдан реквот на текущем тике конкретным дилером - это отдельный вопрос, решить который может единственно дилер. Но приступая к работе на реальном рынке следует исходить из убеждения, что реквот - это нормальное, естественное явление, и торговая технология работающего на реальном счёте советника должна это учитывать.
Наиболее распространена ситуация, при которой внимание трейдера приковано только к своему торговому счёту и событиям вокруг него, в том числе стратегиям, экспертам и прочему. Однако, кроме заинтересованности трейдера существует ещё и экономическая заинтересованность дилера. При "обычной" торговле могут выиграть обе стороны - и трейдер, использующий продуманную стратегию, и дилер, получающий свой процент от совершённых трейдером торговых операций. В этом случае каждая из сторон заинтересована друг в друге и готова друг друга поддерживать. Однако бывают ситуации, когда деятельность одной из сторон противостоит интересам другой стороны. Например, если дилер в одностороннем порядке повышает спред, запрещает использование автоматической торговли или не открывает (закрывает) ордера по первому касанию цены, это противоречит интересам трейдера. Вместе с тем, существует и такая деятельность трейдера, которая противоречит экономическим интересам дилера. Одним из видов такой деятельности является частые торговые операции на небольшую сумму. Технология работы дилера в целом достаточна проста. Дилер собирает заявки трейдеров на покупку и продажу и вступает в отношения с банком или другой финансовой организацией на разницу в их стоимости. Рассмотрим простой пример. Предположим, дилер обслуживает всего 100 трейдеров, 60 из которых купили по 1 лоту евро против доллара, а 40 - продали по 1 лоту той же валютной пары. В этом случае дилер должен купить 20 лотов (разница между 60 и 40) у банка. При этом дилеру безразлично, куда пойдёт курс. В любом случае он получит полный спред по 80 лотам (40+40) и часть спреда от 20 лотов (часть уйдёт в пользу банка). В этом случае источником прибыли/убытка для 40 трейдеров являются убыток/прибыль других 40 трейдеров. Источником прибыли/убытка для оставшихся 20 трейдеров является банк, а в конечном счёте - юридические лица, обслуживающиеся в банке, продающие/покупающие валюту для экспортно-импортных операций. Это - обычный, "нормальный" порядок взаимоотношений между участниками валютного рынка. Но есть и другая подробность отношения дилера с банком или финансовой организацией. Дело в том, что дилер не вступает в отношения с банком при каждой покупке или продаже трейдера на незначительную сумму. Торговые операции между дилером и банком осуществляются несколько реже, чем клики трейдеров в торговом терминале МТ4. Обычно минимальная сумма в отношениях дилера с банком составляет не более $50 000, что в переводе на стоимость ордера с кредитным плечом 1:100 составляет 0,5 лота. Поэтому, если трейдер всё время работает с маленькой суммой, то, в сущности, он торгует с дилером. В этом случае источником прибыли трейдера являются денежные средства дилера! Дилер - такой же участник валютного рынка, как все другие. Дилер обязательно отслеживает и анализирует характер работы своих трейдеров. Разумеется, в пределах своей экономической заинтересованности дилеры могут смотреть сквозь пальцы на беспорядочное частое инвестирование, если оно приводит к явным потерям трейдера или суммарный результат за некоторый период (например, за день) оказывается нулевым. Но ни один здравомыслящий дилер не позволит продолжаться взаимоотношениям, которые приводят к его финансовым потерям. В этом случае он вынужден как-то реагировать - иначе ему просто нечего делать в экономическом пространстве валютного рынка. Обратите внимание, что сложившийся на сегодняшний день порядок взаимоотношений на валютном рынке - вовсе не прихоть и не злая воля дилера. Его отношения с банками тоже находятся "в рамках" договорных условий. Дилер стремится честно заработать свой спред (обсуждение злоупотреблений со стороны дилера выходит за рамки темы статьи). Может быть он и был бы рад "зеркально" ежесекундно торговать с банком, но на сегодняшний день такой возможности у него нет. В условиях частых торговых операций небольшой стоимости, поступающих от одного трейдера, дилер вынужден принимать меры. В таком случае дилер может устно предупредить трейдера о его работе "на грани фола", может отключить трейдеру возможность вести автоматическую торговлю с помощью советников, может увеличить количество рекотируемых торговых операций.
Существует ещё одно ограничение, отличающее реальную торговлю от тестирования и опробования на демо-счёте. Это - максимальное значение стоимости лотов. Каждый дилинговый центр, будь то банк, букмейкерская контора или финансовая организация, не имеют практической возможности оперировать очень крупными суммами. При стоимости ордеров до 10 - 20 тыс. долларов (обратите внимание, что существует кредитное плечо, как правило, 100) дилинговый центр фактически продаёт/покупает сумму 1 млн долларов. Это - не маленькая сумма, но с такими суммами денежных средств дилеры научились работать и успешно работают. Серьёзные затруднения могут возникнуть при стоимости ордеров более 300 -500 тысяч долларов. В этом случае дилинговый центр безусловно будет вести индивидуальную работу с трейдером. 50 млн долларов - это солидная сумма для любой организации. При большой стоимости ордеров не может быть и речи о твёрдых гарантиях со стороны дилингового центра и сама торговля ведётся с позиции понимания этой особенности трейдером. (в самом деле, какой дилер может позволить себе гарантированное открытие ордера огромной стоимости по первому касанию в условиях неожиданного и сильного движения на валютном рынке..). По этой причине пипсующие советники, оперирующие миллионами, - свидетельство глубокого заблуждения трейдера и с реальной жизнью не имеют ничего общего. Не будем также забывать, что дилеры - живые люди со своим образовательным и культурным уровнем, с так и или иначе поставленным у них делом. Одна и та же убыточная для дилера технология может быть сразу выявлена там, где хорошо работают аналитики и не сразу обнаружена дилерами, работающими кое-как или не имеющими необходимого опыта или программного обеспечения. Но в подавляющем большинстве случаев дилеры тоже когда-то были "граальщиками", имеют собственный опыт трейдеров и как правило очень хорошо понимают тонкости торговли на валютном рынке, в том числе знают что такое геометрическая прогрессия , экономическая заинтересованность, агрессивное реинвестирование, большая и малая стоимость ордеров. В целом, любому трейдеру необходимо исходить из положительного утверждения, что квалификация дилеров значительно выше чем у него, а любая позиция трейдера практически по любому вопросу является обоснованной. Судите сами. Каковы (при этих технических и экономических подробностях) могут быть результаты реальной работы эксперта, открывающего в течение года более 20 000 ордеров? Рис.7. Отчёт по тестированию эксперта Грааль_1.
2. Второй "грааль".2.1 Стратегия. Рис. 8. Участки истории кросс-курсов со значительными отклонениями цены (выбросы). Легко заметить, что в ночное время, когда европейская сессия уже закончилась, а азиатская ещё не началась, на графиках некоторых валютных инструментов появляются отдельные бары, цена которых неожиданно и резко отличается от "обычного" ценового потока и выходит за его пределы. В соответствии с формальной логикой достаточно несколько ниже и несколько выше основного потока выставить отложенные ордера типа Limit и часть из них будет открыта с довольно большой вероятностью успеха. А чтобы адекватно реагировать на изменения основного движения курса, отложенные ордера необходимо "таскать" вдоль некоторой средней линии, всё время поддерживая их на некотором заданном расстоянии от средней МА (Moving Average). Для осуществления задуманного наш герой написал эксперт:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Грааль_2.mq4. // Используется в качестве примера в статье "Мой первый Грааль". // Сергей Ковалёв, Днепропетровск, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/. //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int TakeProfit=5; // TakeProfit ордера extern int StopLoss= 29; // StopLoss ордера extern int Distan = 2; // Дистанция от средней МА extern int Cls = 2; // Закрыть при ** пнктов прибыли extern int period_MA=16; // Период средней МА //extern int Time_1 = 0; // Время начала работы //extern int Time_2 = 0; // Время окончания работы extern int Prots = 0; // Процент от свободных средств //-------------------------------------------------------------------------------------------- int Nom_bl, // Номер ордера BuyLimit Nom_sl, // Номер ордера SellLimit total, // Количество лотов bl = 0, // 1 = факт налиия ордера BuyLimit sl = 0, // 1 = факт налиия ордера SellLimit b = 0, // 1 = факт налиия ордера Buy s = 0; // 1 = факт налиия ордера Sell //-------------------------------------------------------------------------------------------- double OP, // OpenPrice (абсолютн. пунктов) SL, // StopLoss ордера (относит.пункт.) TP, // TakeProfit ордера (относит.пункт.) dist, // Дистанция от средней МА(отн.пун.) Level, // Миним. допуст дистанция отл.орд OP_bl, // OpenPrice BuyLimit (абс. пунктов) OP_sl, // OpenPrice SellLimit(абс. пунктов) cls, // Закрыть при ** прибыли (абс. пун.) MA, // Значение МА (курс) spred, // Спред (абс. пунктов) Lot; // Количество лотов //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { Level=MarketInfo(Symbol(),MODE_STOPLEVEL); // Выясним что нам даёт сервер Level=(Level+1)*Point; // ?:) SL=StopLoss*Point; // StopLoss ордера (относит.пункт.) TP=TakeProfit*Point; // TakeProfit ордера (относит.пункт.) dist=Distan*Point; // Дистанция от средней МА(отн.пун.) cls=Cls*Point; // Закрыть при ** прибыли (абс. пун.) spred=Ask-Bid; // Спред (абс. пунктов) return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Количество лотов bl=0; // Обнулимся в начале прохода sl=0; // Обнулимся в начале прохода b=0; // Обнулимся в начале прохода s=0; // Обнулимся в начале прохода //-------------------------------------------------------------------------------------------- for (int i=total; i>=0; i--) // По всем ордерам { if (OrderSelect(i,SELECT_BY_POS)==true && // Выделим ордер OrderSymbol()==Symbol()) { //-------------------------------------------------------------------------------------------- if (OrderType()==OP_BUY) // Ордер Buy { b =1; // Есть такой ордер Close_B(OrderTicket(),OrderLots()); // Закрыть ордер (надо ли решит ф-ия) } //-------------------------------------------------------------------------------------------- if (OrderType()==OP_SELL) // Ордер Sell { s =1; // Есть такой ордер Close_S(OrderTicket(),OrderLots()); // Закрыть ордер (если надо) } //-------------------------------------------------------------------------------------------- if (OrderType()==OP_BUYLIMIT) // Ордер BuyLimit { OP_bl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice BuyLimit(абс. пунктов) Nom_bl=OrderTicket(); bl=1; // Есть такой ордер } //-------------------------------------------------------------------------------------------- if (OrderType()==OP_SELLLIMIT) // ОрдерSellLimit { OP_sl=NormalizeDouble(OrderOpenPrice(),Digits);//OpenPrice SellLimit(абс.пунктов) Nom_sl=OrderTicket(); sl=1; // Есть такой ордер } //-------------------------------------------------------------------------------------------- } } //-------------------------------------------------------------------------------------------- MA = iMA(NULL,0, period_MA, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение МА Modify_order(); // Активизируем модификацию Open_order() ; // Активизируем открытие //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Close_B(int Nomber, double lots) // Закрытие ордеров Buy { //============================================================================================ if (NormalizeDouble(Bid-OrderOpenPrice(),Digits)>=cls)// Если достигнут заданный профит { OrderClose( Nomber, lots, Bid, 1, Yellow); // Закрываемся b = 0; // И больше нет бая } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Close_S(int Nomber, double lots) // Закрытие ордеров Sell { //============================================================================================ if (NormalizeDouble(OrderOpenPrice()-Ask,Digits)>=cls)// Если достигнут заданный профит { OrderClose( Nomber, lots, Ask, 1, Yellow); // Закрываемся s = 0; // И больше нет селла } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Modify_order() // Модификация ордеров { //============================================================================================ if (bl==1) // Если есть БайЛимит { OP=MA-dist; // Он должен стоять здесь if (MathAbs(OP_bl-OP)>0.5*Point) // А если он здесь не стоит { OrderModify(Nom_bl,OP,OP-SL,OP+TP,0,DeepSkyBlue);// Модификация ордера } } //-------------------------------------------------------------------------------------------- if (sl==1) // Если есть СеллЛимит { OP=MA+spred+dist; // Он должен стоять здесь if (MathAbs(OP_sl-OP)>0.5*Point) // А если он здесь не стоит { OrderModify( Nom_sl, OP, OP+SL, OP-TP, 0, Pink);// Модификация ордера } } //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж void Open_order() // Открывающая функция { // int Tek_Time=TimeHour(CurTime()); // Для тестирования по времени // if (Tek_Time>Time_2 && Tek_Time<Time_1) return; // Для тестирования по времени //============================================================================================ if (b==0 && bl==0) // Нет никаких баёв, открываем bl { OP=MA-dist; // Курс открытия ордера bl if(OP>Ask-Level) OP=Ask-Level; // Уточнение ОР в соотв. с допуском OP=NormalizeDouble(OP,Digits); // Нормализация (МА даёт 5й знак) OrderSend(Symbol(),OP_BUYLIMIT, Lots(),OP,3,OP-SL,OP+TP,"",0,0,Blue);// Открываемся bl=1; // Теперь есть бай } //-------------------------------------------------------------------------------------------- if (s==0 && sl==0) // Нет никаких селов, открываем sl { OP=MA+spred+dist; // Курс открытия ордера sl if(OP<Bid+Level) OP=Bid+Level; // Уточнение ОР в соотв. с допуском OP=NormalizeDouble(OP,Digits); // Нормализация (МА даёт 5й знак) OrderSend(Symbol(),OP_SELLLIMIT,Lots(),OP,3,OP+SL,OP-TP,"",0,0,Red);// Открываемся sl=1; // Теперь есть sl } ///============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // Вычисление лотов { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Вычисляем колич. лотов double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Минимально допустимая стоим. лотов if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /* В качестве настраиваемых переменных выбраны StopLoss, TakeProfit, Distan (дистанция, на которой ордер держится "вдоль" основного курса), Cls (минимальное количество заработанных по ордеру пунктов, при которых ордер необходимо закрыть), period_MA (период МА, которая олицетворяет среднюю линию курсов последней истории) и Prots (процент от свободных средств, стоимость ордера). Этого вполне достаточно чтобы осуществить задуманное.
По ходу написания программы наш герой заметил, что её можно совершенствовать до бесконечности, и решил, что "закончить" программу нельзя, её нужно просто "прекратить"! Тестирование эксперта на EURCHF дало следующий результат: (рассмотрим только этот вариант, хотя подобный результат можно получить и для EURGBP).
Рис. 9. Результат тестирования эксперта Грааль_2.mq4 на истории с марта 2005 по июнь 2006 года в масштабе М1 EURUSD на торговых условиях демо-сервера фирмы MIG Investments.
В данном, как и в предыдущем эксперте, тоже используется технология прогрессивного инвестирования. При постоянной стоимости ордеров график баланса выглядит так:
Рис. 10. Результат тестирования эксперта Грааль_2.mq4 на истории с марта 2005 по июнь 2006 года в масштабе М1 валютного инструмента EURUSD на торговых условиях демо-сервера фирмы MIG Investments при постоянной стоимости ордеров. Поначалу наш герой хотел зарабатывать только в ночное время, но потом с удивлением и радостью обнаружил, что эксперт работает успешно в течение всего рабочего дня. Стоит ли говорить, что увидев эту красоту наш герой снова решил "Только я!" и снова стал "зарабатывать". Но не тут-то было.. На этот раз ему пришлось познакомиться с понятием "выброс". 2.3. Ошибки. В представленном варианте эксперта имеется масса недоработок и некорректного программирования. В Modify_order() не учитывается минимально допустимая дистанция для отложенных ордеров, неправильно поставлен учёт открытых ордеров, не предпринимается отдельная модификация TakeProfit с целью "подогнать" профит под Cls, аналитическая часть эксперта "размазана" по всему коду и прочее. Некорректное и тем более небрежное программирование часто приводит к незаметным ошибкам, а иногда и к тиражированию ошибок при их интеграции в другие эксперты. 2.4. Технические ограничения (выбросы). Любые ограничения, технического или организационного характера, как правило в конечном счёте оборачиваются экономическими потерями. Вопрос лишь в том, за чей счёт эти потери будут покрываться. Обычный свечной график, который трейдер видит на экране, является некоторым усреднённым результатом развития рынка на некоторой ограниченной территории (среди европейских банков, например). Можно проанализировать характер изменения курса на небольшом участке истории у разных дилеров. При этом легко заметить, что все эти графики будут, хоть и незначительно, но отличаться. У одних дилеров график будет содержать множество длинных разнонаправленных свечей, в то время как у других дилеров в этот же период можно наблюдать "тишь да гладь". Тиковый трафик - тоже предмет купли-продажи. Он является результатом работы некоторой обрабатывающей программы, отфильтровывающей лишние и неестественные ценовые тики. А они ("ненормальные" тики) появляются. Это бывает, когда в каком-то конкретном банке какой-то конкретный субъект по каким-то своим причинам (мало ли, может срочно нужно) купил или продал некоторую сумму по цене, далёкой от рыночной. Информация об этом событии воспринимается обрабатывающей программой и если это разовая сделка, то это событие не учитывается при формировании конечного вида трафика. В ряде случаев программе трудно понять какая цена является "нормальной", а какая - нет. По этой причине иногда на графике появляются единичные свечи различной высоты (в зависимости от алгоритма обрабатывающей программы). Это и есть выбросы. В том или ином виде проявляющиеся, они не отражают истинное положение дел на валютном рынке. Не трудно сделать эксперт, который вылавливал бы эти "шипы", "иглы", "выбросы" и открывал ордера на самом пике цены. Но нужно чётко понимать, что в условиях ограничения договорных отношений между дилером и банком, банк, как правило, не оплатит дилеру такую сделку, значит источником прибыли трейдера снова станет карман дилера! А этого дилер никак допустить не может, поэтому он всячески борется с трейдерами за осуществление торговых операций по "нормальному" рыночному курсу. В качестве мер по обеспечению для дилера такой возможности обычно в договоре между дилером и трейдером можно прочесть о правах дилера, среди которых - возможность предложить другую котировку, не гарантированное открытие ордеров на сильных движениях цен, открытие отложенных ордеров по второму касанию цены и другие меры предосторожности. В некоторых случаях дилер может аннулировать и уже открытый ордер, если ему покажется, что ордер открыт на выбросе. Так случилось и с нашим героем. Как ни хорош был "грааль" на демо-счёте, а жизнь снова внесла коррективы. На этот раз он не бросал телефонную трубку, а всякий раз внимательно выслушивал объяснения дилеров по фактам принудительного закрытия ордеров. Но когда ему снова отключили возможность использования советников, он не выдержал и опять разорвал свой договор с дилером. Наш герой решил, что всему виной эти минутные тайм-фреймы, сбивающие с толку нормальных людей. Почитав форумы, пообщавшись с другими трейдерами, он заметил, что большинство из них работают в более крупных масштабах тех же валютных инструментов. "Наверное, в этом есть свой смысл", - рассуждал наш герой. Постепенно он пришёл к заключению "Я и Моцарт" и засучив рукава приступил к разработке своего третьего творения - теперь уже не на минутках ("Больше никогда-никогда!"). 3. Третий "грааль".3.1 Формальная стратегия. Усердно и внимательно рассматривая график валютного инструмента EUR|USD в масштабе Н1, применяя для анализа различные индикаторы, наш герой обнаружил очень привлекательную закономерность. Он заметил, что если МА (Moving Average) меньшего периода пересекает МА большего периода, то рынок, как правило, движется в том направлении , куда стремится МА меньшего периода.Рис. 11. Графическое представление стратегии, основанной на пересечении МА разных периодов. Герой также заметил, что выявленная зависимость проявляется на всех таймфреймах, но твёрдо решил работать только на больших. Остаётся только переложить с трудом добытое знание на язык MQL4, чтобы сообщить эксперту в какую сторону и при каких условиях нужно открываться. А когда эксперт будет готов, необходимо оптимизировать параметры - подобрать наиболее эффективные размерности МА и правильно расставить StopLoss и TakeProfit. На этот раз он произвёл на свет вот такой эксперт://жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Грааль_3.mq4. // Используется в качестве примера в статье "Мой первый Грааль". // Сергей Ковалёв, Днепропетровск, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/. //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int MA1 = 11; // Период 1-й МА extern int MA2 = 23; // Период 2-й МА extern double TP = 50; // ТэйкПрофит ордера extern double SL = 15; // СтопЛосс ордера extern double Prots= 0; // Процент от свободных средств //-------------------------------------------------------------------------------------------- int ret, // Направление пересечения total; // Крличество открытых ордеров //-------------------------------------------------------------------------------------------- double Lot, // Количество лотов Pred, // Предыдущее значение 1-й МА (розов) Tek, // Текущее значение 1-й МА (розов) Golub; // Текущее значение 2-й МА(голубая) //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { //============================================================================================ SL = SL*Point; // СтопЛосс в пунктах TP = TP*Point; // ТэйкПрофит в пунктах return; //============================================================================================ } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Общее количество ордеров if (total==2)return; // Уже открыты оба ордера //-------------------------------------------------------------------------------------------- Tek =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение 1-й МА Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Предыдущее значение 2-й МА Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение 2-й МА //-------------------------------------------------------------------------------------------- if (Peresechenie()==1) Open_Buy(); // Движение снизу вверх = откр. Buy if (Peresechenie()==2) Open_Sell(); // Движение сверху вниз = откр. Sell //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() // Функция определения пересечения { //============================================================================================ if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // Пересечение снизу вверх //-------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // Пересечение сверху вниз //============================================================================================ return(ret); // Возвращаем направление пересечен. } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Buy() // Функция открытия Buy { //============================================================================================ if (total==1) // Если ордер всего один.. { // .. значит можно открыть другой OrderSelect(0, SELECT_BY_POS); // Выделим ордер if (OrderType()==0)return; // Если он buy, то не открываемся } OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// Открываемся //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Sell() // Функция открытия Sell { //============================================================================================ if (total==1) // Если ордер всего один.. { // .. значит можно открыть другой OrderSelect(0, SELECT_BY_POS); // Выделим ордер if (OrderType()==1)return; // Если он sell, то не открываемся } OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Открываемся //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() // Вычисление лотов { //============================================================================================ Lot=NormalizeDouble(AccountEquity()*Prots/100/1000,1);// Вычисляем колич. лотов double Min_Lot = MarketInfo(Symbol(), MODE_MINLOT); // Минимально допустимая стоим. лотов if (Lot == 0 ) Lot = Min_Lot; // Для теста на постоян. миним. лотах //============================================================================================ return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /* Этот эксперт, как и предыдущие, тоже оказался незамысловатым.. В начале эксперта содержится блок описания переменных. В функции start() определяется общее количество ордеров, а также значения МА большего и меньшего периода. В случае, если пересечение МА случилось, вызывается соответствующая функция открытия ордеров Open_*(). Для определения факта пересечения МА используется функция Peresechenie(), а для определения стоимости лотов - функция Lots(). Наш герой просмотрел ещё раз свой эксперт, не нашёл к чему придраться ("Простенько и со вкусом!") и поставил эксперт на тестирование. После оптимизации переменных он смог получить замечательный результат:
Рис. 12. Результат тестирования эксперта Грааль_3.mq4 на истории с марта 2005 по июль 2005 года в масштабе Н1 валютного инструмента EURUSD на торговых условиях демо-сервера компании MetaQuotes Software Corp.
Три миллиона за пять месяцев. Замечательно! Но что-то в этом графике баланса напоминало нашему герою горечь предыдущего опыта. И он решил не торопиться. 3.2. Прогрессия. После тестирования этого же эксперта при постоянной стоимости ордеров он получил вполне приличный график изменения баланса: Рис. 13. Результат тестирования эксперта Грааль_3.mq4 на истории с марта 2005 по июль 2005 года в масштабе Н1 валютного инструмента EURUSD на торговых условиях демо-сервера MetaQuotes Software Corp. при постоянной стоимости лотов.
Шесть тысяч пунктов за пять месяцев - это вполне ощутимо. Более тысячи пунктов в месяц! Но наш герой сомневался - ставить или не ставить эксперт на "заработки"? Ведь дважды он уже обжёгся.. Тогда он решил более внимательно посмотреть на таймфрейм с отметками открытия и закрытия ордеров и к своему удивлению обнаружил, что его эксперт без всяких на то видимых оснований открывает ордера не только в момент пересечения МА, но и в других местах!
Рис. 14. Открытие ордеров экспертом Грааль_3.mq4 в ситуациях, не предусмотренных исходной стратегией.
3.3. Ошибки. "Вот это новости! Это наверное кривой MetaEditor!", - была его первая мысль. Но постепенно, настойчиво и последовательно разбирая свой собственный код по косточкам, он снова обнаружил ошибки. Посмотрим и мы. 3.3.1 Отступление от исходной стратегии - алгоритмические ошибки. Обратите внимание на простую функцию:
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() // Функция определения пересечения { //============================================================================================ if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // Пересечение снизу вверх //-------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // Пересечение сверху вниз //============================================================================================ return(ret); // Возвращаем направление пересечен. } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж Казалось бы, всё же очевидно, что тут можно найти? Но ошибка есть. Она состоит в том, что при использовании глобальной переменной ret её значение сохраняется равным последнему вычисленному, то есть, равно 1 или 2. По этой причине функция Peresechenie() независимо от сложившейся ситуации возвращает просто последнее вычисленное значение, поэтому в функции start() постоянно отдаётся приказ на открытие: if (Peresechenie()==1) Open_Buy(); // Движение снизу вверх = откр. Buy if (Peresechenie()==2) Open_Sell(); // Движение сверху вниз = откр. Sell Чтобы внести исправления, достаточно в начале функции Peresechenie() обнулить переменную ret. Обрадовавшись, что нашёл алгоритмическую ошибку, наш герой быстро её исправил, а заодно написал фрагмент, позволяющий открытие только на одном баре. Теперь его эксперт выглядел так: //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // Грааль_31.mq4. // Используется в качестве примера в статье "Мой первый Грааль". // Сергей Ковалёв, Днепропетровск, sk@mail.dnepr.net, ICQ 64015987, http://autograf.dp.ua/. //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж // // //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж extern int MA1 = 11; // Период 1-й МА extern int MA2 = 23; // Период 2-й МА extern double TP = 50; // ТэйкПрофит ордера extern double SL = 15; // СтопЛосс ордера extern double Prots= 0; // Процент от свободных средств //-------------------------------------------------------------------------------------------- int New_Bar, // 0/1 Факт образования нового бара Time_0, // Время начала нового бара ret, // Направление пересечения total; // Крличество открытых ордеров //-------------------------------------------------------------------------------------------- double Lot, // Количество лотов Pred, // Предыдущее значение 1-й МА (розов) Tek, // Текущее значение 1-й МА (розов) Golub; // Текущее значение 2-й МА(голубая) //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int init() { //============================================================================================ SL = SL*Point; // SL в пунктах TP = TP*Point; // ТР в пунктах return; //============================================================================================ } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int start() { //============================================================================================ total=OrdersTotal(); // Общее количество ордеров if (total==2)return; // Уже открыты оба ордера //----------------------------------------------------------------------------- Новый бар ---- New_Bar=0; // Для начала обнулимся if (Time_0 != Time[0]) // Если уже другое время начала бара { New_Bar= 1; // А вот и новый бар Time_0 = Time[0]; // Запомним время начала нового бара } //-------------------------------------------------------------------------------------------- Tek =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение 1-й МА Pred =iMA(NULL,0, MA1, 0,MODE_LWMA, PRICE_TYPICAL, 1);// Предыдущее значение 2-й МА Golub=iMA(NULL,0, MA2, 0,MODE_LWMA, PRICE_TYPICAL, 0);// Текущее значение 2-й МА //-------------------------------------------------------------------------------------------- if (Peresechenie()==1 && New_Bar==1) Open_Buy(); // Движение снизу вверх = откр. Buy if (Peresechenie()==2 && New_Bar==1) Open_Sell(); // Движение сверху вниз = откр. Sell //============================================================================================ return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Peresechenie() { ret=0; // Вот где собака зарыта!!:) //============================================================================================ if ((Pred<=Golub && Tek> Golub) || (Pred< Golub && Tek>=Golub) ) ret=1; // Пересечение снизу вверх //-------------------------------------------------------------------------------------------- if ((Pred>=Golub && Tek< Golub) || (Pred> Golub && Tek<=Golub) ) ret=2; // Пересечение сверху вниз //============================================================================================ return(ret); // Возвращаем направление пересечен. } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Buy() { if (total==1) { OrderSelect(0, SELECT_BY_POS); // Выделим ордер if (OrderType()==0)return; // Если он buy, то не открываемся } OrderSend(Symbol(),0, Lots(), Ask, 0, Ask-SL, Ask+TP, "", 0, 0, Blue);// Открываемся return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж int Open_Sell() { if (total==1) { OrderSelect(0, SELECT_BY_POS); // Выделим ордер if (OrderType()==1)return; // Если он sell, то не открываемся } OrderSend(Symbol(),1, Lots(), Bid, 0, Bid+SL, Bid-TP, "", 0, 0, Red);// Открываемся return; } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж double Lots() { Lot = NormalizeDouble( AccountEquity()*Prots/100/1000, 1);// Вычисляем колич. лотов if (Lot<0.1)Lot = 0.1; // Для теста на постоян. миним. лотах return(Lot); } //жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж /* Тестирование этого эксперта при постоянной стоимости лотов показало куда более скромный результат: Рис. 15. Результат тестирования эксперта Грааль_31.mq4 на истории с марта 2005 по июль 2005 года в масштабе Н1 валютного инструмента EURUSD на торговых условиях демо-сервера MetaQuotes Software Corp. при постоянной стоимости лотов.
Каково же было его изумление, когда он вдруг увидел, что эксперт сам по себе, без изменения кода, на тех же торговых условиях стал монотонно терять депозит!
Рис. 16. Результат тестирования эксперта Грааль_3.mq4 на истории с марта 2005 по июль 2006 года в масштабе Н1 валютного инструмента EURUSD на торговых условиях демо-сервера MetaQuotes Software Corp. при постоянной стоимости лотов.
3.4. Подгонка результатов. Оказывается наш герой просто занимался самообманом. Выяснилось, что нет никакой сложности в том, чтобы для любого немного работающего эксперта подобрать оптимальные параметры на некотором участке исторических данных. Один и тот же эксперт всегда показывает разные результаты на разных исторических периодах. Вопрос сводится к тому, чтобы подобрать такие оптимальные параметры эксперта (если это возможно), при которых небольшие колебания скорости изменения цен на рынке не влияли на работоспособность и результативность эксперта. В целом же следует ориентироваться на стратегию, устойчивую к любым изменениям на рынке, а настройка параметров должна лишь в некоторой мере помочь получить лучший из возможных результатов. Поиск оптимальных настроек для эксперта Грааль_3.mq4 ни к чему не привёл. Тестирование эксперта при разных значениях внешних переменных показывало либо убыток, либо приводило к существенно разным настройкам для разных исторических периодов. По этой причине нашему герою не удалось выделить "основную жилу" в настройках и он пришёл к выводу, что эта стратегия не имеет универсальных настроек на все случаи жизни. Рис. 17. Результат тестирования эксперта Грааль_31.mq4 на истории с марта 2005 по июль 2006 года в масштабе Н1 валютного инструмента EURUSD на торговых условиях демо-сервера MetaQuotes Software Corp. при постоянной стоимости лотов.
Это вселяло в нашего героя надежду на успех.
4. Заключение.
Вместо этого он взял чистый лист бумаги и сформулировал выводы, сделанные на основе усвоенных им уроков:
SK. Днепропетровск. 2006. Прикрепленные файлы:
Предупреждение:
все права на данные материалы
принадлежат MetaQuotes Software Corp. Полная или частичная перепечатка запрещена.
Запустить прилагаемый файл Грааль_31.mq4 не удалось, за то запустил файл названием Grail_31 того же самого автора (copy paste >Program Files >Meta Trader 4 >experts). Очень хотелось узнать, какие результаты будет выдавать такому широкому кругу представлен файл, который вроде бы работет только на прибыль, что мне сразу же показалось подозрительным (тогда все бы пользовались только прибыльными роботами торговли). SL и TP ставь какие хочешь, прибыль - около нуля или идет в минус. Не знаю, что это такое (может подсказка разбирающимся в создании программ торговли или состовляющая плана маркетинга в распространении прикладных программ автора), но пользу я извлек ту, что научился запускать часть Meta Trader 4, предназначенную для тестирования разного рода программ торговли, а все в остольном - очередное информационное барахло. За то, пытаясь запустить Грааль_31.mq4 и ищя информации как это сделать, 'нарвался' на файл 38_31_Ea_Collectio, где куча подобных Грааль_31.mq4. И как щас различть, где правда, где - ложь или просто информационное барахло?
08.09.2011 10:45 SkyBat
Грааль_31.mq4. Как
этот фаил заинсталировать, запустить (я - не програмист)? Он у меня не работает. Фаил
закопировал в Program Files >Meta Trader 4 >experts. Expert Advisors разрешил торговать. .
21.08.2011 13:40 SkyBat
delic: ... 1) я с вас жизею!!! вы ПРОГРАМИСТЫ!!!! но не ИГРОКИ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! вы всё правильно базарите/так вам кажеться/--настрой это,настрой то и тд, вы ищете действительно грааль!... 2) но хрен вам в задницу-даже гитлер не смог найти его со своей МАШИНОЙ!!... 3) советник грааль самый простой и самый продуктивный,тупо заряжаешь его и КОНТРОЛИРУЕШЬ!!!!!! ни каких настроек--настраивают те кто хочет спать и чтоб деньги текли рекой /пока он спит/-это для дебилов и недоумков!!... 4) на всех форумах /где только не был/ вы сами даёте ответ как заработать с помошью советника, повторюсь я ИГРОК!... 5) взял гепарда /думаю попробую/ -зарабатывает и хорошо, но меньше грааля- за месяц только 3 не закрытых ордера/открыл 7 числа/ и вы чухаете какие то супер вопросы,кроме главного--КАК ЗАРАБОТАТЬ!!!!... 6) и на простейшие вопросы мои не смог ответить ни один форум!!! и здесь тоже--хотя здесь по честному написали --ни кто тебе не поможет,вам лиж бы побазарить и показать себя--а бабки?? а бабки потом...
2) а при чем тут хрен в задницу? причем тут гитлер? зиг вам да хайль... 3) а что плохого в том, чтобы деньги текли рекой "сами по себе"? почему бы не заморочицца над этим? вреда не будет! 4) вы ИГРОК, поздравляю! 5) гепарды да, быстро бегают... а мы чухаем! а нафига вам ответ "КАК ЗАРАБОТАТЬ!!!!" ? Вы же ИГРОК. И, судя по верхнему регистру и обилию восклицательных знаков, игрок идейный. Видимо, проигрывать Вам уже нечего... чтож, сочувствую. 6) а простейшие вопросы, очевидно, не такие уж простейшие. и почему бы не побазарить? тем более предметно... форумы для этого и нужны. а какую конкретную цель преследует ваш пост -- остается только гадать... и если Вы думаете, что кто-то вот так просто даст вам все ответы на блюдечке, то "хрен ВАМ в задницу"! люди годами гоняются разгадками, при этом каждому нужен свой ответ, универсального пока не существует!
27.01.2011 19:51 PunkBASSter
хожу по форумам и чатаю комменнтарии!!! я с вас жизею!!! вы ПРОГРАМИСТЫ!!!! но не ИГРОКИ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! вы всё правильно базарите/так вам кажеться/--настрой это,настрой то и тд, вы ищете действительно грааль! но хрен вам в задницу-даже гитлер не смог найти его со своей МАШИНОЙ!! советник грааль самый простой и самый продуктивный,тупо заряжаешь его и КОНТРОЛИРУЕШЬ!!!!!! ни каких настроек--настраивают те кто хочет спать и чтоб деньги текли рекой /пока он спит/-это для дебилов и недоумков!! на всех форумах /где только не был/ вы сами даёте ответ как заработать с помошью советника, повторюсь я ИГРОК! взял гепарда /думаю попробую/ -зарабатывает и хорошо, но меньше грааля- за месяц только 3 не закрытых ордера/открыл 7 числа/ и вы чухаете какие то супер вопросы,кроме главного--КАК ЗАРАБОТАТЬ!!!! и на простейшие вопросы мои не смог ответить ни один форум!!! и здесь тоже--хотя здесь по честному написали --ни кто тебе не поможет,вам лиж бы побазарить и показать себя--а бабки?? а бабки потом
10.01.2011 18:03 delic
Очень интересно! Читал и смеялся, в том числе и над собой. Но я этот абсурд понл за месяц.
28.08.2009 12:24 zoom1974
Херня какая та, делал тестер этих 4 советникои и все падения идет не какого подъема. Почему?
09.08.2009 14:23 Ermak
|