English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Использование WinInet.dll для обмена данными между терминалами через Интернет

Использование WinInet.dll для обмена данными между терминалами через Интернет

MetaTrader 5Интеграция | 5 мая 2010, 10:43
15 087 45
---
---

MetaTrader 5 открывает уникальные возможности для пользователей, применяя в своем арсенале новые элементы пользовательского интерфейса. Благодаря этому, ранее недоступный функционал можно использовать по максимуму.

В этом уроке мы научимся:

  • использовать базовые интернет технологии;
  • обмениваться данными между терминалами посредством сервера;
  • создадим обобщенный библиотечный класс для работы с интернет в среде MQL5.

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

На заметку: для тех, у кого нет доступа к какому-либо серверу с настроенным PHP, предлагаем в качестве рабочей площадки установить комплект Denwer. И использовать для тестирования сервер Apache и PHP на своём localhost.

Для отправки любого запроса на сервер нам понадобится 7 основных функций из библиотеки.

InternetAttemptConnect  Проверка наличия подключения к интернету и попытка его создать
InternetOpen
Инициализирует структуры для работы функций библиотеки WinInet. Эта функция должна вызываться перед вызовом всех остальных функций библиотеки.
InternetConnect Открывает указанный ресурс по указанному адресу HTTP URL или FTP. Возвращает дескриптор на открытое соединение
HttpOpenRequestСоздает дескриптор для HTTP запросов на созданное соединение
HttpSendRequestОтправляет запрос с использованием созданного дескриптора
InternetReadFile Читает данные, полученные от сервера после запроса
InternetCloseHandle Освобождает передаваемый дескриптор

 
Подробное описание всех функций и их параметров вы можете найти в справочной системе MSDN.

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

#import "wininet.dll"
int InternetAttemptConnect(int x);
int InternetOpenW(string &sAgent,int lAccessType,string &sProxyName,string &sProxyBypass,int lFlags);
int InternetConnectW(int hInternet,string &szServerName,int nServerPort,string &lpszUsername,string &lpszPassword,int dwService,int dwFlags,int dwContext);
int HttpOpenRequestW(int hConnect,string &Verb,string &ObjectName,string &Version,string &Referer,string &AcceptTypes,uint dwFlags,int dwContext);
int HttpSendRequestW(int hRequest,string &lpszHeaders,int dwHeadersLength,uchar &lpOptional[],int dwOptionalLength);
int HttpQueryInfoW(int hRequest,int dwInfoLevel,int &lpvBuffer[],int &lpdwBufferLength,int &lpdwIndex);
int InternetReadFile(int hFile,uchar &sBuffer[],int lNumBytesToRead,int &lNumberOfBytesRead);
int InternetCloseHandle(int hInet);
#import

//Также для эстетики кода определим используемые имена констант из wininet.h.
#define OPEN_TYPE_PRECONFIG     0           // использовать конфигурацию по умолчанию
#define FLAG_KEEP_CONNECTION    0x00400000  // не разрывать соединение
#define FLAG_PRAGMA_NOCACHE     0x00000100  // не кешировать страницу
#define FLAG_RELOAD             0x80000000  // получать страницу с сервера при обращении к ней
#define SERVICE_HTTP            3           // требуемый протокол

Подробное описание флагов находится в том же разделе MSDN для каждой вызываемой функции. Если вы желаете посмотреть объявления других констант и функций, то исходный файл wininet.h можете скачать внизу статьи.

1. Правила создания и удаления интернет-сессии

Первое, что мы должны сделать, это создать сессию и открыть соединение с хостом. Создание сессии желательно делать один раз при инициализации программы (например, в функции OnInit). Либо в самом начале работы эксперта, но главное проконтролировать, чтоб её успешное выполнение было только один раз до момента закрытия сессии. И она не вызывалась повторно без надобности каждый раз на новой итерации выполнения OnStart или OnTimer. Это важно для того, чтоб не нагружать слишком частыми вызовами и создание для каждого вызова требуемых структур.

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

   string            Host;       // имя хоста
   int               Port;       // порт
   int               Session;    // дескриптор сессии
   int               Connect;    // дескриптор соединения

bool MqlNet::Open(string aHost,int aPort)
  {
   if(aHost=="")
     {
      Print("-Host is not specified");
      return(false);
     }
   // проверка разрешения DLL в терминале  
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
     {
      Print("-DLL is not allowed");
      return(false);
     }
   // если сессия была опеределена, то закрываем
   if(Session>0 || Connect>0) Close();
   // сообщение про попытку открытия в журнал
   Print("+Open Inet...");
   // если не удалось проверить имеющееся соединение с интернетом, то выходим
   if(InternetAttemptConnect(0)!=0)
     {
      Print("-Err AttemptConnect");
      return(false);
     }
   string UserAgent="Mozilla"; string nill="";
   // открываем сессию
   Session=InternetOpenW(UserAgent,OPEN_TYPE_PRECONFIG,nill,nill,0);
   // если не смогли открыть сессию, то выходим
   if(Session<=0)
     {
      Print("-Err create Session");
      Close();
      return(false);
     }
   Connect=InternetConnectW(Session,aHost,aPort,nill,nill,SERVICE_HTTP,0,0);
   if(Connect<=0)
     {
      Print("-Err create Connect");
      Close();
      return(false);
     }
   Host=aHost; Port=aPort;
   // иначе все проверки завершились успешно
   return(true);
  }

После инициализации дескрипторы Session  и Connect можно использовать во всех последующих функциях. При завершении работы и деинициализации MQL-программы их нужно обязательно удалить. Делается это с помощью функции InternetCloseHandle.

void MqlNet::CloseInet()
  {
   Print("-Close Inet...");
   if(Session>0) InternetCloseHandle(Session); Session=-1;
   if(Connect>0) InternetCloseHandle(Connect); Connect=-1;
  }

Важно! При работе с интернет-функциями необходимо освобождать все получаемые от них дескрипторы с помощью InternetCloseHandle.

2. Отправка запроса на сервер и получение страницы

Для отправки запроса и получения страницы в ответ на запрос нам понадобятся оставшиеся три функции HttpOpenRequest, HttpSendRequest и InternetReadFile. Суть получения страницы в ответ на запрос заключается в обычном сохранении её содержимого в локальный файл.


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

Отправка запроса:

bool MqlNet::Request(string Verb,string Object,string &Out,bool toFile=false,string addData="",bool fromFile=false)
  {
   if(toFile && Out=="")
     {
      Print("-File is not specified ");
      return(false);
     }
   uchar data[];
   int hRequest,hSend,h;
   string Vers="HTTP/1.1";
   string nill="";
   if(fromFile)
     {
      if(FileToArray(addData,data)<0)
        {
         Print("-Err reading file "+addData);
         return(false);
        }
     } // прочитали файл в массив
   else StringToCharArray(addData,data);

   if(Session<=0 || Connect<=0)
     {
      Close();
      if(!Open(Host,Port))
        {
         Print("-Err Connect");
         Close();
         return(false);
        }
     }
   // создаем дескриптор запроса
   hRequest=HttpOpenRequestW(Connect,Verb,Object,Vers,nill,nill,FLAG_KEEP_CONNECTION|FLAG_RELOAD|FLAG_PRAGMA_NOCACHE,0);
   if(hRequest<=0)
     {
      Print("-Err OpenRequest");
      InternetCloseHandle(Connect);
      return(false);
     }
   // отправляем запрос
   // заголовок на отправку
   string head="Content-Type: application/x-www-form-urlencoded";
   // отправили файл
   hSend=HttpSendRequestW(hRequest,head,StringLen(head),data,ArraySize(data)-1);
   if(hSend<=0)
     {
      Print("-Err SendRequest");
      InternetCloseHandle(hRequest);
      Close();
     }
   // читаем страницу 
   ReadPage(hRequest,Out,toFile);
   // закрыли все хендлы
   InternetCloseHandle(hRequest); 
   InternetCloseHandle(hSend);
   return(true);
  }

Параметры функции MqlNet::Request:

  • string Verb – тип запроса “GET” или “POST”;
  • string Object – имя страницы с передаваемыми ей параметрами;
  • string &Out – строка, куда получаем ответ;
  • bool toFile – если toFile=true, то Out обозначает имя файла куда надо получить ответ;
  • string addData – дополнительные данные;
  • bool fromFile – если fromFile=true, то addData обозначает имя файла который надо отправить.

Чтение содержимого из полученного дескриптора

void MqlNet::ReadPage(int hRequest,string &Out,bool toFile)
  {
   // читаем страницу 
   uchar ch[100];
   string toStr="";
   int dwBytes,h;
   while(InternetReadFile(hRequest,ch,100,dwBytes))
     {
      if(dwBytes<=0) break;
      toStr=toStr+CharArrayToString(ch,0,dwBytes);
     }
   if(toFile)
     {
      h=FileOpen(Out,FILE_BIN|FILE_WRITE);
      FileWriteString(h,toStr);
      FileClose(h);
     }
   else Out=toStr;
  }

Параметры функции MqlNet::ReadPage:

  • Int hRequest – дескриптор запроса, откуда читаем данные;
  • string &Out – строка, куда получаем ответ;
  • bool toFile  – если toFile=true, то Out обозначает имя файла куда надо получить ответ.

И, собирая все в одно целое, будем иметь библиотечный класс MqlNet для работы с интернет.

class MqlNet
  {
   string            Host;     // имя хоста
   int               Port;     // порт
   int               Session; // дескриптор сессии
   int               Connect; // дескриптор соединения
public:
                     MqlNet(); // конструктор класса
                    ~MqlNet(); // деструктор
   bool              Open(string aHost,int aPort); // создаем сессию и открываем соединение
   void              Close(); // закрываем сессию и соединение
   bool              Request(string Verb,string Request,string &Out,bool toFile=false,string addData="",bool fromFile=false); // отправляем запрос
   bool              OpenURL(string URL,string &Out,bool toFile); // просто читаем страницу в файл или в переменную
   void              ReadPage(int hRequest,string &Out,bool toFile); // читаем страницу
   int               FileToArray(string FileName,uchar &data[]); // копируем файл в массив для отправки
  };

Вот в принципе и все требуемые функции, которые вполне могут удовлетворить самые разнообразные потребности при работе с интернетом. Рассмотрим примеры их использования.

Пример 1. Автоматическое скачивание MQL-программ в папки терминала. Скрипт MetaGrabber

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

  • анализ URL и разделение его на хост, запрос и имя файла;
  • отправление запроса на хост, получение и сохранение файла в папке терминала \Files;
  • перемещение его из Files в одну из требуемых папок данных:
    \Experts, \Indicators, \Scripts, \Include, \Libraries, \Tester(set), \Templates.

Для решения второй задачи используем класс MqlNet. Для третьей задачи функцию MoveFileEx из Kernel32.dll

#import "Kernel32.dll"
bool MoveFileExW(string &lpExistingFileName, string &lpNewFileName, int dwFlags);
#import "Kernel32.dll"

Для первой задачи сделаем небольшую сервисную функцию разбора строки URL.

Нам требуется выделить из адреса три строки: хост, путь к файлу на сайте и имя файла.
Например, в строке http://www.mysite.com/folder/page.html

- Хост = www.mysite.com
- Запрос = /folder/page.html
- Имя файла = page.html

В случае с CodeBase на сайте MQL5 пути имеют похожую структуру. Например, путь к файлу библиотеки ErrorDescription.mq5 на странице https://www.mql5.com/ru/code/79 имеет вид http://p.mql5.com/data/18/79/ErrorDescription.mqh. Этот путь легко получить – нажав правой кнопкой на ссылке и выбрав команду «Копировать ссылку». Таким образом, этот URL разделяется на две части для запроса плюс имя файла для удобства сохранения.

- Хост = p.mql5.com
- Запрос = /data/18/79/5/ErrorDescription.mqh
- Имя файла = ErrorDescription.mqh

Именно таким разбором строки и будет заниматься следующая функция ParseURL.

void ParseURL(string path,string &host,string &request,string &filename)
  {
   host=StringSubstr(URL,7);
   // убрали
   int i=StringFind(host,"/"); 
   request=StringSubstr(host,i);
   host=StringSubstr(host,0,i);
   string file="";
   for(i=StringLen(URL)-1; i>=0; i--)
      if(StringSubstr(URL,i,1)=="/")
        {
         file=StringSubstr(URL,i+1);
         break;
        }
   if(file!="") filename=file;
  }

Во внешних параметрах скрипта сделаем всего два параметра – URL (путь mql5 файла) и тип папки последующего размещения – то есть, в какую папку терминала его требуется переместить.

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

//+------------------------------------------------------------------+
//|                                                  MetaGrabber.mq5 |
//|                                 Copyright © 2010 www.fxmaster.de |
//|                                         Coding by Sergeev Alexey |
//+------------------------------------------------------------------+
#property copyright "www.fxmaster.de  © 2010"
#property link      "www.fxmaster.de"
#property version               "1.00"
#property description  "Download files from internet"

#property script_show_inputs

#include <InternetLib.mqh>

#import "Kernel32.dll"
bool MoveFileExW(string &lpExistingFileName,string &lpNewFileName,int dwFlags);
#import
#define MOVEFILE_REPLACE_EXISTING 0x1

enum _FolderType
  {
   Experts=0,
   Indicators=1,
   Scripts=2,
   Include=3,
   Libraries=4,
   Files=5,
   Templates=6,
   TesterSet=7
  };

input string URL="";
input _FolderType FolderType=0;
//------------------------------------------------------------------ OnStart
int OnStart()
  {
   MqlNet INet; // переменная для работы в интернете
   string Host,Request,FileName="Recieve_"+TimeToString(TimeCurrent())+".mq5";

   // разделили адрес на запрос
   ParseURL(URL,Host,Request,FileName);

   // открыли сессию
   if(!INet.Open(Host,80)) return(0);
   Print("+Copy "+FileName+" from  http://"+Host+" to "+GetFolder(FolderType));

   // получили файл
   if(!INet.Request("GET",Request,FileName,true))
     {
      Print("-Err download "+URL);
      return(0);
     }
   Print("+Ok download "+FileName);

   // перемещаем в требуемую папку
   string to,from,dir;
   // если никуда перемещать не надо
   if(FolderType==Files) return(0);

   // откуда
   from=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\"+FileName;

   // куда
   to=TerminalInfoString(TERMINAL_DATA_PATH)+"\\";
   if(FolderType!=Templates && FolderType!=TesterSet) to+="MQL5\\";
   to+=GetFolder(FolderType)+"\\"+FileName;

   // перемещаем 
   if(!MoveFileExW(from,to,MOVEFILE_REPLACE_EXISTING))
     {
      Print("-Err move to "+to);
      return(0);
     }
   Print("+Ok move "+FileName+" to "+GetFolder(FolderType));

   return(0);
  }
//------------------------------------------------------------------ GetFolder
string GetFolder(_FolderType foldertype)
  {
   if(foldertype==Experts) return("Experts");
   if(foldertype==Indicators) return("Indicators");
   if(foldertype==Scripts) return("Scripts");
   if(foldertype==Include) return("Include");
   if(foldertype==Libraries) return("Libraries");
   if(foldertype==Files) return("Files");
   if(foldertype==Templates) return("Profiles\\Templates");
   if(foldertype==TesterSet) return("Tester");
   return("");
  }
//------------------------------------------------------------------ ParseURL
void ParseURL(string path,string &host,string &request,string &filename)
  {
   host=StringSubstr(URL,7);
   // убрали
   int i=StringFind(host,"/"); 
   request=StringSubstr(host,i);
   host=StringSubstr(host,0,i);
   string file="";
   for(i=StringLen(URL)-1; i>=0; i--)
      if(StringSubstr(URL,i,1)=="/")
        {
         file=StringSubstr(URL,i+1);
         break;
        }
   if(file!="") filename=file;
  }
//+------------------------------------------------------------------+


Опыты предлагаем проводить над любимым разделом https://www.mql5.com/ru/code. Скачанные файлы сразу будут появляться в навигаторе редактора, и их можно будет компилировать, не перезагружая терминал и редактор. И не блуждая по длинным путям файловой системы в поиске требуемой папки для переноса в неё файла.

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

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

Пример 2. Мониторинг котировок от нескольких брокеров на одном графике

Итак, получать файлы из интернета мы научились. Теперь рассмотрим вопрос интереснее – как эти данные отправить и сохранить на сервере. Для этого нам понадобится дополнительный небольшой PHP-скрипт, который будет размещаться на сервере.  Используя написанный класс MqlNet, создадим эксперт мониторинга - MetaArbitrage. Задачей эксперта в связке с PHP-скриптом будет:

  • отправка экспертом запроса на сервер;
  • формирование на сервере ответной страницы (PHP);
  • прием этой страницы экспертом;
  • её анализ и выдача результата на экран.

Принципиальная схема взаимодействия между MQL-модулем и PHP-скриптом следующая:


Для решения задач - используем класс MqlNet.

Чтоб избежать дублирования данных, а также отсеять устаревшие котировки – будем передавать 4 главных параметра: имя сервер брокера (источник текущих котировок), валюта, цена и время котировки в UTC. Например, запрос для обращения к скрипту на ресурсе нашей компании выглядит так:

www.fxmaster.de/metaarbitr.php?server=Metaquotes&pair=EURUSD&bid=1.4512&time=13286794

Эти параметры и сама котировка сохраняются на сервере и будут выдаваться в ответной странице вместе со всеми другими хранящимися котировками данной валюты.

«Побочное» удобство такого обмена – котировки можно отправлять как из MT5, так и из MT4!

Страница, которая формируется сервером – это обычный CSV файл. Выглядит он в данном скрипте так:

ServerName1; Bid1; Time1
ServerName 2; Bid2; Time2
ServerName 3; Bid3; Time3

ServerName N; BidN; TimeN

Но вы можете добавить в него свои дополнительные параметры (например, тип сервера - демо или реал). Этот CSV-файл сохраняем и разбираем построчно с выводом на экран таблицы значений и линий цены.

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


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


Эта схема будет основой для принципа обмена информацией между любым количеством терминалов. Полный эксперт MetaArbitrage и PHP-скрипт с комментариями скачайте внизу статьи. Подробно про используемые PHP-функции можете прочитать на сайте php.su

Пример 3. Обмен сообщениями (мини-чат)  в терминале. Эксперт MetaChat

Отойдем  немного от торговли и цифр и сделаем приложение, которое даст возможность, не «выходя» из терминала, общаться в чате одновременно с несколькими людьми. Для этого нам понадобится еще один скрипт на PHP, но он, в общем, похож на предыдущий. За исключением того, что в новом вместо анализа времени котировок будет анализ числа строк в файле. Задачей эксперта будет:

  • отправка текстовой строки на сервер;
  • добавление этой строки в общий файл, контроль размера файла, выдача ответного файла (php);
  • получение текущего чата и отображение его на экране.

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


MetaСhat и MetaArbitrage поддерживается на сайте их разработчиков. Там же находятся установленные PHP-скрипты для их работы.
Поэтому если вы хотите протестировать работу или воспользоваться данным сервисом используйте следующую адресацию:
MetaСhat - www.fxmaster.de/metachat.php
MetaArbitrage - www.fxmaster.de/metaarbitr.php

Заключение

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

  • чтение новостей или получение иной информации напрямую в терминал для анализа в экспертах;
  • удаленное управление экспертом;
  • автоматическое обновление версий экспертов/индикаторов;
  • копировщики/трансляторы сделок, рассылка сигналов;
  • скачивание шаблонов в комплекте с индикаторами и set-файлов для экспертов;
  • И многое, многое другое…

В этой статье мы использовали тип GET запросов. Их вполне достаточно, когда необходимо получить файл или отправить запрос с каким-то небольшим количеством параметров для анализа на сервере.

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

Полезные ресурсы

Прикрепленные файлы |
internetlib.mqh (8.6 KB)
metaarbitrage.mq5 (9.34 KB)
metachat.mq5 (5.77 KB)
metagrabber.mq5 (3.28 KB)
metaarbitr.zip (0.81 KB)
wininet.zip (12.81 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (45)
Sergey Naumov
Sergey Naumov | 1 окт. 2019 в 14:51
Может кто знает какие требования к хосту в этой либе (wininet.dll)?
Вот такой не проходит ec2-18-217-190-217.us-east-2.compute.amazonaws.com
Andrey Khatimlianskii
Andrey Khatimlianskii | 1 окт. 2019 в 16:13
Sergey Naumov:
А как вызвать скрипт из индикатора? Это как мне известно тоже нормальными способами невозможно.

https://www.mql5.com/ru/articles/5337

Sergey Naumov
Sergey Naumov | 2 окт. 2019 в 09:44
Спасибо.
Alexandr Gavrilin
Alexandr Gavrilin | 25 дек. 2021 в 21:07
2021.12.26 01:06:05.840 metaarbitrage (EURUSD,H1)       +Open Inet...
2021.12.26 01:06:08.537 metaarbitrage (EURUSD,H1)       Access violation at 0x00007FF93AAE2740 read to 0xFFFFFFFFFFFFFFFF in 'wininet.dll'
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)          crash -->  00007FF93AAE2740 66837C410200      cmp        word [rcx+rax*2+0x2], 0x0
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)                     00007FF93AAE2746 488D4001          lea        rax, [rax+0x1]
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)                     00007FF93AAE274A 75F4              jnz        0x7ff93aae2740
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)                     00007FF93AAE274C 488B0D8D5D3D00    mov        rcx, [rip+0x3d5d8d]
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)                     00007FF93AAE2753 8D044502000000    lea        eax, [rax*2+0x2]
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)                     00007FF93AAE275A 448BC0            mov        r8d, eax
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)                     00007FF93AAE275D 33D2              xor        edx, edx
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       00: 0x00007FF93AAE2740
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       01: 0x000002C546534171
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       02: 0x0000000000CC0038
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       03: 0x000002C500000000
2021.12.26 01:06:08.539 metaarbitrage (EURUSD,H1)       

Вот такое стало вылазить при поптыке проверить.

Alex Renko
Alex Renko | 4 окт. 2023 в 15:45
Крутейшая штука! Особенно для лицензирования советников ... в топку webrequest ... эта вещь я так понимаю даже в тестере работать будет! Вау
MetaTrader 5: Публикация торговых прогнозов и отчетов реальной торговли по e-mail в блогах, социальных сетях и специализированных сайтах MetaTrader 5: Публикация торговых прогнозов и отчетов реальной торговли по e-mail в блогах, социальных сетях и специализированных сайтах
Цель данной статьи - представить готовые решения для публикации прогнозов с использованием MetaTrader 5. Рассмотрен ряд идей: от использования специализированных сайтов для публикации торговых отчетов до создания своего собственного блога и финальной интеграции с социальными микроблогами, которые позволяют объединить множество трейдеров, использующих прогнозы. Все представленные здесь решения на 100% бесплатные и могут быть использованы всеми, кто знаком с базовыми понятиями почтовых и ftp-сервисов. Данные методы могут быть легко использованы и в коммерческих сервисах по предоставлению торговых прогнозов.
ООП в MQL5 на примерах: обработка кодов ошибок и предупреждений ООП в MQL5 на примерах: обработка кодов ошибок и предупреждений
В статье рассматривается пример создания класса для работы с кодами возврата торгового сервера и всеми ошибками, возникающими в процессе работы MQL-программы. После прочтения статьи, вы сможете сформулировать для себя начальное представление о том как работать с классами и объектами в MQL5. И в то же время у вас появится удобный инструмент для обработки ошибок, который в дальнейшем можно будет дорабатывать на свой вкус и цвет.
Конструктор трейдера: Drag Trade Library Конструктор трейдера: Drag Trade Library
В статье описывается библиотека Drag Trade, содержащая функционал для визуальной торговли. Библиотека легко может быть подключена практически к любому советнику. Ваш советник может превратиться из автомата в автоматизированную торгово-информационную систему добавлением нескольких строчек кода и практически без усилий с Вашей стороны.
Связь ICQ и эксперта в MQL5 Связь ICQ и эксперта в MQL5
В статье рассматривается способ двустороннего обмена текстовыми сообщениями между клиентами ICQ, используя средства программирования языка MQL5. Материал заинтересует тех, кто хочет получать торговую информацию из работающего торгового терминала удаленно, например, через ICQ клиента в своем мобильном телефоне или КПК.