Terminal
MQL5
//--- el primer parámetro handle se ignora al obtener el código del últimoo error
int code = (int)CLGetInfoInteger(0,CL_LAST_ERROR);
//--- obtener código del último error de OpenCL
int code = (int)CLGetInfoInteger(0,CL_LAST_ERROR);
string desc; // para obtener la descripción de texto del error
//--- utilizamos el código de error para obtener la descripción de texto del error
if(!CLGetInfoString(code,CL_ERROR_DESCRIPTION,desc))
desc = "cannot get OpenCL error description, " + (string)GetLastError();
Print(desc);
//--- para obtener la descripción del último error de OpenCL sin obtención previa del código, deberemos transmitir CL_LAST_ERROR
if(!CLGetInfoString(CL_LAST_ERROR,CL_ERROR_DESCRIPTION, desc))
desc = "cannot get OpenCL error description, " + (string)GetLastError();
Print(desc);
Por
ahora, como descripción del error, se ofrece el nombre de la
enumeración interna cuyo desciframiento puede verse en la página https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#CL_SUCCESS.
Por ejemplo, si obtenemos CL_INVALID_KERNEL_ARGS, la descripción para
ello será "Returned when enqueuing a kernel when some kernel arguments
have not been set or are invalid". MetaTrader 5 WebTerminal
Terminal
MQL5
class A { }; void OnStart(void) { const A *const arr[][2][3]={}; Print(typename(arr)); }Resultado:
"clase A const * const [][2][3]"
Terminal
MQL5
Correcciones de crash logs.
MetaTrader 5 WebTerminal build 3500
Versión móvil del terminal web
En la nueva versión del terminal web se ha añadido el soporte completo para dispositivos móviles. Ahora la interfaz se adapta automáticamente al tamaño de la pantalla, lo cual permite a los usuarios trabajar cómodamente en la plataforma tanto en teléfonos como tabletas con iOS y Android:
Además, hemos introducido en el terminal web numerosas correcciones y mejoras.
El nuevo terminal web MetaTrader 5 ofrece todas las funciones que necesita un tráder moderno. La aplicación le permitirá:
Terminal
MQL5
bool matrix::CopyTicks(string symbol,uint flags,ulong from_msc,uint count);
bool vector::CopyTicks(string symbol,uint flags,ulong from_msc,uint count);
bool matrix::CopyTicksRange(string symbol,uint flags,ulong from_msc,ulong to_msc);
bool matrix::CopyTicksRange(string symbol,uint flags,ulong from_msc,ulong to_msc);
El
tipo de datos a copiar se indica en el parámetro rates_mask con la
ayuda de la enumeración ENUM_COPY_RATES. Están disponibles los valores
siguientes:COPY_TICKS_INFO = 1, // ticks llamados por los cambios de Bid y/o Ask
COPY_TICKS_TRADE = 2, // ticks llamados por los cambios de Last y Volume
COPY_TICKS_ALL = 3, // todos los ticks en en los que hay cambios
COPY_TICKS_TIME_MS = 1<<8, // tiempo en milisegundos
COPY_TICKS_BID = 1<<9, // precio Bid
COPY_TICKS_ASK = 1<<10, // precio Ask
COPY_TICKS_LAST = 1<<11, // precio Last
COPY_TICKS_VOLUME = 1<<12, // volumen
COPY_TICKS_FLAGS = 1<<13, // banderas de tick
Al
seleccionar varios tipos de datos (solo disponible para matrices), el
orden de las filas de la matriz se corresponderá con el orden de los
valores de la enumeración.bool matrix::Assign(const vector &vec);
Obtendremos como resultado una matriz de una línea.bool vector::Assign(const matrix &mat);
bool vector::Swap(vector &vec);
bool vector::Swap(matrix &vec);
bool vector::Swap(double &arr[]);
bool matrix::Swap(vector &vec);
bool matrix::Swap(matrix &vec);
bool matrix::Swap(double &arr[]);
Cada
array, vector o matriz se refiere a un búfer de memoria que contiene
elementos de ese objeto. El método Swap realmente intercambia los
punteros a estos búferes sin escribir los elementos en la memoria. Así
que una matriz sigue siendo una matriz, y un vector un vector. Al
intercambiar una matriz y un vector se obtiene una matriz de una línea
con elementos vectoriales y un vector con elementos matriciales en
representación plana (puede consultar el método Flat).//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
matrix a= {{1, 2, 3}, {4, 5, 6}};
Print("a before Swap: \n", a);
matrix b= {{5, 10, 15, 20}, {25, 30, 35, 40}, {45, 50, 55, 60}};
Print("b before Swap: \n", b);
//--- intercambiamos de sitio los punteros por las matrices
a.Swap(b);
Print("a after Swap: \n", a);
Print("b after Swap: \n", b);
/*
a before Swap:
[[1,2,3]
[4,5,6]]
b before Swap:
[[5,10,15,20]
[25,30,35,40]
[45,50,55,60]]
a after Swap:
[[5,10,15,20]
[25,30,35,40]
[45,50,55,60]]
b after Swap:
[[1,2,3]
[4,5,6]]
*/
vector v=vector::Full(10, 7);
Print("v before Swap: \n", v);
Print("b before Swap: \n", b);
v.Swap(b);
Print("v after Swap: \n", v);
Print("b after Swap: \n", b);
/*
v before Swap:
[7,7,7,7,7,7,7,7,7,7]
b before Swap:
[[1,2,3]
[4,5,6]]
v after Swap:
[1,2,3,4,5,6]
b after Swap:
[[7,7,7,7,7,7,7,7,7,7]]
*/
}
El
método Swap también permite trabajar con arrays dinámicos (no se puede
transmitir un array de tamaño fijo como parámetro). En este caso, el
array puede ser de cualquier dimensión, pero de un tamaño consistente.
Esto significa que el tamaño total de la matriz o del vector deberá ser
un múltiplo de la dimensionalidad cero de un array. La dimensionalidad
cero de un array es el número de elementos que contiene el primer índice
del array. Por ejemplo, para un array dinámico tridimensional double
array[][2][3], la dimensionalidad cero será el producto de los tamaños
de la segunda y tercera dimensión, es decir, 2x3=6. Por lo tanto, un
array de este tipo solo podrá utilizarse en un método Swap con matrices y
vectores cuyo tamaño total sea un múltiplo de 6: 6, 12, 18, 24, etc.//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- rellenamos la matriz 1x10 con el valor 7.0
matrix m= matrix::Full(1, 10, 7.0);
Print("matrix before Swap:\n", m);
//--- intentamos realizar el intercambio entre la matriz y el array
double array_small[2][5]= {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
Print("array_small before Swap:");
ArrayPrint(array_small);
if(m.Swap(array_small))
{
Print("array_small after Swap:");
ArrayPrint(array_small);
Print("matrix after Swap: \n", m);
}
else // el tamaño de la matriz no es múltiplo del tamaño de la primera dimensión del array
{
Print("m.Swap(array_small) failed. Error ", GetLastError());
}
/*
matrix before Swap:
[[7,7,7,7,7,7,7,7,7,7]]
array_small before Swap:
[,0] [,1] [,2] [,3] [,4]
[0,] 1.00000 2.00000 3.00000 4.00000 5.00000
[1,] 6.00000 7.00000 8.00000 9.00000 10.00000
m.Swap(array_small) failed. Error 4006
*/
//--- tomamos una matriz mayor e intentamos realizar el intercambio de nuevo
double array_static[3][10]= {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{2, 4, 6, 8, 10, 12, 14, 16, 18, 20},
{3, 6, 9, 12, 15, 18, 21, 24, 27, 30}
};
Print("array_static before Swap:");
ArrayPrint(array_static);
if(m.Swap(array_static))
{
Print("array_static after Swap:");
ArrayPrint(array_static);
Print("matrix after Swap: \n", m);
}
else // no se puede utilizar un array dinámico para el intercambio con una matriz
{
Print("m.Swap(array_static) failed. Error ", GetLastError());
}
/*
array_static before Swap:
[,0] [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[0,] 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000 10.00000
[1,] 2.00000 4.00000 6.00000 8.00000 10.00000 12.00000 14.00000 16.00000 18.00000 20.00000
[2,] 3.00000 6.00000 9.00000 12.00000 15.00000 18.00000 21.00000 24.00000 27.00000 30.00000
m.Swap(array_static) failed. Error 4006
*/
//--- un nuevo intento de de intercambiar el array y la matriz
double array_dynamic[][10]; // array dinámico
ArrayResize(array_dynamic, 3); // indicamos el tamaño de la primera dimensión
ArrayCopy(array_dynamic, array_static);
//--- ahora utilizaremos un array dinámico para el intercambio
if(m.Swap(array_dynamic))
{
Print("array_dynamic after Swap:");
ArrayPrint(array_dynamic);
Print("matrix after Swap: \n", m);
}
else // no hay error
{
Print("m.Swap(array_dynamic) failed. Error ", GetLastError());
}
/*
array_dynamic after Swap:
[,0] [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[0,] 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000
matrix after Swap:
[[1,2,3,4,5,6,7,8,9,10,2,4,6,8,10,12,14,16,18,20,3,6,9,12,15,18,21,24,27,30]]
*/
}
vector vector::LossGradient(const vector &expected,ENUM_LOSS_FUNCTION loss) const;
matrix matrix::LossGradient(const matrix &expected,ENUM_LOSS_FUNCTION loss) const;
CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER,
FOREIGN KEY(trackartist) REFERENCES artist(artistid)
);
MetaEditor
MetaTester
Terminal
MQL5
bool vector<TDst>::Assign(const vector<TSrc> &assign); bool matrix<TDst>::Assign(const matrix<TSrc> &assign);Ejemplo:
//--- copying matrices matrix b={}; matrix a=b; a.Assign(b); //--- copying an array to a matrix double arr[5][5]={{1,2},{3,4},{5,6}}; Print("array arr"); ArrayPrint(arr); b.Assign(arr); Print("matrix b \n",b); /* array arr [,0] [,1] [,2] [,3] [,4] [0,] 1.00000 2.00000 0.00000 0.00000 0.00000 [1,] 3.00000 4.00000 0.00000 0.00000 0.00000 [2,] 5.00000 6.00000 0.00000 0.00000 0.00000 [3,] 0.00000 0.00000 0.00000 0.00000 0.00000 [4,] 0.00000 0.00000 0.00000 0.00000 0.00000 matrix b [[1,2,0,0,0] [3,4,0,0,0] [5,6,0,0,0] [0,0,0,0,0] [0,0,0,0,0]] */
bool matrix::CopyRates(string symbol,ENUM_TIMEFRAMES period,ulong rates_mask,ulong from,ulong count); bool vector::CopyRates(string symbol,ENUM_TIMEFRAMES period,ulong rates_mask,ulong from,ulong count);El tipo de datos a copiar se indica en el parámetro rates_mask usando la enumeración ENUM_COPY_RATES. Están disponibles los siguientes valores:
Corregido el error de cambio de un parámetro constante transmitido a una función como referencia a un puntero de objeto.
Recordemos que el especificador const declara una variable como constante y no permite cambiar el valor de esa variable en la ejecución del programa. Solo permite la inicialización única de la variable al realizarse su declaración. Ejemplo de constantes en la función OnCalculate:
int OnCalculate (const int rates_total, // price[] array size const int prev_calculated, // bars processed on previous call const int begin, // meaningful data starts at const double& price[] // array for calculation );
Sin embargo, en el ejemplo siguiente, se encontró un error del
compilador que permitía la conversión implícita de punteros para los
parámetros de referencia:
class A {}; const A *a = new A; void foo( const A*& b ) { b = a; } void OnStart() { A *b; foo(b); // no permitido Print( a,":",b ); }Esta operación no válida será ahora detectada por el compilador y generará un error.
MetaEditor
Nuevo terminal web de MetaTrader 5
Le
presentamos el nuevo terminal web para MetaTrader 5. Lo hemos hecho más
moderno y rápido, no solo actualizando su aspecto, sino también
reescribiendo completamente el núcleo. En cuanto a su interfaz, el
terminal web ahora se parece a la ya conocida versión de la plataforma
para iPad:
En comparación con la versión anterior, tiene multitud de características nuevas:
Pruebe ahora el nuevo terminal web en www.mql5.com. Sus brókeres lo tendrán pronto a su disposición.
Terminal
MQL5
//--- matrix a= {{1, 4}, {9, 16}}; Print("matrix a=\n",a); a=MathSqrt(a); Print("MatrSqrt(a)=\n",a); /* matrix a= [[1,4] [9,16]] MatrSqrt(a)= [[1,2] [3,4]] */En el caso de MathMod y MathPow, el segundo parámetro podrá ser un escalar, o una matriz o vector del tamaño correspondiente.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- используем инициализирующую функцию для заполнения вектора vector r(10, ArrayRandom); // массив случайных чисел от 0 до 1 //--- вычислим среднее значение double avr=r.Mean(); // среднее значение массива vector d=r-avr; // вычислим массив отклонений от среднего значения Print("avr(r)=", avr); Print("r=", r); Print("d=", d); vector s2=MathPow(d, 2); // массив квадратов отклонений double sum=s2.Sum(); // сумма квадратов отклонений //--- вычислим стандартное отклонение 2-мя способами double std=MathSqrt(sum/r.Size()); Print(" std(r)=", std); Print("r.Std()=", r.Std()); } /* avr(r)=0.5300302133243813 r=[0.8346201971495713,0.8031556138798182,0.6696676534318063,0.05386516922513505,0.5491195410016175,0.8224433118686484,... d=[0.30458998382519,0.2731254005554369,0.1396374401074251,-0.4761650440992462,0.01908932767723626,0.2924130985442671, ... std(r)=0.2838269732183663 r.Std()=0.2838269732183663 */ //+------------------------------------------------------------------+ //| Заполняет вектор случайными значениями | //+------------------------------------------------------------------+ void ArrayRandom(vector& v) { for(ulong i=0; i<v.Size(); i++) v[i]=double(MathRand())/32767.; }
Mejoradas las funciones matemáticas para trabajar con el tipo float.
Debido a la nueva posibilidad de aplicar funciones matemáticas a
matrices y vectores de tipo float, también se han mejorado las funciones
correspondientes aplicadas a escalares del tipo float. Antes, los
parámetros de estas funciones se convertían incondicionalmente al tipo
double, se llamaba a la implementación correspondiente de la función
matemática y luego el resultado se convertía en float. Ahora, en el caso
del tipo float, los parámetros y los resultados no se convierten, ya
que se llaman las implementaciones de las funciones matemáticas
correspondientes al tipo float.
Diferencia en los cálculos usando como ejemplo el seno matemático:
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- массив случайных чисел от 0 до 1 vector d(10, ArrayRandom); for(ulong i=0; i<d.Size(); i++) { double delta=MathSin(d[i])-MathSin((float)d[i]); Print(i,". delta=",delta); } } /* 0. delta=5.198186103783087e-09 1. delta=8.927621308885136e-09 2. delta=2.131878673594656e-09 3. delta=1.0228555918923021e-09 4. delta=2.0585739779477308e-09 5. delta=-4.199390279957527e-09 6. delta=-1.3221741035351897e-08 7. delta=-1.742922250969059e-09 8. delta=-8.770715820283215e-10 9. delta=-1.2543186267421902e-08 */ //+------------------------------------------------------------------+ //| Заполняет вектор случайными значениями | //+------------------------------------------------------------------+ void ArrayRandom(vector& v) { for(ulong i=0; i<v.Size(); i++) v[i]=double(MathRand())/32767.; }
La función de activación en una red neuronal determina cómo la suma ponderada de la señal de entrada se transforma en la señal de salida de un nodo o varios nodos a nivel de red. La elección de la función de activación ejerce una gran influencia en las capacidades y el rendimiento de la red neuronal. Las diferentes partes del modelo pueden usar funciones de activación distintas. En MQL5 no solo se implementan todas las funciones de activación conocidas, sino también las derivadas de la función de activación. Las funciones derivadas son necesarias a la hora de calcular rápidamente una corrección basada en el error resultante durante el entrenamiento de una red neuronal.
AF_ELU Exponential Linear Unit AF_EXP Exponential AF_GELU Gaussian Error Linear Unit AF_HARD_SIGMOID Hard Sigmoid AF_LINEAR Linear AF_LRELU Leaky REctified Linear Unit AF_RELU REctified Linear Unit AF_SELU Scaled Exponential Linear Unit AF_SIGMOID Sigmoid AF_SOFTMAX Softmax AF_SOFTPLUS Softplus AF_SOFTSIGN Softsign AF_SWISH Swish AF_TANH Hyperbolic Tangent AF_TRELU Thresholded REctified Linear Unit
LOSS_MSE Mean Squared Error LOSS_MAE Mean Absolute Error LOSS_CCE Categorical Crossentropy LOSS_BCE Binary Crossentropy LOSS_MAPE Absolute Percentage Error LOSS_MSLE Mean Squared Logarithmic Error LOSS_KLD Kullback-Leibler Divergence LOSS_COSINE Cosine similarity/proximity LOSS_POISSON Poisson LOSS_HINGE Hinge LOSS_SQ_HINGE Squared Hinge LOSS_CAT_HINGE Categorical Hinge LOSS_LOG_COSH Logarithm of the Hyperbolic Cosine LOSS_HUBER Huber
int cl_ctx; //--- инициализация OpenCL контекста if((cl_ctx=CLContextCreate(CL_USE_GPU_DOUBLE_ONLY))==INVALID_HANDLE) { Print("OpenCL not found"); return; }
CalendarValueLast(change, result, "", "EUR")
MetaEditor
'levels.bmp' as 'uint levels[18990]'
Terminal
MQL5
MetaTester
MetaEditor
Correcciones de crash logs.
Terminal
MQL5
double vector.RegressionError(const enum lr_error); double matrix.RegressionError(const enum lr_error); vector matrix.RegressionError(const enum lr_error,const int axis);Los cálculos que se pueden utilizar son:
enum REGRESSION_ERROR { REGRESSION_MAE, // Error medio absoluto REGRESSION_MSE, // Error medio cuadrático REGRESSION_RMSE, // Raíz del error medio cuadrático REGRESSION_R2, // R al cuadrado REGRESSION_MAPE, // Error medio absoluto en porcentaje REGRESSION_MSPE, // Error medio cuadrático en porcentaje REGRESSION_RMSLE // Error medio logarítmico cuadrático };
MetaEditor
Tester
Terminal
Terminal
Terminal
MQL5
void OnStart() { int arr[4][5]= { {22, 34, 11, 20, 1}, {10, 36, 2, 12, 5}, {33, 37, 25, 13, 4}, {14, 9, 26, 21, 59} }; ulong indexes[4][5]; //--- Sort the array arr.ArgSort(indexes,-1,0); Print("indexes"); ArrayPrint(indexes); } // Result log: // indexes // [,0][,1][,2][,3][,4] // [0,] 4 2 3 0 1 // [1,] 2 4 0 3 1 // [2,] 4 3 2 0 1 // [3,] 1 0 3 2 4
void OnStart() { string test="some string"; PrintFormat("String length is %d",test.Length()); } // Result log: // String length is 11
MQL5
double matrix::Flat(ulong index) const; // getter void matrix::Flat(ulong index,double value); // setter
Pseudocódigo para calcular la dirección de un elemento de la matriz:
ulong row=index / mat.Cols(); ulong col=index % mat.Cols(); mat[row,col]
Por ejemplo, para una matriz mat(3,3), el acceso a los elementos puede escribirse como sigue
Tester
Terminal
Terminal
MQL5
VPS
MetaEditor
Tester
Documentación actualizada.
struct POINT { int x,y; }; int GetYFunc(y) { return(y * y); } void SomeFunction(int x1,int x2,int y) { POINT pt={ x1+x2, GetYFunc(y) }; ProcessPoint(pt); };
struct complex { double real; // parte real double imag; // parte imaginaria };El tipo "complex" puede transmitirse mediante un valor en calidad de parámetro para las funciones MQL5 (a diferencia de las estructuras normales, que se transmiten mediante un enlace). Para las funciones importadas desde una DLL, el tipo "complex" debe transmitirse solo mediante un enlace.
complex square(complex c) { return(c*c); } void OnStart() { Print(square(1+2i)); // se transmite una constante como parámetro } // se mostrará "(-3,4)", la representación de línea del número complejoPara los números complejos, en estos momentos están disponibles solo las operaciones sencillas: =, +, -, *, /, +=, -=, *=, /=, ==, !=.
select count(*) as book_count, cast(avg(parent) as integer) as mean, cast(median(parent) as integer) as median, mode(parent) as mode, percentile_90(parent) as p90, percentile_95(parent) as p95, percentile_99(parent) as p99 from moz_bookmarks;