Ваши вопросы по языку MQL4

ИванМН

Местный знаток
Дорогие спецы! Имеем код:

int Handle = FileOpen("2022.02.01 12-00",FILE_ANSI|FILE_WRITE|FILE_COMMON,'-'); //открыли для записи
FileWrite(Handle,"1","643","USDCAD","[11-1.30-0.70]");//записали набор данных
FileSeek(Handle,0,SEEK_SET);//переставили указатель в начало файла (это, думаю, излишне, но всё же)
FileClose(Handle);//закрыли файл
Handle = FileOpen("2022.02.01 12-00",FILE_ANSI|FILE_SHARE_READ|FILE_COMMON,'-');//открыли для чтения
Print(FileTell(Handle)," ",FileReadNumber(Handle)," ",FileReadNumber(Handle));
FileClose(Handle);//закрыли файл

Запись в журнале должна содержать в себе текущую позицию указателя, пробел, первое считанное значение из файла (1), пробел, второе считанное значение из файла (643). Вместо этого в журнал выдаётся следующее:

6 643.0 1.0

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

mobidik

-----
То есть файловый указатель по непостижимой мною причине стоит не на начале файла, а в шести байтах от него, на втором разделителе ("-"), а последующее чтение происходит справа налево. Попытки переставить указатель в начало файла при помощи функции FileSeek успеха не принесли.
Моего интеллекта для осознания причины происходящего недостаточно. Прошу пояснить, что это за дичь.
А вы принты пропишите так:
Print(FileTell(Handle));
Print(FileReadString(Handle));
Print(FileReadString(Handle));
Print(FileReadString(Handle));
Print(FileReadString(Handle));
 

ИванМН

Местный знаток
А вы принты пропишите так:
Print(FileTell(Handle));
Print(FileReadString(Handle));
Print(FileReadString(Handle));
Print(FileReadString(Handle));
Print(FileReadString(Handle));
Я бы хотел понять причину именно в моём коде, а не искать обход. Обход (костыль) я уже сам нашёл и применил, он работает. Но почему некорректно работает мой вариант?
 

mobidik

-----
Я бы хотел понять причину именно в моём коде, а не искать обход. Обход (костыль) я уже сам нашёл и применил, он работает. Но почему некорректно работает мой вариант?
Так нет тут костыля :)
не верный вывод информации.
Если хочется увидеть все в одном принте, тогда так:
C-подобный:
int t = FileTell(Handle);
string a = FileReadString(Handle);
string b = FileReadString(Handle);

Print(/*FileTell(Handle)*/ t," ",/*FileReadNumber(Handle)*/ a," ",/*FileReadNumber(Handle)*/ b);

Сравните результат...
 

ИванМН

Местный знаток
МобиДик, я был не совсем точен, виноват. Для простоты в вопросе я привёл строку записи данных в виде:

FileWrite(Handle,"1","643","USDCAD","[11-1.30-0.70]");

но на самом деле в советнике первые два значения (с которыми я и имею проблему) записываются не строковыми константами, а числами: типа uchar для записи единицы и типа ushort для числа 643:

FileWrite(Handle,uchar(Sets[a].Dir),Sets[a].SL,......);

Стало быть, и считываться они должны функцией FileReadNumber, а не FileReadString, с приведением из double к соответствующему исходному типу. Так почему же указатель стоит не на начале файла, и чтение идёт задом наперёд?
 

mobidik

-----
записываются не строковыми константами, а числами: типа uchar для записи единицы и типа ushort для числа 643:

FileWrite(Handle,uchar(Sets[a].Dir),Sets[a].SL,......);
Да какая разница, справка гласит: "При выводе числовые данные преобразуются в текстовый формат...".
Стало быть, и считываться они должны функцией FileReadNumber, а не FileReadString
FileReadNumber() <=> StrToDouble(FileReadString())
с приведением из double к соответствующему исходному типу
А это уже Ваша задача...
Так почему же указатель стоит не на начале файла, и чтение идёт задом наперёд?
Каким именно образом и направлением идет наполнение ф-ции Print() - мне не известно, но её вывод произойдет только после того, как все необходимые данные будут получены. Из этого можно сделать вывод, что значение указателя выводится то, которое было перед последним обращением к чтению файла, как вариант... Выше я Вам показал, что вывод принтов для каждого значения в отдельности, никаких нареканий не вызывает, все норм.
 

ZNV

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

Ugar

Гуру форума
Здравствуйте.
Помогите, пожалуйста, функцию написать.
Надо из истории по паре вытащить сумму последних убыточных ордеров. Стопом служит прибыльный.
Спасибо.
А в каком порядке должны быть ордера? Может быть в порядке времени открытия, в порядке времени закрытия, по тикетам. От этого зависит как сортировать
 

ZNV

Активный участник
А в каком порядке должны быть ордера? Может быть в порядке времени открытия, в порядке времени закрытия, по тикетам. От этого зависит как сортировать

Та вроде сделал.. Спасибо. Ошибок не обнаружено)


C-подобный:
double sumloss(string s)
{
   double count=0;
   for(int trade=OrdersHistoryTotal()-1; trade>=0; trade--)
   {
      f= OrderSelect(trade, SELECT_BY_POS, MODE_HISTORY);
      if( OrderSymbol()==s )
      {
         if(OrderProfit()<0)
         {
            count += OrderProfit();
         }
         if(OrderProfit()>=0)
         {
            return(count);
         }
      }
     
   }
   return(count);
}
 

Ugar

Гуру форума
Та вроде сделал.. Спасибо. Ошибок не обнаружено)


C-подобный:
double sumloss(string s)
{
   double count=0;
   for(int trade=OrdersHistoryTotal()-1; trade>=0; trade--)
   {
      f= OrderSelect(trade, SELECT_BY_POS, MODE_HISTORY);
      if( OrderSymbol()==s )
      {
         if(OrderProfit()<0)
         {
            count += OrderProfit();
         }
         if(OrderProfit()>=0)
         {
            return(count);
         }
      }
    
   }
   return(count);
}
Ну да, ну да. А в каком порядке они там в истории лежат не важно. Если ордера по одному открываются и закрываются, то вполне пойдёт. Если не учитывать что при сравнении double данных не стоит использовать ==, >=, <=. Но новички это почти никогда не учитывают погрешности.
Вместо
if(OrderProfit()<0)
стоит написать if(OrderProfit()< -0.0001).
А вместо
if(OrderProfit()>=0)
стоит написать if(OrderProfit()> -0.0001).
 

ZNV

Активный участник
Ну да, ну да. А в каком порядке они там в истории лежат не важно. Если ордера по одному открываются и закрываются, то вполне пойдёт. Если не учитывать что при сравнении double данных не стоит использовать ==, >=, <=. Но новички это почти никогда не учитывают погрешности.
Вместо
if(OrderProfit()<0)
стоит написать if(OrderProfit()< -0.0001).
А вместо
if(OrderProfit()>=0)
стоит написать if(OrderProfit()> -0.0001).
А как порядок добавить?
Я просуммировал вручную, перепроверил, у меня все сошлось. Разве оно не берет с последних и дальше.. ?? :unsure:
Как порядок добавить?
 

Ugar

Гуру форума
А как порядок добавить?
Я просуммировал вручную, перепроверил, у меня все сошлось. Разве оно не берет с последних и дальше.. ?? :unsure:
Как порядок добавить?
Будет работать по истории так как в истории от последних к первым. Вопрос только в том как в они лежат в истории. А там бардак. Вернее есть закономерность, но она вряд ли понравится.
Короче, если надо в каком то порядке, сначала надо сортировать.
В цикле перебирая ордера внести их в двухмерный массив. В первое измерение внести данные по которому надо отсортировать, во второе тикеты ордеров.
Потом сортировать массив с помощью ArraySort.
Дальше в цикле перебирать ордера в массиве выбирать по тикету из второго измерения и уже суммировать прибыль.
 
  • Like
Реакции: ZNV

ИванМН

Местный знаток
Да какая разница, справка гласит: "При выводе числовые данные преобразуются в текстовый формат...".

FileReadNumber() <=> StrToDouble(FileReadString())

А это уже Ваша задача...

Каким именно образом и направлением идет наполнение ф-ции Print() - мне не известно, но её вывод произойдет только после того, как все необходимые данные будут получены. Из этого можно сделать вывод, что значение указателя выводится то, которое было перед последним обращением к чтению файла, как вариант... Выше я Вам показал, что вывод принтов для каждого значения в отдельности, никаких нареканий не вызывает, все норм.
В общем, если резюмировать: получать и использовать значения из файла надо "поштучно", одно за другим - на каждое полученное значение своё применение этого значения. Если пытаться делать это "потоком" - каждое значение получается из файла в рамках единого применения, - начинается какая-то лютая ересь, описанная мной выше. Очевидно, эти процессы не до конца проработаны разработчиками и носят частично неопределённый характер.
 

mobidik

-----
Если пытаться делать это "потоком" - каждое значение получается из файла в рамках единого применения, - начинается какая-то лютая ересь, описанная мной выше.
Нет, не верно. Исходя из Вашей логики, функция должна возвращать промежуточный результат в процессе своей работы. Т.е., сперва, ф-ция Print() напечатала номер положения указателя, затем продолжила свою работу, прочла первую строку данных - дополнила к ранее напечатанному, затем прочла следующую строку и снова дополнила к ранее напечатанному и т.д..? Вот это бред, не так ли? Вывод на печать произойдет тогда, когда будет выполнен весь код внутри ф-ции, согласно её алгоритма работы. В данном случае, на печать будет выведен результат после прочтения всех данных и, соответственно, на тот момент положение файлового указателя уже не будет в самом начале файла.
А не знание, не понимание, процессов заложенных разработчиком, приводит вот к таким выводам:
Очевидно, эти процессы не до конца проработаны разработчиками и носят частично неопределённый характер.
 

ZNV

Активный участник
Здравствуйте.
Вопрос по iCustom. Как проверить найден ли подключаемый индикатор?
Проблема в том что значения некоторых индикаторов, возвращают 0 как результат. И iCustom = 0, не будет говорить о не нахождении... :unsure:
 

AlexeyVik

Программист mql4 mql5
Здравствуйте.
Вопрос по iCustom. Как проверить найден ли подключаемый индикатор?
Проблема в том что значения некоторых индикаторов, возвращают 0 как результат. И iCustom = 0, не будет говорить о не нахождении... :unsure:
В случае отсутствия индикатора получишь ошибку
4072ERR_INDICATOR_CANNOT_LOADОшибка загрузки пользовательского индикатора

Следовательно после iCustom() поставь проверку типа if(GetLastError() == ERR_INDICATOR_CANNOT_LOAD)
 
  • Love
Реакции: ZNV

ZNV

Активный участник
Здравствуйте.
В подвальном индикаторе, на картинке, график цен разных пар. Как привести все к значению от 0 до 100% ?
... по типу стохастика или рси.
Я их код смотрел, но ничего не понял... :(
 

Вложения

  • EURJPYM15.png
    EURJPYM15.png
    69,9 КБ · Просмотры: 39

AlexeNP

Гуру форума
Здравствуйте.
В подвальном индикаторе, на картинке, график цен разных пар. Как привести все к значению от 0 до 100% ?
... по типу стохастика или рси.
Я их код смотрел, но ничего не понял... :(
max - максимальное значение по истории, min - минимальное... cur - текущее значение

percent = 100*(cur - min)/(max - min)
 
  • Like
Реакции: ZNV

ZNV

Активный участник
Скажите, есть ли способ проверить быстродействие индикатора? Его нагрузку в каком то измерении...?

Я хочу сравнить 2 индикатора, по нагрузке, какой "легче".
 
Верх