//+------------------------------------------------------------------+ //| TrailingBySAR_02.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #define SAR_DATA_INDEX 1 // бар, с которого получаем данные Parabolic SAR #include // заменим торговые функции методами Стандартной Библиотеки //--- input parameters input ENUM_TIMEFRAMES InpTimeframeSAR = PERIOD_CURRENT; // Parabolic SAR Timeframe input double InpStepSAR = 0.02; // Parabolic SAR Step input double InpMaximumSAR = 0.2; // Parabolic SAR Maximum input ulong InpMagic = 123; // Magic Number //--- global variables int ExtHandleSAR=INVALID_HANDLE; // хэндл Parabolic SAR double ExtStepSAR=0; // шаг Parabolic SAR double ExtMaximumSAR=0; // максимум Parabolic SAR CTrade ExtTrade; // экземпляр класса торговых операций //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- устанавливаем в объект торгового класса магический номер ExtTrade.SetExpertMagicNumber(InpMagic); //--- устанавливаем параметры Parabolic SAR в допустимых пределах ExtStepSAR =(InpStepSAR<0.0001 ? 0.0001 : InpStepSAR); ExtMaximumSAR=(InpMaximumSAR<0.0001 ? 0.0001 : InpMaximumSAR); //--- при ошибке создания индикатора выводим сообщение в журнал и выходим с ошибкой из OnInit ExtHandleSAR =iSAR(Symbol(), InpTimeframeSAR, ExtStepSAR, ExtMaximumSAR); if(ExtHandleSAR==INVALID_HANDLE) { PrintFormat("Failed to create iSAR(%s, %s, %.3f, %.2f) handle. Error %d", Symbol(), TimeframeDescription(InpTimeframeSAR), ExtStepSAR, ExtMaximumSAR, GetLastError()); return(INIT_FAILED); } //--- успешно return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- если не новый бар - уходим из обработчика if(!IsNewBar()) return; if(MQLInfoInteger(MQL_TESTER)) { //--- получаем данные Parabolic SAR с баров 1 и 2 double sar1=GetSARData(SAR_DATA_INDEX); double sar2=GetSARData(SAR_DATA_INDEX+1); //--- если структура цен заполнена и данные от Parabolic SAR получены MqlTick tick={}; if(SymbolInfoTick(Symbol(), tick) && sar1!=EMPTY_VALUE && sar2!=EMPTY_VALUE) { //--- если Parabolic SAR на баре 1 ниже цены Bid, а на баре 2 выше - открываем длинную позицию if(sar1tick.bid) ExtTrade.Buy(0.1); //--- если Parabolic SAR на баре 1 выше цены Ask, а на баре 2 ниже - открываем короткую позицию if(sar1>tick.ask && sar2=0; i--) { //--- получаем тикет очередной позиции ulong pos_ticket=PositionGetTicket(i); if(pos_ticket==0) continue; //--- получаем символ и магик позиции string pos_symbol = PositionGetString(POSITION_SYMBOL); long pos_magic = PositionGetInteger(POSITION_MAGIC); //--- пропускаем позиции, не соответствующие фильтру по символу и магику if((magic!=-1 && pos_magic!=magic) || pos_symbol!=Symbol()) continue; //--- если цены получить не удалось - идём далее if(!SymbolInfoTick(Symbol(), tick)) continue; //--- получаем тип позиции, цену её открытия и уровень StopLoss ENUM_POSITION_TYPE pos_type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double pos_open=PositionGetDouble(POSITION_PRICE_OPEN); double pos_sl =PositionGetDouble(POSITION_SL); //--- если условия для модификации StopLoss подходят - модифицируем стоп позиции if(CheckCriterion(pos_type, pos_open, pos_sl, value_sl, trailing_step_pt, trailing_start_pt, tick)) ExtTrade.PositionModify(pos_ticket, value_sl, PositionGetDouble(POSITION_TP)); } } //+------------------------------------------------------------------+ //|Проверяет критерии модификации StopLoss позициии и возвращает флаг| //+------------------------------------------------------------------+ bool CheckCriterion(ENUM_POSITION_TYPE pos_type, double pos_open, double pos_sl, double value_sl, int trailing_step_pt, int trailing_start_pt, MqlTick &tick) { //--- если стоп позиции и уровень стопа для модификации равны - возвращаем false if(NormalizeDouble(pos_sl-value_sl, Digits())==0) return false; double trailing_step = trailing_step_pt*Point(); // переводим шаг трала в цену double stop_level = StopLevel(2)*Point(); // переводим уровень StopLevel символа в цену int pos_profit_pt = 0; // прибыль позиции в пунктах //--- в зависимости от типа позиции проверяем условия для модицикации StopLoss switch(pos_type) { //--- длинная позиция case POSITION_TYPE_BUY : pos_profit_pt=int((tick.bid-pos_open)/Point()); // рассчитываем прибыль позиции в пунктах if(tick.bid-stop_level>value_sl // если цена и отложенный от неё уровень StopLevel выше уровня StopLoss (соблюдена дистанция по StopLevel) && pos_sl+trailing_steptrailing_start_pt) // если тралим при любой прибыли или прибыль позиции в пунктах больше значения начала трейлинга - возвращаем true ) return true; break; //--- короткая позиция case POSITION_TYPE_SELL : pos_profit_pt=int((pos_open-tick.ask)/Point()); // рассчитываем прибыль позиции в пунктах if(tick.ask+stop_levelvalue_sl || pos_sl==0) // если уровень StopLoss ниже, чем шаг трала, отложенный от текущего StopLoss позиции или у позиции ещё не установлен StopLoss && (trailing_start_pt==0 || pos_profit_pt>trailing_start_pt) // если тралим при любой прибыли или прибыль позиции в пунктах больше значения начала трейлинга - возвращаем true ) return true; break; //--- по умолчанию вернём false default: break; } return false; } //+------------------------------------------------------------------+ //| Функция трейлинга StopLoss по индикатору Parabolic SAR | //+------------------------------------------------------------------+ void TrailingStopBySAR(const long magic=-1, const int trailing_step_pt=0, const int trailing_start_pt=0) { //--- получаем значение Parabolic SAR с первого бара таймсерии double sar=GetSARData(SAR_DATA_INDEX); //--- если данные получить не удалось - уходим if(sar==EMPTY_VALUE) return; //--- вызываем универсальную функцию трала с указанием цены StopLoss, полученной от Parabolic SAR TrailingStopByValue(sar, magic, trailing_step_pt, trailing_start_pt); } //+------------------------------------------------------------------+