Errores, fallos, preguntas - página 2452

 
A100:

El que copia los arrays no es por las reglas a = b, sino por las reglas deArrayCopy( a, b )

¿Te lo has inventado tú o está escrito en algún sitio?
Te recuerdo que este es un operador de asignación implícita para estructuras con arrays dinámicos.

 
Sergey Dzyublik:

¿Lo inventaron ellos mismos o está escrito en alguna parte?
Te recuerdo que es el trabajo del operador de asignación implícita para estructuras con arrays dinámicos.

No fue mi idea, sino la de los desarrolladores.

        uchar a[], b[]; a = b; //Error: invalid array access
¿Por qué hay un error? ¿Lo envolviste en una estructura y el error desapareció? ¿Y por qué? ¿Qué ha cambiado fundamentalmente? Mis respuestas anteriores
 
Alexey Viktorov:

Sólo se trata de organizar la secuencia de acciones y acontecimientos.

Tú mismo has citado el manual, que dice que la coherencia no está garantizada. Por eso es arriesgado.

Ya he empezado a reescribir el código según los consejos de Vladimir, pero me he tropezado con un caso en el que el cierre es más largo que un tic - doble conteo de nuevo (el nodo de filtro en el conteo es muy pesado). Hasta ahora no se me ha ocurrido nada mejor que detenerme antes del cierre total en aras del compromiso con la velocidad de optimización.

Es viernes :) Quizá después de descansar un poco se me ocurra algo.

En cualquier caso, gracias por las ideas, ¡no se perderán!

 
A100:

No fue mi idea, sino la de los desarrolladores.

Nunca entendí dónde estaba escrito, pero no importa...
Gracias por el cholivar.

Lo apoyó con una muleta y siguió corriendo:

struct MyArray{
   uchar data[];
   
   void operator=(MyArray &bytes){
      ArrayCopy(this.data, bytes.data);
      ArrayResize(this.data, ArraySize(bytes.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            
}
 
Igor Zakharov:

Tú mismo has citado el manual, que dice que la coherencia no está garantizada. Por eso es arriesgado.

Ya he empezado a reescribir el código según los consejos de Vladimir, pero me he tropezado con un caso en el que el cierre es más largo que un tic - doble conteo de nuevo (el nodo de filtro en el conteo es muy pesado). Hasta ahora no se me ha ocurrido nada mejor que detenerme antes del cierre total en aras del compromiso con la velocidad de optimización.

Es viernes :) Quizá después de descansar un poco se me ocurra algo.

De todos modos, gracias por las ideas, ¡no se van a desperdiciar!

Me refería a mi propia coherencia.

Según mis observaciones, resulta que después de OnTick, cuando se produce la transacción, la ejecución del código se pasa a la función OnTradeTransaction sin esperar al siguiente tick. Por lo tanto, no hay diferencia en el procesamiento del cierre por sus propias funciones o por OnTradeTransaction. Pero prefiero trabajar con OnTradeTransaction. Lo principal es organizar correctamente la secuencia de operaciones sin depender de la secuencia de transacciones procedentes del servidor. Y es importante entender correctamente esta secuencia. De nuevo, según mis propias observaciones, la secuencia puede romperse en el tipo de transacción. Es decir, se puede realizar primero TRADE_TRANSACTION_DEAL_ADD y luego TRADE_TRANSACTION_HISTORY_ADD, mientras que lógicamente primero se debe añadir una orden al historial y luego una transacción.

ps; Entonces, como dije, al filtrar la transacción TRADE_TRANSACTION_DEAL_ADD se puede filtrar por apertura de posición y por cierre de posición. Después de todo, estamos hablando de un Asesor Experto para el mercado de divisas y una cuenta, ¿verdad? Por lo tanto, no es necesario recalcular todas las posiciones en cada estornudo. Basta con añadir uno si se abrió, o eliminar uno de los contados si se cerró.
 
Alexey Viktorov:

del mercado de divisas y de la cuenta, ¿verdad?

Rejilla :) Sí.

La lógica actual es la siguiente: hay una estructura que almacena toda la información sobre cada parrilla: símbolo-número de posiciones-lote-ganancia y algunas otras cosas sin importancia... El beneficio se recalcula por temporizador, si hay órdenes (robot multisímbolo). Pero los lotes y la cantidad se recalcularon en OnTradeTransaction (en caso de que el usuario "ayudara").

Quería comprobar un caso cuando una parrilla, por ejemplo, está en beneficio por 100$, y la otra está en pérdida por 50$ - para cerrar ambas con un beneficio de 50$ para evitar que crezca.

Por el momento lo he hecho:

void  OnTradeTransaction(
   const MqlTradeTransaction&    trans,     // trade transaction structure 
   const MqlTradeRequest&        reqst,     // request structure 
   const MqlTradeResult&         reslt      // response structure 
    )
{
 int index=-1;
 for(index=0;index<symbols_total;index++)
  if(ARRAY[index].symbol==trans.symbol) break; //нашли индекс символа по которому прошла трансакция в массиве структур
 
 if(index>=0) CountOrders(index); //пересчитали элемент
}

Hasta ahora he añadidoCountOrders()después de cerrar un par de rejillas. Para un probador de estrategias, funciona. Para una cuenta real utilizaré el esquema de Vladimir (con una matriz de tickets cerrados).

Por cierto, el cierre del par no se ha justificado - el drawdown no disminuye considerablemente, mientras que el beneficio se reduce decentemente.

 
Vladimir Karputov:

Yo renunciaría a TODOS los tiempos, Sleep y OnTimer para la tarea de cerrar posiciones. Yo haría lo siguiente: disparar órdenes de cierre - salida OnTick, en el siguiente tick comprobar: si las posiciones con entradas necesarias siguen vivas - disparar órdenes de cierre de nuevo y así sucesivamente en un círculo a través de la entrada/salida a OnTick.

La lógica es la siguiente: el cierre de una posición es la primera prioridad, por lo que el bucle de cierre está al principio de OnTick. Y la formación de la matriz de entradas de cierre puede estar en cualquier lugar de OnTick - incluso en el final.

Tarde o temprano, usted terminará con lo siguiente: necesita cerrar una posición, se envía una orden de cierre (MQL5), es decir, se envía una orden del tipo opuesto, ya que no está rastreando las acciones de trading en el manejador apropiado (o no está guardando el estado de la posición en su EA) y en el siguiente tick una orden de cierre puede estar en proceso de ser enviada y usted enviará otra orden. El resultado es una posición en sentido contrario.

 
Alexey Kozitsyn:

Tarde o temprano, te encontrarás con lo siguiente: necesitas cerrar una posición, envías una orden de cierre (MQL5), es decir, envías una orden del tipo contrario, ya que no haces un seguimiento de las acciones comerciales en el manejador correspondiente (o no guardas el estado de la posición en tu EA) y en el siguiente tick puede estar en proceso de envío una orden de cierre, pero envías otra orden. El resultado es una posición en la dirección opuesta.

Para tal caso tenemos:

10036

TRADE_RETCODE_POSITION_CLOSED

Laposición con el POSITION_IDENTIFIERespecificado ya ha sido cerrada

La posición de cierre se envía con el ticket de la posición a cerrar, por lo que es poco probable que se produzca lo descrito.

 
Sergey Dzyublik:

Nunca entendí dónde está escrito, pero no importa...
Gracias por el cholivar.

Lo apoyó con una muleta y siguió corriendo:

Bueno, es extraño cómo se copian los arrays, pero a algunos incluso les gusta...

He hecho una envoltura más o menos adecuada sobre un array y no tengo problemas.

https://www.mql5.com/ru/forum/221917/page26#comment_11233214

 
A100:

No fue mi idea, sino la de los desarrolladores.

No recuerdo que hayan dicho eso.

El operador de asignación está pensado para crear una copia idéntica de un objeto. Ese es su propósito. Cuando equiparas algo a algo, obviamente deberías obtener una copia completa en el lado izquierdo, no otra cosa. Así que obviamente hay un error aquí.