Тест в Билд 215

 

Вот такой эксперт

#import "Import_Fun.ex4"
   int Import_Fun();
#import

int start()
   {
   static int Cn = 0;
   Cn++;
   if (Cn>3)
      return;

   Alert("start() ==========================");
   bool Channal   = false;                                  // Объекта заданного типа нет
   int Obj_Tot = ObjectsTotal();
   Alert("======Obj_Tot = ", Obj_Tot);

   for(int k=0; k<Obj_Tot; k++)                             // Пройдёмся по объектам, 
      {
      string His_Name = ObjectName(k) ;                     // Имя текущего объекта
      Alert("======His_Name (",k,")= ", His_Name);
      if (ObjectType(His_Name) == OBJ_STDDEVCHANNEL)
         {
         Alert("======ObjectType = ", ObjectType(His_Name));
         Channal = true;                                    // Факт, что объект такого типа в окне ЕСТЬ
         break;                                             // Выходим из цикла перебора объектов 
         }
      }

   if (Channal == false)                                    // Если объекта заданного типа нет
      {
      Alert("======Канала нет. Создаём канал, обращаясь к импортированной функции");
      Import_Fun();                                         // Создаём канал
      }
   else
      Alert("======Канал есть.");
   return;
   }

Вот такая функция

#property library   
int Import_Fun()
   {    
   string My_Chan_Name = "My_Channel";                      // Имя создаваемого канала
   static int Cnt = 0;
   Cnt++;
   if (Cnt>3)
      return(0);
   
   Alert("Import_Fun() --------------");
   bool Channal   = false;                                  // Объекта заданного типа нет
   int Obj_Tot = ObjectsTotal();
   Alert("------Obj_Tot вход= ", Obj_Tot);
   for(int k=0; k<Obj_Tot; k++)                             // Пройдёмся по объектам, 
      {
      string His_Name = ObjectName(k) ;                     // Имя текущего объекта
      if (His_Name == My_Chan_Name)
         Alert("------Найден (где?) объект с именем:");
      Alert("------His_Name = ", His_Name);
      if (ObjectType(His_Name) == OBJ_STDDEVCHANNEL)
         {
         Channal = true;                                    // Факт, что объект такого типа в окне ЕСТЬ
         break;                                             // Выходим из цикла перебора объектов 
         }
      }
   if (Channal == false)                                    // Если объекта заданного типа нет
      {
      Alert("------Создаём канал ");
      ObjectCreate (My_Chan_Name, OBJ_STDDEVCHANNEL,0,0,0); // Создаём его.. 
      ObjectSet(My_Chan_Name, OBJPROP_TIME1, Time[5]);      // Устанавливаем координаты
      ObjectSet(My_Chan_Name, OBJPROP_TIME2, Time[0]);      // Устанавливаем координаты 
      ObjectSet(My_Chan_Name, OBJPROP_COLOR, Orange);       // Устанавливаем координаты 

      Obj_Tot = ObjectsTotal();                             
      Alert("------Obj_Tot >>>>>>> ", Obj_Tot);
      }
   return;
   }

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

Если сразу после этого запустить тест в режиме визуализации, то эксперт не видит объект, созданный в импорт. функции.

Тот же результат можно получить, если сначала исполнить визуализацию, а потом обычное тестирование. Логи:


14:52:25 Test_Error: loaded successfully
14:52:31 Test_Error started for testing
14:52:31 2007.08.03 00:00 Test_Error EURUSD,M15: Alert: start() ==========================
14:52:31 2007.08.03 00:00 Test_Error EURUSD,M15: Alert: ======Obj_Tot = 0
14:52:31 2007.08.03 00:00 Test_Error EURUSD,M15: Alert: ======Канала нет. Создаём канал, обращаясь к импортированной функции
14:52:31 2007.08.03 00:00 Import_Fun EURUSD,M15: loaded successfully
14:52:31 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: Import_Fun() --------------
14:52:31 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: ------Obj_Tot вход= 0
14:52:31 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: ------Создаём канал
14:52:31 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: ------Obj_Tot >>>>>>> 1
14:52:31 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: start() ==========================
14:52:31 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: ======Obj_Tot = 1
14:52:31 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: ======His_Name (0)= My_Channel
14:52:31 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: ======ObjectType = 6
14:52:31 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: ======Канал есть.
14:52:31 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: start() ==========================
14:52:31 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: ======Obj_Tot = 1
14:52:31 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: ======His_Name (0)= My_Channel
14:52:31 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: ======ObjectType = 6
14:52:31 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: ======Канал есть.
14:52:32 Test_Error started for testing
14:52:32 2007.08.03 00:00 Test_Error EURUSD,M15: Alert: start() ==========================
14:52:32 2007.08.03 00:00 Test_Error EURUSD,M15: Alert: ======Obj_Tot = 0
14:52:32 2007.08.03 00:00 Test_Error EURUSD,M15: Alert: ======Канала нет. Создаём канал, обращаясь к импортированной функции
14:52:32 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: Import_Fun() --------------
14:52:32 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: ------Obj_Tot вход= 0
14:52:32 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: ------Создаём канал
14:52:32 2007.08.03 00:00 Import_Fun EURUSD,M15: Alert: ------Obj_Tot >>>>>>> 1
14:52:32 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: start() ==========================
14:52:32 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: ======Obj_Tot = 0
14:52:32 2007.08.03 00:15 Test_Error EURUSD,M15: Alert: ======Канала нет. Создаём канал, обращаясь к импортированной функции
14:52:32 2007.08.03 00:15 Import_Fun EURUSD,M15: Alert: Import_Fun() --------------
14:52:32 2007.08.03 00:15 Import_Fun EURUSD,M15: Alert: ------Obj_Tot вход= 1
14:52:32 2007.08.03 00:15 Import_Fun EURUSD,M15: Alert: ------Найден (где?) объект с именем:
14:52:32 2007.08.03 00:15 Import_Fun EURUSD,M15: Alert: ------His_Name = My_Channel
14:52:32 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: start() ==========================
14:52:32 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: ======Obj_Tot = 0
14:52:32 2007.08.03 00:30 Test_Error EURUSD,M15: Alert: ======Канала нет. Создаём канал, обращаясь к импортированной функции
14:52:32 2007.08.03 00:30 Import_Fun EURUSD,M15: Alert: Import_Fun() --------------
14:52:32 2007.08.03 00:30 Import_Fun EURUSD,M15: Alert: ------Obj_Tot вход= 1
14:52:32 2007.08.03 00:30 Import_Fun EURUSD,M15: Alert: ------Найден (где?) объект с именем:
14:52:32 2007.08.03 00:30 Import_Fun EURUSD,M15: Alert: ------His_Name = My_Channel
14:52:42 Import_Fun EURUSD,M15: removed
14:52:42 Test_Error EURUSD,M15: removed


По-моему, это только верхушка айсберга.

В реальном коде также не работает, например, IsDemo(). В ряде случаев терминал вылетает (моё сообщение в https://www.mql5.com/ru/forum/52504 от 09.04.08 22:59 ).

 
SK извните за теоретическое предположение, но это RefreshRates(), т.е. что то с не так координатами объекта,
т.к. у меня графика в свернутом окне и в демо и в реал и в визуал и в оптимизации - везде работает без нареканий.
Попробуйте координаты передавать 100%, например из глобальных.
 

Я недостаточно знаю, чтобы сделать самостоятельный вывод о причине этой проблемы.

По моим представлениям RefreshRates() тут ни при чём. Обратите внимание, эксперт то работает, то не работает. Видимо, проблема как-то связана с идентификацией окон, используемых при тестировани, визуализации и обычной работе.

Использовать GV-переменные можно. Но во-первых, для начала нужно всё же понимать причину проблемы. Во-вторых, GV-переменные будут доступны и другим экспертам, работающим в терминале, поэтому не хочется же таким корявым способом.. Да и нет, наверное. Сами посудите: эксперт собственными средствами не видит объект в окне. Что ж толку подсказывать ему из-за угла. И потом: какая же уверенность в том, что подсказка (через GV) будет верной, если нет уверенности, что не только эксперт, но и функция смотрит куда следует?..


Тут либо я чего-то не учитываю в своих рассуждениях, либо это специфическая ситуация, не рассмотренная при разработке тестера (в обычном окне вроде бы всё работает).


Кстати, Korey, не затруднит Вас прогнать это на своём ПК? Экзешник функции не забудьте положить в папку library.

Интересно что получится..

 

to SK

Прогоню/попробую через несколько часов.
Но у меня был эксперт с 6-ю граф/линиями и одним каналом, правда небольшого объема, без подгрузки,
Линии перестравались через 3-5 баров, канал был приклеен к нулевому баром, и подтаскивал хвост.
Никаких проблем.
Однако, встречал подобное изчезновение, когда вместо координат в объект передавался мусор, т.е.
объект снимался по жесткой ошибке.
В частности, без рефреша только TimeCurent() TimeLocal() свежие, все остальное не обновляется,
а теперь может быть, что и не наполняется.

 

to SK

Рынок уснул.
Уже проверил на первый раз.
Загрузил в либ под именем Import_Fun, компильнул.
На первый взгляд в реале, в демо, в визуал - все работает как часики.
Удаляем советник. Загружаем. Демо/реал - канал есть.
Далее тестер.
С первого раза в оптимизаторе ошибка
0045F4A0:3E37 [004632D7] ?ExecuteStaticAsm@CExpertInterior (terminal.exe)
Далее без ошибки.
на втором старте Визуал - нет канала, и т.д. нет канала.

Грузим другой советник стартуем в визуал, затем снова SK=
то же самое: на первом визуал старте есть канал, на втором и т.д. -нет.
Т.е. загрузка другого светника в тестер что то почистила.

Тогда Перекомпилируем советника без смены имени в тестере есть канал!!! повторные - нет.
Перекомпилиреум - опять есть.
Т.е. ошибка снимается перезагрузкой самого советника, но не функциии.
Но вдруг опять ошибка, теперь уже в визуал.
бла бла бла и в конце:
0045F4A0:3E37 [004632D7] ?ExecuteStaticAsm@CExpertInterior (terminal.exe)
==критичесую ошибку вызывает модуль исполняющий статические ASM проги, т.е. исполнение формата .ех4
получается, Что-то косо встает и возникает обращение за границы памяти именно в обрамлении тестера.

 

Вот и у меня примерно так же.

Насколько я понял, компиляция тут ни при чём. Можно и не перекомпилировать. С первого раза всё работает нормально, а при любом повторном тестировании 2 варианта: либо работает неправильно, либо вылетает в трубу. А уж где там какая память за какие границы.. и главное, какое она имеет право вылезать за границы? - это я уже сказать не могу.

Беда в том, что я из-за этого не могу AG довести до ума. И не знаю, то ли я сам нахомутал чего, то ли тестер..

 
if(Obj_Tot>0)
   {
   for(int k=Obj_Tot-1; k>=0; k--)

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

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

 
Но в теле то советника работает, неужто места совсем не осталось
 
Korey:
Но в теле то советника работает, неужто места совсем не осталось

Ё-маё.. Да в теле-то работает.

У меня их в теле.. не знаю точно, но что-то около 500. И все работают как написаны, как задумано. А вот эта импортированная очень нужна. В ней юзер будет свои гениальные стратегические мысли под AG писать. Ну,.. вернее, так планировалось. А что теперь получится не знаю..

 

помучал немного, еще граф объект добавил

При втором старте число граф объектов=0
но выдает ошибку 4200 = объект с этим именем уже создан.

"блабла" это принт из импортируемой функции = ошибок нет, к импорту функций вообще претензий нет.

Однако,

<объектов счетчик> = 0, а +2 объекта с именами уже есть от прошлого старта, с каждым стартом еще +2 и так пока на ошибку не вылетит

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


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

Число объектов ноль, а число имен Visual окна не ноль.

-указующий на имена объектов указатель/счетчик или того хуже - дескриптор))) не сбрасывается при повторном старте в тестере, от него и выход за пределы памяти.


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

2008.04.12 03:19:01 2007.11.25 22:00 SK GBPUSD,H1: SK getlasterror=0 0
2008.04.12 03:19:01 2007.11.25 22:00 SKF GBPUSD,H1: 11111 funk11111=4200
2008.04.12 03:19:01 2007.11.25 22:00 SK GBPUSD,H1: SK getlasterror=0 0
2008.04.12 03:19:01 2007.11.25 22:00 SKF GBPUSD,H1: blabla bla
2008.04.12 03:19:01 2007.11.25 22:00 SKF GBPUSD,H1: funk=4200
2008.04.12 03:19:01 2007.11.25 22:00 SKF GBPUSD,H1: funk=0
2008.04.12 03:19:01 2007.11.25 22:00 SKF GBPUSD,H1: blabla bla
2008.04.12 03:19:01 SK started for testing

 

Модернизированный вариант с подробностями :


#import "Import_Fun.ex4"
   int Import_Fun();
#import

int start()
   {
   static int Cn = 0;
   Cn++;
   if (Cn>3)
      return;

   Alert("start() ==========================");
   bool Channal   = false;                                  // Объекта заданного типа нет
   int Obj_Tot = ObjectsTotal();
   Alert("======Obj_Tot = ", Obj_Tot);

   for(int k=0; k<Obj_Tot; k++)                             // Пройдёмся по объектам, 
      {
      string His_Name = ObjectName(k) ;                     // Имя текущего объекта
      Alert("======His_Name (",k,")= ", His_Name);
      if (ObjectType(His_Name) == OBJ_STDDEVCHANNEL)
         {
         Alert("======ObjectType = ", ObjectType(His_Name));
         Channal = true;                                    // Факт, что объект такого типа в окне ЕСТЬ
         break;                                             // Выходим из цикла перебора объектов 
         }
      }

   if (Channal == false)                                    // Если объекта заданного типа нет
      {
      Alert("======Канала нет. Создаём канал, обращаясь к импортированной функции");
      Import_Fun();                                         // Создаём канал
      }
   else
      {
      Alert("======Канал есть.");
      Alert("======Cмотрим что получилось в ЭКСПЕРТЕ:");
      int    _T1 = ObjectGet( His_Name, OBJPROP_TIME1 );    // Характеристики объекта
      int    _T2 = ObjectGet( His_Name, OBJPROP_TIME2 );    // Характеристики объекта
      double _P1 = ObjectGet( His_Name, OBJPROP_PRICE1);    // Характеристики объекта
      double _P2 = ObjectGet( His_Name, OBJPROP_PRICE2);    // Характеристики объекта
      Alert("_T1=",_T1,"   _T2=",_T2,"   _P1=",_P1,"   _P2=",_P2);
      }
   return;
   }

#property library   
int Import_Fun()
   {    
   string My_Chan_Name = "My_Channel";                      // Имя создаваемого канала
   static int Cnt = 0;
   Cnt++;
   if (Cnt>3)
      return(0);
   
   Alert("Import_Fun() --------------");
   bool Channal   = false;                                  // Объекта заданного типа нет
   int Obj_Tot = ObjectsTotal();
   Alert("------Obj_Tot вход= ", Obj_Tot);
   for(int k=0; k<Obj_Tot; k++)                             // Пройдёмся по объектам, 
      {
      string His_Name = ObjectName(k) ;                     // Имя текущего объекта
      if (His_Name == My_Chan_Name)
         Alert("------Найден (где?) объект с именем:");
      Alert("------His_Name = ", His_Name);
      
      if (ObjectType(His_Name) == OBJ_STDDEVCHANNEL)
         {
         Channal = true;                                    // Факт, что объект такого типа в окне ЕСТЬ
         break;                                             // Выходим из цикла перебора объектов 
         }
      }
   if (Channal == false)                                    // Если объекта заданного типа нет
      {
      Alert("------Создаём канал  TIME1=",Time[5],"   Time2=",Time[0]);
      ObjectCreate (My_Chan_Name, OBJ_STDDEVCHANNEL,0,0,0); // Создаём его.. 
      ObjectSet(My_Chan_Name, OBJPROP_TIME1, Time[5]);      // Устанавливаем координаты
      ObjectSet(My_Chan_Name, OBJPROP_TIME2, Time[0]);      // Устанавливаем координаты 
      ObjectSet(My_Chan_Name, OBJPROP_COLOR, Orange);       // Устанавливаем координаты 

      Obj_Tot = ObjectsTotal();                             
      Alert("------Obj_Tot >>>>>>> ", Obj_Tot);
      Alert("------Cмотрим что получилось в ИМПОРТНОЙ функции:");
      int    _T1 = ObjectGet( My_Chan_Name, OBJPROP_TIME1 );    // Характеристики объекта
      int    _T2 = ObjectGet( My_Chan_Name, OBJPROP_TIME2 );    // Характеристики объекта
      double _P1 = ObjectGet( My_Chan_Name, OBJPROP_PRICE1);    // Характеристики объекта
      double _P2 = ObjectGet( My_Chan_Name, OBJPROP_PRICE2);    // Характеристики объекта
      Alert("_T1=",_T1,"   _T2=",_T2,"   _P1=",_P1,"   _P2=",_P2);
      }
   return;
   }