Terminal
MQL5
//--- первый параметр handle игнорируется при получении кода последней ошибки int code = (int)CLGetInfoInteger(0,CL_LAST_ERROR);
//--- получить код последней OpenCL ошибки int code = (int)CLGetInfoInteger(0,CL_LAST_ERROR); string desc; // для получения текстового описания ошибки //--- используем код ошибки для получения текстового описания ошибки if(!CLGetInfoString(code,CL_ERROR_DESCRIPTION,desc)) desc = "cannot get OpenCL error description, " + (string)GetLastError(); Print(desc); //--- чтобы получить описание последней OpenCL ошибки без предварительного получения кода, нужно передать CL_LAST_ERROR if(!CLGetInfoString(CL_LAST_ERROR,CL_ERROR_DESCRIPTION, desc)) desc = "cannot get OpenCL error description, " + (string)GetLastError(); Print(desc);Пока в качестве описания ошибки отдаётся имя внутреннего перечисления, расшифровку которого можно посмотреть на странице https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#CL_SUCCESS. Например, если получено значение CL_INVALID_KERNEL_ARGS, описание для него "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)); }Результат:
"class A const * const [][2][3]"
Terminal
MQL5
Исправления по крешлогам.
MetaTrader 5 WebTerminal build 3500
Мобильная версия веб-терминала
В новой версии веб-терминала добавлена полноценная поддержка мобильных устройств. Теперь его интерфейс автоматически адаптируется по размеру экрана, позволяя пользователям удобно работать в платформе на телефонах и планшетах с iOS и Android:
Помимо этого, в веб-терминал внесено множество исправлений и улучшений.
Новый веб-терминал MetaTrader 5 поддерживает все функции, которые нужны современному трейдеру. Приложение позволяет:
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);Тип копируемых данных указывается в параметре flags при помощи перечисления ENUM_COPY_TICKS. Доступны следующие значения:
COPY_TICKS_INFO = 1, // тики, вызванные изменениями Bid и/или Ask COPY_TICKS_TRADE = 2, // тики, вызванные изменениями Last и Volume COPY_TICKS_ALL = 3, // все тики, в которых есть изменения COPY_TICKS_TIME_MS = 1<<8, // время в миллисекундах COPY_TICKS_BID = 1<<9, // цена Bid COPY_TICKS_ASK = 1<<10, // цена Ask COPY_TICKS_LAST = 1<<11, // цена Last COPY_TICKS_VOLUME = 1<<12, // объем COPY_TICKS_FLAGS = 1<<13, // флаги тикаПри выборе нескольких типов данных (доступно только для матриц) порядок строк в матрице будет соответствовать порядку значений в перечислении.
bool matrix::Assign(const vector &vec);Результатом будет однострочная матрица.
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[]);Каждый массив, вектор или матрица ссылаются на буфер памяти, который содержит элементы данного объекта. Метод Swap фактически меняет местами указатели на данные буферы, не проводя записи элементов в памяти. Поэтому матрица остается матрицей, а вектор вектором. При обмене матрицы и вектора вы получите однострочную матрицу с элементами вектора и вектор с элементами матрицы в плоском представлении (смотрите метод 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); //--- обменяем указатели на матрицы местами 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]] */ }Метод Swap также позволяет работать с динамическими массивами (массив фиксированного размера в качестве параметра передавать нельзя). При этом массив может быть любой размерности, но согласованного размера. Это означает, что общий размер матрицы или вектора должен быть кратен нулевой размерности массива. Нулевой размерностью массива называется количество элементов, которые содержатся по первому индексу массива. Например, для динамического трехмерного массива double array[][2][3] нулевой размерностью будет произведение размеров второго и третьего измерения, то есть 2x3=6. Значит, такой массив можно использовать в методе Swap только с матрицами и векторами, общий размер которых кратен 6: 6, 12, 18, 24 и т.д.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- заполним матрицу 1x10 значением 7.0 matrix m= matrix::Full(1, 10, 7.0); Print("matrix before Swap:\n", m); //--- попробуем провести обмен между матрицей и массивом 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 // размер матрицы не кратен размеру первого измерения массива { 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 */ //--- возьмем матрицу побольше и снова попробуем провести обмен 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 // статический массив нельзя использовать для обмена с матрицей { 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 */ //--- еще одна попытка обменять массив и матрицу double array_dynamic[][10]; // динамический массив ArrayResize(array_dynamic, 3); // выставим размер первого измерения ArrayCopy(array_dynamic, array_static); //--- теперь для обмена используем динамический массив if(m.Swap(array_dynamic)) { Print("array_dynamic after Swap:"); ArrayPrint(array_dynamic); Print("matrix after Swap: \n", m); } else // нет ошибки { 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);Пример:
//--- копирование матриц matrix b={}; matrix a=b; a.Assign(b); //--- копирование массива в матрицу 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);Тип копируемых данных указывается в параметре rates_mask при помощи перечисления ENUM_COPY_RATES. Доступны следующие значения:
Исправлена ошибка изменения константного параметра, переданного в функцию в виде ссылки на указатель объекта.
Напомним, что спецификатор const объявляет переменную константой и не позволяет изменять значение этой переменной в процессе выполнения программы. Допускается только однократная инициализация переменной при ее объявлении. Пример константных переменных в функции OnCalculate:
int OnCalculate (const int rates_total, // размер массива price[] const int prev_calculated, // обработано баров на предыдущем вызове const int begin, // откуда начинаются значимые данные const double& price[] // массив для расчета );
Но в примере ниже обнаружилась ошибка компилятора, который позволял неявное приведение указателей для параметров-ссылок:
class A {}; const A *a = new A; void foo( const A*& b ) { b = a; } void OnStart() { A *b; foo(b); // недопустимо Print( a,":",b ); }Теперь данная недопустимая операция будет детектироваться компилятором и выдавать ошибку.
MetaEditor
Новый веб-терминал MetaTrader 5
Представляем
абсолютно новый веб-терминал для MetaTrader 5. Мы сделали его
современным и быстрым, обновив не только внешний вид, но и полностью
переписав ядро. В плане интерфейса веб-терминал стал похож на уже
привычную версию платформы для iPad:
По сравнению со старой версии в нем появилось множество новых функций:
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]] */В случае MathMod и MathPow в качестве второго параметра может быть использован как скаляр, так и матрица или вектор соответствующего размера.
//+------------------------------------------------------------------+ //| 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.; }
Доработаны математические функции для работы с типом float.
В связи с появившейся возможностью применения математических функций к
матрицам и векторам типа float, были также доработаны соответствующие
функции, применяемые к скалярам типа float. Раньше параметры этих
функций безусловно приводились к типу double, вызывалась соответствующая
реализация математической функции, и затем результат приводился к типу
float. Теперь в случае типа float параметры и результаты не подвергаются
приведению, так как вызываются реализации математических функций,
соответствующих типу float.
Разница в вычислениях на примере математического синуса:
//+------------------------------------------------------------------+ //| 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.; }
Функция активации в нейронной сети определяет, как взвешенная сумма входного сигнала преобразуется в выходной сигнал узла или узлов на уровне сети. Выбор функции активации имеет большое влияние на возможности и производительность нейронной сети. В разных частях модели могут использоваться разные функции активации. В MQL5 реализованы не только все известные функции активации, но и производные активационной функции. Производные функции нужны для быстрого вычисления поправки на основании полученной ошибки во время обучения нейронной сети.
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 Mean 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
Исправления по крешлогам.
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);В качестве метрик могут использоваться:
enum REGRESSION_ERROR { REGRESSION_MAE, // Средняя абсолютная ошибка REGRESSION_MSE, // Средняя квадратичная ошибка REGRESSION_RMSE, // Корень из средней квадратичной ошибки REGRESSION_R2, // R в квадрате REGRESSION_MAPE, // Средняя абсолютная ошибка в процентах REGRESSION_MSPE, // Среднеквадратичная ошибка в процентах REGRESSION_RMSLE // Среднеквадратичная логарифмическая ошибка };
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]; //--- Отсортируем массив arr.ArgSort(indexes,-1,0); Print("indexes"); ArrayPrint(indexes); } // Результат в журнале: // 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()); } // Результат в журнале: // String length is 11
MQL5
double matrix::Flat(ulong index) const; // getter void matrix::Flat(ulong index,double value); // setter
Псевдокод вычисления адреса элемента матрицы:
ulong row=index / mat.Cols(); ulong col=index % mat.Cols(); mat[row,col]
Например, для матрицы matrix mat(3,3) доступы можно записать так:
Tester
Terminal
Terminal
MQL5
VPS
MetaEditor
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; // вещественная часть double imag; // мнимая часть };Тип "complex" может передаваться по значению в качестве параметра для MQL5-функций (в отличие от обычных структур, которые передаются только по ссылке). Для функций, импортируемых из DLL, тип "complex" должен передаваться только по ссылке.
complex square(complex c) { return(c*c); } void OnStart() { Print(square(1+2i)); // в качестве параметра передается константа } // будет выведено "(-3,4)" - это строковое представление комплексного числаДля комплексных чисел на данный момент доступны только простые операции: =, +, -, *, /, +=, -=, *=, /=, ==, !=.
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;