English Español Deutsch 日本語 Português
preview
Разработка системы репликации (Часть 42): Проект Chart Trade (I)

Разработка системы репликации (Часть 42): Проект Chart Trade (I)

MetaTrader 5Примеры | 24 июля 2024, 11:34
312 1
Daniel Jose
Daniel Jose

Введение

В предыдущей статье Разработка системы репликации (Часть 41): Начало второй фазы (II) я показал, как создать индикатор для использования в качестве мыши. Возможно, вы подумали, что это ерунда, и в долгосрочной перспективе от этого не будет никакой пользы. Если это так, то лишь потому, что вы так и не поняли, что происходит.

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

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

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

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

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

Это кажется хорошим решением, разве не так? И именно это мы делали, создавая индикатор мыши. На основе этого индикатора мы начнем создавать серию деталей и компонентов, которые нам очень помогут.

С самого начала этой серии о разработке системы репликации/моделирования, я говорил, что идея состоит в том, чтобы использовать платформу MetaTrader 5 одинаково как в разрабатываемой нами системе, так и на реальном рынке. Важно, чтобы это было сделано должным образом. Никто не хочет тренироваться и учиться сражаться, используя одни инструменты, в то время как во время боя ему придется пользоваться другими. Поверьте, использование системы репликации/моделирования — это тренировка, а торговля на РЕАЛЬНОМ счете — настоящий бой. В реальном бою нужно использовать то, чему вы научились и к чему привыкли на тренировках.

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

Простой инструмент – это Chart Trade. В своей последней версии он был представлен в статье: Разработка торгового советника с нуля (часть 30): CHART TRADE теперь как индикатор?!. По сравнению с тем, что мы сделаем сейчас, этот индикатор покажется детской игрушкой, настолько он прост и неуниверсален. Давайте создадим новый Chart Trade, который сможет гармонично сосуществовать с уже созданным индикатором, а именно — с индикатором мыши.


Новый Chart Trade

Chart Trade, рассмотренный в вышеупомянутой статье, будет служить нам основой, однако мы не будем использовать ни его код, ни шаблон (template). Мы создадим другой, гораздо более зрелый и адекватный нашим потребностям.

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

Начнем с того, что наш Chart Trade использует недавно представленную мной концепцию: программирование RAD. Слово RAD происходит от RapidApplicationDevelopment, что в переводе означает: быстрая разработка приложений. Я познакомился с этой концепцией много лет назад, когда начал программировать для систем Windows. Она очень помогает в эффективном создании приложений, позволяя уделять больше времени работе непосредственно с кодом, вместо того, чтобы беспокоиться о внешнем виде программы. В статье Несколько индикаторов на одном графике (часть 06): превращаем MetaTrader 5 в систему RAD (II), я показал, как использовать нечто подобное в MetaTrader 5.

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

Новый шаблон будет иметь вид, как на рисунке 01, представленном ниже:

Рисунок 01

Рисунок 01 - Шаблон RAD

Именно так. На рисунке 01 изображен реальный вид, который будет иметь Chart Trade. Это шаблон Chart Trade, а не сам Chart Trade, последний можно увидеть в видео 01, чуть ниже, где я демонстрирую взаимодействие между ним и индикатором мыши. Посмотрите видео и обратите внимание, как это работает. Видео наглядно представляет все то, что будет рассмотрено в этой статье, поэтому рекомендуется к просмотру.


Видео 01 - Демонстрационное видео

Исходя из того, что все уже ознакомились с видео 01, приступим к рассмотрению кода индикатора Chart Trade. Но сначала нам нужно сделать небольшое добавление в код класса C_Terminal, как показано в следующем фрагменте.

Фрагмент класса C_Terminal

156. //+------------------------------------------------------------------+
157.            bool IndicatorCheckPass(const string szShortName)
158.                    {
159.                            string szTmp = szShortName + "_TMP";
160.                            
161.                            if (_LastError != ERR_SUCCESS) return false;
162.                            IndicatorSetString(INDICATOR_SHORTNAME, szTmp);
163.                            if (ChartWindowFind(m_Infos.ID, szShortName) != -1)
164.                            {
165.                                    ChartIndicatorDelete(m_Infos.ID, 0, szTmp);
166.                                    Print("Only one instance is allowed...");
167.            
168.                                    return false;
169.                            }
170.                            IndicatorSetString(INDICATOR_SHORTNAME, szShortName);
171.                            ResetLastError();
172.    
173.                            return true;
174.                    }
175. //+------------------------------------------------------------------+

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

Но прежде чем перейти к исходному классу, который будет поддерживать наш Chart Trade, давайте сначала рассмотрим код индикатора. Я меняю порядок изложения, чтобы объяснение класса было более подходящим. Полный код индикатора можно увидеть ниже.

Исходный код индикатора Chart Trade

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property description "Base version for Chart Trade (DEMO version)"
04. #property version   "1.42"
05. #property link "https://www.mql5.com/pt/articles/11652"
06. #property indicator_chart_window
07. #property indicator_plots 0
08. //+------------------------------------------------------------------+
09. #include <Market Replay\Chart Trader\C_ChartFloatingRAD.mqh>
10. //+------------------------------------------------------------------+
11. C_ChartFloatingRAD *chart = NULL;
12. //+------------------------------------------------------------------+
13. int OnInit()
14. {
15.     chart = new C_ChartFloatingRAD("Indicator Chart Trade", new C_Mouse("Indicator Mouse Study"));
16.     if (_LastError != ERR_SUCCESS)
17.     {
18.             Print("Error number:", _LastError);
19.             return INIT_FAILED;
20.     }
21.     
22.     return INIT_SUCCEEDED;
23. }
24. //+------------------------------------------------------------------+
25. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
26. {
27.     return rates_total;
28. }
29. //+------------------------------------------------------------------+
30. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
31. {
32.     (*chart).DispatchMessage(id, lparam, dparam, sparam);
33.     
34.     ChartRedraw();
35. }
36. //+------------------------------------------------------------------+
37. void OnDeinit(const int reason)
38. {
39.     delete chart;
40.     
41.     ChartRedraw();
42. }
43. //+------------------------------------------------------------------+


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

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

Думаю, никаких сложностей с пониманием строк кода индикатора возникнуть не должно. Пожалуй, единственная, которая потребует немного больше работы, — это строка 15. Но и она тоже довольно проста. Мы используем два оператора new для инициализации обоих классов.

Единственное, на что следует обратить внимание, — это информация, передаваемая в виде строковых переменных (string). Первая переменная string относится к имени, которое будет распознаваться MetaTrader 5, когда индикатор находится на графике. Вторая —относится к имени индикатора мыши. Это определено в коде индикатора мыши. Более подробную информацию можно найти в статье: Разработка системы репликации (Часть 41): Начало второй фазы (II).

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


Класс C_ChartFloatingRAD

Несмотря на название, этот класс в основном предназначен для работы с индикатором Chart Trade. На текущем этапе разработки он уже содержит всю необходимую логику, чтобы обеспечить нам поведение, как на видео 01. То есть, если мы проводим исследование, мы не сможем перемещать окно, даже если кликнем по нему и перетащим мышью. Во время исследования перемещение окна невозможно.

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

Исходный код класса C_ChartFloatingRAD

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #include "../Auxiliar/C_Terminal.mqh"
05. #include "../Auxiliar/C_Mouse.mqh"
06. //+------------------------------------------------------------------+
07. class C_ChartFloatingRAD : private C_Terminal
08. {
09.     private :
10.             struct st00
11.             {
12.                     int     x, y, cx, cy;
13.                     string  szObj_Chart;
14.                     long    WinHandle;
15.             }m_Info;
16. //+------------------------------------------------------------------+
17.             C_Mouse *m_Mouse;
18. //+------------------------------------------------------------------+
19.             void CreateWindowRAD(int x, int y, int w, int h)
20.                     {
21.                             m_Info.szObj_Chart = (string)ObjectsTotal(GetInfoTerminal().ID);
22.                             ObjectCreate(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJ_CHART, 0, 0, 0);
23.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = x);
24.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = y);
25.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XSIZE, w);
26.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YSIZE, h);
27.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_DATE_SCALE, false);
28.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_PRICE_SCALE, false);
29.                             m_Info.WinHandle = ObjectGetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_CHART_ID);
30.                             m_Info.cx = w;
31.                             m_Info.cy = 26;
32.                     };
33. //+------------------------------------------------------------------+
34. inline void UpdateChartTemplate(void)
35.                     {
36.                             ChartApplyTemplate(m_Info.WinHandle, "IDE_RAD.tpl");
37.                             ChartRedraw(m_Info.WinHandle);
38.                     }
39. //+------------------------------------------------------------------+
40.     public  :
41. //+------------------------------------------------------------------+
42.             C_ChartFloatingRAD(string szShortName, C_Mouse *MousePtr)
43.                     :C_Terminal()
44.                     {
45.                             if (!IndicatorCheckPass(szShortName)) SetUserError(C_Terminal::ERR_Unknown);
46.                             m_Mouse = MousePtr;
47.                             CreateWindowRAD(0, 0, 170, 240);
48.                             UpdateChartTemplate();
49.                     }
50. //+------------------------------------------------------------------+
51.             ~C_ChartFloatingRAD()
52.                     {
53.                             ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Chart);
54.                             delete m_Mouse;
55.                     }
56. //+------------------------------------------------------------------+
57.             void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
58.                     {
59.                             static int sx = -1, sy = -1;
60.                             int x, y, mx, my;
61.     
62.                             switch (id)
63.                             {
64.                                     case CHARTEVENT_MOUSE_MOVE:
65.                                             if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft))
66.                                             {
67.                                                     x = (int)lparam;
68.                                                     y = (int)dparam;
69.                                                     if ((x > m_Info.x) && (x < (m_Info.x + m_Info.cx)) && (y > m_Info.y) && (y < (m_Info.y + m_Info.cy)))
70.                                                     {
71.                                                             if (sx < 0)
72.                                                             {
73.                                                                     ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false);
74.                                                                     sx = x - m_Info.x;
75.                                                                     sy = y - m_Info.y;
76.                                                             }
77.                                                             if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = mx);
78.                                                             if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = my);
79.                                                     }
80.                                             }else if (sx > 0)
81.                                             {
82.                                                     ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true);                                                
83.                                                     sx = sy = -1;
84.                                             }
85.                                             break;
86.                             }
87.                     }
88. //+------------------------------------------------------------------+
89. };
90. //+------------------------------------------------------------------+
91. 


Но разве это все? Где коды создания объектов? Манипуляции мышью?

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

Можно проводить исследования, используя мышь, можно кликнуть и перетащить окно Chart Trade, — и все благодаря только этому коду. Еще несколько вещей будут добавлены в этот код класса, чтобы сделать окно функциональным и обеспечить возможность отображения актива. Кнопки станут функциональными, и можно будет редактировать значения, которые пока еще не представлены. На самом деле, здесь не хватает еще кое-каких доработок, но не ожидайте увидеть создание этих объектов здесь. Я использую другой способ сделать наше окно функциональным и покажу это в следующей статье.

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

Начнем со строки 07. Обратите внимание, что класс C_ChartFloatingRAD наследуется от класса C_Terminal. Поскольку мы всегда должны предоставлять минимальные привилегии наследованию, мы делаем наследование частным. Таким образом, никакой другой код не будет иметь доступа к классу C_Terminal, по крайней мере, через класс C_ChartFloatingRAD. Это не проблема, поскольку в коде индикатора не упоминается какой-либо код класса C_Terminal.

Уяснив этот момент, можно переходить к конструктору. Так процесс выполнения станет легче для восприятия.

Конструктор начинается со строки 42. Обратите внимание, что он будет принимать string и объект, фактически указатель, для ссылки на индикатор мыши. В строке 43 мы производим необходимую инициализацию класса C_Terminal. Когда мы переходим к коду конструктора, начиная со строки 45, мы делаем вызов кода проверки, чтобы убедиться, что индикатор Chart Trade отсутствует на графике. Если эта проверка не проходит, мы указываем это в константе _LastError, используя вызовSetUserError.

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

В строке 46 мы сохраняем указатель, который был передан с помощью вызова оператора new. Это находится в коде индикатора Chart Trade. Увидеть этот вызов можно в строке 15 кода индикатора. НЕВАЖНО присутствует ли индикатор мыши на графике в момент выполнения строки 46. Повторюсь, потому что это важно: наличие индикатора на графике в момент вызова НЕ ИМЕЕТ ЗНАЧЕНИЯ.

А что действительно важно (и многие могут этого не понять), так это имя, которое передается в вызове, видимом в строке 15 кода индикатора Chart Trade. Эта переменная string, которая передается в конструктор класса C_Mouse, вот что имеет значение. Но никак не присутствие или отсутствие на графике индикатора.

Может показаться, что это не имеет смысла. Но он есть. Чтобы его уловить, необходимо вернуться к предыдущей статье Разработка системы репликации (Часть 41): Начало второй фазы (II) и обратить внимание на строку 169 в коде класса C_Mouse. Именно эта строка, и только она, обеспечит правильную работу кода, представленного в классе C_ChartFloatingRAD. Поэтому необходимо правильно указать название индикатора мыши, чтобы платформа MetaTrader 5 cмогла найти его, когда будет необходимо выполнить строку 169 в классе C_Mouse.

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

В строке 47 мы вызываем функцию, которая находится на строке 19. Эта функция на строке 19 — просто процедура, создающая объект OBJ_CHART на графике. Только это. Однако в строке 29 мы сохраняем ID этого объекта, чтобы иметь возможность использовать его очень конкретным образом позже. Думаю, что ни у кого не возникнет затруднений с пониманием остальных строк этой процедуры.

Возвращаясь к коду конструктора, — в строке 48 есть еще один вызов. Этот вызов выполнит процедуру, представленную в строке 34. В рамках этой процедуры, на данный момент, у нас есть две строки — 36 и 37. Строка 36 будет искать шаблон (template), который мы указываем, — именно тот, который виден на рисунке 01. А в строке 37 мы заставляем MetaTrader 5 обновить объект OBJ_CHART, чтобы template отобразился.

Таким образом, мы представляем наш Chart Trade. Правда, он еще не функционален. Однако мы уже можем произвести некую «манипуляцию», чтобы понять взаимодействие между индикатором мыши и индикатором Chart Trade.

Код деструктора достаточно прост, он не требует особых объяснений. Но нам нужно внимательно изучить код обработки сообщений: процедура DispatchMessage начинается со строки 57. Здесь происходит взаимодействие между двумя индикаторами.

В основном, на данный момент, мы будем обрабатывать только событие движения мыши, которое начинается со строки 64. Но внимание: мы не будем делать это обычным способом. Мы будем обрабатывать событие движения мыши совершенно по-другому. Для тех, кто привык программировать определенным образом, это может показаться совершенно безумным или, как некоторые говорят:"Very crazy"😂.  

Для лучшего понимания (и именно поэтому я не показываю другие вещи в этой статье), вам нужно обратиться к предыдущему материалу Разработка системы репликации (Часть 41): Начало второй фазы (II). Мы имеем дело не с одним, а с двумя индикаторами одновременно. Они взаимодействуют, чтобы сосуществовать в гармонии, а пользователь мог выполнять то, что показано в видео 01.

В этом коде обработки сообщений индикатора Chart Trade мы упомянем индикатор мыши только один раз. Это упоминание делается в строке 65. Сконцентрируйтесь, чтобы понять, что происходит. Если вы это поймете, остальное будет проще простого.

Здесь может быть две ситуации. Первая — когда индикатор мыши находится на графике, и вторая — когда индикатора на графике нет. Напомню, что индикатор должен иметь то имя, которое мы указали в конструкторе класса C_ChartFloatingRAD. Если имя отличается, MetaTrader 5 нам не поможет, и мы столкнемся с ситуацией, когда индикатора на графике нет. Обратите внимание на эту деталь.

Как только это станет ясно, и вы четко осознаете эти две ситуации, мы можем начать дальнейшее объяснение.

Когда это происходит, вызов в строке 65 выполнит вызов из строки 158 класса C_Mouse (из предыдущей статьи). В строке 15 кода индикатора Chart Trade мы сообщаем конструктору класса C_Mouse, что будем использовать класс C_Mouse в качестве транслятора. Строка 158 класса C_Mouse вызовет строку 163, чтобы проверить, произошло ли нажатие кнопки, указанной в строке 65 класса C_ChartFloatingRAD.

В момент выполнения строки 165 в классе C_Mouse, код поймет, что мы используем транслятор. Затем мы выполним строку 169, чтобы захватить handle индикатора мыши. В это время мы обратимся за помощью к MetaTrader 5, поэтому указанные имена должны совпадать. Если MetaTrader 5 найдет индикатор, на который мы ссылаемся, handle получит индекс для доступа к буферу индикатора. Если буфер можно прочитать, строка 172 захватит данные указателя мыши. Если буфер не может быть прочитан, функция завершится ошибкой, что также приведет к сбою функции в строке 158. Это приведет к сбою проверки, присутствующей в строке 65 класса C_ChartFloatingRAD. Таким образом, мы получим указание на то, что клик не произошел.

Вся эта логика будет работать в двух ситуациях:

  • Когда индикатор мыши отсутствует на графике. Помните, что он должен иметь то же имя, что было указано, чтобы MetaTrader 5 мог его найти.
  • Когда мы проводим исследование на графике, используя индикатор мыши.

В любой из этих двух ситуаций строка 65 класса C_ChartFloatingRAD будет указывать на сбой при клике мышью.

Эта часть кажется запутанной? Не волнуйтесь, дальше все становится еще интереснее.

Теперь проанализируем ситуацию, когда MetaTrader 5 находит индикатор мыши, и мы хотим перемещать индикатор Chart Trade по графику, как показано на видео 01. Чтобы понять, как это произойдет, вам необходимо разобраться в следующих статьях:

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

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

В любом случае, в какой-то момент вызов, присутствующий в строке 65 класса C_ChartFloatingRAD, встретится с вызовом из строки 181 класса C_Mouse. Когда это произойдет, строка 160 класса C_Mouse проверит переданный ей код кнопки. Если код соответствует переданному, функция вернет истинное значение. В этот момент и на протяжении всего времени, пока кнопка мыши будет нажата, будет выполняться код, присутствующий между строками 67 и 79.

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

Теперь возникает вопрос: почему в строках 67 и 68 я использую значения, предоставленные MetaTrader 5, а не индикатором мыши? Конечно не потому, что это красивее или проще. Есть причина использовать значения, предоставленные MetaTrader 5, а не значения индикатора. Чтобы понять это, нужно посмотреть код в классе C_Mouse между строками 203 и 206. В этих строках мы выполняем преобразование, трансформацию и корректировку координат мыши. При этом координаты мыши перестают быть экранными (x и y) и становятся активными (цена и время).

Это очень полезно для работы с определенными типами задач, но проблематично, когда нам нужно работать по-другому. Если в строках 67 и 68 класса C_ChartFloatingRAD использовать код, подобный показанному ниже:

x = (*m_Mouse).GetInfoMouse().Position.X;
y = (*m_Mouse).GetInfoMouse().Position.Y;

Мы получим движение объекта OBJ_CHART, как если бы он был привязан к координатам актива (цене и времени). Но на самом деле такой объект использует экранные координаты (x, y), поэтому движение будет довольно странным и не таким плавным, как на видео 01. Для некоторых типов объектов действительно желательно использовать координаты, предоставляемые индикатором мыши.


Заключение

В этой статье мы рассмотрели первый этап создания индикатора Chart Trade. Я показал, как можно использовать индикатор мыши в идеальной гармонии с создаваемым нами индикатором Chart Trade, который, правда пока не имеет никакой функциональности, кроме возможности перетаскивания по графику.

В следующей статье мы начнем работать над расширением функционала Chart Trade.


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

Прикрепленные файлы |
Anexo.zip (420.65 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (1)
Sergei Lebedev
Sergei Lebedev | 2 авг. 2024 в 10:24
Очень интересная серия статей, так как в МТ5 нет внутреннего функционала MarketReply.
Просьба к модераторам английского раздела ускорить перевод на английский следующих частей, а именно 43-60!
Алгоритм адаптивного социального поведения — Adaptive Social Behavior Optimization (ASBO): Двухфазная эволюция Алгоритм адаптивного социального поведения — Adaptive Social Behavior Optimization (ASBO): Двухфазная эволюция
Эта статья является продолжением темы социального поведения живых организмов и его воздействия на разработку новой математической модели - ASBO (Adaptive Social Behavior Optimization). Мы погрузимся в двухфазную эволюцию, проведем тестирование алгоритма и сделаем выводы. Подобно тому, как в природе группа живых организмов объединяет свои усилия для выживания, ASBO использует принципы коллективного поведения для решения сложных задач оптимизации.
Теория хаоса в трейдинге (Часть 1): Введение, применение на финансовых рынках и индикатор Ляпунова Теория хаоса в трейдинге (Часть 1): Введение, применение на финансовых рынках и индикатор Ляпунова
Можно ли применять теорию хаоса на финансовых рынках? Чем классическая теория Хаоса и хаотические системы отличаются от концепции, предложенной Биллом Вильямсом, рассмотрим в этой статье.
Расширенные переменные и типы данных в MQL5 Расширенные переменные и типы данных в MQL5
Переменные и типы данных — очень важные темы не только в программировании на MQL5, но и в любом языке программирования. Переменные и типы данных MQL5 можно разделить на простые и расширенные. Здесь мы рассмотрим расширенные переменные и типы данных. Простые мы изучали в предыдущей статье.
Разработка MQTT-клиента для MetaTrader 5: методология TDD (Часть 6) Разработка MQTT-клиента для MetaTrader 5: методология TDD (Часть 6)
Статья является шестой частью серии, описывающей этапы разработки нативного MQL5-клиента для протокола MQTT 5.0. В этой части я опишу основные изменения в нашем первом рефакторинге, получение рабочего проекта наших классов построения пакетов, создание пакетов PUBLISH и PUBACK, а также семантику кодов причин PUBACK.