Какой объем данных можно передать через FrameAdd

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
elibrarius
2660
elibrarius  

Здравствуйте,

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

Пробую передать данные о всех сделках через FrameAdd.

Когда тест по маленькому участку истории - тест проходит, фрейм передается о обрабатывается (записывает сделки в файл).

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


Полагаю, что либо есть ограничение на длинну передаваемого массива data[]. На передачу может отправляться больше 1 мегабайта. Либо новое задание приходит раньше, чем успеет обработаться фрейм.

Использую этот вид вызова.

bool  FrameAdd(
   const string  name,        // публичное имя/метка
   long          id,          // публичный id
   double        value,       // значение
   const void&   data[]       // массив любого типа
   );

Может при пересылке файлами ограничений нет? Или файл не пересылается, а разбирается на массив на передающей стороне и пересылается опять же как массив (т.к. на приемной стороне можно принять только массив).

-----------------

Если большой фрейм поделить на несколько поменьше - и на приемной стороне их собрать в 1 большой массив - получится такой трюк? Окраничение на размер одного фрейма или на общее количество передаваемых данных?

Rashid Umarov
Админ
16680
Rashid Umarov  
Напишите заявку в Сервисдеск, пожалуйста. Предоставьте все данные для воспроизведения.
Maxim Dmitrievsky
19195
Maxim Dmitrievsky  
elibrarius:

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

есть ответ из СД?

Rashid Umarov
Админ
16680
Rashid Umarov  
Maxim Dmitrievsky:

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

Нет, фреймы передаются только в одну сторону. Посмотрите пример в статье Визуализируй стратегию в тестере MetaTrader 5

fxsaber
16823
fxsaber  
Maxim Dmitrievsky:

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

Передать только Агентам локальной машины через FILE_COMMON, отключив всех Агентов, кроме одного.

Получить можно любые данные в общем случае

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Вопросы от начинающих MQL5 MT5 MetaTrader 5

fxsaber, 2017.08.23 14:10

Для записи данных Агентов в один файл нужно использовать Фрейм-режим.

// Пример записи данных Агентов (включая Облачные) в один файл
input int Range = 0;

void OnTick()
{
// ....
}

// Файл открываем только в режимах одиночночного прогона или Фрейма.
const int handle = ((MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_OPTIMIZATION)) || MQLInfoInteger(MQL_FRAME_MODE)) ?
                   FileOpen(__FILE__, FILE_WRITE | FILE_TXT) : INVALID_HANDLE;

// Подготовка данных
void GetData( string &Str, MqlTick &Ticks[], double &Balance )
{
  Str = "Hello World!";
  
  CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, 0, 2); // Последние два тика (пример)
  
  Balance = AccountInfoDouble(ACCOUNT_BALANCE);
}

// Запись данных
void SaveData( const string &Str, const MqlTick &Ticks[], const double Balance )
{
  FileWrite(handle, Str);
  
  for (int i = 0; i < ArraySize(Ticks); i++)
    FileWrite(handle, Ticks[i].bid);
    
  FileWrite(handle, Balance);
}

void OnTesterDeinit()
{
  if (handle != INVALID_HANDLE)  
    FileClose(handle);
    
  ChartClose();
}

#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

double OnTester()
{
  string Str;
  MqlTick Ticks[];
  double Balance;
  
  GetData(Str, Ticks, Balance); // Подготовка данных для записи

  if (MQLInfoInteger(MQL_OPTIMIZATION)) // Оптимизация
  {
    CONTAINER<uchar> Container; // https://www.mql5.com/ru/forum/95447/page4#comment_5464205
    
    Container[0] = Str;
    Container[1] = Ticks;
    Container[2] = Balance;
  
    FrameAdd(NULL, 0, 0, Container.Data); // Отправили данные из Агента на Терминал
  }
  else // Одиночный прогон
  {    
    if (handle != INVALID_HANDLE)
      SaveData(Str, Ticks, Balance); // Данные будут записаны в MQL5\Files-папку Агента (не Терминала)
    
    FileClose(handle);
  }
  
  return(0);
}

void OnTesterPass()
{    
  if (handle != INVALID_HANDLE)
  {
    ulong Pass;
    string Name;
    long ID;
    double Value;
  
    CONTAINER<uchar> Container; // https://www.mql5.com/ru/forum/95447/page4#comment_5464205
  
    while (FrameNext(Pass, Name, ID, Value, Container.Data))
    {
      string Str;
      MqlTick Ticks[];
      double Balance;
      
      // Получили данные от Агента
      Container[0].Get(Str);
      Container[1].Get(Ticks);
      Container[2].Get(Balance);
      
//      FileWrite(handle, Pass);     // Если хочется записать номер прохода
      SaveData(Str, Ticks, Balance); // Данные будут записаны в MQL5\Files-папку Терминала (не Агента)
    }
  }
}

Еще есть пример здесь.

Мне интересно, как будет работать Оптимизатор в Облаке, когда нужно от каждого прохода получить 1 Мб данных, а инет-канал Терминала, например, 100 Кб/сек. Неужели Агенты будут ждать, пока медленный канал заберет его данные? А если медленный канал у самого Агента, несмотря на высокие рейтинги CPU?

Maxim Dmitrievsky
19195
Maxim Dmitrievsky  
Rashid Umarov:
fxsaber:

ушел в раздумья как с этим жить, спасибо :)

elibrarius
2660
elibrarius  

В СД еще не отправлял. На простом (воспроизводимом) примере и 1млн элементов массива отправляются по 8 байт = 8 мб. Из лок. сети данные приходят в полном объеме, без потерь. 10 млн тоже уходят.

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

elibrarius
2660
elibrarius  

Эксперименты:

Ставил запись фреймов самой последней командой в OnDeinit() - не помогло. Фрейм отправляется, принимается и записывется на приемной стороне. После этого агент переходит в failed и начинает работать через несколько минут. Оптимизация стопорится на ~70 проходе - все агенты в зависшем состоянии, через какое-то время разблокируются и снова зависают.

Пробовал отправлять частями - по 1-100 кб - не помогло.

Сохранял массив в файл и отправлял именно файл - не помогло.

Отправлял  не в double, a uchar виде - не помогло.

Ошибок в коде нет, т.к. комментировал строку /* FrameAdd("",0,0,frame); */   и ошибки пропадали.

Еще разные эксперименты делал...нашлись приемлемые варианты:

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

2) Еще нашелся вариант с увеличением передаваемого массива до 1024*1024  элементов 8 мегабайт для double массива.

ArrayResize(frame,1024*1024);
FrameAdd("",0,0,frame);

На приемной стороне считываю только полезные данные, лишние не обрабатываю. Иногда из 8 мб - полезных всего 500 байт, впрочем для локальной сети это не существенные потери. Главное, что работает... почти.
Этот вариант тоже сбоит, но гораздо реже. Иногда 1-2 сбоя за 200 проходов оптимизации иногда и не одного.
Решил работать дальше с этим вариантом.

Почему сбоит вариант с FrameAdd(simb_list,0,0,frame); в основном эксперте выяснить не удалось. Видимо общая сложность эксперта влияет (классы, dll-ки, файлы, индикаторы, памяти нормально потребляет, время расчета долгое) что-то одно из этого сказывается или комбинация факторов - неизвестно. В простом эксперте забор сохраненных данных из  файла и отправка через фрейм - работает.

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

MetaQuotes
Админ
27508
Renat Fatkhullin  

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

На словах такого уровня вопросы не решаются.

elibrarius
2660
elibrarius  
Renat Fatkhullin:

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

На словах такого уровня вопросы не решаются.

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

Приемлемое для меня решение (№2) нашел. Думаю проблема не в отправке фреймов, а в чем то другом.

Например "Еще заметил, что если повторно запустить оптимизацию, сразу после предыдущей, то все агенты получив первое задание сразу переходят в состояние failed." Где то читал, что агенты какое-то время держат кэш, может он мешает?

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