Трейдеры часто используют в своих торговых системах разные виды трейлингстопа. Цели трейлинга тоже могут быть разные, ограничение убытков или получение максимально возможной прибили (в зависимости от Вашей ТС). Для примера возьмем из прошлой статьи «Советник и пользовательской индикатор» эксперт TrendMagic 0.0 и добавим ему обычный трейлингстоп. Который при переходе в зону профита подтягивает стоплос за ценой.
Сначала объявим глобальную переменную TrailingStop что бы в настройках советника можно было изменять параметр трейлинга.
//---- input parameters extern int Magic = 111; //число может быть любым extern int StopLoss = 0; extern int TakeProfit = 0; extern int TrailingStop = 20; extern double Lot = 0.1;
В функции start() добавим всего одну строку для вызова трейлингстопа.
if(total > 0 && TrailingStop > 0) Trailing(); // вызываем функцию трейлингстопа
А сам трейлинг сделаем отдельной функцией.
//+------------------------------------------------------------------+ // Трейлинг | //+------------------------------------------------------------------+ int Trailing() { for(int i = 0; i < total; i ++) // начало цикла { if(OrderSelect(i, SELECT_BY_POS) == false) continue; // если ордер не выбран, возвращаемся в начало цикла if(Magic != OrderMagicNumber()) continue; // если магическое число не совпадает с нашим Magic - возвращаемся в начало цикла Ticket = OrderTicket(); // запоминаем номер ордера if((OrderType() == 1) && (OrderOpenPrice() - Ask > TrailingStop*Point) && ((OrderStopLoss() > Ask + TrailingStop*Point) || (OrderStopLoss()==0))) { if(OrderStopLoss() == NormalizeDouble(Ask + TrailingStop*Point,Digits)) return(0); // что бы избежать ошибки 1 Text ="Sell"; // для функции inf... что бы вывести в сообщении с каким ордером работаем. inf(3, Ticket, -1); // вызываем информационную функцию... сообщаем о попытке модифицировать Sell ордер answer = OrderModify(Ticket,OrderOpenPrice(),NormalizeDouble(Ask + TrailingStop*Point,Digits),OrderTakeProfit(),0,Red); if(answer == true) // если true значит все прошло успешно { // сообщаем об этом inf(4, Ticket, -1); // вызываем информационную функцию... сообщаем что попытка модифицировать Sell ордер удалась return(1); // выходим в start } inf(15, GetLastError()); // если дошли сюда значит есть ошибка... узнаем какая именно return(0); // выходим в start } if((OrderType() == 0) && (Bid - OrderOpenPrice() > TrailingStop*Point) && (OrderStopLoss() < Bid - TrailingStop*Point)) { if(OrderStopLoss() == NormalizeDouble(Bid - TrailingStop*Point,Digits)) return(0); // чтобы избежать ошибки 1 Text ="Buy"; // для функции inf... что бы вывести в сообщении с каким ордером работаем. inf(3, Ticket, -1); // вызываем информационную функцию... сообщаем о попытке модифицировать Buy ордер answer = OrderModify(Ticket,OrderOpenPrice(),NormalizeDouble(Bid - TrailingStop*Point,Digits),OrderTakeProfit(),0,Blue); if(answer == true) // если true значит все прошло успешно { // сообщаем об этом inf(4, Ticket, -1); // вызываем информационную функцию... сообщаем что попытка модифицировать Buy ордер удалась return(1); // выходим в start } inf(15, GetLastError()); // если дошли сюда значит есть ошибка... узнаем какая именно return(0); // выходим в start } } // конец цикла return(0); }
Как всегда выбираем ордер с помощью ф-ции OrderSelect путем перебора в цикле for. Проверяем условия трейлинга, если цена в профите и отошла от цены открытия и стоплоса больше чем задано параметром TrailingStop – модифицируем ордер ф-цией OrderModify (устанавливаем новый уровень стоплоса). Цену открытия и тейкпрофит подставляем прежние (цену открытия в маркет ордерах изменять нельзя).
Здесь все знакомо кроме торговой функции OrderModify.
OrderModify – с ее помощью мы можем изменять разные параметры ордера, уровни стоплоса и тейкпрофита, цену открытия (если это отложенный ордер) и тд.
При расчете и округлении нового стопа может оказаться что новое значение равно нынешнему, при попытке модифицировать будет возвращена ошибка 1 (Нет ошибки, но результат неизвестен). Что бы не допускать подобных ошибок проверяем не равняется ли новое значение старому, если равно обрываем цикл и выходим из функции.
if(OrderStopLoss() == NormalizeDouble(Bid - TrailingStop*Point,Digits)) return(0); // что бы избежать ошибки 1
Для работы «эксперта» нужен индикатор TrendMagic.
Индикатор: TrendMagic
Исходник: TrendMagic-0.1
Индикаторный «советник» и пользовательский индикатор — https://forexlab.ru/mql-advisor-on-indicator/