¿Cómo puedo cambiar la estructura de la variable global en el indicador al pasar a otro marco temporal? - página 4

 
Nikolai Semko:
Personalmente, utilizo los recursos vía sindicato.
Incluso las matrices de estructuras se transfieren fácilmente entre TFs sin necesidad de escribir en un archivo.

¿Podría explicarlo con más detalle? Gracias.

 
Mikhail Nazarenko:

¿Puede explicarlo con más detalle? Gracias.

Lo escribiré en el QB algún día.
En realidad, aquí está la clase para ello.
Y sólo hay que añadir dos líneas al indicador:

  • Cree una instancia de esta clase antes del OnInit, vinculando su matriz de estructuras, que desea pasar entre los TFs. Si no es la primera inicialización, el array de estructuras se llenará con los datos de la TF anterior.
  • En OnDeinit, guarde su matriz a través de un único método en esta clase.

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);
}
//+------------------------------------------------------------------+
El uso de variables terminales globales para transferir parámetros entre TFs me parece una solución muy incómoda.
 
Nikolai Semko:

Lo escribiré en el QB algún día.
De hecho, aquí está la clase para ello.
Y en el indicador sólo hay que añadir dos líneas:

  • Cree una instancia de esta clase antes de OnInit, vinculando su matriz de estructuras a ser pasadas entre TFs. Si no es la primera inicialización, el array de estructuras se llenará con los datos de la TF anterior.
  • En OnDeinit guarde su matriz a través de un único método en esta clase.

Creo que usar variables globales de terminal para pasar parámetros entre TFs es una solución muy torcida.

Gracias, todo está en su punto.

 
Nikolai Semko:

De hecho, aquí está la clase para ello.

A primera vista, la implementación de la conversión T[]<->uint[] no es óptima.
 
fxsaber:
A primera vista, la implementación de la conversión T[]<->uint[] no es óptima.

escribió este código hace mucho tiempo. Puede ser.
Sin embargo, no hay mucho que optimizar allí. Tal vez sólo en algunas cosas pequeñas.
De todos modos, esta clase se puede probar en mi último producto gratuito en el Mercado.

Les agradecería que me sugirieran una implementación mejor.

 
Nikolai Semko:

Les agradecería que me sugirieran una implementación mejor.

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Bibliotecas: 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);                               // Убедились, что все корректно.
}
Archivos adjuntos:
Convert.mqh  4 kb
 
Mikhail Nazarenko:
¿Cómo transferir una variable global, una estructura, un objeto en un indicador al pasar a otro marco temporal? Lo he buscado en Google y no lo he encontrado.

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

Bibliotecas: TradeTransactions

fxsaber, 2018.12.17 23:48

Puedes intercambiar cualquier cosa a través de Recursos.

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

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

No, desgraciadamente, a cara descubierta. No voy a entrar en sus biblias.
Ya he intentado buscar en su código y me he dado cuenta de que no soy lo suficientemente maduro. :))

De todos modos, si abres todos los inluders, tu código será más largo en código fuente y ejecutable.

Además, un par de veces se quemó, cuando utilicé sus liberaciones, y luego encontró la fuente de los frenos durante mucho tiempo, hasta que fueron derribados. Después de eso me rendí.

La principal dificultad de usar su código, que consiste en muchos inludes, es la alta complejidad de la depuración, cuando en cada paso nueva clase, define o macros.
Y me sobra tiempo para la prueba, porque entiendo que apenas es posible acelerar mi algoritmo considerablemente.
El único error que veo ahora es el uso de bucles en lugar de CopyArray en algunos lugares. Después de esta corrección, mi código será casi perfecto en términos de rendimiento y legibilidad.

 
Nikolai Semko:

El único error que veo ahora es que uso bucles en algunos lugares en lugar de CopyArray. Después de esta corrección, mi código será casi perfecto en términos de rendimiento y legibilidad.

Si escribes una medida de rendimiento, sería interesante comparar.

 

:)

Es extraño que nadie escriba sobre las "muletillas", la "reinvención de la rueda", las "dificultades de transferencia de datos a otro terminal","el problema debe resolverse por medios MQL "...
Resulta que las soluciones basadas en las metacitas son muletas y mauvais ton)