Читать книгу 10 роботов для автоматической торговли на Форекс - - Страница 3

Робот 3: «Скальпер Пипсарь» (Scalper)

Оглавление

Скальпер Пипсарь для MetaTrader 5


```mq5

//+–+

//| ScalperPipsar.mq5|

//| Copyright 2023, MetaQuotes Ltd. |

//| https://www.mql5.com |

//+–+

#property copyright "Copyright 2023, MetaQuotes Ltd."

#property link "https://www.mql5.com"

#property version "1.00"


//+–+

//| Входные параметры эксперта |

//+–+

input double LotSize = 0.1; // Размер лота

input int TakeProfit_Pips = 10; // Тейк-профит в пипсах

input int StopLoss_Pips = 5; // Стоп-лосс в пипсах

input int MaxDailyTrades = 100; // Максимум сделок в день

input double MaxSpread_Pips = 0.5; // Максимальный спред в пипсах

input bool UseEquityProtection = true;// Защита по эквити

input double EquityProtectionPercent = 5;// Макс. просадка эквити в %

input int MagicNumber = 789012; // Магический номер

input bool UseNewsFilter = true; // Фильтр новостей

input int NewsBeforeMinutes = 30; // Не торговать за N минут до новостей

input int NewsAfterMinutes = 30; // Не торговать N минут после новостей


// Входные параметры индикаторов

input int FastMA_Period = 5; // Период быстрой MA

input int SlowMA_Period = 10; // Период медленной MA

input ENUM_MA_METHOD MA_Method = MODE_EMA;// Метод MA

input int Volume_Threshold = 100; // Порог объема

input int Momentum_Period = 3; // Период момента

input double MinTickSpeed = 0.5; // Мин. скорость тиков (тиков/сек)


//+–+

//| Глобальные переменные |

//+–+

int handleFastMA, handleSlowMA, handleMomentum;

double fastMA[], slowMA[], momentum[];

datetime lastTradeTime = 0;

int todayTrades = 0;

datetime lastTradeDate = 0;

double initialEquity = 0;

MqlDateTime currentTime;

int tickCounter = 0;

datetime lastTickTime = 0;

double tickSpeed = 0;


// Структура для хранения информации о новостях

struct NewsEvent

{

datetime time;

string currency;

string event;

int impact; // 0=low, 1=medium, 2=high, 3=very high

};


//+–+

//| Expert initialization function |

//+–+

int OnInit()

{

// Проверка входных параметров

if(LotSize <= 0 || LotSize > 100)

{

Print("Некорректный размер лота!");

return INIT_PARAMETERS_INCORRECT;

}


if(TakeProfit_Pips <= 0 || StopLoss_Pips <= 0)

{

Print("Некорректные уровни TP/SL!");

return INIT_PARAMETERS_INCORRECT;

}


// Инициализация индикаторов

handleFastMA = iMA(_Symbol, PERIOD_M1, FastMA_Period, 0, MA_Method, PRICE_CLOSE);

handleSlowMA = iMA(_Symbol, PERIOD_M1, SlowMA_Period, 0, MA_Method, PRICE_CLOSE);

handleMomentum = iMomentum(_Symbol, PERIOD_M1, Momentum_Period, PRICE_CLOSE);


if(handleFastMA == INVALID_HANDLE || handleSlowMA == INVALID_HANDLE ||

handleMomentum == INVALID_HANDLE)

{

Print("Ошибка создания индикаторов!");

return INIT_FAILED;

}


// Установка массивов как таймсерии

ArraySetAsSeries(fastMA, true);

ArraySetAsSeries(slowMA, true);

ArraySetAsSeries(momentum, true);


// Инициализация начального эквити

initialEquity = AccountInfoDouble(ACCOUNT_EQUITY);


// Сброс счетчика сделок при перезагрузке

ResetDailyTradesCounter();


// Создание таймера для мониторинга скорости тиков

EventSetTimer(1);


return INIT_SUCCEEDED;

}


//+–+

//| Expert deinitialization function |

//+–+

void OnDeinit(const int reason)

{

if(handleFastMA != INVALID_HANDLE) IndicatorRelease(handleFastMA);

if(handleSlowMA != INVALID_HANDLE) IndicatorRelease(handleSlowMA);

if(handleMomentum != INVALID_HANDLE) IndicatorRelease(handleMomentum);

EventKillTimer();

}


//+–+

//| Expert tick function |

//+–+

void OnTick()

{

// Подсчет скорости тиков

tickCounter++;

datetime currentTickTime = TimeCurrent();

if(lastTickTime == 0) lastTickTime = currentTickTime;


// Проверяем ежедневный лимит сделок

CheckDailyTradesLimit();


// Проверяем защиту по эквити

if(UseEquityProtection && !CheckEquityProtection()) return;


// Проверяем фильтр новостей

if(UseNewsFilter && IsNewsTime()) return;


// Проверяем спред

if(!CheckSpread()) return;


// Проверяем скорость тиков

if(!CheckTickSpeed()) return;


// Проверяем наличие открытых позиций

if(PositionSelect(_Symbol)) return;


// Получаем данные индикаторов

if(!UpdateIndicators()) return;


// Получаем тиковые данные

MqlTick lastTick;

if(!SymbolInfoTick(_Symbol, lastTick)) return;


// Получаем данные объемов

long volumeArray[];

ArraySetAsSeries(volumeArray, true);

if(CopyTickVolume(_Symbol, PERIOD_M1, 0, 3, volumeArray) <= 0) return;


// Генерируем сигналы

bool buySignal = GenerateBuySignal(lastTick, volumeArray);

bool sellSignal = GenerateSellSignal(lastTick, volumeArray);


// Открываем позиции

if(buySignal)

{

OpenPosition(ORDER_TYPE_BUY);

}

else if(sellSignal)

{

OpenPosition(ORDER_TYPE_SELL);

}

}


//+–+

//| Timer function для подсчета скорости тиков |

//+–+

void OnTimer()

{

datetime currentTime = TimeCurrent();

double timeDiff = currentTime – lastTickTime;


if(timeDiff > 0)

{

tickSpeed = tickCounter / timeDiff;

tickCounter = 0;

lastTickTime = currentTime;

}

}


//+–+

//| Функция генерации сигнала на покупку |

//+–+

bool GenerateBuySignal(MqlTick &tick, long &volumeArray[])

{

// Сигнал по скользящим средним

bool maSignal = fastMA[0] > slowMA[0] && fastMA[1] <= slowMA[1];


// Сигнал по моменту

bool momentumSignal = momentum[0] > 100 && momentum[1] <= 100;


// Проверка объема

bool volumeSignal = volumeArray[0] > Volume_Threshold;


// Проверка цены (микро-паттерны)

bool pricePattern = CheckBullishMicroPattern();


// Комбинированный сигнал

return (maSignal && momentumSignal && volumeSignal && pricePattern);

}


//+–+

//| Функция генерации сигнала на продажу |

//+–+

bool GenerateSellSignal(MqlTick &tick, long &volumeArray[])

{

// Сигнал по скользящим средним

bool maSignal = fastMA[0] < slowMA[0] && fastMA[1] >= slowMA[1];


// Сигнал по моменту

bool momentumSignal = momentum[0] < 100 && momentum[1] >= 100;


// Проверка объема

bool volumeSignal = volumeArray[0] > Volume_Threshold;


// Проверка цены (микро-паттерны)

bool pricePattern = CheckBearishMicroPattern();


// Комбинированный сигнал

return (maSignal && momentumSignal && volumeSignal && pricePattern);

}


//+–+

//| Проверка бычьего микро-паттерна |

//+–+

bool CheckBullishMicroPattern()

{

// Пример: проверка последовательности из 3 последних тиков

MqlRates rates[];

ArraySetAsSeries(rates, true);


if(CopyRates(_Symbol, PERIOD_M1, 0, 5, rates) < 5) return false;


// Паттерн: снижение-снижение-рост (поглощение)

bool pattern1 = rates[3].close < rates[3].open && // Медвежья свеча

rates[2].close < rates[2].open && // Медвежья свеча

rates[1].close > rates[1].open && // Бычья свеча

rates[1].close > rates[2].close; // Закрытие выше предыдущего закрытия


// Паттерн: молот или доджи после снижения

bool pattern2 = rates[2].close < rates[2].open && // Медвежья свеча

(rates[1].high – rates[1].low) > 3 * (rates[1].close – rates[1].open) && // Длинная тень

rates[1].close > rates[1].open; // Закрытие выше открытия


return pattern1 || pattern2;

}


//+–+

//| Проверка медвежьего микро-паттерна |

//+–+

bool CheckBearishMicroPattern()

{

MqlRates rates[];

ArraySetAsSeries(rates, true);


if(CopyRates(_Symbol, PERIOD_M1, 0, 5, rates) < 5) return false;


// Паттерн: рост-рост-снижение (поглощение)

bool pattern1 = rates[3].close > rates[3].open && // Бычья свеча

rates[2].close > rates[2].open && // Бычья свеча

rates[1].close < rates[1].open && // Медвежья свеча

rates[1].close < rates[2].close; // Закрытие ниже предыдущего закрытия


// Паттерн: повешенный или доджи после роста

bool pattern2 = rates[2].close > rates[2].open && // Бычья свеча

(rates[1].high – rates[1].low) > 3 * (rates[1].open – rates[1].close) && // Длинная тень

rates[1].close < rates[1].open; // Закрытие ниже открытия


return pattern1 || pattern2;

}


//+–+

//| Обновление данных индикаторов |

//+–+

bool UpdateIndicators()

{

if(CopyBuffer(handleFastMA, 0, 0, 3, fastMA) <= 0) return false;

if(CopyBuffer(handleSlowMA, 0, 0, 3, slowMA) <= 0) return false;

if(CopyBuffer(handleMomentum, 0, 0, 3, momentum) <= 0) return false;


return true;

}


//+–+

//| Проверка спреда |

//+–+

bool CheckSpread()

{

MqlTick lastTick;

if(!SymbolInfoTick(_Symbol, lastTick)) return false;


double currentSpread = (lastTick.ask – lastTick.bid) / _Point;


return currentSpread <= MaxSpread_Pips;

}


//+–+

//| Проверка скорости тиков |

//+–+

bool CheckTickSpeed()

{

return tickSpeed >= MinTickSpeed;

}


//+–+

//| Проверка времени новостей |

//+–+

bool IsNewsTime()

{

// В реальной реализации здесь должен быть доступ к календарю новостей

// Это примерная заглушка


TimeToStruct(TimeCurrent(), currentTime);


// Пример: не торговать в 8:30-9:00 и 13:30-14:00 (важные релизы)

bool newsTime1 = (currentTime.hour == 8 && currentTime.min >= 30) ||

(currentTime.hour == 9 && currentTime.min == 0);


bool newsTime2 = (currentTime.hour == 13 && currentTime.min >= 30) ||

(currentTime.hour == 14 && currentTime.min == 0);


return newsTime1 || newsTime2;

}


//+–+

//| Проверка защиты по эквити |

//+–+

bool CheckEquityProtection()

{

double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);

double drawdownPercent = ((initialEquity – currentEquity) / initialEquity) * 100;


return drawdownPercent < EquityProtectionPercent;

}


//+–+

//| Проверка дневного лимита сделок |

//+–+

void CheckDailyTradesLimit()

{

datetime currentDate = TimeCurrent();

MqlDateTime dateStruct;

TimeToStruct(currentDate, dateStruct);


// Если день сменился, сбрасываем счетчик

if(lastTradeDate != dateStruct.day)

{

todayTrades = 0;

lastTradeDate = dateStruct.day;

}

}


//+–+

//| Сброс счетчика дневных сделок |

//+–+

void ResetDailyTradesCounter()

{

datetime currentDate = TimeCurrent();

MqlDateTime dateStruct;

TimeToStruct(currentDate, dateStruct);


todayTrades = 0;

lastTradeDate = dateStruct.day;

}


//+–+

//| Открытие позиции |

//+–+

void OpenPosition(ENUM_ORDER_TYPE orderType)

{

// Проверяем лимит сделок

if(todayTrades >= MaxDailyTrades) return;


MqlTradeRequest request = {};

MqlTradeResult result = {};


request.action = TRADE_ACTION_DEAL;

request.symbol = _Symbol;

request.volume = LotSize;

request.type = orderType;

request.type_filling = ORDER_FILLING_IOC; // Немедленное исполнение или отмена

request.deviation = 1; // Минимальное отклонение

request.magic = MagicNumber;


// Установка цен

MqlTick lastTick;

SymbolInfoTick(_Symbol, lastTick);


if(orderType == ORDER_TYPE_BUY)

{

request.price = lastTick.ask;

request.sl = request.price – StopLoss_Pips * _Point;

request.tp = request.price + TakeProfit_Pips * _Point;

}

else // ORDER_TYPE_SELL

{

request.price = lastTick.bid;

request.sl = request.price + StopLoss_Pips * _Point;

request.tp = request.price – TakeProfit_Pips * _Point;

}


// Отправка ордера

if(!OrderSend(request, result))

{

Print("Ошибка открытия позиции: ", GetLastError());

}

else

{

todayTrades++;

Print("Позиция открыта. Сегодня сделок: ", todayTrades);

}

}


//+–+

//| Функция закрытия всех позиций |

//+–+

void CloseAllPositions()

{

for(int i = PositionsTotal()-1; i >= 0; i–)

{

ulong ticket = PositionGetTicket(i);

if(PositionSelectByTicket(ticket))

{

if(PositionGetString(POSITION_SYMBOL) == _Symbol &&

PositionGetInteger(POSITION_MAGIC) == MagicNumber)

{

MqlTradeRequest request = {};

MqlTradeResult result = {};


request.action = TRADE_ACTION_DEAL;

request.position = ticket;

request.symbol = _Symbol;

request.volume = PositionGetDouble(POSITION_VOLUME);

request.deviation = 1;


if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)

{

request.type = ORDER_TYPE_SELL;

request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);

}

else

{

request.type = ORDER_TYPE_BUY;

request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

}


OrderSend(request, result);

}

}

}

}

```


Дополнительные функции для реального скальпинга:


```mq5

//+–+

//| Функция мониторинга стакана цен (упрощенная) |

//+–+

void MonitorMarketDepth()

{

// В MT5 нет прямого доступа к Level II, но можно использовать

// символьные свойства для получения информации о спросе/предложении


MqlTick lastTick;

SymbolInfoTick(_Symbol, lastTick);


// Можно добавить логику анализа объема на текущих ценах

// Например, отслеживать крупные лимитные ордера

}


//+–+

//| Функция анализа кластеров объемов |

//+–+

void AnalyzeVolumeClusters()

{

// Использование индикатора Volume Profile или Cluster Charts

// для определения уровней с максимальным объемом

}


//+–+

//| Функция для работы со стаканом заявок (требует специальных API) |

//+–+

void ProcessMarketDepth()

{

// Для реального доступа к Level II потребуется:

// 1. API от брокера с доступом к стакану

// 2. Специальные библиотеки или плагины

// 3. Прямое подключение к биржевым данным

}

```


Ключевые особенности скальпера:


1. Сверхбыстрая торговля:

· Использование тиковых данных

· Мгновенное исполнение (IOC)

· Минимальные уровни TP/SL (5-15 пунктов)

2. Система защиты:

· Ограничение по количеству сделок в день

· Защита по эквити

· Фильтр по спреду

· Фильтр новостей

3. Мониторинг качества соединения:

· Контроль скорости тиков

· Проверка стабильности подключения

4. Анализ микро-паттернов:

· Свечные паттерны на M1

· Анализ объемов

· Мониторинг момента


Требования для работы скальпера:


1. Технические:

· VPS с низкой задержкой (менее 1 мс к серверу)

· Выделенный канал связи

· Стабильное электропитание

2. Торговые условия:

· ECN счет с сырыми спредами

· Минимальная комиссия

· Разрешение на скальпинг

3. Рыночные условия:

· Высокая ликвидность (мажорные пары)

· Низкая волатильность в азиатскую сессию

· Отсутствие важных новостей


Важно: Скальпинг – это высокочастотная торговля с высокими рисками. Тестируйте стратегию на демо-счете не менее 3 месяцев перед использованием на реальные деньги. Начните с минимального лота и постепенно увеличивайте объемы при стабильной прибыльности.

10 роботов для автоматической торговли на Форекс

Подняться наверх