Preguntas de los principiantes MQL4 MT4 MetaTrader 4 - página 137

 
Игорь Васильев:

Es extraño que el compilador no lo informe cuando ve los comandos de comercio en el código del indicador.

Ahora tendremos que llevar la parte de negociación del indicador al Asesor Experto vinculándolo con él a través de ICustom().

Parece "la cola en la cabeza y el arco en el costado".

El compilador sólo comprueba la sintaxis. Su tarea no es determinar cómo funcionará (o no funcionará) el programa resultante. La inoperatividad de los comandos comerciales sólo puede descubrirse en la fase de ejecución del programa. Es decir, se recibirá un error en tiempo de ejecución.

 

Hola a todos, ¿podrían decirme si es posible hacer lo siguiente?

Hay una estructura, por ejemplo:
// una estructura de algunos eventos.
struct MyStruct
{
Número de int;
datetime DTm;
doble Valor;
Tipo de cadena;
}

Declaro un array dinámico de estructuras de tipo MyStruct:
MyStruct DataEvents[];

Formo y relleno un array en alguna función, por ejemplo
void GetDataEventsTest(MyStruct& DataEvents[], int countEvent=5)
{
MathSrand(GetTickCount());
ArrayResize(DataEvents, countEvent);
int i = 0;
while( i<countEvent )
{
DatosEventos.Número = i;
DataEvents.DTm = TimeCurrent();
DataEvents.Value = (double)MathRand();
if( MathMod(i, 2)>0 ) DataEvents.Type = "Up"; else DataEvents.Type = "Dn";
i = i + 1;
}
}

En algún lugar llenamos el array llamando a GetDataEventsTest():
GetDataEventsTest(DataEvents);

Necesitamos, por ejemplo, insertar un nuevo elemento de tipo MyStruct en medio del intervalo de elementos del array, en algún lugar del índice 2.
La lógica sugiere los siguientes pasos:
ArrayResize(DataEvents, ArraySize(DataEvents)+1);
y algo así:
int iNuevo = 2;
int i = ArraySize(DataEvents) - 2;
while( i>=iNuevo )
{
// DataEvents[i+1] = DataEvents[i]; // no funciona, por supuesto, porque tenemos que trabajar con las direcciones a las que hace referencia el elemento del array, así que
// escribe DataEvents[i+1] en un elemento del array que apunta al elemento del array DataEvents[i];
i = i - 1;
}
... Luego lleno el elemento del array DataEvents[iNew] con datos.


Pregunta, ¿es posible hacer esto con estructuras mql4?

 
GitSM:

Pregunta ¿es posible hacer esto con estructuras en mql4?

Sí, es posible. Si la estructura no tuviera un tipo de datos complejo (aquí incluye la cadena), todo funcionaría a la vez. Y cuando la estructura contiene tipos de datos cuyo tamaño puede cambiar con el tiempo, es necesario sobrecargar el operador de asignación:

struct MyStruct
{
    int Number;
    datetime DTm;
    double Value;
    string Type;

    void operator = (const MyStruct &stMyStruct)
    {
      Number = stMystruct.Number;
      DTm = stMyStruct.DTm;
      Value = stMyStruct.Value;
      Type = stMyStruct.Type;
    }
}
 
Ihor Herasko:

Sí, es posible. Si la estructura no tuviera un tipo de datos complejo (aquí incluye la cadena), funcionaría de inmediato. Y cuando la estructura contiene tipos de datos cuyo tamaño puede cambiar con el tiempo, es necesario sobrecargar el operador de asignación:

Gracias por el consejo.
 

De nuevo surgió una pregunta en la misma dirección que en el último ejemplo.
Si la estructura es compleja y puede contener matrices con otras estructuras. Por ejemplo, hago declaraciones como ésta:

// elemento con propiedades
struct ItemProperty
{
doblemente bajo;
doblemente alta;
doble Medio;
doble rango;
doble área;
Tipo de cadena;

void operator = (const ItemProperty &SourceItemProperty)
{
Low = SourceItemProperty.Low;
Alto = SourceItemProperty.High;
Middle = SourceItemProperty.Middle;
Rango = SourceItemProperty.Range;
Área = SourceItemProperty.Area;
Type = SourceItemProperty.Type;
}
}

// elementos con propiedades estadísticas
struct ItemsProperty;
{
doble MinLow;
doble MaxHigh;
doble AvgRange;
doble AvgArea;
fase de cuerda;

Ítems[];

void operator = (const ItemProperty &SourceItemsProperty)
{
MinLow = SourceItemsProperty.MinLow;
MaxHigh = SourceItemsProperty.MaxHigh;
AvgRange = SourceItemsProperty.AvgRange;
AvgArea = SourceItemsProperty.AvgArea;
Fase = SourceItemsProperty.Phase;

// Items = SourceItemProperty.Items; // ¿Cómo puedo hacer que múltiples variables de array apunten al mismo array físico en memoria?
}
}

// estructura de algunos eventos basados en el análisis de artículos
struct EventProperty
{
Número de int;
datetime DTm;
doble Valor;
Tipo de cadena;

doble Niveles[];
int Pesos[];

ItemsProperty ItemsProp[];

void operator = (const ItemProperty &SourceEventProperty)
{
Número = SourceEventProperty.Number;
DTm = SourceEventProperty.DTm;
Valor = SourceEventProperty.Value;
Type = SourceEventProperty.Type;

// Niveles = SourceEventProperty.Levels; // hay un problema
// Weigths = SourceEventProperty.Weigths; // ehhh.

// ItemsProp = SourceEventProperty.ItemsProp; // aquí también hay un problema

}
}

Declarar una matriz dinámica de eventos:
EventoPropiedad MisEventos[];

Relleno los datos de la matriz de eventos en alguna función.
void GetEventsProperty(EventProperty& MyEvents)
{
// código de llenado
}

y en algún lugar hay que manipular los elementos del array MyEvents añadiéndolos o eliminándolos.

int iNuevo = 2;
int i = ArraySize(MyEvents) - 2;
while( i>=iNuevo )
{
// MyEvents[i+1] = MyEvents[i]; // aquí tenemos un problema
i = i - 1;
}

¿Es posible hacer esto con un array de estructuras en mt4? Resulta que necesitamos poder referirnos a un mismo elemento de matriz de estructuras en memoria desde diferentes variables de referencia, creándolas y borrándolas.
¿Es posible trabajar con un array de referencias a estructuras?

 
GitSM:

¿Es posible hacer esto con un array de estructuras en mt4? Resulta que hay que poder referenciar un mismo elemento del array de estructuras en memoria desde diferentes referencias de variables, creándolas y borrándolas.

¿Es posible trabajar con un array de referencias a estructuras?

En teoría, debería ser así:

struct ItemsProperty;
{
    double MinLow;
    double MaxHigh;
    double AvgRange;
    double AvgArea;
    string Phase;
    
    Item Items[];
    
    void operator = (const ItemProperty &SourceItemsProperty)
    {
        MinLow = SourceItemsProperty.MinLow;
        MaxHigh = SourceItemsProperty.MaxHigh;
        AvgRange = SourceItemsProperty.AvgRange;
        AvgArea = SourceItemsProperty.AvgArea;
        Phase = SourceItemsProperty.Phase;
 
        int nTotal = ArraySize(SourceItemProperty.Items);
        ArrayResize(Items, nTotal);
        for (int i = 0; i < nTotal; ++i)
           Items[i] = SourceItemProperty.Items[i];
    }
}

Y con todas las demás matrices exactamente igual. Pregunta:

¿Cómo puedo hacer que varias variables de array apunten al mismo array físico en memoria?

No lo entiendo.

P. S. Para insertar código, utilice el icono "</>" o Alt+S.

 

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

No lo entiendo.

Lo siento, no he formulado la pregunta correctamente. Si he entendido bien, un array de estructuras es esencialmente referencias-direcciones por índices de array, cada una de las cuales apunta a alguna dirección física en memoria, distribuida de cierta manera según la estructura de datos. Con "¿Cómo hacer que varias variables de array apunten a un mismo array físico en memoria?" me refería a la posibilidad de hacer que MisEventos[2] y MisEventos[5] apunten a una misma estructura en memoria, es decir, MisEventos[2] y MisEventos[5] no deben apuntar a dos estructuras idénticas, deben apuntar a la misma estructura.

La sobrecarga del operador creará una copia de la estructura. Las estructuras de datos pueden ser muy pesadas o puede haber muchas de ellas y no es necesario copiarlas, sólo se necesita un array para saltar de un índice a otro para dirigirse a la estructura de datos. Algo así *MisEventos[2] = *MisEventos[1]. Puede que haya utilizado los punteros de forma incorrecta, así que lo explicaré de esta manera. Tienes que tomar la dirección de Mis Eventos[2] y cambiarla por la dirección de Mis Eventos[1].

Y entonces, no importa lo complejas y pesadas que sean las estructuras de datos, podrías "barajarlas" en el array en el orden que necesites sin apenas desperdiciar recursos computacionales. Después de todo, copiar una dirección de memoria de un lugar a otro es mucho más fácil, órdenes de magnitud más rápidos y no requiere memoria adicional, que copiar estructuras cuya complejidad puede variar mucho para cambiar el índice referenciado a esta estructura en un array.

Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Большую часть времени современные компьютеры простаивают и не используют всех возможностей процессора. Мы предлагаем задействовать их с пользой. Вы можете сдавать мощности вашего компьютера другим участникам нашей сети для выполнения разнообразных...
 
Según tengo entendido, para implementar ese mecanismo de "barajar" referencias a estructuras en un array, estas estructuras tendrán que ser implementadas a través de clases.
He probado este ejemplo y parece que funciona. Entiendo que también tendré que controlar la eliminación de los objetos de clase creados mediante new.
He descrito una clase de prueba y una matriz dinámica de punteros (según entiendo, son esencialmente los mismos enlaces) a clases en la declaración de variables:
class MyClassTest
{
        public:
        int a;
        double b;
        string c;
};

MyClassTest* arrayRefsMyClassTest[];
También hice estas comprobaciones:
Print("Тест операций над массивом ссылок на классы: начало");

// создаём объекты классов и сохраняем ссылки на них в массиве ссылок.
i = 0;
while( i<5 )
{
        ArrayResize(arrayRefsMyClassTest, i+1);
        arrayRefsMyClassTest[i] = new MyClassTest();
        arrayRefsMyClassTest[i].a = i;
        arrayRefsMyClassTest[i].b = 3.14+i;
        arrayRefsMyClassTest[i].c = "testclass" + i;
        i = i + 1;
}

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Изменяем размер массива ссылок на классы");
ArrayResize(arrayRefsMyClassTest, ArraySize(arrayRefsMyClassTest)+2);

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю последнему элементу ссылку во втором элементе");
i =  ArraySize(arrayRefsMyClassTest) - 1;
arrayRefsMyClassTest[i] = arrayRefsMyClassTest[2];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю 2 элементу ссылку в 5 элементе");
arrayRefsMyClassTest[1] = arrayRefsMyClassTest[5];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("\nТест операций над массивом ссылок на классы: конец");
Tengo estos resultados en el registro:
Тест операций над массивом ссылок на классы: начало
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Изменяем размер массива ссылок на классы
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю последнему элементу ссылку во втором элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю 2 элементу ссылку в 5 элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
Тест операций над массивом ссылок на классы: конец
Parece que funciona como se pretende. Las copias superfluas de datos en este caso, según entiendo, no se crean. Si me equivoco, por favor, corríjanme. ¿Quizás haya algún comentario o aclaración?
 
¿Cómo puede MQL5 (o WinAPI) ampliar el gráfico a pantalla completa?
 
GitSM:
Por lo que entendí, para implementar ese mecanismo de "barajar" referencias a estructuras en un array, estas estructuras deben ser implementadas a través de clases.

Sí, lamentablemente, no se pueden hacer punteros a estructuras en MQL. No está claro por qué se hace esa limitación, si se puede hacer con las clases. Al fin y al cabo, las estructuras no difieren realmente de las clases.