English Español Português
preview
Разработка системы репликации (Часть 38): Прокладываем путь (II)

Разработка системы репликации (Часть 38): Прокладываем путь (II)

MetaTrader 5Примеры | 29 апреля 2024, 11:24
420 0
Daniel Jose
Daniel Jose

Введение

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

Самое важное, понять содержание и, прежде всего, то, как был достигнут желаемый результат. Ни в коем случае нельзя дублировать индикатор.

Подтверждая принцип отсутствия дублирования в MetaTrader 5, мы подчеркиваем, что до двусторонней связи между индикатором и советником еще далеко. Мы еще очень далеки от этого. Однако гарантия того, что индикатор не будет продублирован на графике, хотя бы придает спокойствия. И это связано с тем, что при взаимодействии индикатора и советника мы будем знать, что имеем дело с правильным индикатором.

В этой статье мы начнем смотреть на вещи глазами советника, но нам также придется внести некоторые изменения в индикатор, потому что тот индикатор, который был в предыдущей статье, к сожалению, не может среагировать на советник вообще. Это происходит, когда советник хочет что-то узнать.


Создание первого взаимодействия между процессами

Чтобы вы действительно могли понять, что происходит, нам нужно создать несколько контрольных точек. Начнем с кода индикатора; не волнуйтесь, всё это легко для понимания.

Полный код индикатора можно найти ниже:

01. #property copyright "Daniel Jose"
02. #property link      ""
03. #property version   "1.00"
04. #property indicator_chart_window
05. #property indicator_plots 0
06. //+------------------------------------------------------------------+
07. #define def_ShortName       "SWAP MSG"
08. #define def_ShortNameTmp    def_ShortName + "_Tmp"
09. //+------------------------------------------------------------------+
10. input double user00 = 0.0;
11. //+------------------------------------------------------------------+
12. long m_id;
13. //+------------------------------------------------------------------+
14. int OnInit()
15. {
16.     m_id = ChartID();
17.     IndicatorSetString(INDICATOR_SHORTNAME, def_ShortNameTmp);
18.     if (ChartWindowFind(m_id, def_ShortName) != -1)
19.     {
20.             ChartIndicatorDelete(m_id, 0, def_ShortNameTmp);
21.             Print("Only one instance is allowed...");
22.             return INIT_FAILED;
23.     }
24.     IndicatorSetString(INDICATOR_SHORTNAME, def_ShortName);
25.     Print("Indicator configured with the following value:", user00);
26.     
27.     return INIT_SUCCEEDED;
28. }
29. //+------------------------------------------------------------------+
30. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
31. {
32.     return rates_total;
33. }
34. //+------------------------------------------------------------------+


Обратите внимание, что единственным дополнением к коду является строка 25. Она будет нашей строкой проверки, по крайней мере, на первое время. В данный момент нас интересует, как советник взаимодействует с индикатором и можем ли мы отправлять ему информацию или данные.

Следует отметить, что в строке 10 вид информации, ожидаемый индикатором, - это double. Мы сделали так специально, поскольку цель состоит в том, чтобы создать механизм, который сможет заменить глобальную систему терминальных переменных для связи между советником и индикатором. Если разработанные или применяемые средства окажутся неподходящими, то не составит труда заменить эту модель моделью глобальных переменных терминала.

Однако ничто не мешает нам использовать другие виды данных для обеспечения связи, по крайней мере, в том, что касается передачи данных от советника к индикатору.

Теперь, когда мы изменили код индикатора, мы можем перейти к коду советника, который можно увидеть в полном объеме ниже:

01. #property copyright "Daniel Jose"
02. #property link      ""
03. #property version   "1.00"
04. //+------------------------------------------------------------------+
05. input double user00 = 2.0;
06. //+------------------------------------------------------------------+
07. int m_handle;
08. long m_id;
09. //+------------------------------------------------------------------+
10. int OnInit()
11. {
12.     m_id = ChartID();
13.     if ((m_handle = ChartIndicatorGet(m_id, 0, "SWAP MSG")) == INVALID_HANDLE)
14.     {
15.             m_handle = iCustom(NULL, PERIOD_CURRENT, "Mode Swap\\Swap MSG.ex5", user00);
16.             ChartIndicatorAdd(m_id, 0, m_handle);
17.     }
18.     Print("Indicator loading result:", m_handle != INVALID_HANDLE ? "Success" : "Failed");
19.     
20.     return INIT_SUCCEEDED;
21. }
22. //+------------------------------------------------------------------+
23. void OnDeinit(const int reason)
24. {
25.     ChartIndicatorDelete(m_id, 0, "SWAP MSG");
26.     IndicatorRelease(m_handle);
27. }
28. //+------------------------------------------------------------------+
29. void OnTick()
30. {
31. }
32. //+------------------------------------------------------------------+


Для многих данный код советника может показаться довольно странным. Давайте посмотрим, как это работает. Будьте внимательны, потому что это первый этап того, что нам действительно нужно сделать.

В строке 05 мы даем пользователю возможность задать значение, передаваемое индикатору. Помните: мы хотим проверить и понять, как будет происходить связь. Строки 07 и 08 содержат две внутренние глобальные переменные в коде советника. Обычно я не люблю использовать глобальные переменные, но в данном случае можно делать исключение. Содержимое этих переменных будет определено в коде, который обрабатывает команду OnInit, который начинается в строке 10.

Здесь многие скажут: "Вот теперь всё усложняется". Причина в том, что на данном этапе нам необходимо понять несколько моментов.

В строке 12 мы инициализируем переменную, которая будет указывать индекс таймфрейма, на котором находится советник. Но на строке 13 начинаются проблемы для начинающих. Многие просто не добавляют эту строку в свой код, что является ошибкой в некотором смысле. Это конечно не то, что сразу же сломает ваш код; нет, но включение строки 13 в код предотвращает появление некоторых видов ошибок. И многие из этих ошибок - это ошибки по RUN-TIME, которые могут возникнуть в любой момент, что затрудняет их устранение.

Тот факт, что мы используем данный код в строке 13, означает, что, если в MetaTrader 5 уже есть нужный нам индикатор на графике, он вернет "хэндл этого индикатора". Таким образом, нам не нужно брать на себя ответственность за размещение индикатора на графике.

Но если строка 13 показывает, что на графике нет нужного индикатора, мы запустим код, который добавит индикатор на график. Запомните следующий факт: индикатор, который мы хотим и будем использовать, является пользовательским. Для этого мы воспользуемся вызовом iCustom, который можно увидеть в строке 15.

Теперь начинается самая сложная часть этой истории: почему iCustom, присутствующий в строке 15, объявлен таким образом? У вас есть идеи, почему? Чтобы понять это, давайте посмотрим, что говорится в документации:

int  iCustom(
                 string            symbol,   // имя символа
                 ENUM_TIMEFRAMES   period,   // период
                 string            name      // folder/имя_пользовательского_индикатора
                 ...                         // перечисление входных параметров индикатора
             );

Из таблицы выше видно, что первым параметром функции является имя символа. Но в строке 15 кода первым параметром является NULL. Почему это так? Почему мы не использовали константу _Symbol? Причина в том, что для компилятора данные NULL и _Symbol являются одним и тем же. Таким образом, индикатор будет создан с использованием того же символа или актива, что и на графике советника.

Следующий параметр в списке - время, или период графика. И снова у нас нечто отличающееся от того, что многие ожидают. В строке 15 мы используем значение PERIOD_CURRENT, но почему? Причина в том, что мы хотим, чтобы индикатор остался синхронизированным с тем же периодом, что и советник. Одна деталь: если мы хотим, чтобы индикатор смотрел на другой период графика, просто укажем нужный период здесь, в этом параметре. Таким образом, индикатор будет зафиксирован на определенном периоде, а советник сможет перемещаться по разным периодам.

Когда речь заходит о пользовательских индикаторах, я считаю, что именно третий параметр может привести к серьезным последствиям. Многие люди не знают, что сюда поместить, и иногда отказываются, потому что не понимают, либо указывают не на то место. Если мы укажем неправильное местоположение, MetaTrader 5 не сможет найти нужный нам индикатор.

Посмотрите, что объявлено в строке 15, в этом третьем параметре. Мы указываем не просто имя, а имя и путь. Откуда берется эта информация? Чтобы узнать это, нам придется вернуться к предыдущей статье и выяснить, откуда взялась эта информация. Смотрите на рисунок 01.

Рисунок 01

Рисунок 01 - Создание индикатора

На рисунке 01 можно увидеть, откуда берется информация для третьего параметра. Обратите внимание, что это практически одно и то же. Со следующими изменениями: сначала удаляем корневой каталог, в данном случае это будет indicators. Это связано с тем, что MetaTrader 5 сначала будет искать индикатор в данном каталоге. Второй момент заключается в том, что мы добавили файл .ex5. Таким образом, мы получим правильное расположение исполняемого файла. Когда MetaTrader 5 разместит советник на графике и выполнит строку 15, он будет знать, где и какой индикатор нужно использовать.

Ниже мы рассмотрим некоторые вопросы, связанные с этим, а также проблемы, которые могут возникнуть, но сначала давайте разберемся с основами.

Начиная с этого третьего параметра и далее все остальные параметры являются необязательными. Если мы хотим использовать или отправлять значение в индикатор, мы должны сделать это из четвертого параметра. Надо следить за тем, чтобы это происходило в той же последовательности, в которой параметры появляются на индикаторе. Также нужно убедиться в том, чтобы они были одного типа. Нельзя вводить значение double, если индикатор ожидает получить значение float или long. В данном случае MetaTrader 5 выдаст ошибку сразу после запуска индикатора.

Существуют и другие способы передачи параметров индикатору, но пока для простоты мы будем использовать iCustom. Если вы посмотрите на код индикатора, то увидите что в строке 10 ожидается значение double. Данное значение учитывается в индикаторе через советник, в четвертом параметре строки 15 кода советника.

Теперь важный вопрос, которым многие пренебрегают, что приводит к проблемам во всей системе. Это строка 16 в коде советника. Но почему эта строка так важна?

Есть случаи, когда эту строку можно игнорировать, когда речь идет о пользовательских индикаторах; особенно это касается тех индикаторов, которые нам нужны, когда MetaTrader 5 должен поддерживать только один экземпляр индикатора, запущенный на графике. Мы не можем игнорировать или пренебрегать строкой 16 ни в каком виде или форме, и когда строка 16 присутствует, строка 25 также должна быть добавлена.

Эти две строки позволяют избежать проблем. Строка 16 воспроизведет индикатор на графике. Таким образом, если пользователь попытается воспроизвести другой экземпляр индикатора на том же графике, MetaTrader 5 вместе с кодом индикатора запретит запуск нового экземпляра. Если удалить строку 16 из кода советника, пользователь может случайно поместить на график новый экземпляр индикатора, в результате чего не советник, а пользователь запутается в вопросах, связанных с расчетами, которые индикатор выполняет.

В случае с расчетными индикаторами мы сталкиваемся с определенной проблемой, но в случае с таким индикатором, как Chart Trader, проблема еще сложнее. Поскольку в данном случае мы имеем дело с графическими объектами, давайте лучше не будем спешить. Для начала важно разобраться в том, как всё правильно сделать. Тогда мы сможем понять, как делать более сложные вещи.

Я думаю, теперь понятно, насколько важна строка 16. А строка 25 - что она делает? Она удалит с графика индикатор, о котором мы сообщаем. Обратите внимание на один момент: нам необходимо знать имя удаляемого индикатора. Оно помещается в индикатор в строке 24 кода индикатора. Имена должны быть одинаковыми, иначе MetaTrader 5 не поймет, какой индикатор нужно удалить. Кроме того, в некоторых случаях мы также должны сообщить, какое именно подокно задействовано. Поскольку мы не используем подокно, данное значение оставляем равным НУЛЮ.

Теперь, в строке 26 мы удаляем обработчик индикатора, потому что он нам больше не нужен.

Давайте теперь посмотрим, как MetaTrader 5 работает с этой схемой взаимодействия между советником и индикатором. Чтобы понять это, нужно выполнить несколько действий. Поэтому внимательно следите за деталями процесса. И с каждой модификацией тестируйте и экспериментируйте со сгенерированным кодом, потому что каждое из изменений принесет MetaTrader 5 свой способ борьбы с ними. Гораздо важнее не просто прочитать приведенные выше объяснения, а понять происходящее. И чтобы понять, что происходит, когда советник написан определенным образом или когда тот же самый советник запрограммирован по-другому, необходимо рассмотреть три ситуации. Код, используемый в советнике и индикаторе, такой же, как тот, который мы объясняли до сих пор, разница только в содержании, точнее, в наличии или отсутствии строки кода советника.

Давайте теперь сделаем следующее:

  • Сначала скомпилируем код со всеми строками и посмотрим, как система работает в MetaTrader 5.
  • Затем удалим строки 16 и 25 и повторно протестируем систему в MetaTrader 5.
  • Наконец, удалим только строку 16 и оставим строку 25. Повторно протестируем систему.

Можно подумать, что всё это ерунда, что вы, как опытный программист, никогда не допустите таких ошибок. Но знать, что делает и к чему приводит каждая строка кода при выполнении MetaTrader 5, возможно, гораздо важнее, чем кажется.

Если вы дошли до этого этапа, значит, вы поняли вторую фазу, на которой мы можем передавать данные от советника к индикатору, причем без использования глобальных переменных терминала. Вы сделали большой шаг к тому, чтобы стать качественным программистом. Если вы всё еще не поняли, не отчаивайтесь. Вернитесь к началу этой или предыдущей статьи и постарайтесь понять данный шаг. Теперь всё становится очень сложным: я не шучу. Теперь нам нужно сделать так, чтобы индикатор отправлял данные советнику.

Здесь индикатор отправляет данные советнику. В некоторых случаях это может быть довольно просто, это верно. Но все, кто следит за моими статьями, наверняка заметили, что я люблю доводить дело до крайности, заставлять компьютер потеть и просить у его делать всё по-другому. Это потому что я очень хочу, чтобы и язык, и платформа работали в рамках возможного.


IndicatorCreate или iCustom - что лучше использовать?

Многих новичков мучает один вопрос: как вызвать пользовательские индикаторы. Это можно сделать двумя способами. Первый мы рассмотрели в предыдущей теме, где объясняли использование iCustom. Но есть и другой путь, не менее важный. Это связано с тем, что некоторые виды моделирования более привлекательны, в то время как для других будет достаточно использовать iCustom.

Речь не идет о том, что нужно использовать тот или иной метод. Цель - показать, как можно использовать вызов IndicatorCreate, чтобы иметь возможность загружать в том числе собственные индикаторы.

Прежде чем мы начнем, давайте разберемся с одним вопросом. Функция IndicatorCreate не является специальной функцией; на самом деле это базовая функция. А что это значит на самом деле? Базовая функция - это функция, которая по сути служит для развития других функций, но с некоторыми деталями: "производные" функции используют базовую функцию, но упрощают ее использование.

Это достигается тем, что не нужно моделировать вызов так, как мы ожидали бы от базовой функции. Можно использовать более простое и приятное моделирование. Это порождает и другие функции, которые можно увидеть в документации как Технические индикаторы. Среди этих индикаторов есть iCustom, который, по сути, является производной функцией для упрощения моделирования.

Как бы выглядел исходный код советника, о котором шла речь в начале статьи, если бы вместо iCustom мы использовали IndicatorCreate? Ее код можно увидеть ниже:

01. #property copyright "Daniel Jose"
02. #property link      ""
03. #property version   "1.00"
04. //+------------------------------------------------------------------+
05. input double user00 = 2.2;
06. //+------------------------------------------------------------------+
07. int m_handle;
08. long m_id;
09. //+------------------------------------------------------------------+
10. int OnInit()
11. {
12.     MqlParam params[];
13.     
14.     m_id = ChartID();       
15.     if ((m_handle = ChartIndicatorGet(m_id, 0, "SWAP MSG")) == INVALID_HANDLE)
16.     {
17.             ArrayResize(params, 2);
18.             params[0].type = TYPE_STRING;
19.             params[0].string_value = "Mode Swap\\SWAP MSG";
20.             params[1].type = TYPE_DOUBLE;
21.             params[1].double_value = user00;
22.             m_handle = IndicatorCreate(NULL, PERIOD_CURRENT, IND_CUSTOM, ArraySize(params), params);
23.             ChartIndicatorAdd(m_id, 0, m_handle);
24.     }
25.     Print("Indicator loading result:", m_handle != INVALID_HANDLE ? "Success" : "Failed");
26.     
27.     return INIT_SUCCEEDED;
28. }
29. //+------------------------------------------------------------------+
30. void OnDeinit(const int reason)
31. {
32.     ChartIndicatorDelete(m_id, 0, "SWAP MSG");
33.     IndicatorRelease(m_handle);
34. }
35. //+------------------------------------------------------------------+
36. void OnTick()
37. {
38. }
39. //+------------------------------------------------------------------+

Исходный код советника

Обратите внимание и сравните различия между приведенным выше кодом и тем, который мы показали в начале статьи. Оба выполняют одно и то же. Главный вопрос: почему данный код, использующий вызов IndicatorCreate, должен быть выполнен именно таким образом?

На самом деле функция iCustom скрывает именно то, что нам нужно сделать, но давайте разберемся в том, что происходит.

Во-первых, нам нужно объявить переменную, которая объявляется в строке 12 как массив. Обратите внимание, что мы должны сделать это именно так. Если индикатор не присутствует на графике, его нужно будет создать. Для этого мы должны указать функции IndicatorCreate, что и как делать.

Кроме количества параметров, которые мы используем в индикаторе, мы еще должны сообщить функции IndicatorCreate имя индикатора. Таким образом, если мы собираемся вводить всего лишь имя индикатора, функция ArrayResize в строке 17 должна выделить не две, а одну позицию. Если бы мы передавали индикатору 5 параметров, нам пришлось бы назначить 6 позиций; так будет всегда. Посмотрим, сколько параметров нам нужно отправить, и назначим дополнительную позицию.

После того, как это будет понятно, настроим массив, потому что в строке 22 мы сообщаем функции IndicatorCreate, что собираемся использовать пользовательский индикатор. Для этого используется перечисление IND_CUSTOM. Есть несколько вещей, которые нам понадобятся и которые надо сделать. В строке 18 мы видим, как нужно действовать для первой позиции массива. Помните, что MQL5 создан на основе C++, поэтому мы начинаем считать с нуля. Тип информации в первой позиции должен быть STRING, поэтому объявление составляется так, как показано в строке 18.

В строке 19 вводим имя используемого пользовательского индикатора. Внимание: Обратите внимание, что имя индикатора совпадает с тем, которое бы использовалось, если бы мы пользовались вызовом iCustom. Разница лишь в том, что мы не указываем расширение файла. Файл должен быть исполняемым, поэтому его расширение будет .ex5, поэтому указывать расширение необязательно.

ВАЖНО: То, что сделано в строках 18 и 19, должно выполняться каждый раз, когда используется пользовательский индикатор. Если мы используем любой другой индикатор, каким бы он ни был, то, как только мы начнем настраивать данные массива, нам придется указывать параметры так, как мы будем видеть это дальше, то есть начиная со строки 20 и далее.

Теперь, когда мы указали функции IndicatorCreate, какой пользовательский индикатор использовать, давайте начнем заполнять параметры, которые будут ей передаваться: эти параметры должны быть объявлены в правильном порядке. Неважно, какой индикатор используем; подмена типов или объявление неправильных типов приведет к ошибкам RUN-TIME. Поэтому будьте очень внимательны при заполнении этих данных.

В строке 20 мы указываем, что первый параметр будет иметь тип double. Но это может быть любой из видов, определенных в перечислении ENUM_DATATYPE. Можно использовать любой из них, но есть некоторые моменты, которые нужно считать.

Проще говоря, и это очень просто, типы TYPE_DOUBLE и TYPE_FLOAT будут использоваться в данном случае в строке 21, double_value.

Если бы в строке 20 использовался тип TYPE_STRING, то в строке 21 значение было бы приведено к переменной string_value. Для любого из других возможных типов, объявленных в строке 20, значение будет введено в строке 21 с помощью переменной integer_value.

Это очень важно, так что давайте проясним эту информацию. Для лучшего понимания взгляните на таблицу ниже:

Используемый идентификатор Тип данных Куда поместить значение 

TYPE_BOOL  Булевое integer_value

TYPE_CHAR  Char integer_value    
TYPE_UCHAR    Unsigned Char integer_value    
TYPE_SHORT    Short integer_value    
TYPE_USHORT    Unsigned Short integer_value
   
TYPE_COLOUR    Color integer_value
   
TYPE_INT    Integer integer_value
   
TYPE_UINT    Unsigned Integer integer_value
   
TYPE_DATETIME    DateTime integer_value
   
TYPE_LONG    Long integer_value      
TYPE_ULONG    Unsigned Long integer_value
   
TYPE_FLOAT    Float double_value     
TYPE_DOUBLE    Double double_value
   
TYPE_STRING    String string_value    

Таблица совместимости.

Эта таблица наглядно показывает, что мы будем использовать в строке 20 (используемый ID) и какая переменная получит значение в строке 21. Мы должны сделать это для каждого из параметров, которые будут передаваться нашему пользовательскому индикатору. Поскольку мы используем только один параметр, мы будем работать только с ним.

Обратите внимание, что использование вызова IndicatorCreate гораздо более трудоемко, чем его производной, iCustom, это в нашем конкретном случае.

После того, как мы задали все параметры, которые желаем определить, переходим к строке 22, где, собственно, и вызываем функцию. Обратите внимание: мы так сделали, чтобы можно было легко увеличивать или уменьшать масштаб. Все поля заполнены так, что вам не придется снова редактировать строку 22, если нам понадобится изменить индикатор или количество параметров.

Идея заключается в том, чтобы всегда упрощать вещи, а не усложнять их.

Из-за этой дополнительной работы по настройке такого же типа исполнения в MetaTrader 5, в текущих кодах мы не часто увидим, как используется функция IndicatorCreate. Но ничто нам не мешает использовать его.

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

Чтобы немного ускорить процесс, мы используем функцию IndicatorParameters. Как только вызов данной функции будет выполнен, MetaTrader 5 заполнит ее, чтобы сообщить нам, как конкретно настроен тот или иной индикатор. На основе других анализов для изменения конфигурации этого индикатора используется другая функция, обычно IndicatorCreate. Если советник использует этот индикатор для покупки или продажи, он сразу же поймет, что делать, потому что у нас сработает триггер.

Данный вопрос был подробно рассмотрен и продемонстрирован, насколько это возможно, в последовательности автоматизации. Если быть более точным, то в статье "Как построить советник, работающий автоматически (Часть 15): Автоматизация (VII)", мы посмотрели, как использовать индикатор в качестве триггера для покупки или продажи.

Но, как я только что упомянул, мы можем использовать функцию IndicatorParameters, чтобы сделать советник того же типа еще более интересным. Однако мы не будем исследовать использование функции IndicatorParameters, по крайней мере, не в этой последовательности репликации/моделирования. Я лишь хотел упомянуть о пользе этой функции для тех, кто не знает о ее назначении.


Заключение

В этой статье мы максимально просто показали, как отправлять данные в индикатор, хотя мы сделали это с помощью советника. Можно использовать другие типы процессов, например, сценарии. Хотя это было бы неплохо, но на момент написания статьи не было возможности использовать сервисы в качестве способа выполнения этой самой работы из-за особенностей сервисов.

Но это не страшно, мы должны работать с тем, что у нас есть. Однако данный вопрос еще не до конца закрыт. Осталось понять, как в нашем случае передать данные из индикатора в советник, но он отличается от того, что вы думаете; он не будет таким, каким вы его обычно видите или знаете. Помните, что нам нужен способ использовать Chat Trader в системе репликации/моделирования, но мы не хотим использовать для этого глобальные переменные терминала и не хотим компилировать несколько программ, рискуя забыть скомпилировать какую-нибудь из них.

Чтобы узнать, насколько приблизимся к тому, что нам нужно для Chart Trader, нам понадобится еще одна статья. И это будет главной темой следующей статьи из серии: понять, как подойти к тому, что нам нужно для создания Chart Trader.

Не пропустите следующую статью: тема будет очень интересной и захватывающей.

Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/11591

Прикрепленные файлы |
EA.mq5 (1.36 KB)
swap.mq5 (1.31 KB)
Разметка данных в анализе временных рядов (Часть 5):Применение и тестирование советника с помощью Socket Разметка данных в анализе временных рядов (Часть 5):Применение и тестирование советника с помощью Socket
В этой серии статей представлены несколько методов разметки временных рядов, которые могут создавать данные, соответствующие большинству моделей искусственного интеллекта (ИИ). Целевая разметка данных может сделать обученную модель ИИ более соответствующей пользовательским целям и задачам, повысить точность модели и даже помочь модели совершить качественный скачок!
Как разработать агент обучения с подкреплением на MQL5 с интеграцией RestAPI (Часть 2): Функции MQL5 для HTTP-взаимодействия с REST API игры "крестики-нолики" Как разработать агент обучения с подкреплением на MQL5 с интеграцией RestAPI (Часть 2): Функции MQL5 для HTTP-взаимодействия с REST API игры "крестики-нолики"
В этой статье расскажем о том, как MQL5 может взаимодействовать с Python и FastAPI, используя HTTP-вызовы в MQL5 для взаимодействия с игрой "крестики-нолики" на Python. В статье рассматривается создание API с помощью FastAPI для этой интеграции и приводится тестовый скрипт на MQL5, подчеркивающий универсальность MQL5, простоту Python и эффективность FastAPI в соединении различных технологий для создания инновационных решений.
Как добавить Trailing Stop по индикатору Parabolic SAR Как добавить Trailing Stop по индикатору Parabolic SAR
При создании торговой стратегии нам нужно проверить самые разные варианты защитных стопов. И тут напрашивается динамическое подтягивание уровня Stop Loss вслед за ценой. Наилучшим кандидатом для этого является индикатор Parabolic SAR —трудно придумать что-либо проще и нагляднее.
Нейросети — это просто (Часть 87): Сегментация временных рядов Нейросети — это просто (Часть 87): Сегментация временных рядов
Прогнозирование играет важную роль в анализе временных рядов. В новой статье мы поговорим о преимуществах сегментации временных рядов.