English 中文 Español Deutsch 日本語 Português
preview
От начального до среднего уровня: Оператор SWITCH

От начального до среднего уровня: Оператор SWITCH

MetaTrader 5Примеры |
412 0
CODE X
CODE X

Введение

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

В предыдущей статье, "От начального до среднего уровня: Директива #include", мы рассказали об основах использования директивы компиляции #include. Но это был лишь первый шаг для того, чтобы вы адекватно усвоили материал и потратили время на изучение операторов управления потоком выполнения. Очень важно, чтобы вы хорошо изучили и усвоили их, потому что они нам необходимы. Но мы еще не закончили. Нам осталось рассказать еще о двух операторах, присутствующих в MQL5. Эти два оператора довольно сложнее, по крайней мере, с точки зрения нескольких аспектов, которые требуют внимания при их использовании.

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

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

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


Оператор SWITCH

Этот оператор, который буквально означает "переключатель", может заменить оператор IF. Однако есть небольшая деталь, которую необходимо учитывать при использовании оператора SWITCH вместо оператора IF.

Чтобы понять, как это произойдет, нам нужно узнать еще кое-что. В программировании нередки ситуации, когда мы проверяем одну и ту же переменную, чтобы найти ОЧЕНЬ конкретное значение. Выражение "очень конкретное" является ключевым. Это связано с тем, что значение не может быть большим, меньшим или приблизительным, это должно быть именно то, что мы ищем. Ни больше, ни меньше: ТОЧНО.

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

Проще говоря, можно использовать SWITCH вместо нескольких операторов IF только в том случае, если переменная, которую нужно проверять, одинакова в разных условиях IF. Можно проверить, равна ли переменная определенному значению. Но невозможно проверить, больше она или меньше заданного значения. Кроме того, размер в битах влияет на результат проверки. Это очень простое описание функции оператора SWITCH.

При таком объяснении идея может показаться сложной или, по крайней мере, непрактичной. Однако всё совсем не так, как вы думаете. Оператор SWITCH часто используется в различных ситуациях. Хотя на первый взгляд он может показаться ограниченным и сложным в использовании, он очень полезен.

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

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

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     uchar counter = 5;
07. 
08.     if (counter == 5) Print("The counter value is five."); else
09.     if (counter == 3) Print("The counter value is three."); else
10.     if (counter == 1) Print("The counter value is one."); else
11.         Print("The counter value is unknown.");
12. }
13. //+------------------------------------------------------------------+

Код 01

Я знаю, что многие посмотрят на это и скажут: "Код довольно-таки базовый". Да, я знаю, но нам действительно нужно начать с чего-то очень простого. Иначе можно запутаться в попытках понять, что будет дальше.

Одного лишь взгляда на этот код достаточно, чтобы понять, что будет отображаться в терминале MetaTrader 5, поэтому я считаю излишним показывать печатное сообщение. Если не можете понять это, просто взглянув на этот код, я настоятельно рекомендую вам остановиться, вернуться назад и начать с самого начала, просмотрев начальные статьи. Начните с первой статьи под названием "От начального до среднего уровня: Переменные (I)". Не думайте, что вы сможете научиться программировать, пропуская шаги, потому что это не так. Прежде чем отправляться на неведомую территорию, ознакомьтесь с базовыми понятиями и операторами.

Хорошо, давайте продолжим. Здесь отчетливо видно, что мы имеем то, что было определено в начале этой темы. Иными словами, у нас есть одна переменная, значение которой оценивается в разных операторах IF. И в каждом из них мы проверяем одно значение. Мы не ищем, где больше или меньше, а ищем именно точное значение, это ключевой момент. То есть, получив нечто похожее на показанное в коде 01, мы можем использовать более элегантный оператор. Данный оператор - это оператор SWITCH.

С учетом этого давайте рассмотрим еще один фрагмент кода, который при выполнении приведет к тому же результату. Он показан ниже:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     uchar counter = 5;
07. 
08.     switch (counter)
09.     {
10.         case 5:
11.             Print("The counter value is five.");
12.             break;
13.         case 3:
14.             Print("The counter value is three.");
15.             break;
16.         case 1:
17.             Print("The counter value is one.");
18.             break;
19.         default:
20.             Print("The counter value is unknown.");
21.     }
22. }
23. //+------------------------------------------------------------------+

Код 02

Вот и всё, дорогой читатель. Код 02 аналогичен коду 01 и дает точно такой же результат, между ними нет никакой разницы. Но вы можете подумать: "Ух ты, это выглядит гораздо сложнее. Я предпочитаю использовать код 01 вместо кода 02". Правда, на первый взгляд, код 02 кажется гораздо сложнее. Так почему же при реализации своих программ кто-то предпочтет использовать код 02, а не код 01? На самом деле, объяснить использование оператора SWITCH в ее самом базовом и простом виде не так уж и просто. Однако я могу уверить, что оператор SWITCH имеет значительное преимущество перед оператором IF во многих ситуациях. Это связано с возможностью оператора SWITCH, которой нет у оператора IF: способность обрабатывать значения, отличающиеся от тех, которые мы проверяем.

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

Хорошо, давайте посмотрим на код 02 без спешки. Здесь можно наблюдать некоторые интересные детали в его использовании. Во-первых, что здесь делает этот оператор BREAK? Разве это не оператор, используемый внутри циклов? Именно так. Оператор BREAK, который вы видите здесь, на самом деле используется в циклах. Однако иногда он используется и в операторе SWITCH. Это позволяет нам контролировать его работу. Другими словами, когда мы используем оператор BREAK, мы говорим компилятору, что хотим, чтобы его выполнение остановилось в этой конкретной точке в процедуре SWITCH, и таким образом, компилятор точно знает, что делать. В некотором смысле это похоже на то, что происходит внутри цикла. Разница лишь в том, что здесь есть четкое разделение между выполняемыми задачами. Не волнуйтесь, мы дойдем и до этого момента. Но сначала мы поговорим о том, что также можно наблюдать здесь: о зарезервированных словах CASE. Если обратить внимание на коды 01 и 02, то заметим определенное сходство в их структуре.

Оператор SWITCH отображается как `if`, за которым следует блок кода. Слово CASE выступает в качестве оператора равенства, показанного в каждом выражении оператора IF в коде 01. Далее находится значение, которое в точности совпадает со значением каждого выражения оператора IF. Интересно, не правда ли? Это не совпадение, дорогой читатель. Вот как работает оператор SWITCH и как его следует понимать при практическом использовании. По этой причине при поверхностном рассмотрении оператор SWITCH может показаться гораздо более сложным, чем он есть на самом деле. Но когда мы это понимаем, всё становится простым и очень интересным, и вскоре мы начнем думать о новых возможностях.

Однако в коде 01 есть строка 11, которая выполняется, если ни одно значение не соответствует ожидаемому. То же самое относится и к SWITCH. Для этого мы используем еще одно зарезервированное слово: DEFAULT. Внутри подпрограммы или блока SWITCH данное слово указывает компилятору, что если не найдено значение, соответствующее значению, проверенному в выражении SWITCH, то должна выполняться альтернативная подпрограмма. Обычно так называемый оператор DEFAULT располагается в конце блока внутри SWITCH. Таким образом, сохраняется структурная логика оператора. Однако не существует правил, указывающих, где его следует расположить. Это может показаться немного необычным.

Интересно, не так ли? Однако стоит отметить одну деталь, которая еще больше проясняет полезность оператора SWITCH. Она относится к следующему факту: оператор IF выполнит соответствующую процедуру только в том случае, если значение выражения будет истинным. Независимо от значения, результат должен быть истинным, чтобы программа выполнилась. В случае с оператором SWITCH ситуация несколько иная. В этом случае значение выражения должно быть проверено с численным образом. То есть на самом деле важно, равно значение или нет тому значению, которое проверено в выражении оператора SWITCH. Блок CASE будет выполнен только в том случае, если значение равно тому значению, которое указано в выражении оператора SWITCH. Однако блок CASE завершается оператором BREAK или в конце блока SWITCH. Поэтому будьте внимательны.

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

Хорошо, в любом случае, давайте посмотрим, как будет выглядеть поток выполнения оператора SWITCH. Это хорошо видно на рисунке ниже:

Рисунок 01

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

Давайте перейдем к объяснениям. Как видите, всё начинается как и в любом другом операторе. Иными словами, когда мы используем зарезервированное слово для обозначения оператора, который нужно использовать. С этого момента и до конца, когда будет достигнута точка выхода, всё происходящее принадлежит подпрограмме в операторе SWITCH. Всё, что происходит здесь, не будет видно ни одному другому оператору. Понимание этого очень важно чтобы разобраться в том, что мы рассмотрим далее в этой статье.

Теперь перейдем к выражению. Это выражение следует понимать в числовых, а не логических терминах. Что это означает на практике? Это значит, что использование в выражении условий типа "больше, чем" или "меньше, чем" не даст того эффекта, который можно себе представить. Таким образом, это не что-то вроде оператора IF, где нас интересует, является ли выражение истинным или ложным. В случае с SWITCH выражение ВСЕГДА ДОЛЖНО РАССМАТРИВАТЬСЯ КАК ЧИСЛО, и полученное число будет зависеть от следующего шага.

Следующий шаг - это операторы CASE. На этом этапе выражение будет проверено логически, то есть оно будет анализироваться как истинное или ложное. Но подождите минутку. Кажется, есть какое-то противоречие. Только что было сказано, что выражение НЕ будет анализироваться как истинное или ложное, а будет анализироваться с помощью числовых значений. И теперь говорится, что оно будет проанализировано как истинное или ложное? Сейчас нужно определиться, потому что так никто не поймет.

На самом деле, это может показаться немного запутанным. Вы видите, что выражение сравнивается с несколькими операторами CASE, и здесь нет определенного порядка. Выражение и оператор CASE отличаются только тем, что между ними есть числовые значения. Однако, когда выполняется оператор CASE, он проверяет значение логически, то есть как true или false. Именно по этой причине рядом с оператором CASE я включаю другую информацию: VALUE. Это то, что проверит значение выражения на соответствие с оператором CASE и разрешит или запретит выполнение ROUTINE. Чтобы включить или выключить выполнение чего-нибудь, нам нужно логически сравнить значения. Это делает объяснение каждой детали данного оператора немного сложным, так как многие могут представить, что проверка выполняется в начальном выражении, в то время как на самом деле она происходит во время выполнения оператора CASE.

Разве я не говорил, что оператор SWITCH может вас запутать, если вы не поняли то, что объяснялось в предыдущих статьях? И всё же мы работаем с ним на самом базовом уровне.

В любом случае, когда оператор CASE проверит, что выражение равно VALUE, тогда выполнится ROUTINE. С этим закончили. Теперь перейдем к той части, которая будет объяснена позже и которая как раз и является красной линией на изображении 01. В этой строке всё становится по-настоящему сложным. Но сейчас мы не будем говорить об этом. Мы проигнорируем эту красную линию в данный момент. Если не хотите изучать, что происходит, когда поток проходит эту линию, не стоит пока этим заниматься. Сделайте так: в конце кода ROUTINE нужно поместить оператор BREAK. Выполнив это, мы, наконец, достигнем точки выхода оператора SWITCH. Данный оператор очень забавный, но в некоторых ситуациях он может стать головной болью, поскольку существуют способы построения кода, которые делают его разбор очень сложным, если мы не понимаем операторов управления потоком.

Хорошо, всё ясно и замечательно. Но у меня есть вопрос. В предыдущих статьях мы увидели, что оператор BREAK позволяет выйти из цикла без вычисления его выражения. Я это понимаю, но, когда я увидел этот оператор SWITCH вместе с оператором BREAK, я немного растерялся. Если мы находимся внутри цикла и используем оператор BREAK внутри SWITCH, как было указано, не приведет ли это к тому, что цикл завершится раньше, чем ожидалось? Это хороший вопрос. Вопрос от человека, который действительно следит и понимает все статьи, которые я публиковал до сих пор на эту тему. Давайте сделаем следующее: поскольку мы уже знаем, как создать цикл и управлять его работой изнутри с помощью операторов BREAK, RETURN и CONTINUE, давайте сделаем нечто, что всё это объяснит наглядно.

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

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " Counting...");
07.     Print(__FUNCTION__, " ", __LINE__, " Pit Stop :: ", Tic_Tac());
08.     switch (Tic_Tac())
09.     {
10.         case true:
11.             Print(__FUNCTION__, " ", __LINE__, " Return TRUE");
12.             break;
13.         case false:
14.             Print(__FUNCTION__, " ", __LINE__, " Return FALSE");
15.             break;
16.     }
17. }
18. //+------------------------------------------------------------------+
19. bool Tic_Tac(void)
20. {
21.     static uchar counter = 10;
22. 
23.     while (true)
24.     {
25.         switch (counter)
26.         {
27.             case 8:
28.                 counter = counter - 1;
29.                 return false;
30.             case 6:
31.                 Print("Press TAB to continue or ESC to abort the count.");
32.                 counter = counter - 1;
33.                 break;
34.             case 5:
35.                 if (TerminalInfoInteger(TERMINAL_KEYSTATE_TAB))
36.                 {
37.                     Print("Accelerating count.");
38.                     counter = 2;
39.                 } else if (TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE))
40.                 {
41.                     Print("General panic...");
42.                     return false;
43.                 }
44.                 continue;
45.             case 0:
46.                 return true;
47.             default:
48.                 counter = counter - 1;
49.         }
50.         Print(__FUNCTION__, " ", __LINE__, " :: ", counter);
51.         Sleep(300);
52.     }
53.     Print(__FUNCTION__, " ", __LINE__, "This line will never be executed.");
54. }
55. //+------------------------------------------------------------------+

Код 03

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

Анимация 01

На анимации 01 можно увидеть, что происходит при нажатии клавиши ESC. Когда будет нажата клавиша TAB, мы увидим несколько иное. Это показано на следующей анимации.

Анимация 02

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

Что ж, я не буду вдаваться в подробности некоторых деталей. Я хочу, чтобы вы просмотрели и изучили предыдущие статьи, чтобы действительно узнать, как работают операторы управления потоком. Тем не менее, я объясню как всё происходит в коде 03.

Начнем с точки входа в код, то есть с OnStart. Строка 6 показывает, на каком этапе находится реализация. Данная строка выводится во время выполнения. Однако в случае со строкой 7 всё происходит не сразу. Это происходит так, потому что вызов функции Tic_Tac выполняется в той же строке. Поэтому полное выполнение строки 7 откладывается до тех пор, пока функция Tic_Tac не выполнит свои задачи.

Оказавшись внутри функции Tic_Tac в строке 19, она попадает в бесконечный цикл в строке 23. Но не волнуйтесь, хотя этот цикл бесконечен, есть точки, в которых мы можем вырваться из него. Будьте внимательны, ничего не пропускайте. Обратите внимание, что в строке 25 мы используем оператор управления потоком SWITCH. При каждом интересующем нас значении отсчета мы будем выполнять определенное действие. Помните, что переменная count - статическая. Это очень важно. Таким образом, когда счетчик достигнет значения 8, мы вернемся к вызывающей программе с ложным значением. В этот момент строка 7 будет полностью выполнена. Это объясняет, почему на экране терминала появляется сообщение. После этого в строке 8 снова вызывается функция Tic_Tac. Но на этот раз мы будем использовать возврат функции в качестве выражения оператора SWITCH. Опять же, выполнение оператора должно ждать, пока функция Tic_Tac выполнит свои задачи. Затем мы возвращаемся к выполнению кода в строке 19.

Но постойте, разве мы не ушли на 29-й строке? Не заставит ли это код повторить всё с самого начала, в результате чего мы снова завершим цикл из строки 23 ровно на строке 29? На самом деле, это может случиться. Однако, поскольку строка 28 выполнилась до возврата к вызывающей программе, мы теперь нацелены не на значение восемь, а на значение семь. Поскольку в операторе SWITCH в строке 25 нет действий, которые привели бы к выполнению выражения со значением семь, в этом случае мы перейдем к строке 47. Так как строке 47 поручено выполнить только строку 48, которая уменьшает счетчик на одну единицу, теперь мы будем стремиться к значению шесть.

Однако после завершения части, соответствующей оператору SWITCH, мы выполним строки 50 и 51. По этой причине некоторые значения не отображаются на терминале, например, семь. Но как только мы выведем значение шесть, мы вернемся в начало цикла и снова выполним оператор SWITCH. Теперь выражение имеет значение шесть и, следовательно, с ним связан CASE. Будьте внимательны. Когда строка 31 будет выполнена, на терминал выведется новое сообщение. Затем, в строке 32, счетчик будет указывать на значение пять. Но что происходит тогда в строке 33, где у нас есть оператор BREAK? Именно здесь многие начинающие программисты путаются. Это связано с тем, что данный оператор BREAK, как объяснялось в предыдущей статье, приводит к завершению цикла, в котором он объявлен. Это факт, и он был продемонстрирован в статье, где объясняли этот оператор. Однако в данном конкретном случае это не так. В этом случае оператор SWITCH имеет приоритет над всеми циклами, в которых он используется. То есть оператор BREAK относится к оператору SWITCH, а не к рассматриваемому циклу, будь то WHILE, DO WHILE или FOR.

Я знаю, что это может быть немного запутанным, но чтобы показать, что именно так и происходит на самом деле, я включил в строку 53 сообщение, которое НИКОГДА не будет выведено в коде 03, даже несмотря на наличие оператора BREAK в строке 33. Это единственный разрыв, присутствующий во всем коде 03.

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

Таким образом, когда оператор BREAK будет выполнен в строке 33, мы перейдем непосредственно к строке 50. Помните, что счетчик был уменьшен в строке 32. По этой причине в выводимом сообщении укажем, что значение переменной подсчета равно 5.

Цикл выполняется снова, и оператор SWITCH проверяется еще раз. Теперь выражение указывает на значение пять. Поскольку с этим значением связан CASE, мы выполним его. И вот тут происходит что-то интересное. Тут важно понять, что происходит в этот момент. Здесь мы будем ждать, пока пользователь нажмет одну из клавиш, указанных в сообщении, которое было выведено, когда счетчик имел значение шесть. Но (и это главное, что вам нужно понять), если пользователь не нажмет ни одной клавиши, будет выполнен оператор CONTINUE, расположенный в строке 44. Теперь возникает вопрос. Поскольку оператор CONTINUE всегда связан с циклом, мы сразу же вернемся к строке 23. Поэтому строки 50 и 51 перестанут выполняться до тех пор, пока значение выражения будет равно пяти. Когда пользователь нажмет на клавишу, поток снова изменится. В этом случае выполнится строка 38, в результате чего счетчик изменится на значение два. В противном случае выполнится оператор в строке 42. В любом случае, в какой-то момент, либо в строке 42, либо в строке 46, цикл будет прерван. Однако ни в одном из этих случаев строка 53 не выполнится. Затем мы вернемся к строке 8. В этот момент выражение должно быть проверено. Но ведь можно подумать: разве SWITCH не должен анализировать выражение численно? Почему значения CASE имеют булевый тип? Для меня это не имеет смысла. И в этом вся суть дела. Когда мы объясняли оператор IF, мы говорили о преобразовании значения в истинный или ложный. Что касается ложного значения, то здесь нет никаких изменений, но для истинного значения всё обстоит несколько иначе. Это происходит так, потому что значение TRUE, которое мы видим в строке 10, на самом деле является значением один. То есть, если функция Tic_Tac возвращает значение, равное либо нулю, либо единице, данный оператор SWITCH в строке 8 сможет понять его и отобразить один из двух вариантов. Однако если мы модифицируем функцию Tic_Tac, чтобы она возвращала значение, отличающееся от нуля или единицы, оператор SWITCH в строке 8 не найдет соответствия, связанного с возвращаемым значением. В этом случае сообщение не отображается.

Однако важно отметить следующий момент. Если вместо SWITCH в восьмой строке мы используем оператор IF, то на экран может быть выведено сообщение. Это зависит от того, как мы реализуем оператор `if`. Поскольку цель этой статьи - заставить читателя начать думать как программист, я не буду показывать вам, как следует действовать в этом случае. Я упоминаю данные факты только для того, чтобы вы начали рассуждать как программист и попытались понять, что на самом деле делает каждый оператор, а также его возможности и ограничения в управлении потоком.


Заключительные идеи

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

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

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

Прикрепленные файлы |
Anexo.zip (1.43 KB)
Биологический нейрон для прогнозирования финансовых временных рядов Биологический нейрон для прогнозирования финансовых временных рядов
Выстраиваем биологически верную систему нейронов для прогнозирования временных рядов. Внедрение плазмоподобной среды в архитектуру нейронной сети создало своеобразный "коллективный разум", где каждый нейрон влияет на работу системы не только через прямые связи, но и посредством дальнодействующих электромагнитных взаимодействий. Как покажет себя нейронная система моделирования мозга на рынке?
Реализация советника Deus: Автоматическая торговля с RSI и скользящими средними в MQL5 Реализация советника Deus: Автоматическая торговля с RSI и скользящими средними в MQL5
В статье описываются шаги по внедрению советника Deus на основе индикаторов RSI и скользящей средней для управления автоматической торговлей.
Нейросети в трейдинге: Мультизадачное обучение на основе модели ResNeXt Нейросети в трейдинге: Мультизадачное обучение на основе модели ResNeXt
Фреймворк многозадачного обучения на основе ResNeXt оптимизирует анализ финансовых данных, учитывая их высокую размерность, нелинейность и временные зависимости. Использование групповой свертки и специализированных голов позволяет модели эффективно извлекать ключевые признаки исходных данных.
Разработка системы репликации (Часть 64): Нажатие кнопки воспроизведения в сервисе (V) Разработка системы репликации (Часть 64): Нажатие кнопки воспроизведения в сервисе (V)
В данной статье мы рассмотрим, как исправить две ошибки в коде. Однако я постараюсь объяснить их так, чтобы вы, начинающие программисты, поняли, что не всегда всё происходит так, как вы предполагали. Но это не повод отчаиваться, это возможность учиться. Представленные здесь материалы предназначены только для обучения. Ни в коем случае не рассматривайте это приложение как окончательное, цели которого иные, кроме изучения представленных концепций.