How do I move the global variable structure in the indicator when moving to another timeframe? - page 4

 
Nikolai Semko:
Personally, I use resources via union.
Even arrays of structures are easily transferred between TFs without writing to a file.

Could you elaborate on that. Thank you.

 
Mikhail Nazarenko:

Can you elaborate on that? Thank you.

I'll write it down in the Buy More sometime.
Actually, here is the class for it.
And you just need to add two lines to the indicator:

  • Create an instance of this class before the OnInit, linking your array of structures, which you want to pass between the TFs. If it's not the first initialization, the array of structures will be filled with data from the previous TF.
  • At OnDeinit, save your array via a single method in this class.

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);
}
//+------------------------------------------------------------------+
I find the use of global terminal variables to transfer parameters between TFs a very awkward solution.
 
Nikolai Semko:

I'll write it down in the QB sometime.
Actually, here's the class for it.
And in the indicator you only need to add two lines:

  • Create an instance of this class before OnInit and bind your array of structures to be passed between TFs. If it's not the first initialization, the array of structures will be filled with data from the previous TF.
  • In OnDeinit save your array via a single method in this class.

I think using global terminal variables to pass parameters between TFs is a very crooked solution.

Thanks, that's all on point.

 
Nikolai Semko:

In fact, here's the class for it.

At first sight, implementation of the T[]<->uint[] conversion is not optimal.
 
fxsaber:
At first sight, implementation of the T[]<->uint[] conversion is not optimal.

wrote this code a long time ago. It may be.
There is nothing much to optimize there though. Maybe only in some small things.
Anyway, this class can be tried in my latest free product in the Market.

I would be grateful if you could suggest a better implementation.

 
Nikolai Semko:

I would be grateful if you could suggest a better implementation.

Forum on trading, automated trading systems and trading strategy testing

Libraries: 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);                               // Убедились, что все корректно.
}
Files:
Convert.mqh  4 kb
 
Mikhail Nazarenko:
How to transfer a global variable, structure, object in an indicator when moving to another timeframe? Googled it and couldn't find it.

Forum on trading, automated trading systems and testing trading strategies

Libraries: TradeTransactions

fxsaber, 2018.12.17 23:48

You can trade anything through Resources.

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

#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:

Not, unfortunately, a barefaced one. I won't go into your bibles.
I've already tried to look into your code and realized I'm not mature enough. :))

Anyway, if you open all the inluders, your code will be longer in source code and executable.

Also, a couple of times burned, when I used your libs, and then found the source of brakes for a long time, until they were torn down. After that I gave up.

Main difficulty of using your code, which consists of many inludes, is high complexity of debugging, when at each step new class, defines or macros.
And I spare time for the test, because I understand that it is hardly possible to speed up my algorithm considerably.
The only one bug I see now is using loops instead of CopyArray in some places. After this fix my code will be almost perfect in terms of performance and readability.

 
Nikolai Semko:

The only bug I see now is that I use loops in some places instead of CopyArray. After this fix my code will be almost perfect in terms of performance and readability.

If you write a performance measurement, it would be interesting to compare.

 

:)

It's strange that no one writes about "crutches", "reinvention of a wheel", "difficulties of data transfer to another terminal","the problem must be solved by MQL means "...
It turns out that solutions based on metaquotes are crutches and mauvais ton)

Reason: