PDA

View Full Version : Определение тренда при помощи экстремумов. Часть 2.



Scriptong
24-11-2010, 19:28
В результате проведения предыдущего опыта проекта MQLabs (http://www.fxtrade.ru/mqlabs/18.11.2010-mqlabs-opredelenie-trenda-pri-pomoshchi-ekstremumov) был получен индикатор RFractals_SuppAndRes, который по заданному рангу экстремумов определяет текущее направление тренда и ключевые точки разворота сложившегося движения. Располагая подобным индикатором, можно создать полноценную торговую систему, основанную на его показаниях.

Трактовать показания одного и того же индикатора можно множеством способов, что приводит к появлению неисчислимого количества экспертов, основанных на одном и том же указателе. Аналогичная ситуация сложилась и с индикатором RFractals_SuppAndRes. Отображаемые им данные можно использовать в различных сочетаниях, но все же существует наиболее очевидный способ применения его сигналов, который и станет основой будущего эксперта (см. рис. 1)

http://www.forextrade.ru/media/Image/MQLabs/91_ag/figure1.png
Рис. 1. Сигналы индикатора RFractals_SuppAndRes.

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

http://www.forextrade.ru/media/Image/MQLabs/91_ag/Tabl1.png
Табл. 1. Свод торговых приказов.

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

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

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

http://www.forextrade.ru/media/Image/MQLabs/91_ag/figure2.png
Рис. 2. Нахождение цены выше линии сопротивления, не ставшее итогом пробития.

В момент фиксации линии тренда (25.08.2010 16:00) цена находится выше уровня сопротивления. Открывать длинную сделку в таком случае не нужно, т.к. цена пробила линию тренда, когда та еще не была сформирована. Такую линию тренда следует признать несостоявшейся. Аналогичная ситуация может возникнуть и с линией поддержки: в момент формирования линии цена находится ниже уровня поддержки. Это исключение также будет распространяться на те случаи, когда начало торговли приходится на моменты состоявшегося пробития линии тренда. Реакция на такое событие будет одинакова: торговые приказы не отдаются.

Приступим к созданию советника, руководствуясь описанными выше принципами заключения сделок. Сначала опишем настроечные параметры эксперта:

extern string A1 = "Объем открываемых сделок";
extern double Lots = 0.1;
extern string A2 = "Максимальное количество одновременно существующих сделок";
extern int MaxDeals = 3;
extern string A3 = "Количество баров для формирования экстремума";
extern int ExtremumRange = 15;
extern string A4 = "Кол-во пунктов, необходимое для фиксации пробития линии тренда";
extern int BreakPoints = 10;
extern string A5 = "Цвета линий поддержки и сопротивления";
extern color SupportColor = Red;
extern color ResistanceColor = Lime;
extern string A6 = "Прочие параметры эксперта";
extern string OpenOrderSound = "ok.wav"; // Звуковой сигнал при открытии позиции
extern int MagicNumber = 11253; // Уникальный идентификатор своих ордеров
Объем всех открываемых экспертом сделок на протяжении одного сеанса торговли является фиксированной величиной. Изменять его возможно только при перезагрузке советника, редактируя значение параметра Lots. Максимальное количество сделок, открытых в одном направлении, пользователь может ограничить при помощи параметра MaxDeals. Считаются как сделки, так и отложенные ордера. То есть если максимум равен трем сделкам, то при существовании двух сделок Buy и одного ордера Buy Stop, новый ордер Buy Stop установлен не будет.

Далее следуют два параметра, которые перекочевали из индикатора RFractals_SuppAndRes в эксперт. Первый параметр не изменил своего названия - ExtremumRange. С его помощью указывается ранг экстремумов, т.е. количество баров, среди которых находится минимум или максимум. Второй параметр BreakPoints соответствует параметру, который в индикаторе RFractals_SuppAndRes называется BitPoints. Это количество пунктов, на которое цена должна превысить (или оказаться ниже) линию тренда, чтобы можно было говорить о пробитии уровня сопротивления или поддержки.

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

Определив настроечные параметры, можно переходить к вычислению торговых сигналов. В качестве торгового сигнала в описываемой системе выступают уровни поддержки и сопротивления, а вход в рынок производится отложенными ордерами. Сигналом установки ордера Buy Stop является наличие уровня сопротивления выше текущей цены, а сигналом установки ордера Sell Stop является наличие уровня поддержки ниже цены. Таким образом, необходимо определить тип текущей линии тренда и рассчитать ее значение, соответствующее текущему (нулевому) бару. Эти расчеты возложим на функцию GetSignal:

//+-------------------------------------------------------------------------------------+
//| Вычисление уровней открытия сделок |
//+-------------------------------------------------------------------------------------+
void GetSignal(int num)
{
// - 1 - ===================== Проверка необходимости выполнения расчетов ===============
if (Time[num] == LastSignal) return;
// - 1 - ============================== Окончание блока =================================

// - 2 - =============== Поиск экстремума среди доступных ExtremumRange баров ===========
int high = iHighest(NULL, 0, MODE_HIGH, ExtremumRange, num+1);
int low = iLowest(NULL, 0, MODE_LOW, ExtremumRange, num+1);
// - 2 - ============================== Окончание блока =================================

// - 3 - =============== Определение факта наличия экстремума ===========================
if (high == num + center) // Обнаружен новый максимум
{
TimeUp2 = TimeUp1; // Первый минимум становится вторым
UpV2 = UpV1;
TimeUp1 = Time[high]; // А первый максимум обновляется
UpV1 = High[high];
}

if (low == num + center) // Обнаружен новый минимум
{
TimeDn2 = TimeDn1; // Первый минимум становится вторым
DnV2 = DnV1;
TimeDn1 = Time[low]; // А первый минимум обновляется
DnV1 = Low[low];
}
if (TimeDn2 == 0 || TimeUp2 == 0) return; // Нет смысла продолжать расчет, если не
// ..все экстремумы определены
// - 3 - ============================== Окончание блока =================================

// - 4 - =================== Поиск линий поддержки/сопротивления ========================
if (UpV1 > UpV2 && DnV1 > DnV2) // Первый максимум выше второго и..
{ // ..первый минимум выше второго
if (LastLine != TimeDn1) // Если нашли новый максимум
{
LastLine = TimeDn1; //Обновляем время формирования последней
// ..линии
ShowTrend(TimeDn2, DnV2, LastLine, DnV1,
SupportColor); // Отображаем линию поддержки
LastLineType = -1; // Сформирована линия поддержки
}
}
// - 4 - ============================== Окончание блока =================================

// - 5 - ====================== Проверка наличия нисходящего канала =====================
else
if (UpV1 < UpV2 && DnV1 < DnV2) // Первый минимум ниже второго и..
{ // ..первый максимум ниже второго
if (LastLine != TimeUp1) // Если нашли новый минимум
{
LastLine = TimeUp1; //Обновляем время формирования последней
// ..линии
ShowTrend(TimeUp2, UpV2, LastLine, UpV1,
ResistanceColor); // Отображаем линию сопротивления
LastLineType = 1; // Сформирована линия сопротивления
}
}
// - 5 - ============================== Окончание блока =================================

// - 6 - ====================== Расчет цены линии на текущем баре =======================
if (num == 0) // Расчет цены необходим только в случае
{ // ..запроса на нулевом баре
if (TimeE1 > 0) int NE1 = iBarShift(NULL, 0, TimeE1); // Номер бара по времени
if (TimeE2 > 0) int NE2 = iBarShift(NULL, 0, TimeE2); // Номер бара по времени
LinePrice = (EV1*NE2 - EV2*NE1)/(NE2 - NE1); // Нахождение коэффициента B..
// ..линии поддержки или сопротивления
}
// - 6 - ============================== Окончание блока =================================

LastSignal = Time[num];
}
В качестве аргумента функции передается номер бара num, для которого необходимо произвести вычисления. Предполагается, что каждый последующий вызов функции происходит с указанием бара, время открытия которого больше, чем время открытия бара, использовавшегося в момент предыдущего вызова функции, т.к. в алгоритме применен принцип накопления данных.

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

Метод нахождения и обновления экстремумов, примененный в функции GetSignal, немного отличается от способа, использованного в индикаторе RFractals_SuppAndRes, где экстремумы характеризовались номерами баров. В случае разработки эксперта такая характеристика не подходит, т.к. при появлении нового бара все имеющиеся бары меняют свои индексы. Единственная характеристика, которая остается неизменной, это время открытия бара. Его и будем сохранять. С этой целью будем использовать переменные TimeUp1, TimeUp2, TimeDn1 и TimeDn2. Индекс 1 соответствует более позднему экстремуму (находится правее по графику цен). Если в будущем понадобится преобразовать время в номер бара, то достаточно будет использовать функцию iBarShift.

Нахождение очередного экстремума происходит в блоке 2. Это две простые строки, определяющие индекс максимального и минимального баров на предыдущем участке. Признаком формирования нового экстремума является номер бара, соответствующий центральному бару участка. Объясняется это просто. Если индекс бара экстремума больше индекса центрального бара (левее на графике), то такой экстремум мы должны были наблюдать на предыдущем баре, т.е. этот экстремум уже зафиксирован. Если индекс бара экстремума меньше индекса центрального бара (правее на графике), то этот экстремум еще нельзя считать сформированным, т.к. мы не располагаем достаточным количеством баров правее него. Они появятся позже. На описанном принципе базируется алгоритм блока 3, отслеживающий формирование нового экстремума. При этом экстремум, бывший до этого первым, становится вторым (время TimeUp2, значение UpV2 или время TimeDn2, значение DnV2), а в качестве первого экстремума выступает вновь найденный максимум или минимум. Заканчивается блок проверкой значений вторых экстремумов. Если второй максимум или минимум еще не определен (обработано мало исторических данных), то функция GetSignal заканчивает свое исполнение.

Четвертый и пятый блоки подобны. Они описывают ситуации наличия восходящего или нисходящего трендов. В обоих случаях сначала проверяется наличие новой линии тренда, которая идентифицируется по времени наиболее позднего экстремума (переменная LastLine). Если факт наличия новой линии подтвержден, то переменная LastLine получает новое значение. Также обновляется значение переменной LastLineType, которая отвечает за тип последней линии тренда. Финальным аккордом в каждом из блоков является отображение уровня поддержки или сопротивления при помощи вызова функции ShowTrend.

При помощи шестого блока формируется значение линии тренда, соответствующее нулевому бару. Если параметр num не равен нулю, то расчет произведен не будет, т.к. его результаты будут неверными и невостребованными. Переменные TimeE1 и TimeE2 соответствуют времени формирования бара первого и второго экстремумов последней линии тренда. Такое же соответствие имеют переменные EV1 и EV2, в которых сохраняются ценовые значения экстремумов. Обновление значений TimeE1, TimeE2, EV1 и EV2 происходит в теле функции ShowTrend, что позволяет быть уверенным в корректности их значений в любой момент времени. Исходя из значений TimeE1 и TimeE2, легко определить индексы баров NE1 и NE2, соответствующих этим датам. Далее следует расчет цены LinePrice, который представляет собой нахождение коэффициента B, использующегося в уравнении прямой. Так как текущий бар имеет индекс 0, то значение коэффициента B будет являться ценой, соответствующей уровню линии тренда на текущем баре.

Имея значения LinePrice, LastLine и LastLineType, рассчитанные в итоге выполнения функции GetSignal, можно приступать к совершению торговых операций, за что обычно отвечает функция Trade. Но перед принятием решения об установке нового ордера следует иметь данные об уже установленных ордерах. Эту работу выполняет функция FindOrders:

//+-------------------------------------------------------------------------------------+
//| Функция поиска своих ордеров |
//+-------------------------------------------------------------------------------------+
void FindOrders()
{
// - 1 - ======================= Инициализация переменных ===============================
ArrayInitialize(BuyTicket, -1); // До выполнения поиска считаем,..
ArrayInitialize(BuyType, -1); // .. что ни одного ордера нет
ArrayInitialize(SellTicket, -1); // До выполнения поиска считаем,..
ArrayInitialize(SellType, -1); // .. что ни одного ордера нет
Buys = 0; Sells = 0; // Количество ордеров каждого типа
MaxBuyTime = 0; MaxSellTime = 0; // Время открытия последнего ордера
int total = OrdersTotal() - 1;
// - 1 - ============================== Окончание блока =================================

// - 2 - ======================= Поиск по списку ордеров терминала ======================
for (int i = total; i >= 0; i--) // Используется весь список ордеров
if (OrderSelect(i, SELECT_BY_POS)) // Убедимся, что ордер выбран
if (MathFloor(OrderMagicNumber()/1000) == MagicNumber &&// Ордер открыт экспертом,..
OrderSymbol() == Symbol()) // ..который прикреплен к текущей..
{ // ..валютной паре
int num = MathMod(OrderMagicNumber(), 100); // Номер ордера в серии
if (MathMod(OrderType(), 2) == 0) // Если ордер Buy-типа
{
BuyTicket[num] = OrderTicket();
BuyType[num] = OrderType();
MaxBuyTime = MathMax(OrderOpenTime(), MaxBuyTime);
Buys++;
}
else // Если ордер Sell-типа
{
SellTicket[num] = OrderTicket();
SellType[num] = OrderType();
MaxSellTime = MathMax(OrderOpenTime(), MaxSellTime);
Sells++;
}
}
// - 2 - ============================== Окончание блока =================================
}
В общем случае эксперт должен оперировать неограниченным количеством ордеров (ограничимся разумным пределом в 100 ордеров). Поэтому перед проведением анализа текущей ситуации необходимо рассортировать имеющиеся ордера по типам и очередности открытия. С этой целью будет использоваться кодирование поля Magic Number каждого ордера. Значение поля включит в себя стандартный идентификатор эксперта, порядковый номер ордера среди себе подобных и тип ордера (указание типа делается с прицелом на доработку стратегии для использования в AutoGraf 4.0, чтобы не было совпадающих Magic Number). Кодирование производится по следующей формуле:

MN = MagicNumber*1000 + Type*100 + Num,
где MN - поле Magic Number ордера, MagicNumber - идентификатор ордеров эксперта, указанный пользователем в параметре MagicNumber, Type - тип ордера (от 0 до 5), Num - порядковый номер ордера среди себе подобных.

Складирование собранной информации осуществляется в массивы BuyTicket (тикеты найденных ордеров Buy и Buy Stop), BuyType (тип ордера - Buy или Buy Stop), SellTicket (тикеты ордеров Sell и Sell Stop) и SellType (тип ордера - Sell или Sell Stop). Значение -1 в соответствующем элементе массива свидетельствует об отсутствии ордера. Поэтому перед началом поиска элементы всех перечисленных массивов заполняются значением -1. Количество ордеров каждого типа определяется переменными-счетчиками Buys и Sells. Для определения времени открытия наиболее позднего ордера своего типа используются переменные MaxBuyTime и MaxSellTime.

Заполнение массивов происходит во втором блоке функции путем последовательного перебора всех открытых в терминале ордеров. Для отделения собственных ордеров эксперта от прочих необходимо убедиться в совпадении идентификатора ордера с идентификатором эксперта. Это производится путем деления значения поля Magic Number на 1000 с отбрасыванием дробной части. Если ордер распознан как собственный, то его тикет и тип сохраняются в соответствующих типу ордера массивах. Номер элемента массива, в который производится запись, совпадает с порядковым номером ордера в серии. Порядковый номер определяется путем получения остатка от деления поля Magic Number на 100.

Использование полученных за время выполнения функции FindOrders данных осуществляется в теле функции Trade:

//+-------------------------------------------------------------------------------------+
//| Открытие позиций |
//+-------------------------------------------------------------------------------------+
void Trade()
{
// - 1 - ======================== Поиск своих ордеров ===================================
if (LastBar == Time[0]) return;
// - 1 - ==================== Окончание блока ===========================================

// - 2 - ================== Обработка ситуации существования линии поддержки ============
if (LastLineType < 0)
{
FindOrders(); // Произведем поиск ордеров
double SL = NP(LinePrice - BreakPoints*Point); // Вычисление уровня стопа для Buy
if (!CheckStopOfBuy(SL)) // Проверка правильности уровня стопа
return; // ..у существующих длинных сделок
if (SL > Bid) // Если текущая цена ушла далеко от..
{ // ..уровня входа, то выходим
LastBar = Time[0];
return;
}
if (Sells == 0 || // Если ордер SellStop не установлен..
(Sells > 0 && SellType[Sells-1] != OP_SELLSTOP))// ..или имеющаяся сделка не..
{ // ..Sell Stop, то устанавливаем
if (Sells < MaxDeals && MaxSellTime < LastLine+center*Period()*60) // Кол-во..
// ..коротких сделок не достигло..
// ..максимума и по текущей линии..
// ..поддержки еще не было реакции
if (OpenOrderCorrect(OP_SELLSTOP, Lots, NP(SL), 0, 0, Sells) != 0)
return;
}
else // Если ордер установлен, то..
if (!CheckPriceOfSellStop(SL)) // ..передвигаем его
return;
}
// - 2 - ==================== Окончание блока ===========================================

// - 3 - ============== Обработка ситуации существования линии сопротивления ============
if (LastLineType > 0)
{
FindOrders(); // Произведем поиск ордеров
SL = NP(LinePrice + BreakPoints*Point + Spread);// Вычисление уровня стопа для Sell
if (!CheckStopOfSell(SL)) // Проверка правильности уровня стопа
return; // ..у существующих коротких сделок
if (Ask > SL) // Если текущая цена ушла далеко от..
{ // ..уровня входа, то выходим
LastBar = Time[0];
return;
}
if (Buys == 0 || // Если ордер BuyStop не установлен..
(Buys > 0 && BuyType != OP_BUYSTOP))// ..или имеющаяся сделка не..
{ // ..Buy Stop, то устанавливаем
if (Buys < MaxDeals && MaxBuyTime < LastLine+center*Period()*60) // Кол-во..
// ..длинных сделок не достигло..
// ..максимума и по текущей линии..
// ..сопротивления еще не было реакции
if (OpenOrderCorrect(OP_BUYSTOP, Lots, NP(SL), 0, 0, Buys) != 0)
return;
}
else // Если ордер установлен, то..
if (!CheckPriceOfBuyStop(SL)) // ..передвигаем его
return;
}
// - 3 - ==================== Окончание блока ===========================================

LastBar = Time[0]; // Отмечаем, что проведение торговых..
// ..операций на текущем баре более..
// ..не требуется
}
Как и в случае с функцией GetSignal, исполнение функции Trade ограничивается однократным вызовом на одном баре. Для этого существует переменная LastBar. Если ее значение равно времени открытия текущего бара (Time[0]), то выполнение функции Trade досрочно прекращается.

Далее алгоритм ветвится на два схожих блока: блок 2 и блок 3. Второй блок исполняется, когда значение LastLineType отрицательно, т.е. существует линия поддержки. В этом случае уровень стопа (SL) для длинных позиций рассчитывается как переменная LinePrice (цена, соответствующая линии поддержки), из значения которой вычтено BreakPoints пунктов. Посредством вызова функции CheckStopOfBuy проверяется соответствие уровней стоп-приказов имеющихся ордеров Buy значению SL. В случае обнаружения несоответствия, уровень такого ордера корректируется. Дополнительной обязанностью функции CheckStopOfBuy является удаление найденных отложенных ордеров Buy Stop, т.к. во время существования линии поддержки из отложенных ордеров может присутствовать только Sell Stop.

После успешного выполнения функции CheckStopOfBuy (при неудачном завершении происходит досрочный выход из функции Trade) проверяется взаимное расположение уровня SL и текущей цены Bid. Если стоп выше текущей цены (линия поддержки выше цены), то никакие действия в дальнейшем не предпринимаются (невозможно установить Sell Stop). В противном случае производится установка нового ордера Sell Stop или перемещение цены открытия имеющегося ордера. При этом производится проверка достижения максимального количества ордеров и проверка отработки текущей линии тренда (т.е. по этой линии тренда уже был установлен ордер). При отдаче приказа установки ордера Sell Stop в качестве одного из параметров передается текущее количество ордеров Sell - Sells. Это значение является порядковым номером нового ордера, которое кодируется в поле Magic Number.

Аналогичным образом работает блок 3. Сначала вычисляется стоп для коротких позиций (к нему добавляется спрэд, т.к. закрытие коротких позиций производится по цене Ask), затем проверяется правильность стопа существующих сделок Sell и удаление ордеров Sell Stop. После этого устанавливается или перемещается ордер Buy Stop.

Рассматривать функции CheckStopOfBuy, CheckStopOfSell, CheckPriceOfBuyStop и CheckPriceOfSellStop нет необходимости. Подобные функции использовались во многих экспертах MQLabs. Поэтому сразу же перейдем к проверке полученного эксперта.


[B]Тестирование эксперта
Наиболее удобным для тестирования большинства экспертов является таймфрейм Н1. Он позволяет получить достаточное количество сделок за относительно короткий промежуток времени. Еще одним его неоспоримым качеством является сохранение баланса между краткосрочными и долгосрочными сделками. Исторический период тестирования: 01.01.2009 - 20.11.2010. Для каждой из тестируемых валютных пар индивидуально были подобраны значения трех настроечных параметров: MaxDeals, ExtremumRange и BreakPoints. Полученные результаты приведены ниже (см. рис. 3 - 6).

http://www.forextrade.ru/media/Image/MQLabs/91_ag/EURUSD.gif
Рис. 3. Результаты тестирования эксперта RFractals на валютной паре EURUSD.

EURUSD. Значения параметров: MaxDeals = 7, ExtremumRange = 9, BreakPoints = 9. Кривая баланса выглядит не очень уверенно, но радует тот факт, что угол ее наклона увеличивается к окончанию тестирования. Чистая прибыль 10 964 доллара при максимальной просадке 2 339 долларов, фактор восстановления 4.69. Это очень неплохие показатели для EURUSD.

http://www.forextrade.ru/media/Image/MQLabs/91_ag/USDCHF.gif
Рис. 4. Результаты тестирования эксперта RFractals на валютной паре USDCHF.

USDCHF. Значения параметров: MaxDeals = 7, ExtremumRange = 7, BreakPoints = 1. Кривая баланса совершенно неприятная, склонная к хаотическим движениям. Доверия не вызывает. Чистая прибыль 3 371 доллара при максимальной просадке 2 390 долларов, фактор восстановления 1.41. Ничего хорошего ждать от применения стратегии на данной валютной паре не приходится.

http://www.forextrade.ru/media/Image/MQLabs/91_ag/GBPUSD.gif
Рис. 5. Результаты тестирования эксперта RFractals на валютной паре GBPUSD.

GBPUSD. Значения параметров: MaxDeals = 6, ExtremumRange = 9, BreakPoints = 3. Кривая баланса стремительно набрала высоту в течение первых 60-ти сделок, а затем успокоилась. Хотя стоит отметить тот факт, что в конце тестирования произошел очередной скачок вверх. Это позитивный момент. Чистая прибыль 15 310 долларов при максимальной просадке 3 293 доллара, фактор восстановления 4.65. Как видно, немного не дотянулись показатели до евро.

http://www.forextrade.ru/media/Image/MQLabs/91_ag/USDJPY.gif
Рис. 6. Результаты тестирования эксперта RFractals на валютной паре USDJPY.

USDJPY. Значения параметров: MaxDeals = 7, ExtremumRange = 19, BreakPoints = 1. Кривую баланса охарактеризовать однозначно достаточно сложно. С одной стороны, она упорно растущая. С другой стороны, флэт последнего периода тестирования не может не настораживать. Чистая прибыль 4 123 доллара при максимальной просадке 2 177 долларов, фактор восстановления 1.89.


Доработка стратегии для использования в AutoGraf 4.0
Для получения стратегии AutoGraf из разработанного советника потребуется перенесение настроечных параметров эксперта в настроечные параметры AutoGraf 4.0. Это касается лишь трех параметров: MaxDeals, которому будет соответствовать AT_1, ExtremumRange, которому будет соответствовать AT_2, и BreakPoints, которому будет соответствовать AT_3. Значение параметра Lots можно изменять во время исполнения стратегии при помощи панели настроек AutoGraf.

Запуск стратегии в среде AutoGraf 4.0 состоит из следующих шагов:
Получить файл по ссылке Файлы стратегий для AutoGraf 4.0 (http://www.forextrade.ru/media/Image/MQLabs/91_ag/AG_RFractals.zip) и распаковать полученный архив в папку MT4\experts\libraries (с перезаписью файлов AG_AT.ex4 и AG_AT.mq4). Запустить AutoGraf. Для работы стратегии в ключе приведенных результатов в окне настроек AutoGraf (закладка "Входные параметры") установить нужные значения параметров AT_1 (например, 7), AT_2 (например, 9) и AT_3 (например, 9). Полное повторение результатов при этом не гарантируется. Выбрать стратегию №5. Для этого необходимо передвинуть вверх значок So и среди названий стратегий найти значок S5, который также потянуть вверх. Запустить функцию автоматической торговли, передвинув значок AT в верхнее положение.


Индикатор RFractals_SuppAndRes (http://www.forextrade.ru/media/Image/MQLabs/91_ag/RFractals_SuppAndRes.mq4)
Советник RFractals_Expert (http://www.forextrade.ru/media/Image/MQLabs/91_ag/RFractals_Expert.mq4)
Файлы стратегий для AutoGraf 4.0 (http://www.forextrade.ru/media/Image/MQLabs/91_ag/AG_RFractals.zip)
Полные результаты тестирования эксперта (http://www.forextrade.ru/media/Image/MQLabs/91_ag/Test.zip)

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