Читать книгу 10 роботов для автоматической торговли на Форекс - - Страница 1
Робот 1: «Следователь за трендом» (Trend Follower) – MQL5 Код
ОглавлениеВот полный код советника для MetaTrader 5, реализующий стратегию следования за трендом:
```mql5
//+–+
//| TrendFollower.mq5 |
//| Автор: Алготрейдинг Книга |
//| https://example.com |
//+–+
#property copyright "Алготрейдинг Книга"
#property link "https://example.com"
#property version "1.00"
//+–+
//| Входные параметры советника |
//+–+
input double LotSize = 0.1; // Размер лота
input int FastMAPeriod = 50; // Период быстрой MA
input int SlowMAPeriod = 200; // Период медленной MA
input int ADXPeriod = 14; // Период ADX
input double ADXThreshold = 25.0; // Пороговое значение ADX для силы тренда
input int StopLoss = 200; // Стоп-лосс в пунктах
input int TakeProfit = 400; // Тейк-профит в пунктах
input bool UseTrailingStop = false; // Использовать трейлинг-стоп
input int TrailingStop = 100; // Размер трейлинг-стопа в пунктах
input int MagicNumber = 123456; // Магический номер для идентификации ордеров
input string OrderComment = "TrendFollower"; // Комментарий к ордерам
//+–+
//| Глобальные переменные |
//+–+
int fastMAHandle; // Хэндл для быстрой MA
int slowMAHandle; // Хэндл для медленной MA
int adxHandle; // Хэндл для ADX
double prevFastMA = 0; // Значение быстрой MA на предыдущем баре
double prevSlowMA = 0; // Значение медленной MA на предыдущем баре
//+–+
//| Функция инициализации советника |
//+–+
int OnInit()
{
// Проверка входных параметров
if(FastMAPeriod >= SlowMAPeriod)
{
Alert("Ошибка: Период быстрой MA должен быть меньше периода медленной MA");
return INIT_PARAMETERS_INCORRECT;
}
if(LotSize <= 0 || LotSize > 100)
{
Alert("Ошибка: Неверный размер лота");
return INIT_PARAMETERS_INCORRECT;
}
// Создание хэндлов для индикаторов
fastMAHandle = iMA(_Symbol, _Period, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
slowMAHandle = iMA(_Symbol, _Period, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
adxHandle = iADX(_Symbol, _Period, ADXPeriod);
// Проверка создания хэндлов
if(fastMAHandle == INVALID_HANDLE || slowMAHandle == INVALID_HANDLE || adxHandle == INVALID_HANDLE)
{
Alert("Ошибка создания индикаторов");
return INIT_FAILED;
}
// Получение начальных значений индикаторов
double fastMA[1], slowMA[1];
if(CopyBuffer(fastMAHandle, 0, 1, 1, fastMA) < 1 || CopyBuffer(slowMAHandle, 0, 1, 1, slowMA) < 1)
{
Alert("Ошибка копирования данных индикаторов");
return INIT_FAILED;
}
prevFastMA = fastMA[0];
prevSlowMA = slowMA[0];
Print("Советник TrendFollower успешно инициализирован");
return INIT_SUCCEEDED;
}
//+–+
//| Функция деинициализации советника |
//+–+
void OnDeinit(const int reason)
{
// Освобождение хэндлов индикаторов
if(fastMAHandle != INVALID_HANDLE)
IndicatorRelease(fastMAHandle);
if(slowMAHandle != INVALID_HANDLE)
IndicatorRelease(slowMAHandle);
if(adxHandle != INVALID_HANDLE)
IndicatorRelease(adxHandle);
Print("Советник деинициализирован, причина: ", reason);
}
//+–+
//| Функция обработки тиков |
//+–+
void OnTick()
{
// Проверяем, есть ли уже открытые позиции этим советником
if(PositionsTotal() > 0)
{
CheckForClose(); // Проверяем условия для закрытия
ManageTrailingStop(); // Управляем трейлинг-стопом
return;
}
// Проверяем условия для открытия новой позиции
CheckForOpen();
}
//+–+
//| Проверка условий для открытия позиции |
//+–+
void CheckForOpen()
{
// Получаем значения индикаторов на текущем и предыдущем барах
double fastMA[2], slowMA[2], adxValue[2];
if(CopyBuffer(fastMAHandle, 0, 0, 2, fastMA) < 2) return;
if(CopyBuffer(slowMAHandle, 0, 0, 2, slowMA) < 2) return;
// Получаем значение линии ADX (индекс направленного движения)
if(CopyBuffer(adxHandle, 0, 0, 2, adxValue) < 2) return;
// Проверяем условия для BUY (покупки)
// 1. Быстрая MA пересекла медленную MA снизу вверх
// 2. ADX выше порогового значения (сильный тренд)
if(fastMA[1] <= slowMA[1] && fastMA[0] > slowMA[0] && adxValue[0] > ADXThreshold)
{
OpenPosition(ORDER_TYPE_BUY);
}
// Проверяем условия для SELL (продажи)
// 1. Быстрая MA пересекла медленную MA сверху вниз
// 2. ADX выше порогового значения (сильный тренд)
else if(fastMA[1] >= slowMA[1] && fastMA[0] < slowMA[0] && adxValue[0] > ADXThreshold)
{
OpenPosition(ORDER_TYPE_SELL);
}
// Сохраняем текущие значения для следующего сравнения
prevFastMA = fastMA[0];
prevSlowMA = slowMA[0];
}
//+–+
//| Открытие позиции |
//+–+
void OpenPosition(ENUM_ORDER_TYPE orderType)
{
// Подготовка данных для торгового запроса
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
// Установка символа
request.symbol = _Symbol;
request.volume = LotSize;
request.magic = MagicNumber;
request.comment = OrderComment;
// Установка типа ордера
request.type = orderType;
// Расчет цены входа
if(orderType == ORDER_TYPE_BUY)
{
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.sl = request.price – StopLoss * _Point;
request.tp = request.price + TakeProfit * _Point;
}
else if(orderType == ORDER_TYPE_SELL)
{
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
request.sl = request.price + StopLoss * _Point;
request.tp = request.price – TakeProfit * _Point;
}
// Установка отклонения от цены
request.deviation = 10;
request.type_filling = ORDER_FILLING_FOK;
// Отправка торгового запроса
if(OrderSend(request, result))
{
if(result.retcode == TRADE_RETCODE_DONE)
{
Print("Позиция открыта успешно. Тикет: ", result.order);
}
else
{
Print("Ошибка открытия позиции. Код: ", result.retcode, " Комментарий: ", result.comment);
}
}
else
{
Print("Ошибка OrderSend. Код ошибки: ", GetLastError());
}
}
//+–+
//| Проверка условий для закрытия позиции |
//+–+
void CheckForClose()
{
// Получаем значения индикаторов на текущем баре
double fastMA[1], slowMA[1];
if(CopyBuffer(fastMAHandle, 0, 0, 1, fastMA) < 1) return;
if(CopyBuffer(slowMAHandle, 0, 0, 1, slowMA) < 1) return;
// Проверяем все открытые позиции
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
long positionType = PositionGetInteger(POSITION_TYPE);
// Закрываем BUY позицию если быстрая MA пересекла медленную сверху вниз
if(positionType == POSITION_TYPE_BUY && fastMA[0] < slowMA[0])
{
ClosePosition(i);
}
// Закрываем SELL позицию если быстрая MA пересекла медленную снизу вверх
else if(positionType == POSITION_TYPE_SELL && fastMA[0] > slowMA[0])
{
ClosePosition(i);
}
}
}
}
//+–+
//| Закрытие позиции |
//+–+
void ClosePosition(int positionIndex)
{
// Получаем информацию о позиции
ulong ticket = PositionGetTicket(positionIndex);
if(ticket <= 0) return;
// Подготовка торгового запроса
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = _Symbol;
request.volume = PositionGetDouble(POSITION_VOLUME);
request.magic = MagicNumber;
request.comment = "Close by signal";
// Установка цены закрытия
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
request.type = ORDER_TYPE_SELL;
}
else
{
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.type = ORDER_TYPE_BUY;
}
request.deviation = 10;
request.type_filling = ORDER_FILLING_FOK;
// Отправка запроса на закрытие
if(OrderSend(request, result))
{
if(result.retcode == TRADE_RETCODE_DONE)
{
Print("Позиция закрыта успешно. Тикет: ", result.order);
}
else
{
Print("Ошибка закрытия позиции. Код: ", result.retcode);
}
}
}
//+–+
//| Управление трейлинг-стопом |
//+–+
void ManageTrailingStop()
{
if(!UseTrailingStop) return;
for(int i = PositionsTotal() – 1; i >= 0; i–)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
ulong ticket = PositionGetTicket(i);
if(ticket <= 0) continue;
double currentSL = PositionGetDouble(POSITION_SL);
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
long positionType = PositionGetInteger(POSITION_TYPE);
// Для длинной позиции (BUY)
if(positionType == POSITION_TYPE_BUY)
{
double newSL = currentPrice – TrailingStop * _Point;
if(newSL > currentSL && newSL > openPrice)
{
ModifyStopLoss(ticket, newSL);
}
}
// Для короткой позиции (SELL)
else if(positionType == POSITION_TYPE_SELL)
{
double newSL = currentPrice + TrailingStop * _Point;
if(newSL < currentSL && newSL < openPrice)
{
ModifyStopLoss(ticket, newSL);
}
}
}
}
}
//+–+
//| Модификация стоп-лосса |
//+–+
void ModifyStopLoss(ulong ticket, double newStopLoss)
{
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(result);
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.symbol = _Symbol;
request.sl = newStopLoss;
request.magic = MagicNumber;
// Сохраняем текущий тейк-профит
request.tp = PositionGetDouble(POSITION_TP);
if(OrderSend(request, result))
{
if(result.retcode == TRADE_RETCODE_DONE)
{
Print("Стоп-лосс модифицирован. Новый SL: ", newStopLoss);
}
}
}
//+–+
//| Функция для логов |
//+–+
void PrintStatus()
{
double fastMA[1], slowMA[1], adxValue[1];
if(CopyBuffer(fastMAHandle, 0, 0, 1, fastMA) < 1) return;
if(CopyBuffer(slowMAHandle, 0, 0, 1, slowMA) < 1) return;
if(CopyBuffer(adxHandle, 0, 0, 1, adxValue) < 1) return;
Print("Текущие значения: FastMA=", fastMA[0], " SlowMA=", slowMA[0], " ADX=", adxValue[0]);
}
```
Инструкция по установке и использованию:
1. Установка советника:
· Сохраните код в файл TrendFollower.mq5
· Поместите файл в папку MQL5/Experts/ вашего терминала MetaTrader 5
· Перезапустите MetaTrader 5 или обновите список экспертов (Навигатор -> Эксперты -> Обновить)
2. Настройка параметров:
Основные параметры:
· LotSize = 0.1 – Размер лота (рекомендуется начинать с 0.01)
· FastMAPeriod = 50 – Период быстрой скользящей средней
· SlowMAPeriod = 200 – Период медленной скользящей средней
· ADXPeriod = 14 – Период индикатора ADX
· ADXThreshold = 25.0 – Минимальное значение ADX для силы тренда
· StopLoss = 200 – Стоп-лосс в пунктах
· TakeProfit = 400 – Тейк-профит в пунктах
Дополнительные параметры:
· UseTrailingStop = false – Включить трейлинг-стоп
· TrailingStop = 100 – Размер трейлинг-стопа в пунктах
· MagicNumber = 123456 – Уникальный идентификатор ордеров
3. Рекомендации по использованию:
Оптимизация параметров:
```mql5
// Для разных таймфреймов рекомендуются разные настройки:
// Дневной график (D1):
FastMAPeriod = 20
SlowMAPeriod = 50
StopLoss = 300
TakeProfit = 600
// Четырехчасовой график (H4):
FastMAPeriod = 14
SlowMAPeriod = 50
StopLoss = 150
TakeProfit = 300
// Часовой график (H1):
FastMAPeriod = 10
SlowMAPeriod = 30
StopLoss = 100
TakeProfit = 200
```
Дополнительные улучшения стратегии:
1. Фильтр волатильности:
```mql5
// Добавить в CheckForOpen():
double atrValue = iATR(_Symbol, _Period, 14, 0);
if(atrValue > 0.005) // Пример фильтра по ATR
{
// Торговать только при достаточной волатильности
}
```
1. Фильтр по времени:
```mql5
// Не торговать во время выхода важных новостей
bool IsTradingTime()
{
MqlDateTime time;
TimeCurrent(time);
// Не торговать с 13:00 до 15:00 (пример)
if(time.hour >= 13 && time.hour < 15)
return false;
return true;
}
```
1. Управление капиталом:
```mql5
// Вместо фиксированного лота использовать процент от депозита
double riskPercent = 2.0; // Риск 2% от депозита
double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * riskPercent / 100;
double lotSize = riskAmount / (StopLoss * _Point * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE));
```
4. Важные предупреждения:
1. Всегда тестируйте на демо-счете перед использованием на реальных деньгах
2. Адаптируйте параметры под конкретную валютную пару и таймфрейм
3. Мониторьте работу советника, особенно в первые недели торговли
4. Учитывайте спреды и свопы – они могут существенно повлиять на прибыльность
5. Используйте VPS для круглосуточной работы советника
5. Ограничения данной реализации:
1. Советник открывает только одну позицию на символ
2. Не учитывает корреляции между разными инструментами
3. Нет защиты от "зависаний" и сбоев связи
4. Требует постоянного мониторинга и периодической оптимизации параметров
Этот код представляет собой базовую реализацию стратегии следования за трендом. Для профессионального использования рекомендуется добавить дополнительные фильтры, улучшенное управление капиталом и систему мониторинга.