Функции для советников и индикаторов

Тема в разделе "Индикаторы и советники для Metatrader", создана пользователем Alex F, 25 апр 2017.

  1. Alex F

    Alex F Суслик

    В данной теме предлагаю выкладывать готовые функции для MetaTrader 4/5 для написания советников.
    Очень часто разработчикам, особенно новеньким в этой сфере, приходится искать в интернете решение той или иной задачи. Предлагаю аккумулировать данные вещи в одной теме.
    По мере наполнения предложенные функции будут выноситься в шапку тему для более простого поиска.

    Код:
    bool bCheckOrders()
    {
       for(int i = 0; i <= OrdersTotal(); i++)
          if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
             if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
             {
                return(false);
             }
       return(true);
    }
    Возврат True = нет открытых ордеров, возврат False - есть открытые ордера
    Код:
    void TrailingStop(int iMagic)
    {
       bool res=false;
       double _TrailingStop = TrailingStop;
       
       for(int i=0;i<OrdersTotal();i++)
       {
          if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) continue;
          if(OrderMagicNumber()!=iMagic || OrderSymbol()!=Symbol()) continue;
         
          if(OrderType() == OP_BUY)
             {
                if(((Bid-OrderOpenPrice()) > (Point*_TrailingStop)) && (OrderStopLoss() < (Bid-Point*_TrailingStop))){
                   res = OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*_TrailingStop,OrderTakeProfit(),0,GreenYellow);
                   }
             }
       
          if(OrderType() == OP_SELL)
             {
                if(((OrderOpenPrice() - Ask) > (Point * _TrailingStop)) && (OrderStopLoss() > (Ask + Point * _TrailingStop))){
                   res = OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*_TrailingStop,OrderTakeProfit(),0,Red);
                   }
             }
       }
    }
    Передаваемое значение iMagic - номер Magic ордера.
    
    Передаваемые значения: номер ордера.
    double GetSpread()
    {
    RefreshRates();
    double spread = MathAbs(Ask-Bid)*Point;
    return spread;
    }
    Возврат значения спред в абсолютном (положительном значении)
    Код:
    void CloseDirect(int ticket, string comm)
      {
        double closeprice;
        if(OrderSelect(ticket,SELECT_BY_POS,MODE_TRADES))
          {
            RefreshRates();
            if (OrderType()==OP_BUY)
              closeprice=Bid;
            else
              closeprice=Ask;   
            if (OrderClose(OrderTicket(),OrderLots(),closeprice,5,Green))
            {
              Print(comm, OrderTicket());
            }
            else
              {
                Print("ОШИБКА в CloseDirect():OrderClose() - ",GetLastError());
              }
          }
        else
          {
            Print("ОШИБКА в CloseDirect():OrderSelect() - ",GetLastError());
          }
      }
    int ticket - номер ордера
    string comm - тип ордера (OP_BUY, OP_SELL)
    Код:
       void BU()
      {
             if(OrderType()==OP_BUY)
              {
               if(OrderOpenPrice()<=(Bid-Point*BULevel)&&OrderOpenPrice()>OrderStopLoss())
                bool bu_buy=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,Green);
               } 
             if(OrderType() == OP_SELL)
               {
                if(OrderOpenPrice()>=(Ask+Point*BULevel)&&OrderOpenPrice()<OrderStopLoss())
                  bool bu_sell=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,Red);
               }
      }
    BULevel - внешняя переменная (пункты), при достижении которого ордер переводится в безубыток.
    Код:
    int StdWeek()
       {
       int iDay  = ( TimeDayOfWeek(TimeCurrent()) + 6 ) % 7 + 1,                    // convert day to standard index (1=Mon,...,7=Sun)
       iWeek = (TimeDayOfYear(TimeCurrent()) - iDay + 10 ) / 7;                // calculate standard week number
       return(iWeek);
       }
    Код:
    //Расчет экстремумов за указанный период
    double _Highest(int period, int shift, int TimeFrame)
    {
       return(iHigh(Symbol(),TimeFrame,iHighest(Symbol(), TimeFrame, MODE_HIGH, period,shift)));
    }
    
    double _Lowest(int period, int shift, int TimeFrame)
    {
       return(iLow(Symbol(),TimeFrame,iLowest(Symbol(), TimeFrame, MODE_LOW, period, shift)));
    }
    Функция, возвращающая экстремумы (High и Low) на указанном ТФ.
    Например:
    _Highest(1 , 1, PERIOD_W1); - вернет High прошлой недельной свечи
    _Highest(1 , 2, PERIOD_W1); - вернет High позапрошлой недельной свечи
     
    Последнее редактирование: 4 май 2017
    AAA+, Мастер с йодом и Димка нравится это.
  2. Димка

    Димка Старший трейдер

    Столкнулся с такой проблемой, если открываемый ордер закроется (по СЛ или ТП) на баре, на котором открылся, то происходит повторная отправка ордера, т.к. сигнал ещё действует. Решение данной проблемы очень простое (не мое, нашел в сети). Решение в запоминании времени бара на котором пришел сигнал. Суть проста, делать попытку открытия ордера пока запомненное время не равно времени текущего бара, если попытка отправки прошла удачно, то запоминаем время текущего бара.
    Выглядит это так:
    перед открытием ордера делаем такую проверку
    if(ti!=Time[0]) где ti - переменная в которой хранится время открытия бара на котором был последний вход, Time[0] - время открытия текущего бара
    дальше идет ваш код открытия ордера, и если советник его открыл то присваиваем ti время открытия текущего бара (запоминаем его)
    ti=Time[0];
    Вот в принципе и все, такая проверка позволит открыть на одном баре только одну сделку. И не забываем что ti перед этим надо объявить, у меня выглядит так datetime ti=0;.
    Вот что получается без такой проверки:
    [​IMG]
     
    Последнее редактирование модератором: 27 авг 2018