Новая версия платформы MetaTrader 5 build 5430: Улучшенные графики на движке Blend2D - страница 17

 
Пропала прозрачность при использовании ResourceCreate(resource_name, pixels, width, height, 0, 0, width, COLOR_FORMAT_ARGB_NORMALIZE). Неделю-две назад всё работало как нужно. Код для воспроизведения:
void OnStart()
{
   const int width = 128;
   const int height = 128;
   uint pixels[];
   ArrayResize(pixels, width * height);

   uint alpha = 128;
   uint red = 255;
   uint green = 0;
   uint blue = 0;
   uint clr = (alpha << 24) | (red << 16) | (green << 8) | blue;

   for(int i = 0; i < width * height; i++)
   {
      pixels[i] = clr;
   }

   string resource_name = "CustomRedSquare";
   if(!ResourceCreate(resource_name, pixels, width, height, 0, 0, width, COLOR_FORMAT_ARGB_NORMALIZE))
   {
      Print("Ошибка создания ресурса: ", GetLastError());
      return;
   }

   string obj_name = "MyBitmapLabel";
   if(!ObjectCreate(0, obj_name, OBJ_BITMAP_LABEL, 0, 0, 0))
   {
      Print("Ошибка создания объекта: ", GetLastError());
      return;
   }

   if(!ObjectSetString(0, obj_name, OBJPROP_BMPFILE, "::" + resource_name))
   {
      Print("Ошибка назначения ресурса объекту: ", GetLastError());
      return;
   }

   ObjectSetInteger(0, obj_name, OBJPROP_CORNER, 0);
   ObjectSetInteger(0, obj_name, OBJPROP_XDISTANCE, 100);
   ObjectSetInteger(0, obj_name, OBJPROP_YDISTANCE, 100);

   ChartRedraw();
}
 
Ilya Filatov #:
Пропала прозрачность при использовании ResourceCreate(resource_name, pixels, width, height, 0, 0, width, COLOR_FORMAT_ARGB_NORMALIZE). Неделю-две назад всё работало как нужно. Код для воспроизведения:

У меня тоже:


 

В последнем билде 5481 и точно нескольких перед ним obj_text кушают неприлично много памяти - по мегабайту на каждый. В 5430 такого нет.

Код скрипта для проверки:

//+------------------------------------------------------------------+
//|                                  OBJ_TEXT_Interactive_Test.mq5   |
//|                          Interactive Text Objects Memory Test    |
//+------------------------------------------------------------------+
#property script_show_inputs
#property version   "1.00"

input int ObjectsPerBatch = 100;       // Объектов за одно нажатие
input string TestSymbol = "";    // Символ
input ENUM_TIMEFRAMES TestTimeframe = PERIOD_M1;

int g_batch_count = 0;
long g_chart_id = 0;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   Print("\n========================================");
   Print("=== OBJ_TEXT INTERACTIVE TEST ===");
   Print("Build: ", TerminalInfoInteger(TERMINAL_BUILD));
   Print("Press TAB to add ", ObjectsPerBatch, " text objects");
   Print("Press DELETE to remove all objects");
   Print("Press ESC to exit");
   Print("========================================\n");
   
   g_chart_id = ChartID();
   
   // Начальная память
   long mem_start = TerminalInfoInteger(TERMINAL_MEMORY_USED);
   Print("Memory at start: ", mem_start, " MB");
   Print("Objects on chart: ", ObjectsTotal(g_chart_id));
   Print("\nWaiting for key press...\n");
   
   // Цикл ожидания нажатий клавиш
   while(!IsStopped())
     {
      Sleep(100);
      
      // Проверяем нажатия клавиш
      if(TerminalInfoInteger(TERMINAL_KEYSTATE_TAB) < 0)
        {
         AddTextObjects();
         Sleep(300); // Защита от повторных нажатий
        }
      
      if(TerminalInfoInteger(TERMINAL_KEYSTATE_DELETE) < 0)
        {
         DeleteAllObjects();
         Sleep(300);
        }
      
      if(TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE) < 0)
        {
         Print("\nExiting...");
         break;
        }
     }
   
   Print("\n========================================");
   Print("=== TEST FINISHED ===");
   Print("========================================");
  }

//+------------------------------------------------------------------+
//| Добавление пакета текстовых объектов                             |
//+------------------------------------------------------------------+
void AddTextObjects()
  {
   long mem_before = TerminalInfoInteger(TERMINAL_MEMORY_USED);
   int obj_before = ObjectsTotal(g_chart_id);
   
   datetime time = iTime(TestSymbol, TestTimeframe, 50);
   double price = iClose(TestSymbol, TestTimeframe, 50);
   
   Print("--- Adding batch #", g_batch_count + 1, " ---");
   Print("Memory BEFORE: ", mem_before, " MB");
   Print("Objects BEFORE: ", obj_before);
   
   // Создаем объекты
   for(int i = 0; i < ObjectsPerBatch; i++)
     {
      string name = "Text_" + IntegerToString(g_batch_count) + "_" + IntegerToString(i);
      
      ObjectCreate(g_chart_id, name, OBJ_TEXT, 0, time, price + i * 0.0001);
      ObjectSetString(g_chart_id, name, OBJPROP_TEXT, "Test " + IntegerToString(i));
      ObjectSetInteger(g_chart_id, name, OBJPROP_COLOR, clrRed);
      ObjectSetInteger(g_chart_id, name, OBJPROP_FONTSIZE, 8);
      ObjectSetString(g_chart_id, name, OBJPROP_FONT, "Arial");
     }
   
   ChartRedraw(g_chart_id);
   Sleep(100); // Даем время на обработку
   
   long mem_after = TerminalInfoInteger(TERMINAL_MEMORY_USED);
   int obj_after = ObjectsTotal(g_chart_id);
   
   Print("Memory AFTER: ", mem_after, " MB");
   Print("Objects AFTER: ", obj_after);
   Print("Memory DIFF: +", mem_after - mem_before, " MB");
   Print("Objects DIFF: +", obj_after - obj_before);
   Print("Memory per object: ", DoubleToString((mem_after - mem_before) / (double)ObjectsPerBatch, 6), " MB\n");
   
   g_batch_count++;
  }

//+------------------------------------------------------------------+
//| Удаление всех объектов                                           |
//+------------------------------------------------------------------+
void DeleteAllObjects()
  {
   long mem_before = TerminalInfoInteger(TERMINAL_MEMORY_USED);
   int obj_before = ObjectsTotal(g_chart_id);
   
   Print("--- Deleting ALL objects ---");
   Print("Memory BEFORE: ", mem_before, " MB");
   Print("Objects BEFORE: ", obj_before);
   
   ObjectsDeleteAll(g_chart_id, -1, OBJ_TEXT);
   ChartRedraw(g_chart_id);
   Sleep(100);
   
   long mem_after = TerminalInfoInteger(TERMINAL_MEMORY_USED);
   int obj_after = ObjectsTotal(g_chart_id);
   
   Print("Memory AFTER: ", mem_after, " MB");
   Print("Objects AFTER: ", obj_after);
   Print("Memory DIFF: ", mem_after - mem_before, " MB");
   Print("Objects DIFF: ", obj_after - obj_before);
   
   if(mem_after < mem_before)
      Print("Memory FREED: ", mem_before - mem_after, " MB\n");
   else if(mem_after > mem_before)
      Print("!!! MEMORY LEAK: +", mem_after - mem_before, " MB !!!\n");
   else
      Print("Memory unchanged\n");
   
   g_batch_count = 0;
  }
//+------------------------------------------------------------------+
 

Обновился до Билд 5482, пропала прозрачность объектов

Постоянно валят ошибки

ResourceCreate(): 4006 / no memory for parameter string

но картинка меняется правда без прозрачности

До это все работало несколько лет четко без ошибок


 
pivalexander #:

Обновился до Билд 5482, пропала прозрачность объектов

Прозрачность раньше пропала. А у меня с 5480 вообще до 5482 не обновляется (всё время жду починки прозрачности).

Ранее терминал обновлялся как из пушки. Сервер MQ Demo.


 
Ilya Filatov #:

Прозрачность раньше пропала. А у меня с 5480 вообще до 5482 не обновляется (всё время жду починки прозрачности).

Ранее терминал обновлялся как из пушки. Сервер MQ Demo.


Откатил до 5430, все опять заработало 
 

Баг.
Если провести оптимизацию с форвардом, то при экспорте экспортируются 2 файла: бектеста и форвард теста. Ожидаемое поведение.

Если потом сделать оптимизацию без форварда,


то при экспорте логично экспортировать один файл, но в дополнение к нему экспортируется еще и последний форвард.

Удаляю из папки все файлы,


экспортирую и получаю в ней 2 файла.


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

 

Потом еще не каждый поймет, какой файл нужно использовать.

Я после изучения вижу, что с цифрой 40 перед хешем означает бектест, а 43 форвард. Но далеко не каждый это знает и многие будут обрабатывать/сохранять не тот файл.

 
Forester #:

многие будут обрабатывать/сохранять не тот файл.

Ни разу не экспортировал, хоть работаю с opt-файлами очень давно.

Я после изучения вижу, что с цифрой 40 перед хешем означает бектест, а 43 форвард.

Такой подход видится хорошим.

#property script_show_inputs      
      
#include <fxsaber\MultiTester\MTTester.mqh>    // https://www.mql5.com/ru/code/26132
#include <fxsaber\TesterCache\TesterCache.mqh> // https://www.mql5.com/ru/code/26223

input int inPos = 0; // opt-file number

bool Load( const uchar &Bytes[], TESTERCACHE<ExpTradeSummary> &CacheClassic, TESTERCACHE<MATHEMATICS> &CacheMath, bool &IsMath )
{
  bool Res = false;
  
  IsMath = (Res = CacheMath.Load(Bytes)) || !(Res = CacheClassic.Load(Bytes));
  
  return(Res);
}

bool IsForward( const string FileName )
{
  // https://www.mql5.com/ru/forum/499840/page17#comment_58744626
  return(false);
}

void OnStart()
{
  string Path;
  string FileNames[];
  
  if (inPos < MTTESTER::GetOptCacheFileNames(Path, FileNames))
  {
    TESTERCACHE<ExpTradeSummary> CacheClassic;
    TESTERCACHE<MATHEMATICS> CacheMath;

    bool IsMath;
    uchar Bytes[];    

    if (!IsForward(FileNames[inPos]) &&
        (MTTESTER::FileLoad(Path + FileNames[inPos], Bytes) > 0) &&
        Load(Bytes, CacheClassic, CacheMath, IsMath))
    {
      // https://www.mql5.com/ru/forum/497682/page10#comment_58431996
      #define CACHE2(A) (IsMath ? CacheMath.##A : CacheClassic.##A)
      #define CACHE(A) CACHE2(A)

      Print(FileNames[inPos]);
      Print(CACHE(Header.ToString()));
    }
  }
}
Для Маркета в описании продукта просят запустить соответствующий mklink, который cache-папку помещает в песочницу. По аналогии с этим.
MQL5 Program Packer
MQL5 Program Packer
  • 2020.02.18
  • www.mql5.com
This is MQL5 project packer: assemble all source and resource files from dependencies into a single ZIP.
 
fxsaber #:
Ни разу не экспортировал, хоть работаю с opt-файлами очень давно.

Такой подход видится хорошим.

Для Маркета в описании продукта просят запустить соответствующий mklink, который cache-папку помещает в песочницу. По аналогии с этим.

Ну это для своей программы можно как-то отделять. Т.е. это решение только для меня. Придумаю что-то.

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

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