Как перениести глобальную переменную, структуру в индикаторе при переходе на другой таймфрейм? - страница 4

 
Nikolai Semko:
Лично я использую ресурсы через union. 
Легко передаются даже массивы структур между ТФ  без записи в файл.

А можно подробнее. Спасибо.

 
Mikhail Nazarenko:

А можно подробнее. Спасибо.

В КБ как-нибудь запишу.
Собственно вот класс для этого.
А в индикатор нужно только добавить две строчки:

  • Создать перед OnInit экземпляр этого класса, привязав ваш массив структур, который нужно передавать между ТФ. Если это не первая инициализация, то массив структур будет заполнен данными предыдущего ТФ.
  • в OnDeinit сохранить ваш массив через единственный метод в этом классе. 

template <typename T>
class CStructArr {
 private:
   union StructUint {
      T st;
      uint u[1+sizeof(T)/4];
   };
   string            Name;
   uint              Var[];
   int               w;
   int               h;
   StructUint        su;
   int               size;

 public:
   CStructArr(const string name,T &var[]);
   ~CStructArr();
   bool              Set(T &var[]);
   //bool              Save();
   T                 value[];
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template <typename T>
CStructArr::CStructArr(const string name,T &var[]) {
   //ulong tt=GetMicrosecondCount();
   size = ArraySize(var);
   w=1+size*sizeof(T)/4;
   ArrayResize(Var,w);
   h=1;
   Name="::"+name+ IntegerToString(ChartGetInteger(0,CHART_WINDOW_HANDLE));
   if(ResourceReadImage(Name,Var,w,h)) {
      size = 4*(w-1)/sizeof(T);
      ArrayResize(value,size);
      ArrayResize(var,size);
      for (int j=0; j<size; j++) {
         for(int i=0; i<sizeof(T)/4; i++) su.u[i]=Var[j*sizeof(T)/4+i];
         value[j]=su.st;
         var[j]=value[j];
      }
   } else {
      for (int j=0; j<size; j++) {
         su.st=var[j];
         for(int i=0; i<sizeof(T)/4; i++) Var[j*sizeof(T)/4+i]=su.u[i];
         value[j]=var[j];
      }
      if(!ResourceCreate(Name,Var,w,1,0,0,0,COLOR_FORMAT_XRGB_NOALPHA)) printf("Error create Resource: "+DoubleToString(GetLastError(),0));
   }
   //tt=GetMicrosecondCount()-tt;
   //Print("!!!!!!!!  =  "+string(tt));
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template <typename T>
CStructArr::~CStructArr() {
   if(_UninitReason!=REASON_RECOMPILE && _UninitReason!=REASON_CHARTCHANGE) ResourceFree(Name);
}
//+------------------------------------------------------------------+
template <typename T>
bool CStructArr::Set(T &var[]) {
   size = ArraySize(var);
   ArrayResize(value,size);
   w=1+size*sizeof(T)/4;
   ArrayResize(Var,w);
   for (int j=0; j<size; j++) {
      su.st=var[j];
      for(int i=0; i<sizeof(T)/4; i++) Var[j*sizeof(T)/4+i]=su.u[i];
      value[j]=var[j];
   }
   if(!ResourceCreate(Name,Var,w,1,0,0,0,COLOR_FORMAT_XRGB_NOALPHA)) {
      printf("Error create Resource: "+DoubleToString(GetLastError(),0));
      return(false);
   } else return(true);
}
//+------------------------------------------------------------------+
ЗЫ Использовать глобальные переменные терминала для передачи параметров между ТФ считаю очень кривым решением.
 
Nikolai Semko:

В КБ как-нибудь запишу.
Собственно вот класс для этого.
А в индикатор нужно только добавить две строчки:

  • Создать перед OnInit экземпляр этого класса, привязав ваш массив структур, который нужно передавать между ТФ. Если это не первая инициализация, то массив структур будет заполнен данными предыдущего ТФ.
  • в OnDeinit сохранить ваш массив через единственный метод в этом классе. 

ЗЫ Использовать глобальные переменные терминала для передачи параметров между ТФ считаю очень кривым решением.

Спасибо, все по делу.

 
Nikolai Semko:

Собственно вот класс для этого.

На первый взгляд, реализация конвертации T[]<->uint[] неоптимальна.
 
fxsaber:
На первый взгляд, реализация конвертации T[]<->uint[] неоптимальна.

писал давно этот код. Может быть.
Хотя вроде там особо оптимизировать нечего. Может только в мелочах.
Во всяком случае этот класс в работе можно опробовать в моем последнем бесплатном продукте в Маркете.

Буду благодарен, если предложите более оптимальную реализацию. 

 
Nikolai Semko:

Буду благодарен, если предложите более оптимальную реализацию.

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

Библиотеки: TradeTransactions

fxsaber, 2019.03.15 07:36

// Быстрый кастинг массивов.
#include <fxsaber\TradeTransactions\Convert.mqh> // https://www.mql5.com/ru/code/22166

void OnStart()
{
  MqlTick Ticks[];

  MqlRates Rates[];  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 10, Rates); // Получили котировки.
  CONVERT::ArrayToArray(Rates, Ticks);              // Кастинг MqlRates[] -> MqlTick[].

  MqlRates Rates2[];    
  CONVERT::ArrayToArray(Ticks, Rates2);             // Кастинг MqlTick[] -> MqlRates[].
  ArrayPrint(Rates2);                               // Убедились, что все корректно.
}
Файлы:
Convert.mqh  4 kb
 
Mikhail Nazarenko:
Как перениести глобальную переменную, структуру, объект в индикаторе при переходе на другой таймфрейм? Гуглил не нашел.

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

Библиотеки: TradeTransactions

fxsaber, 2018.12.17 23:48

Можно обмениваться чем угодно через Ресурсы.

// Пример обмена любыми данными (включая строковые массивы).

#include <fxsaber\TradeTransactions\ResourceData.mqh> // https://www.mql5.com/ru/code/22166

#define PRINT(A) Print(#A + " = " + (string)(A));

void OnStart()
{    
  // Произвольные данные для примера
  string Str[] = {"123", "Hello World!"};
  double Num = 5;
  MqlTick Tick = {0};
  Tick.bid = 1.23456;

  const RESOURCEDATA<uint> Resource; // Ресурс для обмена данными
  CONTAINER<uint> Container;         // Создаем контейнер - все будет храниться в массиве простого типа (в примере выбран uint)
  
  // Заполняем контейнер разными данными
  Container[0] = Str;
  Container[1] = Num;
  Container[2] = Tick;
    
  // Распечатаем типы хранимых в контейнере данных
  for (int i = 0; i < Container.GetAmount(); i++)
    PRINT(Container[i].GetType())

  Resource = Container.Data;  // Отправили данные на обмен
  
  CONTAINER<uint> Container2; // Сюда будем получать данные
  
  Resource.Get(Container2.Data); // Получили данные
      
  // Получим данные в исходном виде
  string Str2[];
  Container[0].Get(Str2);                // Получили массив
  ArrayPrint(Str2);

  PRINT(Container[1].Get<double>())      // Получили число
  PRINT(Container[2].Get<MqlTick>().bid) // Получили структуру  
}
 
fxsaber:

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

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

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

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

 
Nikolai Semko:

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

Если напишите замер производительности, будет интересно сравнить.

 

:)

Странно что теперь никто не пишет про "костыли", "изобретение велосипеда", "сложности переноса данных на другой терминал", "задача должна решаться средствами MQL "...
Получается что решения от метаквотов - это костыли и моветон)

Причина обращения: