Errores, fallos, preguntas - página 2451

 
Un archivo con un # en su nombre no puede ser añadido al almacenamiento. ¿Es un comportamiento normal o un error?
 

Si hablamos de FX, ahí los ticks no cambian mucho el precio (normalmente). Pero en otros mercados una orden puede resbalar seriamente con un enfoque tic. Sigo siendo partidario de probar entre garrapatas, no veo ningún perjuicio, el beneficio potencial está ahí.

Tenemos que intentar...

 
La histéresis en acción... en un ejemplo de cómo funciona un operador de copia de asignación implícita en las estructuras.

#define  PRINT(x) Print(#x, ":", string(x))

struct MyArray{
   uchar data[];
};


void OnStart(){
   MyArray tmp_arr;
   
   MyArray huge_arr;
   ArrayResize(huge_arr.data, 1000);
   ArrayInitialize(huge_arr.data, 0x8);
   
   MyArray small_arr;
   ArrayResize(small_arr.data, 10);
   ArrayInitialize(small_arr.data, 0x1);
   
   
   tmp_arr = small_arr;
   Print("\r\nTest with small_arr");
   PRINT(ArraySize(tmp_arr.data));
   PRINT(tmp_arr.data[0]);
   PRINT(tmp_arr.data[ArraySize(tmp_arr.data)-1]);
   
   tmp_arr = huge_arr;
   Print("\r\nTest with huge_arr");
   PRINT(ArraySize(tmp_arr.data));
   PRINT(tmp_arr.data[0]);
   PRINT(tmp_arr.data[ArraySize(tmp_arr.data)-1]);
   
   tmp_arr = small_arr;
   Print("\r\nTest with small_arr");
   PRINT(ArraySize(tmp_arr.data));
   PRINT(tmp_arr.data[0]);
   PRINT(tmp_arr.data[ArraySize(tmp_arr.data)-1]);
}

Resultado:
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   Test with small_arr
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   ArraySize(tmp_arr.data):10
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   tmp_arr.data[0]:1
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   tmp_arr.data[ArraySize(tmp_arr.data)-1]:1
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   Test with huge_arr
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   ArraySize(tmp_arr.data):1000
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   tmp_arr.data[0]:8
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   tmp_arr.data[ArraySize(tmp_arr.data)-1]:8
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   Test with small_arr
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   ArraySize(tmp_arr.data):1000
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   tmp_arr.data[0]:1
2019.05.03 14:29:14.005 Test_push (EURUSD,H1)   tmp_arr.data[ArraySize(tmp_arr.data)-1]:8
 
Sergey Dzyublik:
La histéresis en acción... mediante un ejemplo de cómo funciona un operador de copia implícito en las estructuras.

Probablemente, para detectar una cosa así, había que llegar a un estado/estúpido interno de "aquí no puede funcionar nada, pero lo voy a comprobar de todas formas" en busca de un error en el código propio.

 
fxsaber:

Supongo que para detectar algo así, has tenido que llegar a un estado interno/estúpido de "aquí no puede fallar nada, pero lo voy a comprobar de todas formas" en busca de un fallo en tu código.

El código estaba analizando el flujo de bytes para un protocolo particular.
Los datos desempaquetados y desempaquetados (datos para el siguiente nivel de encapsulación) no coincidían.

 
Sergey Dzyublik:

El código estaba analizando el flujo de bytes para un protocolo específico.
Los datos desempaquetados y desempaquetados (datos para el siguiente nivel de encapsulación) no coincidían.

No es difícil detectar esa tarea. Qué suerte.
 
Sergey Dzyublik:
La histéresis en acción... Un ejemplo de cómo funciona un operador de copia implícita en las estructuras.

¿Cuál es la pregunta?

void OnStart()
{
        int a[]; ArrayResize( a, 3 ); ArrayInitialize( a, 3 );
        int b[]; ArrayResize( b, 2 ); ArrayInitialize( b, 2 );

En MQL, una entrada condicional

//                 a = b;

es igual a

        ArrayCopy( a,  b );

Resultado:

        ArrayPrint( a );
}

2 2 3

 
A100:

¿Cuál es la pregunta?


En mi opinión, el operador de copia de la asignación debería copiar no sólo los elementos del array en sí, sino también su número, dejando válida la cantidad de memoria reservada.

Y ahora es prácticamente lo siguiente:

int size;
size = 4; // size == 4
size = 8; // size == 8
size = 4; //  size == 8



Código fuente:

struct MyArray{
   uchar data[];
}

MyArray GetArray(int i){
   MyArray arr;
   
   if (i%2 == 0){
      ArrayResize(arr.data, 8);
      ArrayInitialize(arr.data, 0x8);
   }else{
      ArrayResize(arr.data, 4);
      ArrayInitialize(arr.data, 0x4);
   }
   return arr;
}

void OnStart(){
   MyArray arr_1 = GetArray(1);
   ArrayPrint(arr_1.data);		// 4 4 4 4
   
   MyArray arr_2 = GetArray(2);         
   ArrayPrint(arr_2.data);              // 8 8 8 8 8 8 8 8
   
   arr_2 = arr_1;
   ArrayPrint(arr_2.data);              // 4 4 4 4 8 8 8 8
}
 
Sergey Dzyublik:


El operador de copia debe copiar no sólo los elementos del array en sí, sino su número, dejando válida la cantidad de memoria reservada.

¿Por qué entonces

struct MyArray {
        uchar data[];
};
void OnStart()
{
        { uchar   a[], b[]; a = b; } //(1) Error
        { MyArray a,   b;   a = b; } //(2) нормально
}

en (1) el error y en (2) está bien? ¿Cuál es la diferencia?

La diferencia es que los arrays se copian no por las reglas a = b, sino por las reglas ArrayCopy( a, b )

No por las reglas a = b, porque no existe, y si existiera, el error (1) no existiría


 
Igor Zakharov:

Contar en cada tic es un recurso intensivo, especialmente en el probador de estrategias. ¿No sería más correcto recalcular sólo el evento Trade, es decir, cuando algo en la lista de posiciones abiertas realmente cambia? Con OnTradeTransaction(), es más fácil controlar la intervención del usuario en el EA. (Hay algunos precedentes :)

En este robot estaba probando la posibilidad de cerrar la parrilla por el esquema: Pérdida + beneficio > X , luego cerrar ambos (normalmente en diferentes símbolos). Pero se produce un fallo, porque aunque están cerradas, el probador no se da cuenta y pasa a la siguiente iteración, "emparejando" por error las existentes con las ya cerradas. Así que tuve que añadir un recálculo después de cada cierre.

Tengo recálculo con reinicio de contador y en todos los abiertos primero, no +1 / -1

Estoy de acuerdo, fue arriesgado usar inicialmente OnTradeTransaction() En realidad, probablemente me negaré a usarlo en los casos en que mis peticiones no sean asíncronas - sólo causan problemas.

No es nada arriesgado. La cuestión está sólo en organizar la secuencia de acciones y eventos. El consejo de Fool es correcto: cerrar el par y dejar el bucle hasta el siguiente tick. En el siguiente tic, los precios no son necesariamente peores de lo que son. Tal vez, sea mejor cerrarlo un poco más tarde, pero no habrá confusión sobre qué se cerró con qué.

La segunda variante: organizar el bucle no por PositionsTotal, sino por el array creado previamente. Y al cerrar algún par, estos tickets deben ser eliminados del array. Esto no permitirá que las posiciones cerradas se vuelvan a cerrar. En general, una fuga de la fantasía y la lógica de las acciones.