Problemas de cierre, por favor, ayuda - página 8

 
Ais:

Hola Cameofx,
Gracias por su amable respuesta.
Este sistema de codificación es muy simple y fácil.
Todo se hace manualmente en MetaEditor.
De hecho, el sistema está siendo diseñado para desarrollar grandes programas fácilmente y con alta velocidad.
El sistema debe ser también flexible y fiable.
¡Saludos!

Ais, gracias por tu respuesta. He aprendido mucho de tus posts :)

Cameo

 

Hola amigos!

Una cosa del pasado se cierne sobre mí día tras día.
Esto es documentación para AIS5 Trade Machine.
Volveré tan pronto como Dios decida.

¡Adiós por ahora!

 

Hola Ais
Se echará mucho de menos tu ausencia. Cuídate.
Nos alegramos de tu regreso.
Tu amigo, Salud

 

Hola Ais
A su regreso, siento agobiarle inmediatamente con más preguntas. No es tu sistema en particular, tengo este problema con casi todos los programas. Tiene que ver con las funciones definidas por el usuario. Cómo obtiene la función definida por el usuario su definición.
Por ejemplo:

int       iSignalOpen ()     //       - i      17 l       1 o     //< This is what iSignalOpen function will do.....
{                                                                 //< When the chart is opened, first pass..
if    ( ( iTradeBarTime    == iTime   ( 0 , 0 , 0 ) )   //< false input, EMPTY == (0,0,0)------|
      &&         //                                         &&                                 |--(return)EMPTY
      ( iTradeBarOnce    == 1 ))                        //< true  input, 1 == 1 ---------------|
      return ( EMPTY);
      
// This proves, 'EMPTY' will always be returned when the chart first opens. At the next tick...       
// ... 'iTime' will have parameters, example: (EUR/USD,HOUR_1,1) it is a predefined function so that...
// ... these parameters will be collected so that an expression can be calculated. Where as the... 
// ... 'iTradeBarTime' is not predefined. 'iTradeBarTime' was assigned 'EMPTY' at declaration earlier in the program.
// 'iTradeBarTime' knows that it is 'EMPTY'and nothing else. 
// When and how did 'iTradeBarTime' get deifined to collect data so that it's value can be other than 'EMPTY'? 
// The 'iTradeBarTime' has to have the same values as the 'iTime', or the input will never be 'true'?
// If it is never 'true', the return is always 'EMPTY'? 
No puedo encontrar ninguna respuesta firme en el libro o el foro. En un esquema de lógica de relés, una puerta AND funcionaría igual que el ejemplo anterior. Sólo cuando hay dos entradas "verdaderas", habrá una salida "verdadera". Sólo entonces continuará el control.
Esperando su respuesta. Gracias por adelantado.
Saludos
 

Hola Huckleberry

Vamos a aclarar esta parte del código.

1. Probablemente las principales dificultades:
1.1. todos los humanos piensan y actúan de forma diferente;
1.
2.Me gusta utilizar un número estrictamente limitado de tipos de datos;
1.3.
1.3. Me gusta utilizar sólo tipos de datos "estándar":
1.3.1. "int",
1.3.2. "double",
1.3.3. "string";
1.4. Utilizo otros tipos de datos sólo en casos especiales;
1.
5.1.5. Denoto el tipo de los elementos de mi programa con una letra minúscula en la primera posición de los nombres:
1.5.1. "i" para el tipo de datos "int",
1.5.2. "d" para el tipo de datos "double",
1.5.3. "s" para el tipo de datos "string",
1.5.4. "r" para el tipo de datos "undefined";
1.6. esta técnica de programación me ayuda a controlar el casting de tipos;
1.7. las funciones y constantes predefinidas pueden tener también los siguientes tipos de datos:
1.7.1. "bool",
1.7.2. "color",
1.7.3. "datetime";
1.8. Siempre trato de fundir estos tipos al tipo "int";
1.9. por hoy mi fundición de datos suele ser implícita;
1.10. algunos aspectos esenciales de mis técnicas de programación:
1.10.1. 1.10.1. Me gustaba utilizar el par de constantes "TRUE" y "EMPTY" en lugar del par de constantes "TRUE" y "FALSE";
1
.10.2. En las sentencias "if" a veces utilizaba "1" y "0" en lugar de "TRUE" y "FALSE";
1.10.3. Utilicé la constante "EMPTY" con valor negativo "-1" para denotar resultados inválidos para elementos de datos sin signo;
1.10.4. en el futuro utilizaré el tipo "bool" con el prefijo "b" en los nombres.

2. Debemos conocer los siguientes tipos de datos MQL4:
2.1. "int" es un <!>significado</!> número entero largo de 4 bytes con valores de -2147483648 a 2147483647;
2.2. "datetime" es un <!>sin signo</!> número entero largo de 4 bytes con valores de 0 a 4294967295;
2.3. asignando los valores de "datetime" a las variables "int", obtenemos resultados correctos hasta aproximadamente el 2038.01.01.

3. Debemos conocer la función "iTime ( símbolo, timeframe, shift )" de la siguiente manera:
3.1. esta función siempre devuelve un valor de tipo "datetime";
3.2. existen 2 casos diferentes de devolución:
3.2.1. "0" si el historial local está vacío;
3.2.2. tiempo de apertura de la barra indicado con "shift" en todos los demás casos;
3.3. "iTime ( 0, 0, 0 )" devuelve el tiempo de apertura para la barra cero del gráfico actual;
3.4. mientras la barra cero sea la misma, "iTime ( 0, 0, 0 )" devuelve el mismo valor;
3.5. cuando la barra cero actual se completa, esta barra se convierte en la barra número 1 y comienza la formación de la nueva barra cero;
3.6. "iTime ( 0, 0, 0 )" devuelve el nuevo valor;
3.7. así, el valor de "iTime ( 0, 0, 0 )" cambia cuando la barra cero cambia.

4. Hemos impedido trabajar con el historial vacío en el bloque de programa "2.2.3.1. Inspección de datos del historial".

5.Cuando la orden se cierra con éxito en la función "iTryClose" asignamos "iTradeBarTime = iTime ( 0, 0, 0 ) ;".

6. En la función "iSignalOpen" inspeccionamos si "iTradeBarTime == iTime ( 0, 0, 0 )".

7. Si es cierto y la repetición de la operación está prohibida por "iTradeBarOnce = 1 ;" entonces prohibimos la apertura de la señal por el valor "EMPTY".

Saludos

 

Hola Ais
Gracias por tu respuesta. Me pondré a estudiar el tema y volveré pronto.
Saludos

 

Hola Ais,
Perdona la lentitud de mi respuesta. Empecé a trabajar de nuevo en mi ocupación habitual el lunes. El tiempo es un poco más corto estos días. El tiempo de estudio es más corto.
Como había mencionado anteriormente dentro de este hilo, me gusta desglosar las cosas hasta las tuercas y los tornillos. Cómo un piñón proporcionó el poder a otro y así sucesivamente. Así que he encontrado que el control dentro del programa es fascinante. Por favor, comprenda que le doy todo el respeto por la paciencia y el conocimiento que ha proporcionado, pero tengo preguntas tiene a por qué el bloque 2.2.3.1 es necesario.
¿Cómo puede ser el iBaseLag + iBaseBar una expresión?
He entendido que iBaseLag y iBaseBar están dentro del parámetro para iHighest y iLowest. A menos que sean números explícitos,
cómo se puede determinar qué número exacto será. iBaseLag es 20, que representa 20 barras utilizadas para el cálculo de la media.
iBaseBar representa en qué barra debe comenzar el promedio. Las barras 1 a 20, en este caso, la barra cero no se considera.
Me tomé la libertad de acortar el programa en /* 2.2.3.1*/. Probé el programa y encontré los mismos resultados. Cuando se ejecuta el programa en condiciones reales de comercio, esto puede no ser una buena idea.
¿Cuál es su opinión, por favor?
Además, su explicación al bloque 2.1.2 ha aclarado mi confusión. El iTime devuelve la hora de apertura de la barra cero.
iTradeBarTime es un datetime de tipo cast también. El programa sabe en qué barra se ha producido la operación, por lo tanto sólo una operación por barra. . . iTradeBarOnce == 1
Gracias
Voy a estudiar más en los próximos días. Pero, ¿se puede utilizar el bloque 2.1.1 de reservered para una función que proporcione posiciones adicionales a las existentes. Ejemplo: un largo existente, y luego añadir tres o más largos?
Con las funciones que ya están en el programa, ¿habría conflictos con las posiciones adicionales?
Gracias de nuevo por todo. Que te vaya bien
Saludos

 

Hola Huckleberry,

Veamos con atención la parte principal del programa, incluyendo el bloque 2.2.3.1.:

////////////////////////////////////////////////////////////////////<        14>
// < 2.2.3. Code : Special : Start >                              //<          >
int       start   ()         //       - i       9 l       - o     //<          >
{                                                                 //<          >
// < 2.2.3.1. History data inspection 4 >`````````````````````````//<          >
static    int       iTrigger   = 0       ; if ( iTrigger == 0 ) { //<          >
  if  ( ( iTime ( 0 , 0 , 0 ) == 0                          )     //<          >
  ||    ( iBars ( 0 , 0     )  < iBaseLag     + iBaseBar    ) )   //<          >
          return                         ; else iTrigger  = 1 ; } //<          >
// </2.2.3.1. History data inspection 4 >`````````````````````````//<          >
//                                                                //<          >
// < 2.2.3.2. Main routine 3 >````````````````````````````````````//<          >
int       iTicket           = iGetTicket ()                     ; //<          >
//                                                                //<          >
if      ( iTicket < 0 )       iTryOpen   ()                     ; //<          >
else                          iTryClose  ()                     ; //<          >
// </2.2.3.2. Main routine 3 >````````````````````````````````````//<          >
//                                                                //<          >
// < 2.2.3.3. Exception handler 2 >```````````````````````````````//<          >
int       iTrap   =           GetLastError ()                   ; //<          >
if      ( iTrap   > 0 )       Alert  ( "Exception " , iTrap   ) ; //<          >
// </2.2.3.3. Exception handler 2 >```````````````````````````````//<          >
}                                                                 //<          >
// </2.2.3. Code : Special : Start >                              //<          >
////////////////////////////////////////////////////////////////////<         0>

Este código funciona de la siguiente manera:

1. el bloque 2.2.3.1., el primer bloque del programa, es un simple disparador:
1.1. "static int iTrigger" almacena su propio valor durante toda la vida del programa, tal es "static";
1.2. inicialmente "iTrigger == 0";
1.3. la declaración "if ( iTrigger == 0 )" se ejecuta en cada tick;
1
.4. la primera vez, cuando "iTrigger == 0", se ejecuta la inspección de los datos de la historia dentro del bloque {..};
1.5. si los datos de la historia son incorrectos, se ejecuta la sentencia "return;";
1.6. significa que la ejecución de la función principal "start ()" ha finalizado;
1
.7. en el siguiente tick se ejecuta de nuevo la sentencia "if ( iTrigger == 0 )";
1.8. si los datos históricos son correctos, se ejecuta la sentencia "iTrigger = 1 ;";
1.9. entonces continúa la ejecución de la función principal "start ()";
1.10. en el siguiente tick se ejecuta de nuevo la sentencia "if ( iTrigger == 0 )";
1.11. el valor de "iTrigger" ahora y en el futuro siempre será "== 1" porque es estático;
1.12. así que en el futuro la inspección de los datos históricos siempre se saltará;
1.13. así es el trigger simple;

2. la inspección de los datos de la historia consta de dos partes:
2.1. comprobar si la historia local está vacía "iTime ( 0, 0, 0 ) == 0";
2.2. comprobar si el tamaño de la historia local es suficiente para el cálculo de "iATR ( 0, 0, iBaseLag, iBaseBar )", donde:
2.2.1. "iBaseBar" es la barra inicial de "iATR";
2.2.2. "iBaseLag" es el número de barras de promedio de "iATR";
2.2.3. "iBaseLag + iBaseBar" es una expresión habitual, el resultado es siempre la suma de "iBaseLag" e "iBaseBar";
2.2.4. en otras palabras, la expresión "iBaseLag + iBaseBar" es equivalente a la suma de "iBaseLag" e "iBaseBar";
2.2.5. podemos asignar cualquier valor para "iBaseLag" e "iBaseBar" en la entrada del programa en el bloque 1.1.1.;
2.2.6. dejemos que asignemos "iBaseLag = 100 ;" e "iBaseBar = 7 ;";
2.2.7. entonces el cálculo correcto de "iATR ( 0, 0, iBaseLag, iBaseBar )" será posible, si el tamaño de la historia local es igual a 107 o mayor, porque el último número de barra para el cálculo es
#106 y el número de barra cero siempre se considera.

Es posible añadir cualquier número de funciones en cualquier programa, el bloque 2.1.1 sólo demuestra una muestra de la posible implementación.
Proporcionar posiciones adicionales requerirá un código de análisis y gestión de posiciones mucho más complejo que la función 2.1.4.
Pero todo es posible.

Saludos

 

Hola Ais
Gracias por su rápida respuesta. Puedo seguir gran parte de lo que expones. Especialmente sobre la función iATR. Dices que el uso de la expresión iBaseLag + iBasebar, en sí misma, es una parte aceptable de la fórmula. Tenía la impresión de que tenían que estar con los parámetros de una función definida o no estaban permitidos. Esto es para comprobar el tamaño del historial local, si realmente hay suficientes barras para continuar. ¿Es eso lo que está señalando? Así que muchos más pasos, pero los pasos necesarios para lograr el objetivo. Pasos que se pasarían por alto, o se darían por sentados.
Ya masticaré el resto. Gracias por su tiempo.
Saludos

 

Hola Huckleberry
MQL4 es un entorno muy amigable, especialmente comparado con, por ejemplo, C o ensambladores.
Los requisitos para varias comprobaciones y otros trucos se reducen significativamente.
Pero las implementaciones de las máximas comprobaciones posibles en el entorno de desarrollo siempre reducen el rendimiento.
En cualquier caso, el programador siempre es responsable del mal comportamiento del programa.
Así que para mí es mejor una nueva comprobación redundante que, por ejemplo, la corrupción elemental de los límites.
Saludos