Asesores Expertos: Programación en MQL5 para tráders: códigos fuente del libro: Parte 7

 

Programación en MQL5 para tráders: códigos fuente del libro: Parte 7:

La séptima y última parte del libro, abarcaremos las características avanzadas de la API MQL5 que resultarán útiles a la hora de desarrollar programas para MetaTrader 5. Algunas de ellas tienen una naturaleza más particular, como los instrumentos financieros personalizados y el calendario económico incorporado, mientras que otras suponen tecnologías universales, como las funciones de red, las bases de datos y la criptografía.

Programación en MQL5 para tráders: códigos fuente del libro: Parte 7

Autor: MetaQuotes

 
Buenos recursos de aprendizaje
 
Aprenda
 
Aquí hay pequeñas correcciones de errores y mejoras para la caché de calendario y filtro.
MQL5 Book: Advanced language tools / Economic calendar / Transferring calendar database to tester
MQL5 Book: Advanced language tools / Economic calendar / Transferring calendar database to tester
  • www.mql5.com
The calendar is available for MQL programs only online, and therefore testing news trading strategies poses some difficulties. One of the solutions...
Archivos adjuntos:
 

¿Pueden decirme si se trata de un error o no entiendo algo?

Archivo MarginProfitMeter.mqh.

// Convertir la cantidad de dinero "actual" en dinero "de la cuenta".
bool Convert(const string current, const string account,
             const bool ask, double &margin, const datetime moment = 0)
  {
   string rate;
   int dir = FindExchangeRate(current, account, rate);
   if(dir == +1)
     {
      margin *= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_BID : SYMBOL_ASK) :
                GetHistoricPrice(rate, moment, ask);
     }
   else
      if(dir == -1)
        {
         margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
        }
      else
        {
         static bool once = false;
         if(!once)
           {
            Print("Can't convert ", current, " -> ", account);
            once = true;
           }
        }
   return true;
  }

Es imposible dividir por cero, ¿no?


Además, este método debería devolver el margen, pero devuelve el precio. Entiendo que en algún sitio este precio debería multiplicarse por el tamaño del contrato, pero no entiendo dónde hacerlo correctamente.

¿Debo añadirlo en esta función o desde dónde llamamos a esta función?

 
Aleksandr Slavskii #:

¿Puede decirme si se trata de un error o si me estoy perdiendo algo?

Archivo MarginProfitMeter.mqh

Es imposible dividir por cero, ¿no?

Efectivamente, no se puede.

margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);

Hay un operador ternario después del símbolo de división con la asignación "/=". Así que si momet==0, entonces:

margin /= SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID)

si no:

margin /= GetHistoricPrice(rate, moment, ask)

Pero aún así añadiría una comprobación de cero de ambas funciones....


Además, este método debería devolver margen, pero devuelve precio. Entiendo que en algún sitio este precio debería multiplicarse por el tamaño del contrato, pero no entiendo dónde hacerlo más correctamente....

A juzgar por la descripción

// Convierte la cantidad de dinero "actual" en dinero "de la cuenta".

el método convierte el dinero (divisa) actual en dinero (divisa) del depósito. Y a juzgar por el código, el método convierte el margen en la moneda del depósito.

Si tiene éxito, el método devolverá true. Y también calculará la nueva cantidad corregida de margen, almacenándola en la variable margen. Es un parámetro en el enlace:

double &margin

Para que puedas obtenerlo como resultado del cálculo.

 
Denis Kirichenko #:

Realmente no puedes.

Hay un operador ternario después del símbolo de división con asignación "/=". Así que si momet==0, entonces:

Sí. Así es, un operador ternario. Estoy cansado esta mañana, me estoy volviendo tonto.


Denis Kirichenko #:

A juzgar por la descripción

el método convierte dinero corriente (moneda) en dinero de depósito (moneda). Y a juzgar por el código, el método convierte el margen en la moneda del depósito.

No, ahora también es correcto.


Pido disculpas, cometí un pequeño error en el código.


De todas formas sirve de poco, porque al final sigue contando mal el margen si el volumen es superior a tres.

EURUSD; margin = 24668.8  //  OrderCalcMargin()
EURUSD; margin = 10889.599999999999 // MarginProfitMeter.mqh 

Cálculo del margen para diez contratos.

 
Denis Kirichenko #:
margin /= momento == 0? SymbolInfoDouble(rate, ask ? SYMBOL_ASK: SYMBOL_BID): GetHistoricPrice(rate, moment, ask);

Un poco mal. La condición(margen /= momento)==0 y luego el operador ternario...

 
Alexey Viktorov #:

Un poco mal. La condición (margen /= momento)==0 y luego un operador ternario...

De alguna manera no estoy de acuerdo. Intenta cumplir esta condición primero:

double margin = 1.5;
datetime moment = 0;
margin /= moment;

Entonces estás dividiendo erizos en erizos, lo cual es cuestionable en sí mismo.

Y las operaciones de asignación tienen una prioridad muy baja, sólo zpt tiene una prioridad más baja.

El compilador también se enfada:

possible loss of data due to type conversion from 'datetime' to 'double'

Y la lógica de la función es la conversión de márgenes. Por lo que yo entiendo, momento = 0 es ahora, entonces:

margin /= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                GetHistoricPrice(rate, moment, ask);

significa que si es ahora, pedimos el precio actual. Y si es en el pasado, nos referimos a los precios históricos. Y habiendo obtenido el precio deseado, al final dividimos el valor del margen por este precio con la asignación.... y con su lógica, resulta que en el momento = 0, vamos a obtener no la conversión de margen, pero sólo el precio de mercado o el precio del pasado....


En general, sería mejor escribir entre paréntesis para un libro de texto:

margin /= (moment == 0) ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
 
Denis Kirichenko #:

De alguna manera no estoy de acuerdo. Intenta cumplir esa condición primero:

Esto divide entonces a los erizos en erizos, lo que en sí mismo ya es cuestionable.

Y las operaciones de asignación tienen una prioridad muy baja, sólo zpt tiene una prioridad más baja.

Y el compilador también se enfada:

Y la lógica de la función es la conversión de márgenes. Por lo que entiendo, momento = 0 es ahora. Entonces:

significa que si es ahora, pedimos el precio actual. Y si es en el pasado, entonces nos referimos a los precios históricos. Y habiendo obtenido el precio deseado, al final dividimos el valor del margen por este precio con la asignación.... y con su lógica, resulta que con momento = 0, no vamos a obtener no una conversión de margen, pero sólo un precio de mercado o un precio del pasado ...


En general, sería mejor escribir entre paréntesis para un libro de texto:

Convincente. Estoy de acuerdo, no estaba atento. Pero si escribes para un libro de texto y para que sea comprensible incluso para mí, entonces sería mejor así

margin /= ( moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask));