Полезные функции и др. в помощь разработчику экспертов

Хранилище собственных творений: индикаторы, скрипты, советники, в общем, все, на что муза вдохновила. Так же полезное ПО, взятое из открытых источников в Интернет.
Бонус за сообщение 0.4$
Ответственный Модератор - Рэндом

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 07 мар 2015, 07:29

Открытие позиции по выбранной цене.

Код: выделить все
void OpenPosition(string sy, int op, double ll, double sl, double tp, int mn, string co)
{
/*
   Версия   : 12.02.2014     
   Автор прототипа Ким Игорь В. aka KimIV.                                               
   Описание : Открывает позицию по рыночной цене.                           
   Параметры:                                                               
   sy - наименование инструмента   ("0" - текущий символ)         
   op - операция {OP_BUY; OP_SELL}                                                           
   ll - лот                                                               
   sl - уровень стоп (0)                                                     
   tp - уровень тейк  (0)                                                   
   mn - MagicNumber                                                       
   co - комментарий ("" - нет комментария)                                                       
*/
   datetime ot;
   double   pp, pa, pb;
   int      dg, err, it, ticket = 0;

   if(sy == "0") sy = Symbol();
   if(co == "") co = WindowExpertName() + " " + GetNameTF(Period());
   for(it = 1; it <= NumberOfTry; it++)
   {
      if(!IsTesting() && (!IsExpertEnabled() || IsStopped()))
      {
         Print("OpenPosition(): Остановка работы функции");
         break;
      }
      while(!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      dg = (int)MarketInfo(sy, MODE_DIGITS); // надо бы по уму сделать!
      pa = MarketInfo(sy, MODE_ASK);
      pb = MarketInfo(sy, MODE_BID);
      if(op == OP_BUY) pp = pa; else pp = pb;
      pp = NormalizeDouble(pp, dg);
      ot = TimeCurrent();
      if(MarketWatch)
         ticket = OrderSend(sy, op, ll, pp, Slippage, 0, 0, co, mn, 0, CLR_NONE);
      else
         ticket = OrderSend(sy, op, ll, pp, Slippage, sl, tp, co, mn, 0, CLR_NONE);
      if(ticket > 0)
      {
         if (UseSound) PlaySound(SoundSuccess); break;
      }
      else
      {
         err = GetLastError();
         if(UseSound) PlaySound(SoundError);
         if(pa == 0 && pb == 0) Message("Проверьте в Обзоре рынка наличие символа " + sy);
         // Вывод сообщения об ошибке
         Print("Error(",err,") opening position: ",f_ErrorDescription(err),", try ",it);
         Print("Ask=",pa," Bid=",pb," sy=",sy," ll=",ll," op=",GetNameOP(op),
            " pp=",pp," sl=",sl," tp=",tp," mn=",mn);
         // Блокировка работы советника
        // if(err == 2 || err == 64 || err == 65 || err == 133)
         if(err == 2 || err == 64 || err == 65 || err == 132 || err == 133)
         {
            gbDisabled = True; break;
         }
         // Длительная пауза
         //if(err == 4 || err == 131 || err == 132)
         if(err == 6)
         {
            Sleep(1000*300); break;
         }
        // if(err == 128 || err == 142 || err == 143)
         if(err == 4 || err == 146 || err == 137)
         {
            Sleep(1000 * 66.666);
            if(ExistPositions(sy, op, mn, ot))
            {
               if(UseSound) PlaySound(SoundSuccess); break;
            }
         }
    //  if(err==140 || err==148 || err==4110 || err==4111) break;
      if(err==4110 || err==4111) break;
      if(err==141) Sleep(1000*100);
      if(err==145) Sleep(1000*17);
      if(err==146) while (IsTradeContextBusy()) Sleep(1000*11);
      if(err!=135) Sleep(1000*7.7);
    }
  }
  if(MarketWatch && ticket > 0 && (sl > 0 || tp > 0))
  {
    if(OrderSelect(ticket, SELECT_BY_TICKET)) ModifyOrder(-1, sl, tp, 0);
  }
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 07 мар 2015, 07:34

Замечание: в прошлых функциях и в дальнейшем могут быть использованы следующие переменные

Код: выделить все
   bool     AllMessages,
              PrintEnable;
   bool     gbDisabled;    // Флаг блокировки советника
   bool     MarketWatch;   // Запросы под исполнение "Market Watch"
   int       Slippage;      // Проскальзывание цены
   int       NumberOfTry;   // Количество торговых попыток
   bool     UseSound;      // Использовать звуковой сигнал
   string   SoundSuccess;  // Звук успеха
   string   SoundError;    // Звук ошибки
   int       LevelProfit;   // Уровень профита в пунктах
   int       LevelWLoss;    // Уровень безубытка в пунктах

   NumberOfTry    = 5;
   UseSound       = True;
   SoundSuccess   = "ok.wav";       
   SoundError     = "timeout.wav";
   MarketWatch    = True;
   Slippage       = 3; 
   gbDisabled     = False;   
   LevelProfit    = 25;  //25           
   LevelWLoss     = 1;

У меня все организовано в класс, но если функции используются отдельно, то необходимо определить и описать приведенные выше переменные как глобальные для данного модуля.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 12 мар 2015, 13:23

Если мы используем в коде индикатор Larry Williams' Percent Range (iWPR), то зачастую мы ищем момент пересечения его линией
нижней (обычно -80.0) или верхней (обычно -20.0) границы как снизу вверх, так и сверху вниз для определения вхождения и выхода из зоны перепроданности или перекупленности.
Данная функция осуществляет данный контроль:
Код: выделить все
string f_WPRCro(int tf, int pe, double ll, double ml, double hl)
{
/*
   на основе индикатора Larry Williams' Percent Range (iWPR).
   Параметры:                                                               
   tf   - торгуемый таймфрейм графика (0 - текущий ТФ)
   pe   - Период усреднения основной линии индикатора
   ll   - Нижней уровень iWPR (обычно -80 или -70).
   ml   - Средний уровень iWPR (обычно -50).
   hl   - Верхний уровень iWPR (обычно -20 или -30).
   Возвращаемые значения:
   1. WPR пересек уровень hl снизу вверх ("YhDU")
   2. WPR пересек уровень hl сверху вниз ("YhUD")
   3. WPR пересек уровень ll снизу вверх ("YlDU")
   4. WPR пересек уровень ll сверху вниз ("YlUD")
   5. Иные варианты ("NO")
   double iWPR( string symbol, int timeframe, int period, int shift)
*/
   double dblWPR_1 = iWPR(NULL, tf, pe, 1); // Значение индикатора iWPR 1 бар назад
   double dblWPR_2 = iWPR(NULL, tf, pe, 2); // Значение индикатора iWPR 2 бара назад
   if(dblWPR_2 < hl && dblWPR_1 > hl) return("YhDU");
   if(dblWPR_2 > hl && dblWPR_1 < hl) return("YhUD");
   if(dblWPR_2 < ll && dblWPR_1 > ll) return("YlDU");
   if(dblWPR_2 > ll && dblWPR_1 < ll) return("YlUD");
   
return("NO");
}
Последний раз редактировалось Haos 12 мар 2015, 13:46, всего редактировалось 1 раз.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 12 мар 2015, 13:31

Данная функция (незначительно модифицирована мною) является одним из вариантов определения появления нового бара. Крайне важная вещь для тех, кто пишет советники, работающие не на каждом тике!
Код: выделить все
bool f_IsNewBar(string sy, ENUM_TIMEFRAMES tf)
{
/*
   Описание:
   возвращает true если появился новый бар, иначе false 
   Параметры:
   sy - наименование инструмента   ("0" - текущий символ)
   tf - период графика
*/
   static datetime old_Times[21];// массив для хранения старых значений
   bool res = false;               // переменная результата анализа 
   int  i = 0;                     // номер ячейки массива old_Times[]     
   datetime new_Time[1];         // время нового бара
   if(sy == "0") sy = Symbol();
   
   switch(tf)
   {
      case PERIOD_M1:  i= 0; break;
      case PERIOD_M2:  i= 1; break;
      case PERIOD_M3:  i= 2; break;
      case PERIOD_M4:  i= 3; break;
      case PERIOD_M5:  i= 4; break;
      case PERIOD_M6:  i= 5; break;
      case PERIOD_M10: i= 6; break;
      case PERIOD_M12: i= 7; break;
      case PERIOD_M15: i= 8; break;
      case PERIOD_M20: i= 9; break;
      case PERIOD_M30: i=10; break;
      case PERIOD_H1:  i=11; break;
      case PERIOD_H2:  i=12; break;
      case PERIOD_H3:  i=13; break;
      case PERIOD_H4:  i=14; break;
      case PERIOD_H6:  i=15; break;
      case PERIOD_H8:  i=16; break;
      case PERIOD_H12: i=17; break;
      case PERIOD_D1:  i=18; break;
      case PERIOD_W1:  i=19; break;
      case PERIOD_MN1: i=20; break;
     }
   // скопируем время последнего бара в ячейку new_Time[0]   
   int copied = CopyTime(sy, tf, 0, 1, new_Time);
   
   if(copied > 0) // все ок. данные скопированы
   {
      if(old_Times[i] != new_Time[0])       // если старое время бара не равно новому
      {
         if(old_Times[i]!= 0) res = true;    // если это не первый запуск, то истина = новый бар
         old_Times[i] = new_Time[0];        // запоминаем время бара
      }
   }
//----
return(res);
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 12 мар 2015, 13:44

Когда-то писал советники с мартином и необходимо было определять уровень безубытка для всех открытых позиций ("центр масс" как в физике). Разработал для этой цели данную функцию.
Код: выделить все
double CenterOfMass(string sy, int op, int mn)
{
/*
   Версия   : 17.02.2014                                                     
   Описание : Определяет общий уровень безубытка для всех открытых сделок ("центр масс")
   Параметры:                                                               
   sy - наименование инструмента   (0 - текущий символ)                 
   op - операция                   (-1   - любая позиция)                 
   mn - MagicNumber                (-1   - любой магик)
*/
   double   dblQSum = 0;      // объем всех открытых позиции
   double   dblQYSum = 0;     // сумма произведений объемa на цену открытых позициий
   double   dblYc    = 0;     // цена центра масс
   
   if(sy == "0") sy = Symbol();
      for(int i = 0; i < OrdersTotal(); i++)
      {
         if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         {
            if(OrderSymbol() == sy)
            {
               if(OrderType()== OP_BUY || OrderType()== OP_SELL)
               {
                  if(op < 0 || OrderType() == op)
                  {
                     if(mn < 0 || OrderMagicNumber() == mn)
                     {
                        dblQYSum += OrderLots() * OrderOpenPrice();
                        dblQSum  += OrderLots();
                     }
                  }
               }
            }
         }
      }
      dblYc = NormalizeDouble(dblQYSum / dblQSum, Digits);
         
return(dblYc);
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение mfcoder » 12 мар 2015, 23:00

Haos писал(а):Когда-то писал советники с мартином и необходимо было определять уровень безубытка для всех открытых позиций ("центр масс" как в физике). Разработал для этой цели данную функцию.


если передать в параметр op значение -1, то получится фигня, потому что будут учитываться отложенные ордера для учета уровня безубытка, и это будет не тот уровень, который должен быть :-)
Аватар пользователя
mfcoder
 
Сообщений: 1531
Зарегистрирован: 29 июл 2013, 11:55
Средств на руках: 26.85 Доллар
Группа: Базовая
Благодарил (а): 78 раз.
Поблагодарили: 423 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 25 мар 2015, 16:42

Потестил исправление функции, выдающей расстояние от рынка до последней открытой позиции. Кстати, это легко делать путем вывода на экран в комментарии. Теперь выдает по-уму: если сделка пошла в плюс, то расстояние положительное (в пнт.), если в минус - то отрицательное. Применять можно тогда, когда в зависимости от этого расстояния открывается другая позиция.
Функция сторонних ресурсов (переменных, констант и т.п.) не использует.
Код: выделить все
int DistPriceAndLastPos(string sy, int op, int mn)
{
/*
   Версия   : 25.05.2015 г.                                                     
   Описание : Возвращает расстояние (пнт.) между рынком и ценой открытия последней
              открытой позицией (без учета спреда). Т.е. если сделка в профите,
              то значение будет положительным, если в убытке - отрицательным.               
   Параметры:                                                               
   sy - наименование инструмента   ("0" - текущий символ)                 
   op - операция                   (-1   - любая позиция)                 
   mn - MagicNumber                (-1   - любой магик)                   
*/
   datetime t = D'01.01.1970 00:00:00'; // Диапазон значений от 1 января 1970 года
   double   dblAsk,
            dblBid,
            p,
            dblPrice;
   int      intDelta = 0;
     
   if(sy == "0") sy = Symbol();
   p = MarketInfo(sy, MODE_POINT);

   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if((OrderSymbol() == sy) && (op < 0 || OrderType() == op))
         {
            if(mn < 0 || OrderMagicNumber() == mn)
            {       
               if(t < OrderOpenTime())
               {
                  t = OrderOpenTime();
                  dblPrice = OrderOpenPrice();
                  if(OrderType() == OP_BUY)
                  {
                     dblAsk = MarketInfo(sy, MODE_ASK);
                     intDelta = (int)((dblAsk - dblPrice) / p);
                  }
                  if(OrderType() == OP_SELL)
                  {
                     dblBid = MarketInfo(sy, MODE_BID);
                     intDelta = (int)((dblPrice - dblBid) / p);
                  }
               }
            }
         }
      }
   }
return(intDelta);
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 25 мар 2015, 16:53

mfcoder писал(а):
Haos писал(а):Когда-то писал советники с мартином и необходимо было определять уровень безубытка для всех открытых позиций ("центр масс" как в физике). Разработал для этой цели данную функцию.


если передать в параметр op значение -1, то получится фигня, потому что будут учитываться отложенные ордера для учета уровня безубытка, и это будет не тот уровень, который должен быть :-)

Да неужели? У меня всегда правильно работала. Как могут отложенные ордера учитываться, если в коде четко прописано:
Код: выделить все
 if(op < 0 || OrderType() == op)

Или операция любая (-1) т.е. или покупка или продажа или только покупка или только продажа. Покажи код где ты пытался применить функцию - посмотрим.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение mfcoder » 25 мар 2015, 19:53

Haos писал(а):Да неужели? У меня всегда правильно работала. Как могут отложенные ордера учитываться, если в коде четко прописано:
Код: выделить все
 if(op < 0 || OrderType() == op)

Или операция любая (-1) т.е. или покупка или продажа или только покупка или только продажа. Покажи код где ты пытался применить функцию - посмотрим.


точняк, ошибся я :smu:sche_nie:
Аватар пользователя
mfcoder
 
Сообщений: 1531
Зарегистрирован: 29 июл 2013, 11:55
Средств на руках: 26.85 Доллар
Группа: Базовая
Благодарил (а): 78 раз.
Поблагодарили: 423 раз.

Полезные функции и др. в помощь разработчику экспертов

Сообщение Haos » 31 мар 2015, 15:59

Функция возвращает минимальный размер лота из открытых позиций. Сторонние ресурсы (переменные и т.п.) не используются.
Код: выделить все
/*
   Описание : Возвращает минимальный размер лота из открытых позиций     
   Параметры:                                                             
   sy - наименование инструмента   (""   - любой символ,                 
                                   "0" - текущий символ)                 
   op - операция                   (-1   - любая позиция)                 
   mn - MagicNumber                (-1   - любой магик)                   
*/
double GetMinLotFromOpenPos(string sy, int op, int mn)
{
   double l = 0;
   int    i, k = OrdersTotal();
   if(sy == "0") sy = Symbol();
   for (i=0; i<k; i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == sy || sy == "")
         {
            if(OrderType() == OP_BUY || OrderType() == OP_SELL)
            {
               if(op < 0 || OrderType() == op)
               {
                  if(mn < 0 || OrderMagicNumber() == mn)
                  {
                     if(l == 0 || l > OrderLots()) l = OrderLots();
                  }
               }
            }
         }
      }
   }
return(l);
}
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.


Вернуться в Творческая мастерская

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 60

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения