Possible loss of data due to type conversion mql4 как исправить

Введение

При использовании новой версии компилятора языка MQL4 некоторые старые программы могут выдавать ошибки.

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

Новый компилятор позволяет обнаружить реальные или потенциальные источники ошибок и повысить качество кода.

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

  1. Ошибки компиляции
    • 1.1. Идентификатор совпадает с зарезервированным словом
    • 1.2. Специальные символы в наименованиях переменных и функций
    • 1.3. Ошибки использования оператора switch
    • 1.4. Возвращаемые значения у функций
    • 1.5. Массивы в аргументах функций
  2. Ошибки времени выполнения
    • 2.1. Выход за пределы массива (Array out of range)
    • 2.2. Деление на ноль (Zero divide)
    • 2.3. Использование 0 вместо NULL для текущего символа
    • 2.4. Строки в формате Unicodе и их использование в DLL
    • 2.5. Совместное использование файлов
    • 2.6. Особенность преобразования datetime
  3. Предупреждения компилятора
    • 3.1. Пересечения имен глобальных и локальных переменных
    • 3.2. Несоответствие типов
    • 3.3. Неиспользуемые переменные

1. Ошибки компиляции

При наличии ошибок в коде программа не может быть скомпилирована.

Для полного контроля всех ошибок рекомендуется использовать строгий режим компиляции, который устанавливается директивой:

#property strict

Этот режим значительно упрощает поиск ошибок.

1.1. Идентификатор совпадает с зарезервированным словом

Если наименование переменной или функции совпадает с одним из зарезервированных слов:

int char[];  
int char1[]; 
int char()   
{
 return(0);
}

то компилятор выводит сообщения об ошибках:

Рис.1. Ошибки "unexpected token" и "name expected"

Рис.1. Ошибки «unexpected token» и «name expected»

Для исправления данной ошибки нужно исправить имя переменной или функции.

1.2. Специальные символы в наименованиях переменных и функций

Если наименования переменных или функций содержат специальные символы ($, @, точка):

int $var1; 
int @var2; 
int var.3; 
void f@()  
{
 return;
}

то компилятор выводит сообщения об ошибках:

Рис.2. Ошибки "unknown symbol" и "semicolon expected"

Рис.2. Ошибки «unknown symbol» и «semicolon expected»

Для исправления данной ошибки нужно скорректировать имена переменных или функций.

1.3. Ошибки использования оператора switch

Старая версия компилятора позволяла использовать любые значения в выражениях и константах оператора switch:

void start()
  {
   double n=3.14;
   switch(n)
     {
      case 3.14: Print("Pi");break;
      case 2.7: Print("E");break;
     }
  }

В новом компиляторе выражения и константы оператора switch должны быть целыми числами, поэтому при использовании подобных конструкций возникают ошибки:

Рис.3. Ошибки "illegal switch expression type" и "constant expression is not integral"

Рис.3. Ошибки «illegal switch expression type» и «constant expression is not integral»

В таких случаях можно использовать явные сравнения численных значений, например:

void start()
  {
   double n=3.14;
   if(n==3.14) Print("Pi");
   else
      if(n==2.7) Print("E");
  }

1.4. Возвращаемые значений функций

Все функции, кроме void, должны возвращать значение объявленного типа. Например:

int function()
{
}

При строгом режиме компиляции (strict) возникает ошибка:

Рис.4. Ошибка "not all control paths return a value"

Рис.4. Ошибка «not all control paths return a value»

В режиме компиляции по умолчанию компилятор выводит предупреждение:

Рис.5. Предупреждение "not all control paths return a value"

Рис.5. Предупреждение «not all control paths return a value»

Если возвращаемое значение функции не соответствует объявлению:

int init()                         
  {
   return;                          
  }

то при строгом режиме компиляции возникает ошибка:

Рис.6. Ошибка "function must return a value"

Рис.6. Ошибка «function must return a value»

В режиме компиляции по умолчанию компилятор выводит предупреждение:

Рис.7. Предупреждение 'return - function must return a value"

Рис.7. Предупреждение ‘return — function must return a value»

Для исправления таких ошибок в код функции нужно добавить оператор возврата return c возвращаемым значением соответствующего типа.

1.5. Массивы в аргументах функций

Массивы в аргументах функций теперь передаются только по ссылке.

double ArrayAverage(double a[])
{
 return(0);
}

Данный код при строгом режиме компиляции (strict) приведет к ошибке:

Рис.8. Ошибка компилятора "arrays passed by reference only"

Рис.8. Ошибка компилятора «arrays passed by reference only»

В режиме компиляции по умолчанию компилятор выводит предупреждение:

Рис.9. Предупреждение компилятора "arrays passed by reference only"

Рис.9. Предупреждение компилятора «arrays passed by reference only»

Для исправления таких ошибок нужно явно указать передачу массива по ссылке, добавив префикс & перед именем массива:

double ArrayAverage(double &a[])
{
 return(0);
}

Следует отметить, что теперь константные массивы (Time[], Open[], High[], Low[], Close[], Volume[]) не могут быть переданы по ссылке. Например, вызов:

ArrayAverage(Open);

вне зависимости от режима компиляции приводит к ошибке:

Рис.10. Ошибка 'Open' - constant variable cannot be passed as reference

Рис.10. Ошибка ‘Open’ — constant variable cannot be passed as reference

Для устранения подобных ошибок нужно скопировать необходимые данные из константного массива:

   
   double OpenPrices[];
   
   ArrayCopy(OpenPrices,Open,0,0,WHOLE_ARRAY);
   
   ArrayAverage(OpenPrices);

2. Ошибки времени выполнения

Ошибки, возникающие в процессе исполнения кода программы принято называть ошибками времени выполнения (runtime errors). Такие ошибки обычно зависят от состояния программы и связаны с некорректными значениями переменных.

Например, если переменная используется в качестве индекса элементов массива, то ее отрицательные значения неизбежно приведут к выходу за пределы массива.

2.1. Выход за пределы массива (Array out of range)

Эта ошибка часто возникает в индикаторах при обращении к индикаторным буферам. Функция IndicatorCounted() возвращает количество баров, неизменившихся после последнего вызова индикатора. Значения индикаторов на уже рассчитанных ранее
барах не нуждаются в пересчете, поэтому для ускорения расчетов
достаточно обрабатывать только несколько последних баров.

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



int start()
  {
   
   if (Bars<100) 
     return(-1); 

   
   int counted_bars=IndicatorCounted();
   
   if(counted_bars<0) return(-1);
      
   
   int limit=Bars-counted_bars;

   
   if(counted_bars==0) 
     {
      limit--;  
      
      limit-=10;
     }
   else 
     {     
      
      limit++;
     } 
   
   for (int i=limit; i>0; i--)
   {
     Buff1[i]=0.5*(Open[i+5]+Close[i+10]) 
   }
}

Часто встречается некорректная обработка случая counted_bars==0 (начальную позицию limit нужно уменьшить на значение, равное 1 + максимальный индекс относительно переменной цикла).

Также следует помнить о том, что в момент исполнения функции start() мы можем обращаться к элементам массивов индикаторных буферов от 0 до Bars()-1. Если есть необходимость работы с массивами, которые не являются индикаторными буферами, то их размер следует увеличить при помощи функции ArrayResize() в соответствии с текущим размером индикаторных буферов. Максимальный индекс элемента для адресации также можно получить вызовом ArraySize() с одним из индикаторных буферов в качестве аргумента.

2.2. Деление на ноль (Zero divide)

Ошибка «Zero divide» возникает в случае, если при выполнении операции деления делитель оказывается равен нулю:

void OnStart()
  {

   int a=0, b=0,c;
   c=a/b;
   Print("c=",c);
  }

При выполнении данного скрипта во вкладке «Эксперты» возникает сообщение об ошибке и завершении работы программы:

Рис.11. Сообщение об ошибке "zero divide"

Рис.11. Сообщение об ошибке «zero divide»

Обычно такая ошибка возникает в случаях, когда значение делителя определяется значениями каких-либо внешних данных. Например, если анализируются параметры торговли, то величина задействованной маржи оказывается равна 0 если нет открытых ордеров. Другой пример: если анализируемые данные считываются из файла, то в случае его отсутствия нельзя гарантировать корректную работу. По этой причине желательно стараться учитывать подобные случаи и корректно их обрабатывать.

Самый простой способ — проверять делитель перед операцией деления и выводить сообщение об некорректном значении параметра:

void OnStart()
  {

   int a=0, b=0,c;
   if(b!=0) {c=a/b; Print(c);}
   else {Print("Error: b=0"); return; };
  }

В результате критической ошибки не возникает, но выводится сообщение о некорректном значении параметра и работа завершается:

Рис. 12. Сообщение о некорректном значении делителя

Рис. 12. Сообщение о некорректном значении делителя

2.3. Использование 0 вместо NULL для текущего символа

В старой версии компилятора допускалось использование 0 (нуля) в качестве аргумента в функциях, требующих указания финансового инструмента.

Например, значение технического индикатора Moving Average для текущего символа можно было запрашивать следующим образом:

AlligatorJawsBuffer[i]=iMA(0,0,13,8,MODE_SMMA,PRICE_MEDIAN,i); 

В новом компиляторе для указания текущего символа нужно явно указывать NULL:

AlligatorJawsBuffer[i]=iMA(NULL,0,13,8,MODE_SMMA,PRICE_MEDIAN,i); 

Кроме того, текущий символ и период графика можно указать при помощи функций Symbol() и Period().

AlligatorJawsBuffer[i]=iMA(Symbol(),Period(),13,8,MODE_SMMA,PRICE_MEDIAN,i); 

2.4. Строки в формате Unicodе и их использование в DLL

Строки теперь представляют собой последовательность символов Unicode.

Следует учитывать этот факт и использовать соответствующие функции Windows. Например, при использовании функций библиотеки wininet.dll вместо InternetOpenA() и InternetOpenUrlA() следует вызывать InternetOpenW() и InternetOpenUrlW().

В MQL4 изменилась внутренняя структура строк (теперь она занимает 12 байт), поэтому при передаче строк в DLL следует использовать структуру MqlString:

#pragma pack(push,1)
struct MqlString
  {
   int      size;       
   LPWSTR   buffer;     
   int      reserved;   
  };
#pragma pack(pop,1)

2.5. Совместное использование файлов

В новом MQL4 при открытии файлов необходимо явно указывать флаги FILE_SHARE_WRITE и FILE_SHARE_READ для совместного использования.

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

Например, при работе с оффлайновыми графиками требуется явно указывать флаги совместного доступа:

   
   ExtHandle=FileOpenHistory(c_symbol+i_period+".hst",FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ);

Подробности можно найти в статье в статье «Оффлайновые графики и новый MQL4«.

2.6. Особенность преобразования datetime

Следует иметь ввиду, что преобразование типа datetime в строку теперь зависит от режима компиляции:

  datetime date=D'2014.03.05 15:46:58';
  string str="mydate="+date;

Например, попытка работы с файлами, имя которых содержит двоеточие, приведет к ошибке.

3. Предупреждения компилятора

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

Чистый код не должен содержать предупреждений.

3.1. Пересечения имен глобальных и локальных переменных

Если на глобальном и локальном уровнях присутствуют переменные с одинаковыми именами:

int i; 
void OnStart()
  {

   int i=0,j=0; 
   for (i=0; i<5; i++) {j+=i;}
   PrintFormat("i=%d, j=%d",i,j);
  }

то компилятор выводит предупреждение и укажет номер строки, на которой объявлена глобальная переменная:

Рис.13. Предупреждение "declaration of '%' hides global declaration at line %"

Рис.13. Предупреждение «declaration of ‘%’ hides global declaration at line %»

Для исправления таких предупреждений нужно скорректировать имена глобальных переменных.

3.2. Несоответствие типов

В новой версии компилятора введена операция приведения типов.

#property strict
void OnStart()
  {
   double a=7;
   float b=a;
   int c=b;
   string str=c;
   Print(c);
  }

В строгом режиме компиляции при несоответствии типов компилятор выводит предупреждения:

Рис.14. Предупреждения "possible loss of data due to type conversion" и "implicit conversion from 'number' to 'string'

Рис.14. Предупреждения «possible loss of data due to type conversion» и «implicit conversion from ‘number’ to ‘string’

В данном примере компилятор предупреждает о возможной потере точности при присвоении различных типов данных и неявном преобразовании типа int в string.

Для исправления нужно использовать явное приведение типов:

#property strict
void OnStart()
  {
   double a=7;
   float b=(float)a;
   int c=(int)b;
   string str=(string)c;
   Print(c);
  }

3.3. Неиспользуемые переменные

Наличие переменных, которые не используются в коде программы (лишние сущности) не является хорошим тоном.

void OnStart()
  {
   int i,j=10,k,l,m,n2=1;
   for(i=0; i<5; i++) {j+=i;}
  }

Сообщения о таких переменных выводятся вне зависимости от режима компиляции:

Рис.15. Предупреждения "variable '%' not used'

Рис.15. Предупреждения «variable ‘%’ not used’

Для исправления нужно убрать неиспользуемые переменные из кода программы.

Выводы

В статье рассмотрены типичные проблемы, с которыми могут столкнуться программисты при компиляции старых программ, содержащих ошибки.

Во всех случаях при отладке программ рекомендуется использовать строгий режим компиляции.

Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.

  • #1

Здравствуйте
При компиляции появляется ошибка
possible loss of data due to type conversion
указывающая на то что в этой строке возможна потеря данных при конвертации

NormalizeDouble(Price_Cls, MarketInfo(OrderSymbol(), MODE_DIGITS));

по причине MarketInfo(OrderSymbol(), MODE_DIGITS)
Явное приведение данных не привело к результату
Замена на Digits помогает, но по регламенту исполняемой задачи не подходит.
Буду рад помощи.
Благодарен.

  • #2

Здравствуйте
При компиляции появляется ошибка
possible loss of data due to type conversion
указывающая на то что в этой строке возможна потеря данных при конвертации

NormalizeDouble(Price_Cls, MarketInfo(OrderSymbol(), MODE_DIGITS));

по причине MarketInfo(OrderSymbol(), MODE_DIGITS)
Явное приведение данных не привело к результату
Замена на Digits помогает, но по регламенту исполняемой задачи не подходит.
Буду рад помощи.
Благодарен.

Маркетинфо функция дробная. А там надо целочисленные данные. По мнению компилятора дробные данные будут потеряны.
NormalizeDouble(Price_Cls, (int)MarketInfo(OrderSymbol(), MODE_DIGITS));

  • #3

Доброго времени суток!
Прошу помочь в исправлении предупреждения.
Есть код:

datetime double_in_datatime(double _Use_Time)
   {
   datetime _Currently = iTime(NULL,1440,0);
   double _Hour = MathFloor(_Use_Time);
   double _Min = (_Use_Time - MathFloor(_Use_Time))*100;
   [U]datetime _Sec_in_Hour = _Hour*3600;[/U]
   [U]datetime _Sec_in_Min  = _Min*60;[/U]
   datetime _Ret = _Currently + _Sec_in_Hour + _Sec_in_Min;
   return(_Ret);
   }

В подчеркнутых строках выдает предупреждение: «возможна потеря данных из-за преобразования типов»

  • #4

Доброго времени суток!
Прошу помочь в исправлении предупреждения.
Есть код:

datetime double_in_datatime(double _Use_Time)
   {
   datetime _Currently = iTime(NULL,1440,0);
   double _Hour = MathFloor(_Use_Time);
   double _Min = (_Use_Time - MathFloor(_Use_Time))*100;
   [U]datetime _Sec_in_Hour = _Hour*3600;[/U]
   [U]datetime _Sec_in_Min  = _Min*60;[/U]
   datetime _Ret = _Currently + _Sec_in_Hour + _Sec_in_Min;
   return(_Ret);
   }

В подчеркнутых строках выдает предупреждение: «возможна потеря данных из-за преобразования типов»

Ну а зачем-же ты входящей переменной присваиваешь тип datetime?
Если уж это так необходимо, то тогда пиши
datetime Sec_in_Hour = (datetime) _Houe*3600;
или
datetime Sec_in_Hour = datetime (_Houe*3600);

  • #5

Ну а зачем-же ты входящей переменной присваиваешь тип datetime?
Если уж это так необходимо, то тогда пиши
datetime Sec_in_Hour = (datetime) _Houe*3600;
или
datetime Sec_in_Hour = datetime (_Houe*3600);

Если честно, то я этот код «слизал» на другом сайте. И как на счет присвоенного типа double в верхних строчках?

Здравствуйте.
При компиляции индикатора, возникла такая ошибка:
possible loss of data due to type conversion Portfolio_v5.mq4 117 7
Ругается на эту строчку:

basket=FileReadArray(pairs,Pairs,0,ArraySize(Pairs));

{
basket=FileReadArray(pairs,Pairs,0,ArraySize(Pairs));
FileClose(pairs);
}

Администратор запретил публиковать записи гостям.

Vlad023 пишет:

Здравствуйте.
При компиляции индикатора, возникла такая ошибка:
possible loss of data due to type conversion Portfolio_v5.mq4 117 7
Ругается на эту строчку:

basket=FileReadArray(pairs,Pairs,0,ArraySize(Pairs));

{
basket=FileReadArray(pairs,Pairs,0,ArraySize(Pairs));
FileClose(pairs);
}

Это не ошибка (error), а предупреждение (warning).
Сообщение означает дословно: «возможны потери данных из-за преобразования типов».

Поправьте эту строчку так:

basket=(int)FileReadArray(pairs,Pairs,0,ArraySize(Pairs));

а в общем ничего страшного не произойдет и без редактирования — просто исчезнет предупреждение.

Администратор запретил публиковать записи гостям.

I wrote this sample code for learning purposes but I can’t seem to solve the warning message of «possible loss of data due to type conversion«.

I have tried to search online but I can’t seem to find a solution on how to pass the value of the MQL5 built-in functions without getting this warning.

The iAMA built-in function of MQL5 returns an integer and this integer is getting assigned to a variable of type integer (as shown in the sample code below). I am not sure why there is a data loss warning if both of them are integers.

Note: The code is compiling and running well but for educational purposes, I would like to understand how to solve this warning message.

Your help will be much appreciated!

Here is the code:

// --- Information Properties
#property description "Adaptive Moving Average Function Test"

//--- Core Properties
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

// --- Styling & Labels Properties
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlack
#property indicator_width1  2
#property indicator_label1  "Adaptive Moving Average"

//--- Constant Variables
const int ama_period  = 34;
const int ama_fast_ma = 2;
const int ama_slow_ma = 34;

//--- Global Variables
double ama_src = PRICE_MEDIAN;

//--- Buffers
double ama_buffer[];

//--- Handles
int ama_buffer_handle;

//+------------------------------------------------------------------+
//| Indicator Initialization                                         |
//+------------------------------------------------------------------+

int OnInit()
{
//--- Buffers Assignment
    SetIndexBuffer(0, ama_buffer, INDICATOR_DATA);

//--- Accuracy Setting
    IndicatorSetInteger(INDICATOR_DIGITS, _Digits);

//--- First Bar Setting
    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, ama_period - 1);

//--- Line Shifts Calculations
    PlotIndexSetInteger(0, PLOT_SHIFT, 0);

//--- Labels Calculations
    PlotIndexSetString(0, PLOT_LABEL, "AMA");

//--- Handles Calculations
    ama_buffer_handle = iAMA(NULL, 0, ama_period, ama_fast_ma, ama_slow_ma, 0, ama_src);

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//|  OnCalculate function                                            |
//+------------------------------------------------------------------+

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    if(rates_total < ama_period)
    {
        return(0);
    }

//--- Troubleshooting: Data Calculation
    int calculated = BarsCalculated(ama_buffer_handle);
    if(calculated < rates_total)
    {
        Print("Not all data of ama_buffer_handle is calculated (", calculated, " bars). Error ", GetLastError());
        return(0);
    }

//--- Troubleshooting: Data Copying
    int to_copy;
    if(prev_calculated > rates_total || prev_calculated < 0)
    {
        to_copy = rates_total;
    }
    else
    {
        to_copy = rates_total - prev_calculated;
        if(prev_calculated > 0)
        {
            to_copy++;
        }
    }

//--- Copy & Validate Buffers
    if(CopyBuffer(ama_buffer_handle, 0, 0, to_copy, ama_buffer) <= 0)
    {
        Print("getting ama_buffer_handle is failed! Error ", GetLastError());
        return(0);
    }
  
    if(IsStopped())
    {
        return(0);
    }

    return(rates_total);
}

//+——————————————————————+
//|                                                        Test4.mq4 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+——————————————————————+
#property copyright «Copyright 2018, MetaQuotes Software Corp.»
#property link      «https://www.mql5.com»
#property version   «1.00»
#property strict

//——————————————————————
extern double Lots                            = 0.1;
extern int    TakeProfit                      = 300;
extern int    StopLoss                        = 50;
extern int    TakeProfitStop                  = 5;
extern int    StopLossStop                    = 20;
extern int    Magic                           = 111;
extern int    MagicStop                       = 112;
extern int    Slippage                        = 3;
extern bool   BorderCloseTrueMediomCloseFalse = True;
extern bool   AddStopOrdersFalse              = True;
extern int    StopOrdersShift                 = 20;
//——————————————————————
extern string TMA             = «Параметры индикатора TMA»;
extern string TimeFrame       = «current time frame»;
extern int    HalfLength      = 56;
extern int    Price           = PRICE_CLOSE;
extern double ATRMultiplier   = 2.0;
extern int    ATRPeriod       = 100;
extern bool   Interpolate     = true;
//——————————————————————
double PriceHigh, PriceLow, PriceMedium, SL, TP, BuyStopPrice, SellStopPrice;
int Ticket, Ticket2, Ticket3;

int OnInit()
{
   if (Digits == 3 || Digits == 5)
   {
      TakeProfit     *= 10;
      StopLoss       *= 10;
      Slippage       *= 10;
      TakeProfitStop *= 10;
      StopLossStop   *= 10;
   } 
   return(INIT_SUCCEEDED);
}
//+——————————————————————+
//| Expert deinitialization function                                 |
//+——————————————————————+
void OnDeinit(const int reason)
{

   

}
//+——————————————————————+
//| Expert tick function                                             |
//+——————————————————————+
void OnTick()
{
   PriceHigh   = iCustom(NULL, 0, «TMA_Fair», TimeFrame, HalfLength, Price, ATRMultiplier, ATRPeriod, Interpolate, 1, 0);
   PriceLow    = iCustom(NULL, 0, «TMA_Fair», TimeFrame, HalfLength, Price, ATRMultiplier, ATRPeriod, Interpolate, 2, 0);
   PriceMedium = iCustom(NULL, 0, «TMA_Fair», TimeFrame, HalfLength, Price, ATRMultiplier, ATRPeriod, Interpolate, 0, 0);

   
   Comment(«PriceMedium: » + DoubleToStr(PriceMedium, 5));

   
   if(CountSell() == 0 && Bid >= PriceHigh)
   {
      Ticket = OrderSend(OrderSymbol(), OP_SELL, Lots, Bid, Slippage, 0, 0, «TMA robot», Magic, 0, Red);
      if (Ticket > 0)
      {
         SL = NormalizeDouble(Bid + StopLoss*Point, Digits);
         TP = NormalizeDouble(Bid — TakeProfit*Point, Digits);

         
         if (OrderSelect(Ticket, SELECT_BY_TICKET))
             if(!OrderModify(Ticket, OrderOpenPrice(), SL, TP, 0))
                Print(«Ошибка модификации ордера на продажу»);

               
      } else Print(«Ошибка открытия ордера на продажу»);
   }

    
    if(CountBuy() == 0 && Ask <= PriceLow)
    {
      Ticket = OrderSend(OrderSymbol(), OP_BUY, Lots, Ask, Slippage, 0, 0, «TMA robot», Magic, 0, Blue);
      if (Ticket > 0)
      {
         TP = NormalizeDouble(Ask + TakeProfit*Point, Digits);
         SL = NormalizeDouble(Ask — StopLoss*Point, Digits);

         
         if (OrderSelect(Ticket, SELECT_BY_TICKET))
             if(!OrderModify(Ticket, OrderOpenPrice(), SL, TP, 0))
                Print(«Ошибка модификации ордера на покупку»);  
      } else Print(«Ошибка открытия ордера на покупку»);
     } 
      if (Ask <= PriceLow && CountSell() > 0 && BorderCloseTrueMediomCloseFalse == True)
      {
         for (int i = OrdersTotal() — 1; i>=0; i—)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderMagicNumber() == Magic && OrderType() == OP_SELL)
                  if(!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Black))
                     Print(«Ошибка закрытия ордера»);
            }
         }
      }

      
      if (Ask <= PriceMedium && CountSell() > 0 && BorderCloseTrueMediomCloseFalse == False)
      {
         for (int i = OrdersTotal() — 1; i>=0; i—)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderMagicNumber() == Magic && OrderType() == OP_SELL)
                  if(!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Black))
                     Print(«Ошибка закрытия ордера»);
            }
         }
      }

      
      if (Bid >= PriceHigh && CountBuy() > 0 && BorderCloseTrueMediomCloseFalse == True)
      {
         for (int i = OrdersTotal() — 1; i>=0; i—)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderMagicNumber() == Magic && OrderType() == OP_BUY)
                  if(!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Black))
                     Print(«Ошибка закрытия ордера на покупку»);
            }
         }
      }

      
      if (Bid >= PriceMedium && CountBuy() > 0 && BorderCloseTrueMediomCloseFalse == False)
      {
         for (int i = OrdersTotal() — 1; i>=0; i—)
         {
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderMagicNumber() == Magic && OrderType() == OP_BUY)
                  if(!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Black))
                     Print(«Ошибка закрытия ордера на покупку»);
            }
         }
      }

      
      if(CountSell() > 0 && BuyStopCount() == 0 && exBuyStopCount() == 0 && AddStopOrdersFalse == False && OrderSelect(Ticket, SELECT_BY_TICKET) == true)
      {
         BuyStopPrice = NormalizeDouble(OrderOpenPrice() + StopOrdersShift*Point, Digits);
         SL           = NormalizeDouble(BuyStopPrice — StopLossStop*Point, Digits);
         TP           = NormalizeDouble(BuyStopPrice + TakeProfitStop*Point, Digits);

         
         Ticket2 = OrderSend(OrderSymbol(), OP_BUYSTOP, Lots, BuyStopPrice, Slippage, SL, TP, «TMA robot stoporder», MagicStop, 0, Blue);

         
         //if(Ticket2 > 0)
         //{
           // if (OrderSelect(Ticket2, SELECT_BY_TICKET))
             //if(!OrderModify(Ticket2, OrderOpenPrice(), SL, TP, 0))
               // Print(«Ошибка модификации стопордера на продажу»);
         //}else Print(«Ошибка открытия стопордера на продажу»);
      }
       if(CountBuy() > 0 && SellStopCount() == 0 && exSellStopCount() ==0 && AddStopOrdersFalse == False && OrderSelect(Ticket, SELECT_BY_TICKET) == true)
      {
         SellStopPrice = NormalizeDouble(OrderOpenPrice() — StopOrdersShift*Point, Digits);
         SL            = NormalizeDouble(SellStopPrice + StopLossStop*Point, Digits);
         TP            = NormalizeDouble(SellStopPrice — TakeProfitStop*Point, Digits);

         
         Ticket3 = OrderSend(OrderSymbol(), OP_SELLSTOP, Lots, SellStopPrice, Slippage, SL, TP, «TMA robot stoporder», MagicStop, 0, Red);

         
         //if(Ticket3 > 0)
         //{
           // if (OrderSelect(Ticket3, SELECT_BY_TICKET))
             //if(!OrderModify(Ticket3, OrderOpenPrice(), SL, TP, 0))
               // Print(«Ошибка модификации стопордера на продажу»);
         //}else Print(«Ошибка открытия стопордера на продажу»);
      }           
}
//+——————————————————————+
int CountSell()
{
   int count = 0;

   
   for (int trade = OrdersTotal()-1; trade>=0; trade—)
   {
      if(OrderSelect(trade, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == OP_SELL)
            count++;
      }   
   }
   return(count); 
}
//+——————————————————————+
int CountBuy()
{
   int count = 0;

   
   for (int trade = OrdersTotal()-1; trade >= 0; trade—)
   {
      if(OrderSelect(trade, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == OP_BUY)
            count++;
      }   
   }
   return(count); 
}  
//+——————————————————————+
int BuyStopCount()
{
   int scount = 0;

   
   for(int i=OrdersTotal()-1; i>=0; i—)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && 
          OrderMagicNumber() == MagicStop && 
          OrderType() == OP_BUYSTOP)
         {
            scount++;
         }
   }

   
   return(scount);
}
//+——————————————————————+
int SellStopCount()
{
   int scount = 0;

   
   for(int i=OrdersTotal()-1; i>=0; i—)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && 
          OrderMagicNumber() == MagicStop && 
          OrderType() == OP_SELLSTOP)
         {
            scount++;
         }
   }

   
   return(scount);
}
//+——————————————————————+
int exSellStopCount()
{
   int exscount = 0;

   
   for (int trade = OrdersTotal()-1; trade>=0; trade—)
   {
      if(OrderSelect(trade, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicStop && OrderType() == OP_SELL)
            exscount++;
      }   
   }
   return(exscount);
}
//+——————————————————————+
int exBuyStopCount()
{
   int exscount = 0;

   
   for (int trade = OrdersTotal()-1; trade >= 0; trade—)
   {
      if(OrderSelect(trade, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicStop && OrderType() == OP_BUY)
            exscount++;
      }   
   }
   return(exscount);
}   

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как чтобы не нашли украденные смартфоны
  • Как исправить игру чтобы она не выбивала
  • Как найти давление газа в адиабатном процессе
  • Как найти пати для фейсита
  • Как составить интерьер комнаты самостоятельно

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии