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.
Después de 2 meses de pruebas públicas, anunciamos el lanzamiento oficial de la versión web de la plataforma multimercado MetaTrader 5. Ella le permite negociar en los mercados financieros a través de cualquier navegador en cualquier sistema operativo. Y para ello, no es necesario instalar ningún software adicional, de hecho, basta con tener acceso a internet o cualquier navegador web.
La aplicación combina las ventajas clave de la plataforma de escritorio (velocidad, faceta multimercado y características comerciales mejoradas) con la comodidad y el carácter multiplataforma. La principal novedad de la versión actualizada es la profundidad de mercado, así como la colocación con un clic de ordenes de mercado y pendientes.
La plataforma web le permite realizar análisis técnico y realizar
negociaciones de la misma forma como en la versión de escritorio. En la
aplicación, usted tiene a su disposición:
Transferir los certificados SSL desde la plataforma de escritorio a la plataforma móvil ahora es muy cómodo. Ya no será necesario usar iTunes.
En MetaTrader 5 es posible proteger las cuentas de forma adicional con un certificado sin el cual no es posible conectarse. Si el certificado ha sido creado en la versión de escritorio, entonces para acceder a la cuenta en la plataforma móvil, será imprescindible transferirlo.
Para ello, ahora bastará con abrir la plataforma de escritorio y, pulsando el botón derecho en la cuenta en el navegador, elegir la transferencia. Después tendrá que indicar la contraseña de protección del certificado, que solo conocerá usted, y luego abrir la plataforma móvil y conectarse a la cuenta. Al instante se le propondrá importar el certificado.
Aparte de esto, ha aparecido un diálogo de migración para las cuentas trasladadas desde MetaTrader 4. Si han trasladado su cuenta a la plataforma de 5 generación, será calurosamente bienvenido, le contarán todas las novedades y le propondrán cambiar la contraseña.
Era |
Ahora es |
|
---|---|---|
Activación | Todos los tipos de órdenes y SL/TP según Bid/Ask |
Órdenes límite según Bid/Ask Órdenes stop, stop-limit y SL/TP según Last |
Ejecución | Todos los tipos de órdenes pendientes y SL/TP al precio indicado en la orden |
Todos los tipos de órdenes pendientes y SL/TP según los precios de mercado Bid/Ask en el momento de la activación |
Veamos un ejemplo con el instrumento Si-6.16. Con los precios
actuales Bid=72570, Ask=72572, Last=72552 se ha colocado una orden Buy
Stop con un precio de activación de 72580. En el flujo de precios hemos
obtenido los nuevos precios actuales:
En los instrumentos bursátiles, el precio Last es el que activa
las órdenes stop. Por eso, la llegada del precio Last=72580 en el flujo
ha provocado la activación de la orden Buy Stop. Antes, precisamente
este precio 72580 se utilizaba para la ejecución de esta orden. Este
comportamiento era incorrecto, puesto que el precio Ask=72580 para la
ejecución de una operación de compra en el mercado no existe.
En respuesta a las numerosas peticiones de los tráders, se ha desarrollado una versión web de la plataforma MetaTrader 5. El nuevo producto combina la comodidad y el carácter multiplataforma con las ventajas de la quinta versión para PC, es decir: velocidad, faceta multimercado y características comerciales mejoradas.
La plataforma web MetaTrader 5 ya está disponible en el sitio de la MQL5.community. Esta le permite negociar en los mercados financieros a través de cualquier navegador en cualquier sistema operativo (Windows, Mac, Linux). Y para ello, no es necesario instalar ningún software adicional, de hecho, basta con tener acceso a internet.
En la versión beta, los tráders tienen de inmediato a su disposición:
Sistema de compensación
Este sistema presupone que en un momento concreto, en la cuenta puede haber solo una posición abierta del mismo símbolo:
Más abajo mostramos un ejemplo de ejecución de dos operaciones de compra de EURUSD con un volumen de 0.5 cada una de ellas:s each:
Como resultado de la ejecución de estas operaciones, tenemos una posición general con un volumen de 1 lote.
Sistema de cobertura
Este sistema de registro de la posición permite tener multitud de
posiciones comerciales de un mismo instrumento, incluso en direcciones
diferentes.
Si hay una posición abierta de un instrumento
comercial y el tráder efectúa una nueva operación (o se activa una orden
pendiente), se abre una nueva posición. La posición existente no
cambia.
Más abajo mostramos un ejemplo de ejecución de dos operaciones de compra de EURUSD con un volumen de 0.5 cada una de ellas:
Como resultado de la ejecución de estas operaciones, tenemos la apertura de dos posiciones diferentes.
Nuevo tipo de operación comercial Close By
Para las cuentas con cobertura de registro de posiciones se ha añadido
un nuevo tipo de operaciones comerciales: el cierre de una posición con
una opuesta. Esta operación permite cerrar simultáneamente dos
posiciones en direcciones opuestas de un mismo instrumento. Si las
posiciones opuestas tienen una cantidad diferente de lotes, entonces
quedará abierta solo una orden de las dos. Su volumen será igual a la
diferencia de lotes de las dos posiciones cerradas, y la dirección de la
posición y el precio de apertura serán como en la mayor (en volumen) de
las posiciones cerradas.
En comparación con el cierre individual de dos posiciones, el cierre por orden opuesta permite al tráder ahorrarse un spread:
Al cerrar la posición con otra opuesta se establece una orden del tipo "close by". En el comentario a la misma se indican los tickets de las posiciones cerradas. El cierre de una pareja de posiciones opuestas tiene lugar mediante dos operaciones del tipo "out by". La magnitud del beneficio/pérdida total obtenido como resultado del cierre de ambas posiciones, se indica solo en una de las operaciones.
class CAnimal { public: CAnimal(); // constructor virtual void Sound() = 0; // función virtual pura private: double m_legs_count; // número de patas del animal };Aquí la función Sound() es virtual pura, por eso se la declara con el especificador de función virtual pura PURE (=0).
class CAnimal { public: virtual void Sound()=NULL; // PURE method, debe ser redefinido en la clase derivada, la propia clase CAnimal se ha convertido en abstracta y no puede ser creada }; //--- derivada de la clase abstracta class CCat : public CAnimal { public: virtual void Sound() { Print("Myau"); } // PURE es redefinido, la clase CCat no es abstracta y puede ser creada }; //--- ejemplos de uso incorrecto new CAnimal; // error 'CAnimal' - el compilador retorna el error "cannot instantiate abstract class" CAnimal some_animal; // error 'CAnimal' - el compilador retorna el error "cannot instantiate abstract class" //--- ejemplos de uso correcto new CCat; // no hay error, la clase CCat no es abstracta CCat cat; // no hay error, la clase CCat no es abstractaLimitaciones de uso de las clases abstractas
//+------------------------------------------------------------------+ //| Clase básica abstracta | //+------------------------------------------------------------------+ class CAnimal { public: //--- función virtual pura virtual void Sound(void)=NULL; //--- función void CallSound(void) { Sound(); } //--- constructor CAnimal() { //--- invocación directa del método virtual Sound(); //--- invocación indirecta (a través de una tercera función) CallSound(); //--- en el constructor y/o destructor siempre se invocan sus propias funciones, //--- a pesar del carácter virtual y de la redefinición de la función invocada en la derivada //--- si la función invocada es virtual pura, entonces //--- la invocación provocará el error de ejecución crítico: "pure virtual function call" } };Sin embargo, los constructores y destructores de las clases abstractas pueden invocar otras funciones miembro.
typedef int (*TFunc)(int,int);Ahora TFunc es un tipo y se puede declarar la variable-índice a una función:
TFunc func_ptr;En la variable func_ptr se puede guardar la dirección de una función para invocarla más tarde:
int sub(int x,int y) { return(x-y); } int add(int x,int y) { return(x+y); } int neg(int x) { return(~x); } func_ptr=sub; Print(func_ptr(10,5)); func_ptr=add; Print(func_ptr(10,5)); func_ptr=neg; // error: neg no tiene el tipo int (int,int) Print(func_ptr(10)); // error: tiene que haber dos parámetrosLos índices a una función se pueden guardar y transmitir como parámetros. No es posible recibir un índice a un método de clase no estático.
ulong PositionGetTicket( int index // número en la lista de posiciones );
bool PositionSelectByTicket(
ulong ticket // ticket de la posición
);
Sistema de compensación
Este sistema presupone que en un momento concreto, en la cuenta puede haber
solo una posición abierta del mismo símbolo:
En este caso, no tiene importancia como resultado de qué acción se realiza
la operación en la dirección opuesta, si como fruto de la ejecución de
una orden de mercado o debido a la activación de una orden pendiente.
Más abajo mostramos un ejemplo de ejecución de dos operaciones de compra
de EURUSD con un volumen de 0.5 cada una de ellas:
Como resultado de la ejecución de estas operaciones, tenemos una posición
general con un volumen de 1 lote.
Sistema de cobertura
Este sistema de registro de la posición permite tener multitud de posiciones
comerciales de un mismo instrumento, incluso en direcciones diferentes.
Si hay una posición abierta de un instrumento comercial y el tráder efectúa
una nueva operación (o se activa una orden pendiente), se abre una nueva
posición. La posición existente no cambia.
Más abajo mostramos un ejemplo de ejecución de dos operaciones de compra
de EURUSD con un volumen de 0.5 cada una de ellas:
Como resultado de la ejecución de estas operaciones, tenemos la apertura
de dos posiciones diferentes.
Nuevo tipo de operación comercial Close By
Para las cuentas con cobertura de registro de posiciones se ha añadido
un nuevo tipo de operaciones comerciales: el cierre de una posición con
una opuesta. Esta operación permite cerrar simultáneamente dos posiciones
en direcciones opuestas de un mismo instrumento. Si las posiciones opuestas
tienen una cantidad diferente de lotes, entonces quedará abierta solo una
orden de las dos. Su volumen será igual a la diferencia de lotes de las
dos posiciones cerradas, y la dirección de la posición y el precio de apertura
serán como en la mayor (en volumen) de las posiciones cerradas.
En comparación con el cierre individual de dos posiciones, el cierre por
orden opuesta permite al tráder ahorrarse un spread:
Al cerrar la posición con otra opuesta se establece una orden del tipo "close by". En el comentario a la misma se indican los tickets de las posiciones cerradas. El cierre de una pareja de posiciones opuestas tiene lugar mediante dos operaciones del tipo "out by". La magnitud del beneficio/pérdida total obtenido como resultado del cierre de ambas posiciones, se indica solo en una de las operaciones.
class CAnimal { public: CAnimal(); // constructor virtual void Sound() = 0; // función virtual pura private: double m_legs_count; // número de patas del animal };Aquí la función Sound() es virtual pura, por eso se la declara con el especificador de función virtual pura PURE (=0).
class CAnimal { public: virtual void Sound()=NULL; // PURE method, debe ser redefinido en la clase derivada, la propia clase CAnimal se ha convertido en abstracta y no puede ser creada }; //--- derivada de la clase abstracta class CCat : public CAnimal { public: virtual void Sound() { Print("Myau"); } // PURE es redefinido, la clase CCat no es abstracta y puede ser creada }; //--- ejemplos de uso incorrecto new CAnimal; // error 'CAnimal' - el compilador retorna el error "cannot instantiate abstract class" CAnimal some_animal; // error 'CAnimal' - el compilador retorna el error "cannot instantiate abstract class" //--- ejemplos de uso correcto new CCat; // no hay error, la clase CCat no es abstracta CCat cat; // no hay error, la clase CCat no es abstractaLimitaciones de uso de las clases abstractas
//+------------------------------------------------------------------+ //| Clase básica abstracta | //+------------------------------------------------------------------+ class CAnimal { public: //--- función virtual pura virtual void Sound(void)=NULL; //--- función void CallSound(void) { Sound(); } //--- constructor CAnimal() { //--- invocación directa del método virtual Sound(); //--- invocación indirecta (a través de una tercera función) CallSound(); //--- en el constructor y/o destructor siempre se invocan sus propias funciones, //--- a pesar del carácter virtual y de la redefinición de la función invocada en la derivada //--- si la función invocada es virtual pura, entonces //--- la invocación provocará el error de ejecución crítico: "pure virtual function call" } };Sin embargo, los constructores y destructores de las clases abstractas pueden invocar otras funciones miembro.
typedef int (*TFunc)(int,int);Ahora TFunc es un tipo y se puede declarar la variable-índice a una función:
TFunc func_ptr;En la variable func_ptr se puede guardar la dirección de una función para invocarla más tarde:
int sub(int x,int y) { return(x-y); } int add(int x,int y) { return(x+y); } int neg(int x) { return(~x); } func_ptr=sub; Print(func_ptr(10,5)); func_ptr=add; Print(func_ptr(10,5)); func_ptr=neg; // error: neg no tiene el tipo int (int,int) Print(func_ptr(10)); // error: tiene que haber dos parámetrosLos índices a una función se pueden guardar y transmitir como parámetros. No es posible recibir un índice a un método de clase no estático.
ulong PositionGetTicket( int index // número en la lista de posiciones );
bool PositionSelectByTicket(
ulong ticket // ticket de la posición
);
El nuevo sistema es similar al de MetaTrader 4, pero los tráders, además, pueden valerse de todas la ventajas de la quinta versión de la plataforma: ejecución de órdenes usando varias operaciones (incluyendo las parciales), órdenes stop-limit y mucho más.
Será posible probar el comercio con cobertura en cuanto actualice la plataforma. Al abrir una cuenta demo, active la opción "Usar cobertura", que estará disponible si el servidor comercial del bróker ya ha sido actualizado y configurado.
El nuevo sistema es similar al de MetaTrader 4, pero los tráders, además, pueden valerse de todas la ventajas de la quinta versión de la plataforma: ejecución de órdenes usando varias operaciones (incluyendo las parciales), órdenes stop-limit y mucho más.
Será posible probar el comercio con cobertura en cuanto actualice la plataforma. Al abrir una cuenta demo, active la opción "Usar cobertura", que estará disponible si el servidor comercial del bróker ya ha sido actualizado y configurado.