В новой версии платформы прекращается поддержка десктопных и мобильных терминалов старых версий:
Такие терминалы не смогут подключаться к серверам новых версий. Мы настоятельно рекомендуем заранее обновить ваши терминалы.
Для поддержки новых групповых проектов был изменен протокол работы с онлайн хранилищем MQL5 Storage. К сожалению, после обновления на новую версию платформы вам потребуется заново извлечь все данные из хранилища. Сами данные, которые в нем хранятся, не будут затронуты и не потеряются.
Перед обновлением на новую версию платформы мы рекомендуем отправить все локальные изменения в хранилище (выполнить Commit).
Как это происходит
Например, вы можете создать инструмент, который будет показывать индекс доллара (USDX). Его формула будет выглядеть следующим образом:
50.14348112 * pow(ask(EURUSD),-0.576) * pow(USDJPY,0.136) * pow(ask(GBPUSD),-0.119) * pow(USDCAD,0.091) * pow(USDSEK,0.042) * pow(USDCHF,0.036)
Примечание: в исходной формуле индекса доллара используются пары
USDEUR и USDGBP. Поскольку в платформе есть только обратные валютные
пары, в формуле синтетического инструмента для них используется
отрицательная степень и цена Ask вместо Bid.
В режиме реального времени платформа будет
рассчитывать цену нового инструмента на основе котировок шести
других инструментов, предоставляемых вашим брокером. В Обзоре рынка и на
графике вы будете видеть, как изменяется его цена:



int CustomTicksAdd( const string symbol, // имя символа const MqlTick& ticks[] // массив с тиковыми данными, которые необходимо применить к пользовательскому инструменту );Функция CustomTicksAdd позволяет транслировать тики так, как если бы они приходили от сервера брокера. Данные записываются не напрямую в базу тиков, а отправляются в окно "Обзор рынка". И уже из него терминал сохраняет тики в своей базе. При большом объеме данных, передаваемых за один вызов, функция меняет свое поведение для экономии ресурсов. Если передается более 256 тиков, данные делятся на две части. Первая часть (большая) сразу напрямую записывается в базу тиков (как это делает CustomTicksReplace). Вторая часть, состоящая из последних 128 тиков, передается в окно "Обзор рынка" и после этого сохраняется терминалом в базе.




В MetaEditor появились полноценные проекты. Разрабатывать программы стало значительно удобнее.
Теперь в качестве проекта не выступает основной MQ5 файл
программы. Проект — это отдельный файл "MQPROJ", в котором хранятся
настройки программы, параметры компиляции и информация обо всех
используемых файлах. Доступ к основным настройкам проекта организован
через отдельное диалоговое окно, больше нет необходимости указывать их в
исходном коде через #property.
Для удобной работы с проектом предусмотрена отдельная вкладка в
Навигаторе. В ней по категориям отображаются все используемые файлы:
включаемые, ресурсные, заголовочные и т.д. При этом файлы добавляются в
навигатор проекта автоматически. Например, если вы включите новый
MQH-файл в код, он будет автоматически показан в разделе "Dependencies"
навигатора.
Мы сразу же предусмотрели возможность работы с новыми проектами в
онлайн хранилище MQL5 Storage. Теперь намного удобнее заниматься
разработкой больших проектов вместе с другими участникам сообщества
MQL5.community.
Для работы с групповыми проектами добавлен новый раздел Shared Projects. Проект, созданный в этом разделе, сразу же отправляется в хранилище: вы можете быстро раздать права на него другим участникам и приступить к совместной разработке.

При компиляции проекта в Shared Project исполняемый файл EX5 автоматически копируется в локальный каталог Experts, Indicators или Scripts, в зависимости от типа программы. Вы можете сразу запустить программу на графике, не копируя файлы каждый раз вручную.
Изменения в работе с хранилищем MQL5 Storage
Для реализации полноценной работы с групповыми проектами был полностью переделан протокол взаимодействия с хранилищем MQL5 Storage. К сожалению, после обновления на новую версию платформы вам потребуется заново извлечь все данные из хранилища. Сами данные, которые в нем хранятся, не будут затронуты и не потеряются.
Команда "Извлечь данные из хранилища" (Checkout from Storage) теперь недоступна. Для извлечения данных используются команды "Активировать MQL5 Storage" и "Получить файлы из хранилища":
Новые проекты: пример создания и подробности работы
В MetaEditor появилась новая сущность — собственно проект. Это файл с расширением mqproj, в котором хранятся общие свойства программы, а также информация обо всех используемых файлах. Теперь свойствами программы можно удобно управлять в отдельном диалоговом окне MetaEditor, а не изменять их вручную в исходном коде (директивы #property).
Если у вас уже есть разработки, то самый простой способ попробовать новые проекты — воспользоваться командой "Новый проект из исходного файла".

В том же каталоге, что и выбранный исходный файл, будет создан одноименный файл проекта с расширением mqproj. В проект автоматически добавятся основные свойства программы, указанные в виде #property в исходном файле: имя, копирайт, версия, ссылка на разработчика и описание.

В свойствах проектов появились две новые опции для компиляции MQL5-программ:
Для работы с проектом предназначена отдельная вкладка "Проект" в окне "Навигатор". В ней удобно показываются все файлы, используемые в проекте. При генерации проекта из исходного файла в раздел "Dependencies" автоматически добавляются все используемые включаемые файлы (указанные при помощи директивы #include в основном MQ5-файле и во всех включенных в него файлах).
При добавлении новых включаемых файлов в исходный код, они также будут появляться в Навигаторе проекта. В раздел Headers будут добавляться используемые заголовочные файлы, а в раздел Resources — изображения, звуки и другие MQL5-программы, включенные в проект в виде ресурсов. В разделе Sources показываются MQ5-файлы с исходным кодом. В раздел Settings and files можно добавлять другие файлы, например, настройки для тестирования или шаблоны для графиков.
Для добавления существующих файлов в проект и удаления из него файлов воспользуйтесь командами контекстного меню. Будьте внимательны при удалении: вы можете убрать файл из проекта (убрать привязку) или полностью удалить его с жесткого диска:

Новый проект создать также легко, как и обычную MQL5-программу. Нажмите "Новый проект", а затем в Мастере MQL5 выберите тип создаваемой программы и укажите ее свойства (имя, обработчики событий и т.п.).
Для получения исполняемого файла EX5 вы можете открыть проект и выполнить команду компиляции (F7) или же, как раньше, открыть основной MQ5-файл программы и скомпилировать его.
Групповые проекты в MQL5 Storage: подробности работы
Для работы с групповыми проектами предусмотрен раздел Shared Projects. Если у вас еще не подключено хранилище, выполните в контекстном меню этой папки команду Activate MQL5 Storage. MetaEditor сразу же проверит, есть ли в вашем хранилище сохраненные данные, а также доступны ли вам какие-либо групповые проекты. Имеющиеся данные будут сразу же извлечены из хранилища и загружены на компьютер (Checkout). Доступные групповые проекты будут показаны в разделе Shared Projects; чтобы получить их, нажмите "Извлечь файлы из хранилища" в контекстном меню.
Для создания нового группового проекта выберите папку Shared Projects и нажмите "Новый проект":

Далее пройдите стандартные шаги Мастера MQL5: задайте тип, имя и свойства будущей программы. Выбирайте для групповых проектов четкие и понятные имена, чтобы другие участники легко их различали. В имени допускаются только латинские буквы и цифры, пробелы не допускаются.
Сразу после создания проект будет автоматически добавлен в хранилище MQL5 Storage. Используемые файлы стандартной библиотеки в хранилище не добавляются, при необходимости вы можете добавить их вручную.
Чтобы разрешить другим участникам работать с проектом, откройте его свойства: здесь можно назначить права конкретным пользователям (указать логин MQL5.community), а также задать общие параметры групповой работы:

Для удобства работы при компиляции группового проекта конечный
исполняемый файл (EX5) автоматически копируется в папку Experts,
Indicators или Scripts в зависимости от типа программы. Таким образом,
вы сразу можете запустить программу в терминале без ее ручного
копирования в нужный каталог.
Публичные проекты в MQL5 Storage: участие в разработках
Как уже упоминалось выше, у каждого группового проекта в MQL5 Storage есть настройки публичности: проект может быть приватным или же открытым для участия других пользователей. Теперь все проекты, к которым можно свободно присоединиться, отображаются в отдельной вкладке "Публичные проекты".
Каждый может найти интересный проект и принять участие в его разработке. Достаточно нажать "Присоединиться", а затем получить проект из хранилища.


//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- файл шаблона в виде бинарного массива unsigned char my_template[]= { 0xFF,0xFE,0x3C, ... ,0x00 // массив данных в примере сокращен }; //--- сохранение и применение шаблона if(FileSave("my_template.tpl",my_template)) { Print("Custom template saved in \\MQL5\\Files"); if(ChartApplyTemplate(0,"\\Files\\my_template.tpl")) Print("Custom template applied to the current chart"); else Print("Failed to apply custom template"); } else Print("Failed to save custom template"); }


| Функция | Действие |
|---|---|
| CustomSymbolCreate | Создает пользовательский символ с указанным именем в указанной группе |
| CustomSymbolDelete | Удаляет пользовательский символ с указанным именем |
| CustomSymbolSetInteger | Устанавливает для пользовательского символа значение свойства целочисленного типа |
| CustomSymbolSetDouble | Устанавливает для пользовательского символа значение свойства вещественного типа |
| CustomSymbolSetString | Устанавливает для пользовательского символа значение свойства строкового типа |
| CustomSymbolSetMarginRate | Устанавливает для пользовательского символа коэффициенты взимания маржи в зависимости от типа и направления ордера |
| CustomSymbolSetSessionQuote | Устанавливает время начала и время окончания указанной котировочной сессии для указанных символа и дня недели |
| CustomSymbolSetSessionTrade | Устанавливает время начала и время окончания указанной торговой сессии для указанных символа и дня недели |
| CustomRatesDelete | Удаляет все бары в указанном временном интервале из ценовой истории пользовательского инструмента |
| CustomRatesReplace | Полностью заменяет ценовую историю пользовательского инструмента в указанном временном интервале данными из массива типа MqlRates |
| CustomRatesUpdate | Добавляет в историю пользовательского инструмента отсутствующие бары и заменяет существующие бары данными из массива типа MqlRates |
| CustomTicksAdd | Добавляет в ценовую историю пользовательского инструмента данные из массива типа MqlTick. Пользовательский символ должен быть выбран в окне MarketWatch (Обзор рынка) |
| CustomTicksDelete | Удаляет все тики в указанном временном интервале из ценовой истории пользовательского инструмента |
| CustomTicksReplace | Полностью заменяет ценовую историю пользовательского инструмента в указанном временном интервале данными из массива типа MqlTick |
Библиотека размещается в рабочем каталоге терминала в папке Include\Generic.
bool ArraySwap( void& array1[], // первый массив void& array2[] // второй массив );Функция принимает динамические массивы одинакового типа и одинаковых размерностей. Для многомерных массивов количество элементов во всех измерениях кроме первого должно совпадать.







union LongDouble { long long_value; double double_value; };В отличие от структуры, разные члены объединения относятся к одному и тому же участку памяти. В данном примере объявлено объединение LongDouble, в котором значение типа long и значение типа double разделяют одну и ту же область памяти. Важно понимать — невозможно сделать так, чтобы это объединение хранило одновременно целочисленное значение long и вещественное double (как это было бы в структуре), поскольку переменные long_value и double_value накладываются (в памяти) друг на друга. Но зато MQL5-программа в любой момент может обрабатывать информацию, содержащуюся в этом объединении, как целочисленное значение (long) или как вещественное (double). Следовательно, объединение позволяет получить два (или больше) варианта представления одной и той же последовательности данных.
union LongDouble
{
long long_value;
double double_value;
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
LongDouble lb;
//--- получим недействительное число -nan(ind) и выведем его
lb.double_value=MathArcsin(2.0);
printf("1. double=%f integer=%I64X",lb.double_value,lb.long_value);
//--- наибольшее нормализованное число (DBL_MAX)
lb.long_value=0x7FEFFFFFFFFFFFFF;
printf("2. double=%.16e integer=%I64X",lb.double_value,lb.long_value);
//--- наименьшее положительное нормализованное (DBL_MIN)
lb.long_value=0x0010000000000000;
printf("3. double=%.16e integer=%.16I64X",lb.double_value,lb.long_value);
}
/* Результат выполнения
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);}; //--- конструктор по умолчанию Foo(void){value=-1;}; //--- конструктор с параметрами Foo(int v){value=v;}; }; //+------------------------------------------------------------------+ //| структура, содержащая объекты типа 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()); /* Результат выполнения; 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 */ }В неявном операторе осуществляется почленное копирование объектов.
| ENUM_POSITION_REASON | ENUM_DEAL_REASON | ENUM_ORDER_REASON | Описание причины |
|---|---|---|---|
| POSITION_REASON_CLIENT | DEAL_REASON_CLIENT | ORDER_REASON_CLIENT | Операция совершена в результате срабатывания ордера, выставленного из десктопного терминала |
| POSITION_REASON_MOBILE | DEAL_REASON_MOBILE | ORDER_REASON_MOBILE | Операция совершена в результате ордера, выставленного из мобильного приложения |
| POSITION_REASON_WEB | DEAL_REASON_WEB | ORDER_REASON_WEB | Операция совершена в результате срабатывания ордера, выставленного из веб-платформы |
| POSITION_REASON_EXPERT | DEAL_REASON_EXPERT | ORDER_REASON_EXPERT | Операция совершена в результате срабатывания ордера, выставленного из MQL5-программы – советником или скриптом |
| - | DEAL_REASON_SL | ORDER_REASON_SL | Операция совершена в результате срабатывания Stop Loss |
| - | DEAL_REASON_TP | ORDER_REASON_TP | Операция совершена в результате срабатывания Take Profit |
| - | DEAL_REASON_SO | ORDER_REASON_SO | Операция совершена в результате наступления события Stop Out |
| - | DEAL_REASON_ROLLOVER | - | Сделка совершена по причине
переноса позиции |
| - | DEAL_REASON_VMARGIN | - | Сделка совершена по причине начисления/списания вариационной маржи |
| - | DEAL_REASON_SPLIT | - | Сделка совершена по причине сплита (понижения цены) акции или иного актива, по которому открыта имелась позиция на момент объявления сплита |



Обновлена документация.

//+------------------------------------------------------------------+ //| Шаблонная функция | //+------------------------------------------------------------------+ template<typename T1,typename T2> string Assign(T1 &var1,T2 var2) { var1=(T1)var2; return(__FUNCSIG__); } //+------------------------------------------------------------------+ //| Специальная перегрузка для случая 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")); }В результате выполнения кода мы увидим, что для пары int+string была использована шаблонная функция Assign(), а при втором вызове для пары bool+string уже использовалась перегруженная версия.
string Assign<int,string>(int&,string) string Assign(bool&,string)
template<typename T> T Func() { return (T)0; } void OnInit() { Func<double>(); // явная специализация шаблонной функции }Таким образом, специализация происходит не через параметры вызова, а прямым указанием типов.
Обновлена документация.



Обновлена документация.





#resource путь_к_файлу_ресурса as тип_ресурсной_переменной имя_ресурсной_переменной
#resource "data.bin" as int ExtData[] // объявление массива числового типа, содержащего данные из файла data.bin #resource "data.bin" as MqlRates ExtData[] // объявление массива простых структур, содержащего данные из файла data.bin #resource "data.txt" as string ExtCode // объявление строки, содержащей данные файла data.txt #resource "data.txt" as string ExtCode[] // объявление строкового массива, содержащего строки файла data.txt #resource "image.bmp" as bitmap ExtBitmap[] // объявление одномерного массива, содержащего в себе растр из файла BMP, размер массива = height * width #resource "image.bmp" as bitmap ExtBitmap2[][] // объявление двумерного массива, содержащего в себе растр из файла BMP, размер массива [height][width]


Обновлена документация.
string str; ... if(str) // будет ошибка компиляции "Cannot convert type 'string' to 'bool'" (в предыдущих билдах ошибки не было) Print("str is true");Следует написать явное условие:
string str; ... //--- проверка, инициализирована ли строка if(str!=NULL) Print("str is true"); или //--- проверка, является ли значение строки "true" if(StringCompare(str,"true",false)) Print("str is true"); или //--- проверка, что строка является числом и не равна нулю if((int)str!=0) Print("str is true");
Исправления по крешлогам.



void ArrayPrint( const void& array[], // выводимый массив uint digits=_Digits, // количество десятичных знаков после запятой const string separator=NULL, // разделитель между значениями полей структуры ulong start=0, // индекс первого выводимого элемента ulong count=WHOLE_ARRAY, // количество выводимых элементов ulong flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN );ArrayPrint выводит в журнал не все поля массива структур – поля-массивы и поля-указатели объектов пропускаются. Для вывода всех полей такой структуры понадобится собственная функция массового вывода с желаемым форматированием.
//--- выводит значения 10 последних баров MqlRates rates[]; if(CopyRates(_Symbol,_Period,1,10,rates)) { ArrayPrint(rates); Print("Проверка\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()); //--- пример вывода /* [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 Проверка [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[]; //--- сколько памяти использовано изначально Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- сколько памяти использовано для массива размером 1, но с резервом ArrayResize(arr,1,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- после увеличения массива размер используемой памяти не изменится за счет резерва ArrayResize(arr,1024*512,1024*1024); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- после уменьшения массива размер памяти также не изменится ArrayResize(arr,1); Print("Array size:",ArraySize(arr)," Memory used:",MQLInfoInteger(MQL_MEMORY_USED)," MB"); //--- не используемая массивом память освободится за счет удаления резерва 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); }Результат:

#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); //--- }Результат:



Обновлена документация.
Добавлены всплывающие подсказки для кнопок Buy, Sell и Close в диалогах торговли. Подсказки поясняют, какие именно активы будут куплены и проданы при выполнении той или иной операции, помогая начинающим трейдерам понять суть торгового процесса.


Возможности библиотеки
Как использовать
Файлы библиотеки ALGLIB расположены в каталоге \MQL5\Include\Math\Alglib. Для использования функций включите основной файл библиотеки в свою программу:
В стандартную библиотеку включены функции работы с математической статистикой. Теперь в MQL5 доступны возможности языка R — одного из лучших инструментов статистической обработки и анализа данных.
Возможности библиотеки
Статистическая библиотека содержит функции для расчета статистических характеристик данных, а также функции для работы со статистическими распределениями:
Как использовать
Файлы статистической библиотеки расположены в каталоге \MQL5\Include\Math\Stat. Для использования включите файл с нужными функциями в свою программу, например:
#include <Math\Stat\Binomal.mqh> #include <Math\Stat\Cauchy.mqh>
Подробное описание функций библиотеки читайте в статье Статистические распределения в MQL5 - берем лучшее из R.
В стандартную библиотеку включена MQL5-версия библиотеки Fuzzy, в которой реализованы системы нечеткого логического вывода Мамдани и Сугено.
Возможности библиотеки
Как использовать
Файлы библиотеки Fuzzy расположены в каталоге \MQL5\Include\Math\Fuzzy. Для использования включите файл с нужными функциями в свою программу, например:
#include <Math\Fuzzy\mamdanifuzzysystem.mqh> #include <Math\Fuzzy\sugenofuzzysystem.mqh>
Подробное описание библиотеки можно найти в Code Base: Fuzzy - библиотека для работы с нечеткой логикой

long FileLoad( const string filename, // [in] имя файла void &buffer[], // [out] массив, в который считывается файл uint common_flag=0 // [in] 0 - поиск файла в папке Files терминала, FILE_COMMON - в общей папке терминалов ); bool FileSave( const string filename, // [in] имя файла const void &buffer[], // [in] массив, который сохраняется в файл uint common_flag=0 // [in] 0 - создание файла в папке Files терминала, FILE_COMMON - в общей папке терминалов );Пример записи массива тиков в файл с последующим чтением этих данных:
//--- входные параметры input int ticks_to_save=1000; // количество тиков //+------------------------------------------------------------------+ //| 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); //--- если тиковая история синхронизирована, то код ошибки равен нулю if(!GetLastError()==0) PrintFormat("%s: Ticks are not synchronized. Error=",_Symbol,copied,_LastError); //--- запишем тики в файл if(!FileSave(filename,ticks,FILE_COMMON)) PrintFormat("FileSave() failed, error=%d",GetLastError()); } else PrintFormat("Failed CopyTicks(%s), Error=",_Symbol,GetLastError()); //--- теперь прочитаем эти тики обратно из файла 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); } } }
//--- одинаковые свечи, окрашенные в один цвет #property indicator_label1 "One color candles" #property indicator_type1 DRAW_CANDLES //--- указан только один цвет, поэтому все свечи будут одного цвета #property indicator_color1 clrGreenЕсли указано два цвета, контуры свечи будут отрисовываться первым цветом, а тело — вторым цветом.
//--- цвет свечей отличается от цвета теней #property indicator_label1 "Two color candles" #property indicator_type1 DRAW_CANDLES //--- тени и контур свечей зеленого цвета, тело белого цвета #property indicator_color1 clrGreen,clrWhiteЕсли указано три цвета, контур свечи будет нарисован первым цветом, а цвет бычьей и медвежьей свечей будет задаваться вторым и третьим цветом.
//--- цвет свечей отличается от цвета теней #property indicator_label1 "One color candles" #property indicator_type1 DRAW_CANDLES //--- тени и контур зелёного цвета, тело бычьей свечи белого цвета, тело медвежьей свечи красного цвета #property indicator_color1 clrGreen,clrWhite,clrRedТаким образом, с помощью стиля DRAW_CANDLES можно создавать собственные пользовательские варианты раскраски свечей. Все цвета можно также менять динамически в процессе работы индикатора с помощью функции PlotIndexSetInteger(индекс_построения_DRAW_CANDLES, PLOT_LINE_COLOR, номер_модификатора, цвет) , где номер_модификатора можеть иметь следующие значения:
//--- установим цвет контура и теней PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,clrBlue); //--- установим цвет тела для бычьей свечи PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,clrGreen); //--- установим цвет тела для медвежьей свечи PlotIndexSetInteger(0,PLOT_LINE_COLOR,2,clrRed);
Обновлена документация.



class CFoo final { //--- тело класса }; class CBar : public CFoo { //--- тело класса };При попытке наследования от класса с модификатором final, как показано в примере выше, компилятор выдаст ошибку:
class CFoo { void virtual func(int x) const { } };Далее метод переопределяется в наследуемом классе:
class CBar : public CFoo { void func(short x) { } };Но по ошибке тип аргумента изменяется с int на short. Фактически, в этом случае уже происходит не переопределение, а перегрузка метода. Действуя в соответствии с алгоритмом определения перегруженной функции, в определенных ситуациях компилятор может выбрать метод, определенный в базовом классе, вместо переопределенного метода.
class CBar : public CFoo { void func(short x) override { } };Если при переопределении будет изменена сигнатура метода, компилятор не сможет найти в родительском классе метод с точной такой же сигнатурой и выдаст ошибку компиляции:
class CFoo { void virtual func(int x) final { } }; class CBar : public CFoo { void func(int) { } };При попытке переопределения метода с модификатором final, как показано в примере выше, компилятор выдаст ошибку:
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]; // выдаст ошибку приведения указателей, vptr[1] не является объектом CFoo } //+------------------------------------------------------------------+
string text="Hello"; ushort symb=text[0]; // вернет код символа 'H'

Обновлена документация.




Tester: Исправлен расчет комиссии в годовых процентах при тестировании.
Tester: Исправлен пересчет и отображение баланса на графике, формируемом в процессе тестирования.

После 2 месяцев публичного тестирования состоялся официальный выпуск веб-версии мультирыночной платформы MetaTrader 5. Она позволяет торговать на финансовых рынках в любом браузере и любой операционной системе. При этом не требуется устанавливать программу на компьютер, достаточно доступа в интернет и любого веб-браузера.
Приложение сочетает в себе ключевые преимущества десктопной платформы (скорость, мультирыночность и расширенные торговые функции) с удобством и кроссплатформенностью веб-решения. Важным новшеством релизной версии является стакан, который позволяет видеть глубину рынка, а также выставлять одним кликом рыночные и отложенные ордера.
Веб-платформа позволяет проводить технический анализ и совершать торговые
операции точно так же, как в десктопной версии. В приложении доступны:


| Было |
Стало |
|
|---|---|---|
| Срабатывание | Все виды отложенных ордеров и SL/TP по Bid/Ask |
Лимитные ордера по Bid/Ask Стоп, стоп-лимитные и SL/TP ордера по Last |
| Исполнение | Все виды отложенных ордеров и SL/TP по цене, заявленной в ордере |
Все виды отложенных ордеров и SL/TP по рыночным ценам Bid/Ask на момент срабатывания |
Рассмотрим
пример на инструменте Si-6.16. При текущих ценах Bid=72570, Ask=72572,
Last=72552 был выставлен ордер Buy Stop с ценой срабатывания 72580. В
ценовом потоке мы получили новые текущие цены:
На
биржевых инструментах триггером для срабатывания стоп-ордеров является
цена Last. Поэтому, поступление в потоке цены Last=72580 привело к
активации ордера Buy Stop. Ранее именно эта цена 72580 была бы
использована для исполнения данного ордера. Такое поведение было
некорректным, поскольку цены Ask=72580 для исполнения операции на
покупку на рынке нет.


Исправления по крешлогам.
По многочисленным просьбам трейдеров разработана веб-версия торговой платформы MetaTrader 5. Новинка сочетает в себе удобство и кроссплатформенность веб-терминала с преимуществами десктопной "пятерки" — скоростью, мультирыночностью, расширенными торговыми функциями.
Веб-платформа MetaTrader 5 стала доступной на сайте MQL5.community и позволяет торговать на финансовых рынках через любой браузер в любой операционной системе (Windows, Mac, Linux). Для этого не нужно устанавливать никаких программ, достаточно иметь доступ в интернет.
В бета-версии трейдерам сразу же доступны:


Неттинговая система
Эта
система учета подразумевает, что в один момент времени на счете может
быть только одна открытая позиция по одному и тому же символу:
При этом не имеет
значения, в результате какого действия совершается сделка в
противоположном направлении — в результате исполнения рыночного ордера
или срабатывания отложенного.
Ниже приведен пример совершения двух сделок на покупку EURUSD объемом 0.5 лота каждая:

Результатом исполнения этих сделок стала одна общая позиция объемом 1 лот.
Хеджинговая система
Эта
система учета позволяет иметь на счету множество торговых позиций по
одному и тому же инструменту, в том числе — разнонаправленных.
Если
по торговому инструменту есть открытая позиция и трейдер совершает
новую сделку (или срабатывает отложенный ордер), происходит открытие
новой позиции. Существующая позиция не изменяется.
Ниже приведен пример совершения двух сделок на покупку EURUSD объемом 0.5 лота каждая:

Результатом исполнения этих сделок стало открытие двух отдельных позиций.
Новый тип торговой операции Close By
Для
счетов с хеджинговым учетом позиций добавлен новый вид торговых
операций — закрытие позиции встречной. Эта операция позволяет
одновременно закрыть две разнонаправленные позиции по одному и тому же
инструменту. Если встречные позиции имеют разное количество лотов, то
открытым останется только один ордер из двух. Его объем будет равен
разности лотов двух закрытых позиций, а направление позиции и цена
открытия — большей (по объему) из закрываемых позиций.
По сравнению с одиночным закрытием двух позиций, закрытие встречной позволяет сэкономить трейдеру один спред:

При закрытии позиции встречной выставляется ордер типа "close by". В комментарии к нему указываются тикеты закрываемых позиций. Закрытие пары встречных позиций происходит двумя сделками типа "out by". Размер итоговой прибыли/убытка, полученного в результате закрытия обеих позиций, указывается только в одной сделке.


При импорте тикеты ордеров и позиций (в том числе ордеров истории) не
сохраняются, поскольку одной записи в торговой истории MetaTrader 4
может соответствовать до 4 записей в истории MetaTrader 5. Всем торговым
записям проставляются новые тикеты.
Номера счетов могут быть сохранены или заменены новыми в зависимости от того, как брокер произведет импорт.






При тестировании на реальных тиках через MQL5 Cloud Network может передаваться большой объем интернет-трафика. Это может существенно повлиять на итоговую стоимость использования вычислительной сети.
class CAnimal { public: CAnimal(); // конструктор virtual void Sound() = 0; // чисто виртуальная функция private: double m_legs_count; // количество ног животного };Здесь функция Sound() является чисто виртуальной, потому что она объявлена со спецификатором чисто виртуальной функции PURE (=0).
class CAnimal { public: virtual void Sound()=NULL; // PURE method, должен быть переопределен в потомке, сам класс CAnimal стал абстрактным и не может быть создан }; //--- потомок от абстрактного класса class CCat : public CAnimal { public: virtual void Sound() { Print("Myau"); } // PURE переопределен, класс CCat не абстрактный и может быть создан }; //--- примеры неправильного использования new CAnimal; // ошибка 'CAnimal' - компилятор выдаст ошибку "cannot instantiate abstract class" CAnimal some_animal; // ошибка 'CAnimal' - компилятор выдаст ошибку "cannot instantiate abstract class" //--- примеры правильного использования new CCat; // ошибки нет - класс CCat не абстрактный CCat cat; // ошибки нет - класс CCat не абстрактныйОграничения на использование абстрактных классов
//+------------------------------------------------------------------+ //| Абстрактный базовый класс | //+------------------------------------------------------------------+ class CAnimal { public: //--- чисто виртуальная функция virtual void Sound(void)=NULL; //--- функция void CallSound(void) { Sound(); } //--- конструктор CAnimal() { //--- явный вызов виртуального метода Sound(); //--- неявный вызов (через третью функцию) CallSound(); //--- в конструкторе и/или деструкторе всегда вызываются свои функции, //--- несмотря на виртуальность и переопределение вызываемой функции в потомке //--- если вызываемая функция чисто виртуальная, то //--- вызов приведет к критической ошибке выполнения: "pure virtual function call" } };Однако конструкторы и деструкторы абстрактных классов могут вызывать другие функции-члены.
typedef int (*TFunc)(int,int);Теперь TFunc является типом и можно объявить переменную-указатель на функцию:
TFunc func_ptr;В переменную func_ptr можно сохранить адрес функции, чтобы в дальнейшем ее вызывать:
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; // ошибка: neg не имеет тип int (int,int) Print(func_ptr(10)); // ошибка: должно быть два параметраУказатели на функции можно хранить и передавать в качестве параметра. Нельзя получить указатель на нестатический метод класса.
ulong PositionGetTicket( int index // номер в списке позиций );
bool PositionSelectByTicket(
ulong ticket // тикет позиции
);


Неттинговая система
Эта система учета подразумевает, что в один момент времени на счете может
быть только одна открытая позиция по одному и тому же символу:
При этом не имеет значения, в результате какого действия совершается сделка
в противоположном направлении — в результате исполнения рыночного ордера
или срабатывания отложенного.
Ниже приведен пример совершения двух сделок на покупку EURUSD объемом 0.5
лота каждая:

Результатом исполнения этих сделок стала одна общая позиция объемом 1
лот.
Хеджинговая система
Эта система учета позволяет иметь на счету множество торговых позиций по
одному и тому же инструменту, в том числе — разнонаправленных.
Если по торговому инструменту есть открытая позиция и трейдер совершает
новую сделку (или срабатывает отложенный ордер), происходит открытие новой
позиции. Существующая позиция не изменяется.
Ниже приведен пример совершения двух сделок на покупку EURUSD объемом 0.5
лота каждая:

Результатом исполнения этих сделок стало открытие двух отдельных позиций.
Новый тип торговой операции Close By
Для счетов с хеджинговым учетом позиций добавлен новый вид торговых операций
— закрытие позиции встречной. Эта операция позволяет одновременно закрыть
две разнонаправленные позиции по одному и тому же инструменту. Если встречные
позиции имеют разное количество лотов, то открытым останется только один
ордер из двух. Его объем будет равен разности лотов двух закрытых позиций,
а направление позиции и цена открытия — большей (по объему) из закрываемых
позиций.
По сравнению с одиночным закрытием двух позиций, закрытие встречной позволяет
сэкономить трейдеру один спред:

При закрытии позиции встречной выставляется ордер типа "close by". В комментарии к нему указываются тикеты закрываемых позиций. Закрытие пары встречных позиций происходит двумя сделками типа "out by". Размер итоговой прибыли/убытка, полученного в результате закрытия обеих позиций, указывается только в одной сделке.






class CAnimal { public: CAnimal(); // конструктор virtual void Sound() = 0; // чисто виртуальная функция private: double m_legs_count; // количество ног животного };Здесь функция Sound() является чисто виртуальной, потому что она объявлена со спецификатором чисто виртуальной функции PURE (=0).
class CAnimal { public: virtual void Sound()=NULL; // PURE method, должен быть переопределен в потомке, сам класс CAnimal стал абстрактным и не может быть создан }; //--- потомок от абстрактного класса class CCat : public CAnimal { public: virtual void Sound() { Print("Myau"); } // PURE переопределен, класс CCat не абстрактный и может быть создан }; //--- примеры неправильного использования new CAnimal; // ошибка 'CAnimal' - компилятор выдаст ошибку "cannot instantiate abstract class" CAnimal some_animal; // ошибка 'CAnimal' - компилятор выдаст ошибку "cannot instantiate abstract class" //--- примеры правильного использования new CCat; // ошибки нет - класс CCat не абстрактный CCat cat; // ошибки нет - класс CCat не абстрактныйОграничения на использование абстрактных классов
//+------------------------------------------------------------------+ //| Абстрактный базовый класс | //+------------------------------------------------------------------+ class CAnimal { public: //--- чисто виртуальная функция virtual void Sound(void)=NULL; //--- функция void CallSound(void) { Sound(); } //--- конструктор CAnimal() { //--- явный вызов виртуального метода Sound(); //--- неявный вызов (через третью функцию) CallSound(); //--- в конструкторе и/или деструкторе всегда вызываются свои функции, //--- несмотря на виртуальность и переопределение вызываемой функции в потомке //--- если вызываемая функция чисто виртуальная, то //--- вызов приведет к критической ошибке выполнения: "pure virtual function call" } };Однако конструкторы и деструкторы абстрактных классов могут вызывать другие функции-члены.
typedef int (*TFunc)(int,int);Теперь TFunc является типом и можно объявить переменную-указатель на функцию:
TFunc func_ptr;В переменную func_ptr можно сохранить адрес функции, чтобы в дальнейшем ее вызывать:
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; // ошибка: neg не имеет тип int (int,int) Print(func_ptr(10)); // ошибка: должно быть два параметраУказатели на функции можно хранить и передавать в качестве параметра. Нельзя получить указатель на нестатический метод класса.
ulong PositionGetTicket( int index // номер в списке позиций );
bool PositionSelectByTicket(
ulong ticket // тикет позиции
);

MetaEditor: В Мастер MQL5 добавлена ссылка на обучающий видеоролик "Как собрать торгового робота в Мастере MQL5". Посмотрите 3-минутное видео и создайте торгового робота, не написав ни одной строчки кода.
