Моделирование рынка (Часть 07): Сокеты (I)
Введение
В предыдущей статье, "Моделирование рынка (Часть 06): Перенос данных из MetaTrader 5 в Excel", мы рассказали, как можно перенести данные о котировках из MetaTrader 5 в Excel, используя простые средства и только MQL5. Конечно, это был лишь довольно простой пример, который был максимально образовательным. Но можно заметить, что обновление котировок происходило не в режиме реального времени. Однако цель знаний, представленных в предыдущей статье, - показать то, что нам по-настоящему необходимо сделать.
Но поскольку существует несколько способов сделать то же самое, а нас всегда интересует результат, я хочу показать, что на самом деле существует простой способ передачи данных из MetaTrader 5 в другие программы, такие как, например, Excel. Однако основная идея заключается не в том, чтобы перенести данные из MetaTrader 5 в Excel, а в обратном, то есть в переносе данных из Excel или любой другой программы в MetaTrader 5.
Это можно сделать разными способами, некоторые из них простые, другие - более сложные. Одни сделают это в режиме реального времени, а другие - с небольшой задержкой. Важно то, можем ли мы управлять MetaTrader 5 или каким-либо приложением, работающим на нем, с помощью внешних данных. Данный вопрос может показаться тривиальным, но он открывает некоторые прецеденты. Например, можно провести какое-то исследование или анализ с помощью внешней программы, специально разработанной для решения такого типа задач. Вы можете установить точки интереса в виде цены или котировки и поместить эти данные на место, где какое-либо приложение (будь то советник, сервис, скрипт или даже индикатор) сможет их использовать, позволяя получать сигналы прямо на графике и даже, в случае Советника, помогать с принятием решений.
На данном этапе важны только ваши воображение и интерес. Это, по сути, единственное что ограничит наши возможности. Но прежде, чем мы перейдем к разработке того, что нам действительно понадобится в системе репликации/моделирования, мы покажем кое-что ещё. Для этого необходимо представить эти концепции, идеи и возможности, чтобы мы могли действительно понять, что разработаем в дальнейшем, и извлечь максимальную пользу из всех этих знаний.
То, что мы рассмотрим в данной статье, - это шаг вперед в решении того же вопроса, который был представлен в предыдущей статье. Потому что, как уже говорилось ранее, показанная форма не позволяет нам отправлять данные в реальном времени, хотя этого уже достаточно для того, что нам понадобится в системе репликации/моделирования. Однако это не соответствует нашим нуждам, если мы хотим получать информацию в режиме реального времени.
Объяснение концепции
Как уже упоминалось в предыдущей статье, использование RTD или DDE не гарантирует двусторонней связи между MetaTrader 5 и другой программой. Но мы можем применить ту же концепцию, что и в RTD или DDE, чтобы получить двунаправленную связь. Чтобы добиться этого, нам нужно сделать нечто отличное от того, что мы делали до сих пор. На протяжении всего данного этапа разработки мы реализовывали абсолютно всё на чистом MQL5. Однако есть случаи, когда чистого MQL5 недостаточно, потому что некоторые другие программы не могут сделать какие-то вещи без посторонней помощи. Проблема сводится к конкретной вещи: К СОКЕТАМ.
Сокет прочно укоренился в мире вычислительной техники. Если вы не знаете, что это такое и для чего это нужно, я вам советую разобраться в этом, особенно если вы хотите выполнять определенные задачи. С их помощью, мы получаем огромную степень свободы. Мы не будем слишком углубляться в эту тему, так как она охватывает несколько аспектов, которые нужно будет спокойно изучить, если вы действительно хотите работать с сокетами. Но я дам краткое объяснение, чтобы вы не чувствовали себя окончательно растерянными.
Протокол TCP
Прежде всего, необходимо понять, что существует множество различных типов сокетов. Каждый из них служит разным целям. Однако наиболее распространенными являются типы Stream и DataGram. Тип Stream, или потоковый сокет, широко используется в надежных двусторонних связях. Слово "надежный" означает, что получение информации всегда проверяется. Потоковые сокеты используют протокол управления передачей, более известный как TCP.
У данного типа сокетов есть ещё одна важная деталь: они устроены так, что пакеты информации всегда поступают в определенном порядке. Другими словами, можно передавать информацию так, как будто это огромный список, который разворачивается по мере поступления пакетов. Так можно наглядно увидеть, где он чаще всего используется, например, при управлении удаленными приложениями, где нельзя допустить потери данных при передаче и необходима гарантия того, что информация будет получена. Однако это делает работу протокола немного медленнее. Как правило, у протокола следующий вид:

Но с точки зрения программирования нас интересует совсем иное. Речь идет о том, как протокол будет выбран и реализован в коде, который мы создадим. При использовании TCP в Windows или Linux, существуют небольшие структурные различия в коде. Хотя если в коде есть различия, они не мешают общению. То есть можно заставить Windows-приложение взаимодействовать с Linux-приложением с помощью TCP, и оба приложения будут прекрасно понимать друг друга. При условии, однако, что соблюдаются правила связи. То же самое происходит и со следующим протоколом, который мы рассмотрим позже.
Протокол UDP
Теперь давайте перейдем к пониманию типа DataGram. Тип DataGram, также известный как датаграммный сокет, полностью отличается от потокового сокета или TCP. Это связано с тем, что датаграммный сокет ориентирован на однонаправленную и разобщенную связь. Но как это возможно? Как связь может быть односторонней и ненадежной? Ладно, давайте не торопиться с выводами.
Прежде всего, мы должны понимать, что этот сокет использует протокол UDP, то есть наиболее известный. Данный протокол не устанавливает фактического соединения, а просто позволяет отправлять данные. Проще говоря, это похоже на письмо: мы пишем его и отправляем, но, отправив, не знаем, когда оно дойдет до адресата (и дойдет ли).
Но всё гораздо сложнее. Потому что, отправив письмо, мы понимаем, что некоторые детали остались невыясненными. Затем мы пишем ещё одно письмо, чтобы уточнить эти детали. И так может происходить несколько раз, так что в итоге мы отправим все написанные нами письма.
Теперь наступает ключевой момент: если почта работает правильно и ни одно письмо не затерялось, адресат может получить их все сразу. Мы можем получать их в том же порядке, в котором они были отправлены, или в случайном порядке.
Представьте, сколько работы нам придется проделать, чтобы понять смысл отправленного сообщения. Однако, если вы отправили письмо и ожидаете ответа, у вас не будет никакой уверенности или гарантии, что адресат получит его или поймет смысл послания. Поэтому данный протокол UDP является однонаправленным и ненадежным. Теперь понятно, почему мы не можем воспринимать всё буквально? Даже если нам кажется, что он бесполезен, это не так.
Бывают ситуации, например, при запросе данных, когда не является обязательным, чтобы данные шли в последовательности, не говоря уже о том, чтобы все они были получены. Мы можем позволить себе пропустить некоторые из них, а полученных будет достаточно для понимания информации.
Типичный пример - видеозвонки или голосовые звонки, где мы чаще всего обращаем внимание на скорость передачи данных и отдаем ей предпочтение. Другим примером могут служить дистанционные датчики или сенсоры, цель которых - проверить определенное состояние. В подобных ситуациях в большинстве случаев нет необходимости подтверждать получение данных, если объём собранных данных достаточен для анализа информации. Данный протокол имеет следующий типичный формат:

Думаю, это вызовет у вас большой интерес к этой теме и желание углубиться в её изучение. На самом деле, она очень обширна и интересна. Здесь мы предлагаем лишь общее представление о том, что можно сделать. Можно найти несколько человек, комментирующих эту тему в статьях или на форуме сообщества MQL5. В любом случае, тема очень обширна, но мы сделали это краткое введение, чтобы вы могли понять, что мы будем делать дальше.
Программируем скромную систему
Здесь мы вынуждены отступить, потому что для демонстрации того, что нужно сделать, мы должны использовать довольно простой код. Так как MQL5 не позволяет создать сервер непосредственно в языке, мы будем использовать MQL5 для создания клиентской части. Да, мы создадим модель клиент-сервер. Серверная часть будет выполнена с помощью внешнего программирования. В этом случае мы можем использовать любой код или язык, позволяющий создать веб-сервер. Но есть некоторые моменты, на которые следует обратить внимание, например, порт и тип используемого протокола. Для максимальной простоты мы будем использовать код, который можно изучить прямо из источника. Другими словами, мы будем использовать код, который находится в открытом доступе в Интернете. Код сервера можно найти на сайте Microsoft. Можно получить доступ к нему по этой ссылке: Сервер WinSock. Servidor WinSock.
В конце статьи оставим эту ссылку для ознакомления. Это позволит нам шаг за шагом изучить, как работает код, а также другие детали, связанные с сокетами. Это относится не только к серверной части, но и к клиентской, которая также объясняется там.
ВАЖНОЕ ЗАМЕЧАНИЕ: сервер, который мы покажем, - это очень простая модель, которая получает соединение, перехватывает то, что ему отправлено, а затем закрывает соединение, не имея возможности получить другое, возвращая клиенту именно ту информацию, которая была отправлена. То есть это будет эхо-сервер, предназначенный только для демонстрации.
Однако на стороне клиента мы поступим несколько иным способом. Мы создадим клиента непосредственно на MQL5, обходясь без кода на языке C/C++, который можно найти на вышеупомянутом сайте. Таким образом, мы сможем понять, как на самом деле происходит общение. Помните, что вы даже можете превратить MetaTrader 5 в сервер, но это заставит нас использовать DLL. И на данный момент мы не хотим использовать этот тип ресурса. По крайней мере на данный момент.
Давайте теперь приступим! Можно использовать указанный код или создать свой собственный на любом языке или платформе. Идея состоит в том, чтобы создать простую систему, которая послужит отправной точкой для понимания того, как всё работает. Когда сервер будет скомпилирован и запущен, мы перейдем к MQL5-части. Для этого откроем MetaEditor и создадим клиента на чистом MQL5.
Выполняем часть MetaTrader
Прежде чем устанавливать соединение с нашим локальным сервером, нам нужно понять, как правильно устанавливается соединение. Это связано с тем, что по умолчанию MetaTrader 5 не позволяет подключаться к другому серверу, кроме торгового. Это ограничение - мера безопасности, которую мы должны принять и понять. Не было бы целесообразно позволять такой платформе, как MetaTrader, свободно подключаться к любому адресу. Поэтому для того, чтобы MetaTrader разрешил подключение, необходимо произвести небольшую настройку.
Для упрощения понимания мы воспользуемся тем, что можно уже найти в самой документации по MQL5. Поэтому приведенный ниже код не является собственным авторским, а входит в документацию, где его можно найти по запросу SocketCreate. Ниже приведен исходный код в том виде, в котором он представлен в документации:
001. //+------------------------------------------------------------------+ 002. //| SocketExample.mq5 | 003. //| Copyright 2018, MetaQuotes Software Corp. | 004. //| https://www.mql5.com | 005. //+------------------------------------------------------------------+ 006. #property copyright "Copyright 2018, MetaQuotes Software Corp." 007. #property link "https://www.mql5.com" 008. #property version "1.00" 009. #property description "Add Address to the list of allowed ones in the terminal settings to let the example work" 010. #property script_show_inputs 011. 012. input string Address="www.mql5.com"; 013. input int Port =80; 014. bool ExtTLS =false; 015. //+------------------------------------------------------------------+ 016. //| Send command to the server | 017. //+------------------------------------------------------------------+ 018. bool HTTPSend(int socket,string request) 019. { 020. char req[]; 021. int len=StringToCharArray(request,req)-1; 022. if(len<0) 023. return(false); 024. //--- if secure TLS connection is used via the port 443 025. if(ExtTLS) 026. return(SocketTlsSend(socket,req,len)==len); 027. //--- if standard TCP connection is used 028. return(SocketSend(socket,req,len)==len); 029. } 030. //+------------------------------------------------------------------+ 031. //| Read server response | 032. //+------------------------------------------------------------------+ 033. bool HTTPRecv(int socket,uint timeout) 034. { 035. char rsp[]; 036. string result; 037. uint timeout_check=GetTickCount()+timeout; 038. //--- read data from sockets till they are still present but not longer than timeout 039. do 040. { 041. uint len=SocketIsReadable(socket); 042. if(len) 043. { 044. int rsp_len; 045. //--- various reading commands depending on whether the connection is secure or not 046. if(ExtTLS) 047. rsp_len=SocketTlsRead(socket,rsp,len); 048. else 049. rsp_len=SocketRead(socket,rsp,len,timeout); 050. //--- analyze the response 051. if(rsp_len>0) 052. { 053. result+=CharArrayToString(rsp,0,rsp_len); 054. //--- print only the response header 055. int header_end=StringFind(result,"\r\n\r\n"); 056. if(header_end>0) 057. { 058. Print("HTTP answer header received:"); 059. Print(StringSubstr(result,0,header_end)); 060. return(true); 061. } 062. } 063. } 064. } 065. while(GetTickCount()<timeout_check && !IsStopped()); 066. return(false); 067. } 068. //+------------------------------------------------------------------+ 069. //| Script program start function | 070. //+------------------------------------------------------------------+ 071. void OnStart() 072. { 073. int socket=SocketCreate(); 074. //--- check the handle 075. if(socket!=INVALID_HANDLE) 076. { 077. //--- connect if all is well 078. if(SocketConnect(socket,Address,Port,1000)) 079. { 080. Print("Established connection to ",Address,":",Port); 081. 082. string subject,issuer,serial,thumbprint; 083. datetime expiration; 084. //--- if connection is secured by the certificate, display its data 085. if(SocketTlsCertificate(socket,subject,issuer,serial,thumbprint,expiration)) 086. { 087. Print("TLS certificate:"); 088. Print(" Owner: ",subject); 089. Print(" Issuer: ",issuer); 090. Print(" Number: ",serial); 091. Print(" Print: ",thumbprint); 092. Print(" Expiration: ",expiration); 093. ExtTLS=true; 094. } 095. //--- send GET request to the server 096. if(HTTPSend(socket,"GET / HTTP/1.1\r\nHost: www.mql5.com\r\nUser-Agent: MT5\r\n\r\n")) 097. { 098. Print("GET request sent"); 099. //--- read the response 100. if(!HTTPRecv(socket,1000)) 101. Print("Failed to get a response, error ",GetLastError()); 102. } 103. else 104. Print("Failed to send GET request, error ",GetLastError()); 105. } 106. else 107. { 108. Print("Connection to ",Address,":",Port," failed, error ",GetLastError()); 109. } 110. //--- close a socket after using 111. SocketClose(socket); 112. } 113. else 114. Print("Failed to create a socket, error ",GetLastError()); 115. } 116. //+------------------------------------------------------------------+
Исходный код из документации по MQL5
Данный код идеально подходит для объяснения работы и настройки соединений в MetaTrader 5, так как он очень прост и позволяет получить удаленный доступ. Другими словами, мы получим доступ к веб-странице. Я полагаю, что те, кто уже имеет некоторый опыт в сетевом программировании, смогут разобраться в этом коде без труда. Но для тех из вас, кто новичок в этом деле, мы дадим краткое объяснение, поскольку в дальнейшем нам понадобится понять некоторые из появляющихся здесь понятий.
Этот код является скриптом и должен быть скомпилирован как таковой. Использование сокетов в индикаторах невозможно. Для дополнительной информации, посмотрите в документации. Теперь давайте посмотрим, как это работает. В строке 12 мы указываем имя сайта, к которому нужно получить доступ. В строке 13 мы указываем порт, который будем использоваться. В данном случае это порт, который отвечает на запросы типа HTTP. Другими словами, речь идет о веб-сервере. Что можно ожидать от каждого типа порта, смотрите в справочнике.
Когда код запускается (это происходит в строке 71), первое, что мы делаем, - это создаем сокет, что происходит в строке 73. Пока всё просто. Однако нам необходимо проверить, является ли созданный сокет действительным, что и проверяется в строке 75. В строке 78 мы пытаемся подключиться к серверу и порту, указанным в строках 12 и 13. Если подключение не удалось, на экране появится изображение, подобное приведенному ниже:

Вероятно, это сообщение появляется, потому что MetaTrader 5 блокирует соединение. Чтобы включить его, нажмем Ctrl + O и добавим исключение к правилу, как показано ниже:

После внесения изменений, которые показаны выше, можно запустить скрипт снова, и результат будет похож на следующее изображение:

«Но как это произошло? Как мы получили определенную информацию с веб-сервера? Разве для этого не нужно было использовать вызов WebRequest?» На самом деле, это не обязательно. Так называемый WebRequest делает практически то же самое, что мы только что сделали. Однако сейчас мы находимся на уровне, который немного ближе к аппаратному обеспечению. А это связано с тем, что вызов WebRequest создает абстракцию для сокета, расположенного непосредственно под ним. Таким образом, результат одинаков в обоих режимах использования. Мы уже рассматривали раньше использование вызова WebRequest. Более подробную информацию можно найти в следующих статьях:
- Разработка торгового советника с нуля (Часть 15): Доступ к данным в Интернете (II)
- Разработка торгового советника с нуля (Часть 16): Доступ к данным в Интернете (II).
- Разработка торгового советника с нуля (Часть 17): Доступ к данным в Интернете (III)
То, что сделали в трех вышеупомянутых статьях, можно сделать, используя сокеты напрямую. Однако для достижения того же результата нам придется запрограммировать немного больше. Но давайте вернемся к системе, которую мы анализируем в этой статье. После того, как мы скомпилируем код сервера, показанный в предыдущем разделе, нам нужно будет запустить его перед выполнением скрипта, который мы показываем ниже. Помните, что мы можем создать свой собственный сервер на выбранном нами языке. Единственное требование на данный момент - чтобы данные, полученные сервером, передавались клиенту, чтобы у нас было то самое поведение, которое мы объясним.
Давайте посмотрим код на MQL5, который будет нашим клиентом. Ниже можно увидеть его в полном объеме.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. #property version "1.00" 04. #property script_show_inputs 05. //+------------------------------------------------------------------+ 06. input string user00 = "127.0.0.1"; //Address 07. input int user01 = 27015; //Port 08. //+------------------------------------------------------------------+ 09. bool ConnectionWrite(int socket, string szMsg, bool TLS = false) 10. { 11. char buff[]; 12. int len = StringToCharArray(szMsg, buff) - 1; 13. 14. if (len < 0) return false; 15. Print("To Server:", szMsg); 16. return (TLS ? SocketTlsSend(socket, buff, len) : SocketSend(socket, buff, len)) == len; 17. } 18. //+------------------------------------------------------------------+ 19. string ConnectionRead(int socket, uint timeout) 20. { 21. uint len; 22. int ret; 23. char resp[]; 24. string info; 25. uint timeout_check = GetTickCount() + timeout; 26. 27. info = ""; 28. do 29. { 30. len = SocketIsReadable(socket); 31. ret = SocketRead(socket, resp, len, timeout); 32. if (ret > 0) 33. info += CharArrayToString(resp, 0, ret); 34. }while ((GetTickCount() < timeout_check) && (!_StopFlag)); 35. 36. return info; 37. } 38. //+------------------------------------------------------------------+ 39. void OnStart() 40. { 41. int socket = SocketCreate(); 42. 43. if (socket == INVALID_HANDLE) 44. { 45. Print("Unable to create socket. Error: ", GetLastError()); 46. return; 47. } 48. if (!SocketConnect(socket, user00, user01, 1000)) 49. { 50. Print("Connection with the address [", user00,"] in port: ",user01, " failed. Error code: ", GetLastError()); 51. SocketClose(socket); 52. return; 53. } 54. 55. Print("Trying to send ", ConnectionWrite(socket, "Testing Server Echo...") ? "Ok..." : "Failed..."); 56. 57. Print("From Server:", ConnectionRead(socket, 1000)); 58. 59. SocketClose(socket); 60. } 61. //+------------------------------------------------------------------+
Демонстрационный код
Давайте рассмотрим некоторые детали данного кода, прежде чем увидим, как он выполняется в MetaTrader 5. Первая вещь находится в строке 06. Здесь мы указываем, где находится наш сервер. В этом случае мы указываем, что мы находимся на той же машине, где установлен MetaTrader 5. В строке 07 указано, какой порт мы будем использовать на сервере. Очень важный момент: данный порт должен совпадать с портом, указанным в коде сервера. Именно поэтому мы указали на публичный код, который очень хорошо объясняется на вышеупомянутом сайте. В случае сомнений, пожалуйста, обратитесь к документации, доступной на сайте, которая будет приведена в конце статьи для справки.
В принципе, все функции этого MQL5-скрипта не требуют пояснений, но, если вы сомневаетесь, достаточно обратиться к документации, чтобы понять происходящее. Однако есть одна часть, где всё не так однозначно и она требует дальнейшего объяснения.
Прошу заметить, что в строке 28 мы входим в цикл. Его цель - прочитать, что сервер опубликует в сокете. «Но зачем использовать цикл? Разве не достаточно прочитать сокет?» Это может показаться немного запутанным, но на это есть свои причины. Когда что-то отправляется в сокет, мы не знаем, как это будет отправлено, только знаем, что это будет отправлено. Информация может быть передана в одном пакете, но также может быть передана в нескольких небольших пакетах, даже если сообщение относительно короткое.
Данная ситуация затрудняет работу многих людей, начинающих экспериментировать с программированием сокетов. Они думают, что информация будет отправлена одним блоком, в то время как на самом деле она может быть разделена на несколько блоков или пакетов. Но есть ли способ узнать об этом заранее? На самом деле, простого способа не существует. Единственное, что мы можем ожидать, - это то, что отправленный пакет будет получен, и это произойдет, когда мы используем протокол TCP, как мы уже объясняли в начале статьи. Дело в том, что информация обычно отправляется и принимается в виде пакетов.
Чтобы лучше понять это, посмотрите на строку 55. В данной строке мы делаем вызов строки 09, которая получит информацию для размещения в сокете. В строке 15 мы указываем, каким будет сообщение, а в строке 16 отправляем его. Как именно сервер получит сообщение и в каком количестве пакетов, уже не зависит от нас; система сама позаботится об этом разделении.
Как только строка 57 будет выполнена, мы действительно прочитаем то, что опубликовал сервер. Прошу заметить: мы будем читать не то, что отправили мы, а то, что прислал в ответ сервер. Поскольку указанный нами сервер относится к типу «эхо», в ответ будет отправлено то же самое сообщение, которое мы отправили. Это похоже на пингование сервера.
Но так же, как мы не контролируем, как передается сообщение, мы не знаем, сколько пакетов использует сервер для возврата сообщения. Если вы удалите цикл в строке 28, вы выполните только вызов в строке 31 и используете строку 33 для преобразования в строку того, что вернул сервер, и вы заметите, что сообщение выглядит фрагментированным, как будто какая-то часть отсутствует. Однако в определенный момент оно покажет себя в полном объёме. Это связано с тем, что сообщение довольно короткое. И именно такая ситуация оказывается непонятной для многих.
Я знаю, что это может показаться довольно запутанным, и что это не имеет никакой практической пользы. Однако я хотел бы отметить одно: если вы сможете понять, как работают эти два кода - тот, который играет роль сервера, и тот, который работает на MetaTrader 5, - вы поймете, что можно сделать очень многое.
Но прежде, чем запустить данный скрипт в работу, необходимо сообщить MetaTrader 5, что используемый адрес должен быть разрешен. Таким образом, в списке адресов в MetaTrader 5 должно появиться то же значение, что и в строке 06. После этого мы увидим нечто похожее на изображение ниже:

С помощью данной модификации мы сможем запускать обе программы. Чтобы показать, как это делается, мы включили в видео ниже способ локального тестирования работы системы, на случай если у вас нет опыта в многопоточном программировании. Однако я хочу уточнить, что целью видео является не продвижение какого-то конкретного инструмента, я хочу показать тем, кто этого не знает, как запускать многопоточные программы, чтобы разработать их беспрепятственно.
Заключительные идеи
В этой статье дано краткое введение в одну из самых сложных концепций, которые можно использовать в MetaTrader 5: использование сокетов. Цель данной статьи - объяснить основы использования сокетов в MetaTrader 5, чтобы вы могли понять некоторые фундаментальные концепции. Хотя содержание этой статьи является базовым, она необходима для тех, кто хочет изучить сокеты и их применение.
Однако, поскольку всё, что мы здесь сделали, - это сгенерировали эхо на сервере, возможно, не совсем понятно, насколько многого мы можем добиться на самом деле. Чтобы прояснить этот момент, мы сделаем кое-что более подробное в следующей статье, поскольку данная концепция сокетов может сильно помочь вам улучшить качество использования системы репликации/моделирования. Нам всё ещё нужно будет внедрить некоторые вещи, такие как система ордеров, и я серьезно рассматриваю возможность сделать это более сложным способом. Но для того, чтобы вы действительно поняли, что будет запрограммировано, необходимо, чтобы вы сначала разобрались с этими небольшими концепциями, которые я вам здесь показываю.
Если и есть что-то, способное заставить вас усердно изучать программирование, то это СОКЕТЫ, а когда дело доходит до сокетов, вы никогда не можете знать достаточно. И только когда нам кажется, что мы узнаем всё о сокетах, мы понимаем, что нам ещё предстоит открыть для себя много нового. Так что не пропустите следующую статью, потому что мы рассмотрим кое-что очень интересное и легко реализуемое, связанное с этой темой.
Ссылка
Документация по использованию WinSock от Microsoft
| Файл | Описание |
|---|---|
| Experts\Expert Advisor.mq5 | Демонстрирует взаимодействие между Chart Trade и советником (для взаимодействия требуется Mouse Study). |
| Indicators\Chart Trade.mq5 | Создает окно для настройки отправляемого ордера (для взаимодействия требуется Mouse Study). |
| Indicators\Market Replay.mq5 | Создайте элементы управления для взаимодействия с сервисом репликации/моделирования (для взаимодействия требуется Mouse Study). |
| Indicators\Mouse Study.mq5 | Позволяет взаимодействовать между графическими элементами управления и пользователем (необходимо как для воспроизведения, так и для торговли на реальном рынке). |
| Servicios\Market Replay.mq5 | Создает и поддерживает сервис репликации/моделирования рынка (основной файл всей системы). |
| Код VS C++ Server.cpp | Создание и поддержка сокет-сервера на C++ (версия для мини-чата) |
| Код на Python Server.py | Создание и поддержка сокета Python для связи между MetaTrader 5 и Excel. |
| ScriptsCheckSocket.mq5 | Позволяет выполнить тест соединения с внешним сокетом |
| Indicators\Mini Chat.mq5 | Позволяет реализовать мини-чат с помощью индикатора (для работы требуется использование сервера). |
| Experts\Mini Chat.mq5 | Позволяет реализовать мини-чат через советник (для работы требуется использование сервера). |
Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/12621
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Система самообучения с подкреплением для алгоритмической торговли на MQL5
Моделирование рынка (Часть 06): Перенос данных из MetaTrader 5 в Excel
Возможности Мастера MQL5, которые вам нужно знать (Часть 54): Обучение с подкреплением с гибридным SAC и тензорами
Нейросети в трейдинге: Модели многократного уточнения прогнозов (Окончание)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования