Реализация нескольких независимых торговых методов в одном советнике

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Реализация нескольких независимых торговых методов в одном советнике

Сообщение Haos » 17 авг 2021, 14:01

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

Рассмотрим одну из самых простых реализаций на основе функций пользователя без классов и т.п. Т.е. разработчик исходит, по-прежнему, из подхода, чем быстрее написан код - тем он конкурентноспособнее. Т.е. по-прежнему, используются лишь разработанные ранее функции для других советников и рассмотренные, в основном, в данном разделе форума.

Пусть в процессе тестирования, скажем, торговой системы на основе пересечения двух скользящих средних, т.е. классической риверсивной торговой системы, где вход в рынок происходит по сигналу пересечения скользящих средних и больше не используется никаких дополнительных индикаторов, были найдены несколько прибыльных варинтов. В принципе, даже СЛ и ТП не используются, хотя могут быть введены при необходимости.

В процессе оптимизации советника для данной торговли, мы обнаружили, что не одна пара с некоторыми периодами скользящих средних является рабочей, т.е. прибыльной, а много таких пар. Мы на основе подхода для обеспечения максимального хеджирования рисков будущей торговли выбрали две или даже три таких пар. Теперь нам надо написать советник, где все эти пары (будем брать три пары для определенности) будут работать одновременно и независимо.

Прежде всего, в разделе советника для объявления глобальных переменных нам нужно организовать три независимых блока:
Код: выделить все
//*****************************************************************************************

input string   strBlock1 = "Настройка первой пары МАшек";
input double   dblQ1     = 0.01;                   // Размер торгового лота первой пары МАшек
input int      intMAFPe1 = 100;                    // Период быстрой МАшки
input int      intMASPe1 = 1000;                   // Период медленной МАшки

input string   strBlock2 = "Настройка второй пары МАшек";
input double   dblQ2     = 0.01;                   // Размер торгового лота второй пары МАшек
input int      intMAFPe2 = 330;                    // Период быстрой МАшки
input int      intMASPe2 = 990;                    // Период медленной МАшки

input string   strBlock3 = "Настройка третьей пары МАшек";
input double   dblQ3     = 0.01;                   // Размер торгового лота третьей пары МАшек
input int      intMAFPe3 = 200;                    // Период быстрой МАшки
input int      intMASPe3 = 600;                    // Период медленной МАшки

input int      intSI     = 10;                     // Проскальзывание цены (пнт.)
input ENUM_MA_METHOD     intMAMe = MODE_SMA;       // Метод усреднения МАшек
input ENUM_APPLIED_PRICE intMAAp = PRICE_MEDIAN;   // Тип цены быстрой МАшек


//*********************************************************************************************

Блок 1 - это настройка первой пары скользящих средних (МАшек), блок 2 - второй и т.д. Предполагается, что для каждой пары МАшек может быть свой размер торгового лота. Это реализовано через переменные: dblQ1, dblQ2, dblQ3.
Периоды МАшек зададим через переменные: intMAFPe1 ... intMAFPe3 и intMASPe1...intMASPe3. Пусть метод усреднения и тип цены, используемые в каждой паре МАшек будут одинаковые (если предполагается, что они будут разные, то придется ввести переменную для каждого блока отдельно).

Далее нам нужно ввести для каждой пары МАшек свой мэджик. Почему? Чтобы однозначно идентифицировать каждую пару МАшек. Т.е., грубо говоря, это три советника в одном с тремя независимыми мэджиками. Так мы ничего не напутаем в работе и методе анализа результатов торговли, т.к. будем четко управлять каждой позицией каждого блока.
Код: выделить все
//*********************************************************************************************

int      intLoDi;
int      intMagic1 = 202008081;
int      intMagic2 = 202008082;
int      intMagic3 = 202008083;

//***********************************************************************************************

А далее уже идет стандартный код, но несколько дополненный однотипными процедурами в функции OnTick().
Код: выделить все
void OnTick()
{
   // Наличие сигналов на вход в рынок:
   string strSyg1 = f_2MASyg(intMAFPe1, intMASPe1, intMAMe, intMAAp);
   string strSyg2 = f_2MASyg(intMAFPe2, intMASPe2, intMAMe, intMAAp);
   string strSyg3 = f_2MASyg(intMAFPe3, intMASPe3, intMAMe, intMAAp);

   //---------------------------------------------------------------------     
   if(strSyg1 == "UP" || strSyg1 == "DN")
   {   
      // если есть сигнал на пересечения МАшек на прошлом баре:
      // количество открытых покупок и продаж для 1-ой пары:
      int  intBuys1  = f_GetNumberOfPositions("0", OP_BUY,  intMagic1);
      int  intSels1  = f_GetNumberOfPositions("0", OP_SELL, intMagic1);
      f_Trade(strSyg1, intBuys1, intSels1, intMagic1, dblQ1, "1-я пара");   
   }
   //---------------------------------------------------------------------
   if(strSyg2 == "UP" || strSyg2 == "DN")
   {
      // количество открытых покупок и продаж для 2-ой пары:
      int  intBuys2  = f_GetNumberOfPositions("0", OP_BUY,  intMagic2);
      int  intSels2  = f_GetNumberOfPositions("0", OP_SELL, intMagic2);
      f_Trade(strSyg2, intBuys2, intSels2, intMagic2, dblQ2, "2-я пара");
   }
   //---------------------------------------------------------------------
   if(strSyg3 == "UP" || strSyg3 == "DN")
   {
      // количество открытых покупок и продаж для 3-ей пары:
      int  intBuys3  = f_GetNumberOfPositions("0", OP_BUY,  intMagic3);
      int  intSels3  = f_GetNumberOfPositions("0", OP_SELL, intMagic3);
      f_Trade(strSyg3, intBuys3, intSels3, intMagic3, dblQ3, "3-я пара");
   }
   //---------------------------------------------------------------------
}

Всё, что было для кода советника для одной пары МАшек, мы утраиваем. Т.е. я ввожу три переменных strSyg1...strSyg3 для получения сигнала о пересечении для каждой пары. Три раза на каждом тике будет вызываться соответствующая функция для поиска такого сигнала f_2MASyg.
Далее анализируется для каждого блока наличие сигнала, подсчитывается количество открытых позиций уже имеющихся и вызывается дополнительная функция для выполнения единого кода для каждого блока f_Trade. В этой функции происходит открытие или закрытие позиций.

Полный листинг кода см. ниже. Его составляющие разбирем позднее отдельно.
Код: выделить все
/*
Торговля (на М5) тремя наборами МАшек. Быстрая пересекает медленную
сигнал. Никаких СЛ и ТП. Реверс по обратному пересечению.
 */
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link      "https://investforum.ru/"
#property version   "2.00"
#property strict

//*****************************************************************************************

input string   strBlock1 = "Настройка первой пары МАшек";
input double   dblQ1     = 0.01;                   // Размер торгового лота первой пары МАшек
input int      intMAFPe1 = 100;                    // Период быстрой МАшки
input int      intMASPe1 = 1000;                   // Период медленной МАшки

input string   strBlock2 = "Настройка второй пары МАшек";
input double   dblQ2     = 0.01;                   // Размер торгового лота второй пары МАшек
input int      intMAFPe2 = 330;                    // Период быстрой МАшки
input int      intMASPe2 = 990;                    // Период медленной МАшки

input string   strBlock3 = "Настройка третьей пары МАшек";
input double   dblQ3     = 0.01;                   // Размер торгового лота третьей пары МАшек
input int      intMAFPe3 = 200;                    // Период быстрой МАшки
input int      intMASPe3 = 600;                    // Период медленной МАшки

input int      intSI     = 10;                     // Проскальзывание цены (пнт.)
input ENUM_MA_METHOD     intMAMe = MODE_SMA;       // Метод усреднения МАшек
input ENUM_APPLIED_PRICE intMAAp = PRICE_MEDIAN;   // Тип цены быстрой МАшек


//*********************************************************************************************

int      intLoDi;
int      intMagic1 = 202008081;
int      intMagic2 = 202008082;
int      intMagic3 = 202008083;

//***********************************************************************************************

int OnInit()
{
   f_Limitation();
   intLoDi = f_GetLotDigits("0");
     
return(INIT_SUCCEEDED);
}

//***********************************************************************************************

void OnDeinit(const int reason)
{
   f_DeleteComment();
}

//*********************************************************************************************

int f_Limitation()
{
   // проверка на наличие истории:
   if(Bars < intMASPe1)
   {
      Alert("Недостаточное кол-во баров на графике!");
      return(-1);
   }
   
return(1);
}

//*********************************************************************************************

void OnTick()
{
   // Наличие сигналов на вход в рынок:
   string strSyg1 = f_2MASyg(intMAFPe1, intMASPe1, intMAMe, intMAAp);
   string strSyg2 = f_2MASyg(intMAFPe2, intMASPe2, intMAMe, intMAAp);
   string strSyg3 = f_2MASyg(intMAFPe3, intMASPe3, intMAMe, intMAAp);

   //---------------------------------------------------------------------     
   if(strSyg1 == "UP" || strSyg1 == "DN")
   {   
      // если есть сигнал на пересечения МАшек на прошлом баре:
      // количество открытых покупок и продаж для 1-ой пары:
      int  intBuys1  = f_GetNumberOfPositions("0", OP_BUY,  intMagic1);
      int  intSels1  = f_GetNumberOfPositions("0", OP_SELL, intMagic1);
      f_Trade(strSyg1, intBuys1, intSels1, intMagic1, dblQ1, "1-я пара");   
   }
   //---------------------------------------------------------------------
   if(strSyg2 == "UP" || strSyg2 == "DN")
   {
      // количество открытых покупок и продаж для 2-ой пары:
      int  intBuys2  = f_GetNumberOfPositions("0", OP_BUY,  intMagic2);
      int  intSels2  = f_GetNumberOfPositions("0", OP_SELL, intMagic2);
      f_Trade(strSyg2, intBuys2, intSels2, intMagic2, dblQ2, "2-я пара");
   }
   //---------------------------------------------------------------------
   if(strSyg3 == "UP" || strSyg3 == "DN")
   {
      // количество открытых покупок и продаж для 3-ей пары:
      int  intBuys3  = f_GetNumberOfPositions("0", OP_BUY,  intMagic3);
      int  intSels3  = f_GetNumberOfPositions("0", OP_SELL, intMagic3);
      f_Trade(strSyg3, intBuys3, intSels3, intMagic3, dblQ3, "3-я пара");
   }
   //---------------------------------------------------------------------
}

//*********************************************************************************************

void f_Trade(string syg, int bu, int se, int mn, double q, string co)
{

   if(syg == "UP")
   {
      if(se > 0) { f__ClosePositions("0", OP_SELL, mn, intSI); }   
      if(bu == 0) { f_OpenPosition("0", OP_BUY, q, 0, 0, mn, intSI, co); }
   }
   
   else if(syg == "DN")
   {
      if(bu >  0){ f__ClosePositions("0", OP_BUY, mn, intSI); }
      if(se == 0){ f_OpenPosition("0", OP_SELL, q, 0, 0, mn, intSI, co);  }   
   }

}

//*********************************************************************************************

string f_2MASyg(int pe_F, int pe_S, int me, int ap)                 
/*
   08.08.2020 г.
   Ф-ия определяет сигнал по пересечению 2 МАшек (на последнем закрытом баре)
   возвращает "UP" если быстрая МА пересекла вверх медленную МА
   возвращает "DN" если быстрая МА пересекла вниз медленную МА
   возвращает "NO" если нет пересечения
   Параметры:
   pe_F  -  // период быстрой МАшки
   pe_S  -  // период медленной МАшки   
   me  -  // метод усреднения
   ap  -  // тип цены

*/
{
double   dblMAF_1,   // значение быстрой MA на предыдущем баре
         dblMAF_2,   // значение быстрой MA два бара назад
         dblMAS_1,   // значение медленной MA на предыдущем баре
         dblMAS_2;   // значение медленной MA два бара назад
 
   dblMAF_1 = iMA(NULL, 0, pe_F, 0, me, ap, 1);
   dblMAF_2 = iMA(NULL, 0, pe_F, 0, me, ap, 2);
   dblMAS_1 = iMA(NULL, 0, pe_S, 0, me, ap, 1);
   dblMAS_2 = iMA(NULL, 0, pe_S, 0, me, ap, 2);
   
   if(dblMAF_1 > dblMAS_1 && dblMAF_2 < dblMAS_2) return("UP");
   if(dblMAF_1 < dblMAS_1 && dblMAF_2 > dblMAS_2) return("DN");
   
return("NO");
}

//*********************************************************************************************

void f_OpenPosition(string sy, int op, double ll, double sl, double tp, int mn, int si, string co)
{
/*
   Версия   : 13.09.2015                                                     
   Описание : Открывает позицию по рыночной цене   
   Сторонних ресурсов не использует!!!                       
   Параметры:                                                               
   sy - наименование инструмента   ("0" - текущий символ)         
   op - операция {OP_BUY; OP_SELL}                                                           
   ll - лот                                                               
   sl - уровень стоп (0)                                                     
   tp - уровень тейк  (0)                                                   
   mn - MagicNumber
   si - проскальзывание (slippage) (пнт.)                                                       
   co - комментарий ("" - нет комментария)                                                       
*/
   double   pp;
   int      int_Tic     = 0;
   int      int_Try     = 5;              // Количество торговых попыток
   bool     bol_Sou     = true;           // Использовать звуковой сигнал
   string   str_Suc     = "ok.wav";       // Звук успеха
   string   str_Err     = "timeout.wav";  // Звук ошибки
   bool     bol_Sin     = true;           // Использовать значок открытия сделки?
   color    clOpen      = clrNONE,
            clOpenBuy   = LightBlue,      // Цвет значка открытия покупки
            clOpenSell  = LightCoral;     // Цвет значка открытия продажи
   double   dbl_Ask,
            dbl_Bid;
   
   if(sy == "0") sy = Symbol();   
   int int_Dig  = (int) MarketInfo(sy, MODE_DIGITS);
   
   for(int i = 1; i <= int_Try; i++)
   {
      if(!IsTesting() && (!IsExpertEnabled() || IsStopped()))
      {
         Print("OpenPosition(): Остановка работы функции");
         break;
      }
      while(!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      if(op == OP_BUY)
      {
         dbl_Ask  = MarketInfo(sy, MODE_ASK);
         pp = dbl_Ask;
         if(bol_Sin) clOpen = clOpenBuy;
      }
      else if(op == OP_SELL)
      {
         dbl_Bid  = MarketInfo(sy, MODE_BID);
         pp = dbl_Bid;
         if(bol_Sin) clOpen = clOpenSell;
      }
      pp = NormalizeDouble(pp, int_Dig);
      int_Tic = OrderSend(sy, op, ll, pp, si, sl, tp, co, mn, 0, clOpen);
      if(int_Tic > 0)
      {
         if(bol_Sou) PlaySound(str_Suc);
         Print("Функция OrderSend успешно выполнена");
         break;
      }
      else if(int_Tic < 0)
      {
         if(bol_Sou) PlaySound(str_Err);
         Print("OrderSend завершилась с ошибкой #", GetLastError());
      }
   }
}

//*********************************************************************************************

void f__ClosePositions(string sy, int op, int mn, int si)
{
/*
   Описание : Закрытие позиций по рыночной цене
   Используется функция: f__CloseOrder()   
   Параметры:                                                               
   sy - наименование инструмента   ("0" - текущий символ)                 
   op - операция                   (-1   - любая позиция)                 
   mn - MagicNumber                (-1   - любой магик)
   si - проскальзывание (slippage) (пнт.)               
*/
   if(sy == "0") sy = Symbol(); 
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break;
      if((OrderSymbol() == sy) && (op < 0 || OrderType() == op))
      {
         if(OrderType() == OP_BUY || OrderType() == OP_SELL)
         
            if(mn < 0 || OrderMagicNumber() == mn)   
            {
               RefreshRates();
               f__CloseOrder(sy, OrderTicket(), OrderLots(), si);
            }
         
      }
   }
}

//*********************************************************************************************

bool f__CloseOrder(string sy, int ti, double lo, int si)
{
/*
   Описание: 
   Используется функция: f__ProcessError()
   Параметры:                                                               
   sy - наименование инструмента ("0" - текущий символ)                 
   ti - OrderTicket()
   lo - OrderLots()
   si - проскальзывание (slippage) (пнт.)               
*/
   int int_Try = 5; // Количество торговых попыток

   if(lo < MarketInfo(sy, MODE_MINLOT)) return(false);
   if(OrderSelect(ti, SELECT_BY_TICKET) == true)
   {
      int i = 0;
      GetLastError();
      while(i < int_Try)
      {
         RefreshRates();
         double dbl_Pri = MarketInfo(sy, MODE_BID);
         if(OrderType() == OP_SELL) dbl_Pri = MarketInfo(sy, MODE_ASK);
         if(OrderClose(ti, lo, dbl_Pri, si))return(true);
         else
         {
            i++;
            if(!f__ProcessError(GetLastError())) return(false);
         }
      }
   }

return(false);
}

//*********************************************************************************************

bool f__ProcessError(int err)
{
/*
   Описание : Обработка ошибок
   Используется функция: f__PrintError()
   Параметры:                                                               
   err - номер ошибки           
*/
   int iteration;

   if(err > 1) f__PrintError(err);
   switch(err)
   {
   // Некритические ошибки
   case 0:     // ERR_NO_ERROR
   case 135:   // ERR_PRICE_CHANGED
   case 138:   // ERR_REQUOTE
      return(true);
   // Некритические ошибки, требующие таймаута
   case 4:     // ERR_SERVER_BUSY
   case 128:   // ERR_TRADE_TIMEOUT
      Sleep(1000 * 60);
      return(true);   
   case 129:   // ERR_INVALID_PRICE
   case 130:   // ERR_INVALID_STOPS
      //if (WorkMode==ModeManual && ShowConfirm) MessageBox("Неправильные стопы", VISITCARD, MB_OK);
      return(false);
   case 136:   // ERR_OFF_QUOTES
      Sleep(1000 * 5);
      return(true);   
   case 137:   // ERR_BROKER_BUSY
   case 145:   // ERR_TRADE_MODIFY_DENIED
      Sleep(1000 * 15);
      return(true);   
   // Нет связи с сервером. Пытаемся восстановить связь
   case 6:     // ERR_NO_CONNECTION
   {
      bool connect = false;
      iteration = 0;
      while((!connect) || (iteration < 60)) // в течение 5 минут пытаемся подконнектиться к серверу
      {
         Sleep(1000 * 5);
         connect = IsConnected();
         if(connect)
         {
            Print("Связь восстановлена");
            return(true);
         }
         iteration++;
         Print("Связь не восстановлена, прошло ", iteration * 5, " секунд.");
      }
      Print("Соединение в течение ", iteration * 5, " секунд восстановить не удалось.");
      return(false);
   }
   // Подсистема торговли занята. Ждем, пока освободится
   case 146:   // ERR_TRADE_CONTEXT_BUSY
   {
      bool tradecontextbusy = true;
      iteration = 0;
      while((tradecontextbusy) || (iteration < 60)) // в течение 5 минут ждем освобождения подсистемы торговли
      {
         Sleep(1000 * 5);
         tradecontextbusy = IsTradeContextBusy();
         if(!tradecontextbusy)
         {
            Print("Подсистема торговли освободилась.");
            return(true);
         }
         iteration++;
         Print("Подсистема торговли все еще занята, прошло ", iteration * 5, " секунд.");
      }
      Print("Подсистема торговли в течение ", iteration * 5, " секунд не освободилась.");
      return(false);
   }
   // Критические ошибки. Прекращаем попытки открытия ордера
   case 1:     // ERR_NO_RESULT
   case 2:     // ERR_COMMON_ERROR
   case 3:     // ERR_INVALID_TRADE_PARAMETERS
   case 5:     // ERR_OLD_VERSION
   case 7:     // ERR_NOT_ENOUGH_RIGHTS
   case 8:     // ERR_TOO_FREQUENT_REQUESTS
   case 9:     // ERR_MALFUNCTIONAL_TRADE
   case 64:    // ERR_ACCOUNT_DISABLED
   case 65:    // ERR_INVALID_ACCOUNT
   case 131:   // ERR_INVALID_TRADE_VOLUME
   case 132:   // ERR_MARKET_CLOSED
   case 133:   // ERR_TRADE_DISABLED
   case 134:   // ERR_NOT_ENOUGH_MONEY
   case 139:   // ERR_ORDER_LOCKED
   case 140:   // ERR_LONG_POSITIONS_ONLY_ALLOWED
   case 141:   // ERR_TOO_MANY_REQUESTS
   case 142:
   case 143:
   case 144:
   case 147:   // ERR_TRADE_EXPIRATION_DENIED
   case 148:   // ERR_TRADE_TOO_MANY_ORDERS
   case 4110:  // ERR_LONGS_NOT_ALLOWED
   case 4111:  // ERR_SHORTS_NOT_ALLOWED
      return(false);
   case 4109:  // ERR_TRADE_NOT_ALLOWED
      //MessageBox("Для совершения операций необходимо поставить галочку \"Разрешить советнику торговать\" в настройках терминала", VISITCARD, MB_OK);
      return(false);
   }
   return(false);
}

//*********************************************************************************************

int f__PrintError(int err)
{
   Print("ERROR ", err, ":  ", f__Err2str(err));
   return(0);
}

//*********************************************************************************************

//+------------------------------------------------------------------+
//| Получение описания ошибки по ее номеру                           |
//+------------------------------------------------------------------+
string f__Err2str(int err)
{
   switch(err)
   {
   case 0:
      return("Нет ошибки");
   case 1:
      return("Функция модификации ордера пытается изменить уже установленные значения такими же значениями");
   case 2:
      return("Общая ошибка");
   case 3:
      return("В торговую функцию переданы неправильные параметры");
   case 4:
      return("Торговый сервер занят");
   case 5:
      return("Старая версия клиентского терминала");
   case 6:
      return("Нет связи с торговым сервером");
   case 7:
      return("Недостаточно прав");
   case 8:
      return("Слишком частые запросы");
   case 9:
      return("Недопустимая операция нарушающая функционирование сервера");
   case 64:
      return("Счет заблокирован");
   case 65:
      return("Неправильный номер счета");
   case 128:
      return("Истек срок ожидания совершения сделки");
   case 129:
      return("Неправильная цена");
   case 130:
      return("Неправильные стопы");
   case 131:
      return("Неправильный объем сделки");
   case 132:
      return("Рынок закрыт");
   case 133:
      return("Торговля запрещена");
   case 134:
      return("Недостаточно денег для совершения операции");
   case 135:
      return("Цена изменилась");
   case 136:
      return("Нет цен");
   case 137:
      return("Брокер занят");
   case 138:
      return("Реквот! Новые цены");
   case 139:
      return("Ордер заблокирован и уже обрабатывается");
   case 140:
      return("Разрешена только покупка");
   case 141:
      return("Слишком много запросов");
   case 142:
      return("Ордер поставлен в очередь");
   case 143:
      return("Ордер принят дилером к исполнению");
   case 144:
      return("Ордер аннулирован самим клиентом при ручном подтверждении сделки");
   case 145:
      return("Модификация запрещена, так как ордер слишком близок к рынку");
   case 146:
      return("Подсистема торговли занята");
   case 147:
      return("Использование даты истечения ордера запрещено брокером");
   case 148:
      return("Количество открытых и отложенных ордеров достигло предела, установленного брокером");
   case 4109:
      return("Торговля не разрешена. Необходимо включить опцию \"Разрешить советнику торговать\" в свойствах эксперта");
   case 4110:
      return("Длинные позиции не разрешены");
   case 4111:
      return("Короткие позиции не разрешены");
   }
   return("Описание ошибки не известно");
}


//*********************************************************************************************

int f_GetNumberOfPositions(string sy = "", int op = -1, int mn = -1)
{
/*
   Версия   : 28.10.2015 г.                                                 
   Описание : Возвращает количество позиций (покупок или продаж или тех и других вместе)
   Сторонних ресурсов не использует           
   Параметры:                                                               
   sy - наименование инструмента   (""   - любой символ, "0"- текущий символ)             
   op - операция {-1 любая; OP_BUY; OP_SELL}
   mn - MagicNumber  (-1 - любой маджик)               
*/

  int i, k = OrdersTotal(), kp = 0;
  if(k == 0) return(0); // нет позиций вообще никаких
 
  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) kp++;
          }
        }
      }
    }
  }
return(kp);
}

//*********************************************************************************************

int f_GetLotDigits(string sy)
{
/*
   Описание : Количество цифр после запятой в величине лота
   Параметры:                                                               
   sy - наименование инструмента   ("0" - текущий символ) 
*/
   if(sy == "0") sy = _Symbol;

return((int)MathLog10(1 / MarketInfo(sy, MODE_LOTSTEP)));
}

//*********************************************************************************************

void f_DeleteComment()
{
   Comment("\n", "");
}

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

Вернуться в MQL – теория и практика

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

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

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

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

cron