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

В прошлой статье была схема того, что сейчас будем делать. Приготовьте ее, она нам понадобится. Метатрейдер на компьютере уже стоит. Нужен еще учебник по MQL4. Без него мы ничего не сможем. Скачать его можно бесплатно, например, с сайта компании Альпари или смотреть на сайте http://book.mql4.com/ru.

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

Я начну с проверки условия для открытия ордера buy. Опытные программисты советуют везде ставить для себя комментарии, чтобы потом быстро разбираться, что каждая часть робота у вас должна делать. Спустя некоторое время при редактировании комментарии помогут не потеряться в собственном творении.

Поэтому ставим две косых черты, несколько тире и пишем:

//---- Открытие позиции на покупку.

Пишем: if (iRSI

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

Теперь открываем учебник, ищем раздел «Технические индикаторы», находим в списке RSI и смотрим, какие параметры и в каком порядке нужны для этого индикатора.

Выглядит эта страница так:
double iRSI(string symbol, int timeframe, int period, int applied_price, int shift)

Расчет Relative Strength Index.

Параметры:
symbol - Символьное имя инструмента, на данных которого будет вычисляться индикатор. NULL означает текущий символ.
timeframe - Период. Может быть одним из периодов графика. 0 означает период текущего графика.
period - Период усреднения для вычисления индекса.
applied_price - Используемая цена. Может быть любой из ценовых констант.
shift - Индекс получаемого значения из индикаторного буфера (сдвиг относительно текущего бара на указанное количество периодов назад).

Пример:
if(iRSI(NULL,0,14,PRICE_CLOSE,0)>iRSI(NULL,0,14,PR ICE_CLOSE,1)) return(0);

Начинаем набирать. Итак, нужно определиться на каких данных будет вычисляться RSI. Это может быть обозначение валютной пары. После обозначеия iRSI открываем круглую скобку и ставим NULL, как это указано в параметрах индикатора в строке symbol. Пусть берет название валютной пары с рабочего листа.

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

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

КонстантаЗначениеОписание
PERIOD_M111 минута
PERIOD_M555 минут
PERIOD_M151515 минут
PERIOD_M303030 минут
PERIOD_H1601 час
PERIOD_H42404 часа
PERIOD_D114401 день
PERIOD_W1100801 неделя
PERIOD_MN1432001 месяц
0 (ноль)0Период текущего графика
Мы ставим либо 0, и тогда основным рабочим таймфреймом будет тот, который выбран на рабочем листе, куда подключили советника, либо любой из указанных выше. Я взяла 0.

Все наши параметры набираем через запятую, после запятой ставим пробел.

Следующее, что мы должны прописать, это period. Помнится, мы договаривались взять индикатор с периодом 3 (RSI(3)). Ставим троечку.

Дальше идет applied_price. То есть, по каким ценам должен вычисляться индикатор. Я беру PRICE_CLOSE.

Последний параметр shift. Если есть по торговой системе сдвиг линии индикатора, то этот параметр прописывается. У нас его нет. Ставим просто 0. Скобку закрываем.

У меня получилась:

int start()
{

if (flag == 0)
{
//---- Открытие позиции на покупку
if (iRSI(NULL, 0, 3, PRICE_CLOSE, 2) < 25)
if (iRSI(NULL, 0, 3, PRICE_CLOSE, 1) < 25)
if (iRSI(NULL, 0, 3, PRICE_CLOSE, 0) > 25)

Видим, что прописано условие нахождения линии RSI ниже уровня 25 и текущего значения над ним. Нам нужно еще проверить, растет ли RSI. Помните, в схеме робота мы использовали цифры 0,1,2? То есть текущее значение больше предыдущего и предыдущее больше предпредыдущего значения.

Выглядит так:

if (iRSI(NULL, 0, 3, PRICE_CLOSE, 1) < iRSI(NULL, 0, 3, PRICE_CLOSE, 0))
if (iRSI(NULL, 0, 3, PRICE_CLOSE, 2) < iRSI(NULL, 0, 3, PRICE_CLOSE, 1))

Допустим, все условия совпали и надо покупать. Но открыть позицию – треть дела. Как мы будем ее закрывать? Откуда робот узнает, что он должен закрыть? Нам нужно, чтобы после открытия позиции робот получил уникальный номер тикета открытой позиции.

Открываем учебник. Все поставленные чуть выше задачи нам поможет решить раздел «Торговые операции».

Смею вас заверить, что как только вы напишете своего первого робота, он скомпилируется и принесет первое изменение в депозите, пусть даже и отрицательное, остановиться вы уже не сможете: начнете ваять еще и еще. Чтобы робот не запутался, что именно он должен закрыть, введем переменную bull. Это просто название, по которому робот в дальнейшем распознает свою работу. Набираем строку для открытия позиции так же, как делали, описывая RSI:

{
RefreshRates();
bull = OrderSend("EURUSD", OP_BUY, lots, Ask, 0, 0, 0);
if (bull <= 0)
{
Alert("Ошибка открытия позиции: ", GetLastError(), "пробуем открыть еще раз");
Sleep(5000);
RefreshRates();
bull = OrderSend("EURUSD", OP_BUY, lots, Ask, 0, 0, 0);
}
flag = 1;
}

Не редка ситуация, когда цены меняются очень быстро и робот не успевает открыть позицию по тем данным, что он получил. Поэтому возникла еще одна строка (начинается со слова Alert), когда робот выведет не только сообщение об ошибке, но и попытается открыть позицию еще раз через 5000 миллисекунд (команда Sleep).

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

Теперь перейдем к закрытию позиции. Мы помним условие закрытия длинной позиции: RSI выше 70 и начинает падать, то есть предтекущее значение меньше предыдущего, а предыдущее наоборот больше предпредыдущего: 1<2>3. Не буду приводить здесь строку кода для проверки этих условий. Подобное мы делали выше.

Займемся самой командой закрытия: прибьем бычка. Вводим опять какое душе угодно имя переменной (у меня это shoot_bull), командная строка начинает выглядеть так:

{
RefreshRates();
shoot_bull = OrderClose(bull, lots, Bid, 0);
if (shoot_bull == FALSE)
{
Alert("Ошибка закрытия позиции: ", GetLastError(), "пробуем закрыть еще раз");
Sleep(5000);
RefreshRates();
shoot_bull = OrderClose(bull, lots, Bid, 0);
}
flag = 0;
}

По тем же принципам и по схеме из предыдущей статьи пишем код для медвежьей позиции. Переменная при открытии позиции вниз теперь будет называться bear и при ее закрытии shoot_bear.

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

//--Определяем переменные
int bull, bear, flag;
double lots;
bool shoot_bull, shoot_bear;

Давайте вспомним, что указанные переменные у нас делают. Bull и bear в итоге получают номер тикета позиции. Это всегда целое число. Переменная flag работает со значениями 0, 1 и 2, которые тоже у нас останутся целыми числами, что бы ни произошло. Поэтому это переменные типа int. Переменная lots работает с ценой, имеющей цифры после запятой. Это тип переменных double. Переменные с именами shoot_bull и shoot_bear работают с понятиями истина/ложь. Этот тип переменных называется bool. Наверное, ничего бы страшного не произошло, если бы переменная flag была бы отнесена к типу bool.

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

Стоп в этой системе мы не используем. Тейк-профит тоже такой, какой получится. Так как статья должна иметь определенный конечный размер, то лот я указала просто 0,1, без вычислений.

int init()
{
lots = 0.1;
flag = 0;

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

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

Автор статьи: Евгения Мацина, специально для Русского Трейдера.
(с) www.russian-trader.ru

Аннотация:
3 часть цикла статей о создании торгового робота на Форексе с помощью Метатрейдера.