union LongDouble { long long_value; double double_value; };A diferencia de la estructura, los diferentes miembros de una unión se relacionan con una misma zona de la memoria. En este ejemplo se ha declarado la unión LongDouble, en la que el valor del tipo long y el valor del tipo double comparten la misma zona de la memoria. Es importante comprender que no es posible hacer que la unión guarde al mismo tiempo valores de tipo entero long y reales double (como sucedía en la estructura), puesto que las variables long_value y double_value se solapan (en la memoria) una sobre otra. Sin embargo, un programa MQL5 puede en cualquier momento procesar la información que se contiene en esta unión como un valor entero (long) o como uno real (double). Por consiguiente, la unión permite obtener dos (o más) variantes de representación de una misma secuencia de datos.
union LongDouble { long long_value; double double_value; }; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- LongDouble lb; //--- obtenemos el número no válido -nan(ind) y lo mostramos lb.double_value=MathArcsin(2.0); printf("1. double=%f integer=%I64X",lb.double_value,lb.long_value); //--- valor mayor normalizado (DBL_MAX) lb.long_value=0x7FEFFFFFFFFFFFFF; printf("2. double=%.16e integer=%I64X",lb.double_value,lb.long_value); //--- menor positivo normalizado (DBL_MIN) lb.long_value=0x0010000000000000; printf("3. double=%.16e integer=%.16I64X",lb.double_value,lb.long_value); } /* Resultado de la ejecución 1. double=-nan(ind) integer=FFF8000000000000 2. double=1.7976931348623157e+308 integer=7FEFFFFFFFFFFFFF 3. double=2.2250738585072014e-308 integer=0010000000000000 */
class Foo { int value; public: string Description(void){return IntegerToString(value);}; //--- constructor por defecto Foo(void){value=-1;}; //--- constructor con parámetros Foo(int v){value=v;}; }; //+------------------------------------------------------------------+ //| estructura que contiene el objeto del tipo Foo | //+------------------------------------------------------------------+ struct MyStruct { string s; Foo foo; }; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- MyStruct a,b; Foo an_foo(5); a.s="test"; a.foo=an_foo; Print("a.s=",a.s," a.foo.Description()=",a.foo.Description()); Print("b.s=",b.s," b.foo.Description()=",b.foo.Description()); //--- Print("b=a"); b=a; //--- Print("a.s=",a.s," a.foo.Description()=",a.foo.Description()); Print("b.s=",b.s," b.foo.Description()=",b.foo.Description()); /* Resultado de la ejecución; a.s=test a.foo.Description()=5 b.s= b.foo.Description()=-1 b=a a.s=test a.foo.Description()=5 b.s=test b.foo.Description()=5 */ }En el operador implícito se realiza el copiado por miembros de los objetos.
ENUM_POSITION_REASON | ENUM_DEAL_REASON | ENUM_ORDER_REASON | Descripción de las causas |
---|---|---|---|
POSITION_REASON_CLIENT | DEAL_REASON_CLIENT | ORDER_REASON_CLIENT | La operación se ha ejecutado como resultado de la activación de una orden colocada desde el terminal de escritorio |
POSITION_REASON_MOBILE | DEAL_REASON_MOBILE | ORDER_REASON_MOBILE | La operación se ha ejecutado como resultado de una orden colocada desde el terminal móvil |
POSITION_REASON_WEB | DEAL_REASON_WEB | ORDER_REASON_WEB | La operación se ha ejecutado como resultado de la activación de una orden colocada desde la plataforma web |
POSITION_REASON_EXPERT | DEAL_REASON_EXPERT | ORDER_REASON_EXPERT | La operación se ha ejecutado como resultado de la activación de una orden colocada desde un programa MQL5: un asesor o script |
- | DEAL_REASON_SL | ORDER_REASON_SL | La operación se ha ejecutado como resultado de la activación de un Stop Loss |
- | DEAL_REASON_TP | ORDER_REASON_TP | La operación se ha ejecutado como resultado de la activación de un Take Profit |
- | DEAL_REASON_SO | ORDER_REASON_SO | La operación se ha ejecutado como resultado del evento Stop Out |
- | DEAL_REASON_ROLLOVER | - | La transacción se ha ejecutado a causa del traslado de una posición |
- | DEAL_REASON_VMARGIN | - | La transacción se ha ejecutado después de abonarse/retirarse el margen de variación |
- | DEAL_REASON_SPLIT | - | La transacción se ha ejecutado a causa del fraccionamiento (reducción del precio) de una acción u otro activo que tenía una posición abierta en el momento del anuncio del fraccionamiento |
En MetaTrader 5 iOS se ha añadido la posibilidad de abrir rápidamente cuentas preliminares (preliminary) con un bróker. Ahora es suficiente con elegir el punto del menú "Abrir una cuenta real" e indicar su servidor en la lista de servidores. Después de rellenar los datos personales, solo queda adjuntar dos documentos que acrediten su identidad y su dirección, y enviar la solicitud de registro. De esta forma, el bróker podrá abrirle una cuenta real, pidiéndole información adicional en el caso necesario.
En el build 1605 de MetaTrader 5 iOS también se ha optimizado y rediseñado el correo:
Actualización de la documentación.
Se ha añadido a MetaTrader 5 Android la representación de la historia comercial en forma de posiciones. Anteriormente, en la pestaña "Historia" se representaban solo las transacciones y órdenes de la historia, ahora es posible utilizar las posiciones para el análisis comercial. Para ello, todas las transacciones relacionadas con una posición se agrupan en un solo registro, donde se podrá ver:
Añadida la presentación de la historia comercial en forma de posiciones. Anteriormente, en la pestaña "Historia" se exhibían operaciones y órdenes, ahora en esta también se muestran las posiciones. La plataforma comercial reúne los datos de las operaciones relacionadas con una posición, y luego agrupa dichos datos en una única entrada. En esta entrada podrá ver:
//+------------------------------------------------------------------+ //| Función de plantilla | //+------------------------------------------------------------------+ template<typename T1,typename T2> string Assign(T1 &var1,T2 var2) { var1=(T1)var2; return(__FUNCSIG__); } //+------------------------------------------------------------------+ //| Sobrecarga especial para el caso bool+string | //+------------------------------------------------------------------+ string Assign(bool &var1,string var2) { var1=(StringCompare(var2,"true",false) || StringToInteger(var2)!=0); return(__FUNCSIG__); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { int i; bool b; Print(Assign(i,"test")); Print(Assign(b,"test")); }Como resultado de la ejecución de este código, veremos que para la pareja int+string se ha usado la función de plantilla Assign(), y en la segunda llamada bool+string ya se ha usado la función sobrecargada.
string Assign<int,string>(int&,string) string Assign(bool&,string)
template<typename T> T Func() { return (T)0; } void OnInit() { Func<double>(); // especialización explícita de la función de plantilla }De esta forma, la especialización tiene lugar no a través de los parámetros de llamada, sino mediante la indicación directa de los tipos.
Actualización de la documentación.
Actualización de la documentación.
Añadida
la posibilidad de acceder o registrase en MQL5.com a través de
Facebook. Si usted tiene una cuenta en esta red social, ahora con un par
de clicks podrá acceder a los chats y a la gama completa de servicios
para
MetaTrader 5.
#resource ruta_al_archivo_del_recurso as tipo_de_variable_de_recurso nombre_de_la_variable_de_recurso
#resource "data.bin" as int ExtData[] // declaración de matriz de tipo numérico que contiene los datos del archivo data.bin #resource "data.bin" as MqlRates ExtData[] // declaración de matriz de estructuras sencillas que contiene los datos del archivo data.bin #resource "data.txt" as string ExtCode // declaración de línea que contiene los datos del archivo data.txt #resource "data.txt" as string ExtCode[] // declaración de matriz de línea que contiene los datos del archivo data.txt #resource "image.bmp" as bitmap ExtBitmap[] // declaración de matriz unidimensional que contiene el ráster del archivo BMP, tamaño de la matriz = height * width #resource "image.bmp" as bitmap ExtBitmap2[][] // declaración de matriz bidimensional que contiene el ráster del archivo BMP, tamaño de la matriz [height][width]
Actualización de la documentación.
string str; ... if(str) // surgirá el error de compilación "Cannot convert type 'string' to 'bool'" (en los anteriores builds no sucedía así) Print("str is true");Debemos escribir una condición explícita:
string str; ... //--- comprueba si la línea de caracteres ha sido inicializada if(str!=NULL) Print("str is true"); o //--- comprueba si el valor de la línea de caracteres es "true" if(StringCompare(str,"true",false)) Print("str is true"); o //--- comprueba si la línea de caracteres es un número y es distinto de cero if((int)str!=0) Print("str is true");
Correciones de crash logs.
void ArrayPrint( const void& array[], // matriz mostrada uint digits=_Digits, // número de decimales tras la coma const string separator=NULL, // separador entre los valores de los campos de la estructura ulong start=0, // índice del primer elemento mostrado ulong count=WHOLE_ARRAY, // número de elementos mostrados ulong flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN );ArrayPrint no muestra en el diario todos los campos de la matriz de estructuras, los campos-matrices y los campos-punteros de los objetos se omiten. Para mostrar todos los campos de esta estructura será necesaria una función propia de muestra masiva con el fotmato deseado.
//--- muestra los valores de las 10 últimas barras MqlRates rates[]; if(CopyRates(_Symbol,_Period,1,10,rates)) { ArrayPrint(rates); Print("Comprobando\n[time]\t[open]\t[high]\t[low]\t[close]\t[tick_volume]\t[spread]\t[real_volume]"); for(int i=0;i<10;i++) { PrintFormat("[%d]\t%s\t%G\t%G\t%G\t%G\t%G\t%G\t%I64d\t",i, TimeToString(rates[i].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS), rates[i].open,rates[i].high,rates[i].low,rates[i].close, rates[i].tick_volume,rates[i].spread,rates[i].real_volume); } } else PrintFormat("CopyRates failed, error code=%d",GetLastError()); //--- ejemplo de muestra /* [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000 [1] 2016.11.09 05:00:00 1.12296 1.12825 1.11930 1.12747 17829 9 15632176000 [2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000 [3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000 [4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000 [5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000 [6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000 [7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000 [8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000 [9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000 Comprobando [time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume] [0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000 [1] 2016.11.09 05:00:00 1.12296 1.12825 1.1193 1.12747 17829 9 15632176000 [2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000 [3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000 [4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000 [5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000 [6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000 [7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000 [8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000 [9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000 */
void OnStart() { int arr[]; //--- cuánta memoria se ha usado al inicio Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- cuánta memoria se ha usado para la matriz con el tamaño 1, pero con reserva ArrayResize(arr,1,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- tras aumentar la matriz, el tamaño utilizado de la memoria no ha aumentado a cuenta de la reserva ArrayResize(arr,1024*512,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- tras disminuir la matriz, el tamaño de la memoria tampoco cambiará ArrayResize(arr,1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- la memoria no utilizada por la matriz queda libre gracias a la eliminación de la reserva ArrayResize(arr,1,-1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); }
#include <Graphics/Graphic.mqh> double Func1(double x) { return MathPow(x,2); } double Func2(double x) { return MathPow(x,3); } double Func3(double x) { return MathPow(x,4); } void OnStart() { GraphPlot(Func1,Func2,Func3,-2,2,0.05,CURVE_LINES); }Resultado:
#include <Math/Stat/Binomial.mqh> #include <Graphics/Graphic.mqh> void OnStart(void) { double vars[101]; double results[101]; const int N=2000; //--- MathSequence(0,N,20,vars); MathProbabilityDensityBinomial(vars,N,M_PI/10,true,results); ArrayPrint(results,4); GraphPlot(results); //--- }Resultado:
Documentación actualizada.
Añadidas descripciones emergentes para los botones Buy, Sell y Close en los cuadros de diálogo comerciales. Las descripciones aclararán qué activos precisamente se comprarán o venderán al realizar esta o aquella operación, ayudando así a los tráders principiantes a comprender la esencia del proceso comercial.
Asimismo, se ha incluido en la biblioteca una versión MQL5 de la biblioteca de análisis numérico ALGLIB.
Posibilidades de la biblioteca
Cómo usarlo
los archivos de la biblioteca ALGLIB se ubican en el catálogo \MQL5\Include\Math\Alglib. Para usar las funciones, incluya el archivo principal de la biblioteca en su programa:
En la biblioteca estándar se han incluido funciones para trabajar con estadística matemática. Ahora en MQL5 están disponibles las posibilidades del lenguaje R, uno de las mejores herramientas de procesamiento y análisis estadístico de datos.
Posibilidades de la biblioteca
La biblioteca estadística contiene funciones para el cálculo de las características estadísticas de los datos, así como funciones para trabajar con distribuciones estadísticas:
Cómo usarlo
los archivos de la biblioteca estadística se ubican en el catálogo \MQL5\Include\Math\Stat. Para usarla, incluya el archivo con las funciones necesarias en su programa, por ejemplo:
#include <Math\Stat\Binomal.mqh> #include <Math\Stat\Cauchy.mqh>
Puede leer una descripción detallada de las funciones de la biblioteca en el artículo Distribuciones Estadísticas en MQL5: tomando lo mejor de R.
Se ha incluido en la biblioteca estándar una versión MQL5 de la biblioteca Fuzzy, en la que se han implementado los sistemas de inferencia de lógica difusa Mamdani y Sugeno.
Posibilidades de la biblioteca
Cómo usarlo
Los archivos de la biblioteca Fuzzy se encuentran en el catálogo \MQL5\Include\Math\Fuzzy. Para usarla, incluya el archivo con las funciones necesarias en su programa, por ejemplo:
#include <Math\Fuzzy\mamdanifuzzysystem.mqh> #include <Math\Fuzzy\sugenofuzzysystem.mqh>
Podrá encontrar una descripción detallada de la biblioteca en Code Base: Fuzzy - biblioteca para trabajar con lógica difusa
long FileLoad( const string filename, // [in] nombre del archivo void &buffer[], // [out] matriz para la lectura uint common_flag=0 // [in] 0 - búsqueda de un archivo en la carpeta Files del terminal, FILE_COMMON - en la carpeta común de los terminales ); bool FileSave( const string filename, // [in] nombre del archivo const void &buffer[], // [in] matriz para el almacenamiento uint common_flag=0 // [in] 0 - creación de un archivo en la carpeta Files del terminal, FILE_COMMON - en la carpeta común de los terminales );Ejemplo de cómo grabar una matriz de ticks y leerla enseguida:
//--- parámetros de entrada input int ticks_to_save=1000; // número de ticks //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { string filename=_Symbol+"_ticks.bin"; MqlTick ticks[]; //--- int copied=CopyTicks(_Symbol,ticks,COPY_TICKS_ALL,0,ticks_to_save); if(copied!=-1) { PrintFormat(" CopyTicks(%s) copied %d ticks",_Symbol,copied); //--- si la historia de ticks está sicronizada, el código de error será igual a cero if(!GetLastError()==0) PrintFormat("%s: Ticks are not synchronized. Error=",_Symbol,copied,_LastError); //--- escribimos los ticks en el archivo if(!FileSave(filename,ticks,FILE_COMMON)) PrintFormat("FileSave() failed, error=%d",GetLastError()); } else PrintFormat("Failed CopyTicks(%s), Error=",_Symbol,GetLastError()); //--- ahora leemos estos ticks de vuelta desde el archivo ArrayFree(ticks); long count=FileLoad(filename,ticks,FILE_COMMON); if(count!=-1) { Print("Time\tBid\tAsk\tLast\tVolume\tms\tflags"); for(int i=0;i<count;i++) { PrintFormat("%s.%03I64u:\t%G\t%G\t%G\t%I64u\t0x%04x", TimeToString(ticks[i].time,TIME_DATE|TIME_SECONDS),ticks[i].time_msc%1000, ticks[i].bid,ticks[i].ask,ticks[i].last,ticks[i].volume,ticks[i].flags); } } }
//--- velas iguales, pintadas de un mismo color #property indicator_label1 "One color candles" #property indicator_type1 DRAW_CANDLES //--- solo se indica un color, por eso todas las velas serán solo de un color #property indicator_color1 clrGreenSi indicamos dos colores, los contornos se dibujarán con el primer color, y el cuerpo con el segundo.
//--- el color de las velas se diferencia del color de las sombras #property indicator_label1 "Two color candles" #property indicator_type1 DRAW_CANDLES //--- las sombras y el contorno de las velas en color verde, el cuerpo, en color blanco #property indicator_color1 clrGreen,clrWhiteSi se indican tres colores, el contorno de la vela se dibujará con el primer color, y el color de la vela alcista y bajista se establecerá con el segundo y el tercer color.
//--- el color de las velas se diferencia del color de las sombras #property indicator_label1 "One color candles" #property indicator_type1 DRAW_CANDLES //--- las sombras y el contorno de las velas en color verde, el cuerpo de la vela alcista, en color blanco, el cuerpo de la vela bajista, de color rojo #property indicator_color1 clrGreen,clrWhite,clrRedDe esta forma, con la ayuda del estilo DRAW_CANDLES se pueden crear variantes personalizadas propias del color de las velas. Asimismo, todos los colores pueden cambiarse de forma dinámica durante el proceso del trabajo con la ayuda de la función PlotIndexSetInteger(índice_de_la_construcción_DRAW_CANDLES, PLOT_LINE_COLOR, número_del_modificador, color) , donde el número_del_modificador puede tener los valores siguientes:
//--- establecemos el color del contorno y las sombras PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrBlue); //--- establecemos el color del cuerpo para la vela alcista PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrGreen); //--- establecemos el color del cuerpo para la vela bajista PlotIndexSetInteger(0,PLOT_LINE_COLOR,2,clrRed);
Se ha actualizado la documentación.
class CFoo final { //--- cuerpo de la clase }; class CBar : public CFoo { //--- cuerpo de la clase };Al intentar heredar de una clase con el modificador final, como se muestra en el ejemplo de más arriba, el compilador dará error:
class CFoo { void virtual func(int x) const { } };A continuación, el método se redefine en la clase heredada:
class CBar : public CFoo { void func(short x) { } };Pero por error, el tipo de argumento cambia de int a short. De hecho, en este caso ya tiene lugar no la redefinición, sino la sobrecarga del método. Actuando de acuerdo con el algoritmo de definición de la función sobrecargada, en ciertas situaciones el compilador puede elegir el método definido en la clase básica, en lugar del método redefinido.
class CBar : public CFoo { void func(short x) override { } };Si durante la redefinición se cambia la signatura del método, el compilador no podrá encontrar en la clase padre un método con la misma signatura y dará un error de compilación:
class CFoo { void virtual func(int x) final { } }; class CBar : public CFoo { void func(int) { } };Al intentar redefinir un método con el modificador final, como se muestra en el ejemplo de más arriba, el compilador dará error:
Se ha actualizado la documentación.
class CFoo { }; class CBar { }; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { void *vptr[2]; vptr[0]=new CFoo(); vptr[1]=new CBar(); //--- for(int i=0;i<ArraySize(vptr);i++) { if(dynamic_cast<CFoo *>(vptr[i])!=NULL) Print("CFoo * object at index ",i); if(dynamic_cast<CBar *>(vptr[i])!=NULL) Print("CBar * object at index ",i); } CFoo *fptr=vptr[1]; // dará error de transformación de los punteros, vptr[1] no es un objeto de CFoo } //+------------------------------------------------------------------+
string text="Hello"; ushort symb=text[0]; // retornará el código del símbolo 'H'
Se ha actualizado la documentación.