English 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Использование WinInet в MQL5.  Часть 2:  POST-запросы и файлы

Использование WinInet в MQL5. Часть 2: POST-запросы и файлы

MetaTrader 5Примеры | 13 мая 2011, 14:34
6 517 6
---
---


Введение

В прошлом уроке "Использование WinInet.dll для обмена данными между терминалами через Интернет" мы разобрались с работой библиотеки, научились открывать web-страницы, отправлять и принимать данные по GET-запросу.

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

  • создавать и отправлять простые POST запросы на сервер
  • отправлять файлы на сервер методом представления multipart/form-data
  • работать с Cookie, читать информацию с сайтов под своим логином.

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


POST-запросы

Для отправки данных нам понадобится все те же функции wininet.dll и созданный класс CMqlNet, которые были подробно расписаны в прошлой статье.

В связи с большим количеством полей в методе CMqlNet::Request нам пришлось создать отдельную структуру tagRequest, которая содержит в себе все необходимые поля запроса. 

//------------------------------------------------------------------ struct tagRequest
struct tagRequest
{
  string stVerb;   // метод запроса GET/POST/…
  string stObject; // путь к объекту запроса например  "/index.htm" или "/get.php?a=1"  
  string stHead;   // заголовок запроса
  string stData;   // дополнительная строка данных
  bool fromFile;   // если =true, то stData обозначает имя файла данных
  string stOut;    // строка для приема ответа
  bool toFile;     // если =true, то stOut обозначает имя файла для приема ответа

  void Init(string aVerb, string aObject, string aHead, 
            string aData, bool from, string aOut, bool to); // функция инициализации всех полей
};
//------------------------------------------------------------------ Init
void tagRequest::Init(string aVerb, string aObject, string aHead, 
                      string aData, bool from, string aOut, bool to)
{
  stVerb=aVerb;     // метод запроса GET/POST/…
  stObject=aObject; // путь к странице "/get.php?a=1"  или "/index.htm"
  stHead=aHead;     // заголовок запроса, например"Content-Type: application/x-www-form-urlencoded"
  stData=aData;     // дополнительная строка данных
  fromFile=from;    // если =true, то stData обозначает имя файла данных
  stOut=aOut;       // поле для приема ответа
  toFile=to;        // если =true, то stOut обозначает имя файла для приема ответа
}

А также заменить заголовок метода CMqlNet::Request более коротким:

//+------------------------------------------------------------------+
bool MqlNet::Request(tagRequest &req)
  {
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
     {
      Print("-DLL not allowed"); return(false);
     }
//--- проверка разрешения DLL в терминале
   if(!MQL5InfoInteger(MQL5_DLLS_ALLOWED))
     {
      Print("-DLL not allowed");
      return(false);
     }
//--- проверка разрешения DLL в терминале
   if(req.toFile && req.stOut=="")
     {
      Print("-File not specified ");
      return(false);
     }
   uchar data[]; 
    int hRequest,hSend;
   string Vers="HTTP/1.1"; 
    string nill="";

//--- читаем файл в массив
   if(req.fromFile)
     {
      if(FileToArray(req.stData,data)<0)
        {
         Print("-Err reading file "+req.stData);
         return(false);
        }
     }
   else StringToCharArray(req.stData,data);

   if(hSession<=0 || hConnect<=0)
     {
      Close();
      if(!Open(Host,Port,User,Pass,Service))
        {
         Print("-Err Connect");
         Close();
         return(false);
        }
     }
//--- создаем дескриптор запроса
   hRequest=HttpOpenRequestW(hConnect,req.stVerb,req.stObject,Vers,nill,0,
   INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE,0);
   if(hRequest<=0)
     {
      Print("-Err OpenRequest");
      InternetCloseHandle(hConnect);
      return(false);
     }
//--- отправляем запрос
   hSend=HttpSendRequestW(hRequest,req.stHead,StringLen(req.stHead),data,ArraySize(data));
//--- отправляем файл
   if(hSend<=0)
     {
      int err=0;
      err=GetLastError(err);
      Print("-Err SendRequest= ",err);
     }
//--- читаем страницу
   if(hSend>0) ReadPage(hRequest,req.stOut,req.toFile);
//--- закрываем все хендлы
   InternetCloseHandle(hRequest); InternetCloseHandle(hSend);

   if(hSend<=0)
     {
      Close();
      return(false);
     }
   return(true);
  }

Теперь приступим к работе.


Отправка данных на сайт с типом application/x-www-form-urlencoded

В прошлом уроке мы рассмотрели пример - эксперт MetaArbitrage (мониторинг котировок).

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

Чтобы сменить запрос GET на POST, необходимо всего лишь "спрятать" саму строку запроса в тело запроса, идущее после заголовков.

BOOL HttpSendRequest(
  __in  HINTERNET hRequest,
  __in  LPCTSTR lpszHeaders,
  __in  DWORD dwHeadersLength,
  __in  LPVOID lpOptional,
  __in  DWORD dwOptionalLength
);

  • hRequest [in]
     Хендл, возвращенный HttpOpenRequest.
  • lpszHeaders [in]
    Указатель на строку с содержимым заголовков для добавления к запросу. Это параметр может быть пустым.
  • dwHeadersLength [in]
    Длина заголовка в байтах.
  • lpOptional [in]
    Указатель на массив uchar с данными, которые отправляются сразу после заголовка. Этот параметр обычно используется для POST и PUT операций.
  • dwOptionalLength [in]
    Размер данных в байтах. Параметр может быть =0, что означает, что никакие дополнительные данные не отправляются.

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

В примере для MetaArbitrage GET-запрос на сервер выглядел следующим образом:

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


Красным цветом выделен сам запрос. Значит, в случае POST-запроса его текст необходимо перенести в массив данных lpOptional.

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

#include <InternetLib.mqh>

string Server[];        // массив имен серверов
double Long[], Short[]; // массив данных свопов
MqlNet INet;           // экземпляр класса для работы

//------------------------------------------------------------------ OnStart
void OnStart()
{
//--- открываем сессию
  if (!INet.Open("www.fxmaster.de", 80, "", "", INTERNET_SERVICE_HTTP)) return;
 
//--- обнулили массивы
  ArrayResize(Server, 0); ArrayResize(Long, 0); ArrayResize(Short, 0);
//--- файл, куда записывать пример данных свопа
  string file=Symbol()+"_swap.csv";
//--- отправляем свопы
  if (!SendData(file, "GET")) 
  { 
    Print("-err RecieveSwap"); 
    return; 
  }
//--- читаем данные из принятого файла
  if (!ReadSwap(file)) return; 
//--- обновляем информацию о свопах на графике
  UpdateInfo();               
}

Работа скрипта очень проста.

Сначала открывается интернет-сессия INet.Open. Затем функция SendData отправляет данные свопов текущего символа. Затем при успешном выполнении отправки происходит чтение принятых ответных свопов ReadSwap и вывод их на график UpdateInfo.

В данный момент нас будет интересовать только функция SendData.

//------------------------------------------------------------------ SendData bool SendData(string file, string mode) {   string smb=Symbol();   string Head="Content-Type: application/x-www-form-urlencoded"; // заголовок   string Path="/mt5swap/metaswap.php"; // путь к странице   string Data="server="+AccountInfoString(ACCOUNT_SERVER)+               "&pair="+smb+               "&long="+DTS(SymbolInfoDouble(smb, SYMBOL_SWAP_LONG))+               "&short="+DTS(SymbolInfoDouble(smb, SYMBOL_SWAP_SHORT));   tagRequest req; // инициализация параметров   if (mode=="GET")  req.Init(mode, Path+"?"+Data, Head, "",   false, file, true);   if (mode=="POST") req.Init(mode, Path,          Head, Data, false, file, true);   return(INet.Request(req)); // посылаем запрос на сервер }

В этом скрипте мы специально для демонстрации сделали два метода отправки данных - при помощи GET и POST, чтобы вы могли, как говорится, "прочувствовать" их разницу.

Опишем по порядку переменные функции:

  • Head - это заголовок запроса с информацией про тип содержимого. На самом деле это не весь заголовок, который находится в запросе. Остальные поля заголовка создает сама библиотека wininet.dll. Но и их можно модифицировать с помощью функции HttpAddRequestHeaders.
  • Path - это путь к объекту запроса относительно начального домена www.fxmaster.de, по-простому говоря, путь к php-скрипту, который обработает запрос. Кстати, не обязательно запрашивать только php-срипт, это может быть и обычная html-страница (в первом уроке мы запрашивали даже mq5-файл).
  • Data - это конкретно данные, которые передаются на сервер. Запись данных происходит согласно правилам передачи имя параметра=значение. Знак "&" является разделителем данных.

И самое главное: обратите внимание на отличия между заданием GET и POST запросов в tagRequest::Init.

В методе GET путь отправляется вместе с телом запроса (объединяясь знаком "?"), а поле данных lpOptional (в структуре оно имеет имя stData) остается пустым.
В методе POST
путь существует сам по себе, а тело запроса уходит в lpOptional.

Как видите, отличия несущественны. Серверный скрипт metaswap.php, который принимает этот запрос, можно скачать в приложении к статье.


Отправка данных multipart/form-data

На самом деле POST-запросы - это не аналог GET-запросов (иначе бы в них не было необходимости). POST-запросы обладают существенным преимуществом - с их помощью можно передавать файлы с бинарным содержимым.

Дело в том, что запрос с типом urlencoded имеет право отправить только разрешенный набор символов. В противном случае "запрещенные" символы будут заменены кодами. Следовательно, при отправке бинарных данных они будут искажены. То есть передать даже небольшой gif-файл через GET-запрос вы не сможете.

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

Для этого тело запроса делится на разделы. Самое главное то, что каждый раздел может иметь свой тип данных. Например, первый раздел это текст, следующий раздел это image/jpeg и т.д. То есть, в одном запросе на сервер можете передавать сразу несколько разных типов данных.

Рассмотрим структуру такого описания на примере передаваемых данных скрипта MetaSwap.

Заголовок запроса Head будет иметь следующий вид:

Content-Type: multipart/form-data; boundary=РАЗДЕЛИТЕЛЬ\r\n


Ключевое слово РАЗДЕЛИТЕЛЬ – это произвольный набор символов. Но вы должны проследить, чтобы этот набор символов не находился в данных запроса. То есть, эта строка должна быть уникальной, проще говоря, какой-то абракадаброй, по типу hdsJK263shxaDFHLsdhsDdjf9 или что вы сами придумаете :). В PHP обычно данную строку формируют, используя MD5 код текущего времени.

Сам POST-запрос выглядит следующим образом (для упрощения восприятия поля выделены цветом по общему смыслу):

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: form-data; name="Server"\r\n
\r\n
MetaQuotes-Demo

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: form-data; name="Pair"\r\n
\r\n
EURUSD

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: form-data; name="Long"\r\n
\r\n
1.02

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: form-data; name="Short"\r\n
\r\n
-0.05

\r\n
--РАЗДЕЛИТЕЛЬ--\r\n


Мы специально явным образом указали места перевода строки "\r\n", так как они являются обязательными символами в запросе. Как видите, в запросе передаются те же четыре поля данных, причем они передаются обычным текстовым способом.

Важные особенности установки разделителя:

  • Перед разделителем ставится два подряд символа "--".
  • В завершающем разделителе два символа "--" добавляются также и после него.


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

Представим, что некий эксперт в момент закрытия сделки передает снимок чарта и подробный отчет счета в текстовом файле.

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: form-data; name="ExpertName"\r\n
\r\n
MACD_Sample

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: file; name="screen"; filename="screen.gif"\r\n
Content-Type: image/gif\r\n
Content-Transfer-Encoding: binary\r\n
\r\n
......содержимое gif-файла.....

\r\n
--РАЗДЕЛИТЕЛЬ\r\n

Content-Disposition: form-data; name="statement"; filename="statement.csv"\r\n
Content-Type: application/octet-stream\r\n
Content-Transfer-Encoding: binary\r\n
\r\n
......содержимое csv-файла.....

\r\n
--РАЗДЕЛИТЕЛЬ--\r\n


В запросе появились два новых заголовка:

Content-Type - указывает на тип содержимого, все типы четко регламентируется стандартом RFC[2046]. Мы использовали два типа image/gif и application/octet-stream.

Два варианта записи Content-Disposition - file и form-data равноправны и корректно обрабатываются PHP в обоих случаях. То есть вы можете использовать или file, или form-data по вашему усмотрению. Более детальную разницу в их представлении можете наблюдать в Charles.

Content-Transfer-Encoding - указывает на кодировку содержимого. Для текстовых данных может отсутствовать.

Для закрепления материала напишем скрипт ScreenPost, который передает снимок экрана на сервер:

#include <InternetLib.mqh>

MqlNet INet; // экземпляр класса для работы

//------------------------------------------------------------------ OnStart
void OnStart()
{
  // открываем сессию
  if (!INet.Open("www.fxmaster.de", 80, "", "", INTERNET_SERVICE_HTTP)) return;

  string giffile=Symbol()+"_"+TimeToString(TimeCurrent(), TIME_DATE)+".gif"; // имя файла на отправку
 
  // создали скриншот 800х600px
  if (!ChartScreenShot(0, giffile, 800, 600)) { Print("-err ScreenShot "); return; }
 
  // читаем gif-файл в массив
  int h=FileOpen(giffile, FILE_ANSI|FILE_BIN|FILE_READ); if (h<0) { Print("-err Open gif-file "+giffile); return; }
  FileSeek(h, 0, SEEK_SET);
  ulong n=FileSize(h); // узнали размер файла
  uchar gif[]; ArrayResize(gif, (int)n); // создали uichar массив под размер данных
  FileReadArray(h, gif); // прочитали файл в массив
  FileClose(h); // закрыли файл
 
  // создали файл на отправку
  string sendfile="sendfile.txt";
  h=FileOpen(sendfile, FILE_ANSI|FILE_BIN|FILE_WRITE); if (h<0) { Print("-err Open send-file "+sendfile); return; }
  FileSeek(h, 0, SEEK_SET);

  // формируем запрос
  string bound="++1BEF0A57BE110FD467A++"; // разделитель данных запроса
  string Head="Content-Type: multipart/form-data; boundary="+bound+"\r\n"; // заголовок
  string Path="/mt5screen/screen.php"; // путь к странице
 
  // пишем данные
  FileWriteString(h, "\r\n--"+bound+"\r\n");
  FileWriteString(h, "Content-Disposition: form-data; name=\"EA\"\r\n"); // поле "имя эксперта"
  FileWriteString(h, "\r\n");
  FileWriteString(h, "NAME_EA");
  FileWriteString(h, "\r\n--"+bound+"\r\n");
  FileWriteString(h, "Content-Disposition: file; name=\"data\"; filename=\""+giffile+"\"\r\n"); // поле gif-файл
  FileWriteString(h, "Content-Type: image/gif\r\n");
  FileWriteString(h, "Content-Transfer-Encoding: binary\r\n");
  FileWriteString(h, "\r\n");
  FileWriteArray(h, gif); // записали gif-данные
  FileWriteString(h, "\r\n--"+bound+"--\r\n");
  FileClose(h); // закрыли файл

  tagRequest req; // инициализация параметров
  req.Init("POST", Path, Head, sendfile, true, "answer.htm", true);
 
  if (INet.Request(req)) Print("-err Request"); // посылаем запрос на сервер
  else Print("+ok Request");
} 

Серверный скрипт, который принимает данные:

<?php
$ea=$_POST['EA'];
$data=file_get_contents($_FILES['data']['tmp_name']); // данные файла
$file=$_FILES['data']['name'];
$h=fopen(dirname(__FILE__)."/$ea/$file", 'wb'); // создаем файл в папке эксперта 
fwrite($h, $data); fclose($h); // сохраняем данные
?>

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


Работа с Cookie

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

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

Например, когда вы при логине на сервер www.mql5.com  ставите галку "Запомнить меня", то вы тем самым сохраняете Cookie с вашими данными на компьютере. При следующем посещении сайта браузер просто передаст серверу эти Cookie, не спрашивая вас.

Можете для интереса открыть папку (WinXP) C:\Documents and Settings\<Юзер>\Cookies и просмотреть содержимое от различных серверов, которые вы посещаете.

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

Например:

  • Написать эксперт (или внешнее приложение), который раз в час обращается на страницу https://www.mql5.com/ru/job и получать список новых предложений работы.
  • Обращаться на интересующую ветку, например https://www.mql5.com/ru/forum/23, и проверять, нет ли в ней новых сообщений.
  • Также можно проверять наличие новых "личных сообщений" на форумах.

Для установки Cookie в запрос используется функция InternetSetCookie.

BOOL InternetSetCookie(
  __in  LPCTSTR lpszUrl,
  __in  LPCTSTR lpszCookieName,
  __in  LPCTSTR lpszCookieData
);

  • lpszUrl [in] - Имя сервера, например, www.mql5.com
  • lpszCookieName [in]- Имя куки
  • lpszCookieData [in] - Данные этого куки

Чтобы установить несколько Cookie, нужно просто вызвать эту функцию для каждого из них.

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


Заключение

Итак, мы познакомились с еще одним типом HTTP-запросов, получили возможность отправлять бинарные файлы, что позволяет расширить возможности работы с вашими серверами, а также узнали про методы работы с Cookie.

В качестве направлений разработок можно обозначить:

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


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

  1. Прокси для просмотра отсылаемых заголовков http://www.charlesproxy.com/
  2. Описание WinHTTP http://msdn.microsoft.com/en-us/library/aa385331%28VS.85%29.aspx
  3. Описание HTTP Session http://msdn.microsoft.com/en-us/library/aa384322%28VS.85%29.aspx
  4. Комплект Денвер для локальной установки сервера Apache+PHP http://www.denwer.ru/
  5. Виды заголовков запросов http://www.codenet.ru/webmast/php/HTTP-POST.php#part_3_2
  6. Типы запросов http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type
  7. Типы запросов ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/media-types.
  8. Структура использования HINTERNET http://msdn.microsoft.com/en-us/library/aa383766%28VS.85%29.aspx
  9. Работа с файлами http://msdn.microsoft.com/en-us/library/aa364232%28VS.85%29.aspx
  10. Типы данных для перевода в MQL http://msdn.microsoft.com/en-us/library/aa383751%28VS.85%29.aspx


Прикрепленные файлы |
metaswap.zip (0.66 KB)
screenpost.zip (0.33 KB)
metaswap.mq5 (4.82 KB)
screenpost.mq5 (2.59 KB)
internetlib.mqh (12.68 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (6)
Juer
Juer | 16 сент. 2018 в 10:07

В тестере вылетает вот здесь:

if(!https_flag)
           hRequest=HttpOpenRequestW(hConnect, req.stVerb, req.stObject, Vers, nill, 0, INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE, 0); 
        else
           hRequest=HttpOpenRequestW(hConnect, req.stVerb, req.stObject, Vers, nill, 0, INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_SECURE, 0); 

С ошибкой:

2018.09.16 11:11:23.242 2017.01.01 00:00:00   Access violation at 0x00007FFF798662F9 read to 0x0000009500000000 in 'wininet.dll'
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660E0 48895C2418        mov        [rsp+0x18], rbx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660E5 48894C2408        mov        [rsp+0x8], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660EA 55                push       rbp
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660EB 56                push       rsi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660EC 57                push       rdi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660ED 4154              push       r12
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660EF 4155              push       r13
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660F1 4156              push       r14
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660F3 4157              push       r15
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660F5 488D6C24B0        lea        rbp, [rsp-0x50]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798660FA 4881EC50010000    sub        rsp, 0x150
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866101 4D8BF9            mov        r15, r9
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866104 4D8BF0            mov        r14, r8
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866107 488BFA            mov        rdi, rdx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986610A F6056B40380002    test       byte [rip+0x38406b], 0x2
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866111 0F85DF920700      jnz        dword 0x7fff798df3f6
2018.09.16 11:11:23.248 2017.01.01 00:00:00   
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866117 33C9              xor        ecx, ecx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866119 33D2              xor        edx, edx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986611B 448D4158          lea        r8d, [rcx+0x58]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986611F 894C2468          mov        [rsp+0x68], ecx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866123 48894C2450        mov        [rsp+0x50], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866128 48894D80          mov        [rbp-0x80], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986612C 48894DB8          mov        [rbp-0x48], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866130 48894C2470        mov        [rsp+0x70], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866135 48894DD0          mov        [rbp-0x30], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866139 48894DA8          mov        [rbp-0x58], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986613D 448BE9            mov        r13d, ecx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866140 48894C2460        mov        [rsp+0x60], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866145 66898D98000000    mov        [rbp+0x98], cx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986614C 894C2458          mov        [rsp+0x58], ecx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866150 48894D90          mov        [rbp-0x70], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866154 894C245C          mov        [rsp+0x5c], ecx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866158 48894D88          mov        [rbp-0x78], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986615C 48894D98          mov        [rbp-0x68], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866160 488D4DF0          lea        rcx, [rbp-0x10]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866164 E8F7B3F8FF        call       0x7fff797f1560  ; Ñ; (wininet.dll)
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866169 FF1511D23A00      call       qword near [rip+0x3ad211]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986616F 8B0D33313800      mov        ecx, [rip+0x383133]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866175 8BF0              mov        esi, eax
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866177 FF1553D33A00      call       qword near [rip+0x3ad353]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986617D 488BD8            mov        rbx, rax
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866180 4885C0            test       rax, rax
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866183 0F84FAE5FBFF      jz         dword 0x7fff79824783
2018.09.16 11:11:23.248 2017.01.01 00:00:00   
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866189 8BCE              mov        ecx, esi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986618B FF15B7D23A00      call       qword near [rip+0x3ad2b7]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866191 33F6              xor        esi, esi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866193 4885DB            test       rbx, rbx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF79866196 0F84E7920700      jz         dword 0x7fff798df483
2018.09.16 11:11:23.248 2017.01.01 00:00:00   
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF7986619C 488B4B30          mov        rcx, [rbx+0x30]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661A0 488B4328          mov        rax, [rbx+0x28]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661A4 48897328          mov        [rbx+0x28], rsi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661A8 48894DB0          mov        [rbp-0x50], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661AC 488B4B38          mov        rcx, [rbx+0x38]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661B0 48897330          mov        [rbx+0x30], rsi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661B4 48894DA0          mov        [rbp-0x60], rcx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661B8 8B4B40            mov        ecx, [rbx+0x40]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661BB 48897338          mov        [rbx+0x38], rsi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661BF 894C2478          mov        [rsp+0x78], ecx
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661C3 488B4B50          mov        rcx, [rbx+0x50]
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661C7 897340            mov        [rbx+0x40], esi
2018.09.16 11:11:23.248 2017.01.01 00:00:00                 00007FFF798661CA 48894DC8          mov        [rbp-0x38], rcx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661CE 48897350          mov        [rbx+0x50], rsi
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661D2 488945E0          mov        [rbp-0x20], rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661D6 BAFFFFFFFF        mov        edx, 0xffffffff
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661DB 4885FF            test       rdi, rdi
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661DE 0F84AA000000      jz         dword 0x7fff7986628e
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661E4 4883C8FF          or         rax, 0xff
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661E8 0F1F0400          nop        [rax+rax]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661EC 48FFC0            inc        rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661EF 6644392C47        cmp        [rdi+rax*2], r13W
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661F4 75F6              jnz        0x7fff798661ec
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661F6 4C8BE6            mov        r12, rsi
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661F9 483BC2            cmp        rax, rdx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798661FC 0F8730930700      ja         dword 0x7fff798df532
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866202 8D4801            lea        ecx, [rax+0x1]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866205 3BC8              cmp        ecx, eax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866207 0F8225930700      jb         dword 0x7fff798df532
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986620D 8BD9              mov        ebx, ecx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986620F 4803DB            add        rbx, rbx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866212 483BDA            cmp        rbx, rdx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866215 0F8717930700      ja         dword 0x7fff798df532
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986621B 488B0DCE323800    mov        rcx, [rip+0x3832ce]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866222 448BC3            mov        r8d, ebx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866225 33D2              xor        edx, edx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866227 895DB8            mov        [rbp-0x48], ebx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986622A FF1530D13A00      call       qword near [rip+0x3ad130]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866230 4C8BE0            mov        r12, rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866233 48894580          mov        [rbp-0x80], rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866237 488945C0          mov        [rbp-0x40], rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986623B 4885C0            test       rax, rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986623E 0F84EE920700      jz         dword 0x7fff798df532
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866244 448BCB            mov        r9d, ebx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866247 488D442458        lea        rax, [rsp+0x58]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986624C 4C8BC7            mov        r8, rdi
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986624F 4889442438        mov        [rsp+0x38], rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866254 41D1E9            shr        r9d, 1
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866257 4889742430        mov        [rsp+0x30], rsi
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986625C BA00040000        mov        edx, 0x400
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866261 33C9              xor        ecx, ecx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866263 41FFC9            dec        r9d
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866266 895C2428          mov        [rsp+0x28], ebx
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986626A 4C89642420        mov        [rsp+0x20], r12
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986626F FF1503D13A00      call       qword near [rip+0x3ad103]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866275 8945BC            mov        [rbp-0x44], eax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866278 8BC0              mov        eax, eax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986627A 46882C20          mov        [rax+r12], r13b
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986627E 44396C2458        cmp        [rsp+0x58], r13d
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866283 0F8522920700      jnz        dword 0x7fff798df4ab
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866289 BAFFFFFFFF        mov        edx, 0xffffffff
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986628E 4D85F6            test       r14, r14
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866291 7434              jz         0x7fff798662c7
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866293 488D44245C        lea        rax, [rsp+0x5c]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866298 4533C9            xor        r9d, r9d
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986629B 41B8E9FD0000      mov        r8d, 0xfde9
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662A1 4889442428        mov        [rsp+0x28], rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662A6 488D4590          lea        rax, [rbp-0x70]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662AA 498BCE            mov        rcx, r14
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662AD 4889442420        mov        [rsp+0x20], rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662B2 E8D5E0F9FF        call       0x7fff7980438c  ; HttpEndRequestW (wininet.dll)
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662B7 8BF0              mov        esi, eax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662B9 89442468          mov        [rsp+0x68], eax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662BD 85C0              test       eax, eax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662BF 0F858CFD0400      jnz        dword 0x7fff798b6051
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662C5 33F6              xor        esi, esi
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662C7 4D85FF            test       r15, r15
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662CA 0F856F920700      jnz        dword 0x7fff798df53f
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662D0 41BEFFFFFFFF      mov        r14d, 0xffffffff
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662D6 488B85B0000000    mov        rax, [rbp+0xb0]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662DD 4885C0            test       rax, rax
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662E0 0F858C930700      jnz        dword 0x7fff798df672
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662E6 4C8BBDB8000000    mov        r15, [rbp+0xb8]
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662ED 4D85FF            test       r15, r15
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662F0 0F8403010000      jz         dword 0x7fff798663f9
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662F6 0FB7FE            movzx      edi, si
2018.09.16 11:11:23.249 2017.01.01 00:00:00      crash -->  00007FFF798662F9 4D392F            cmp        [r15], r13
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662FC 740C              jz         0x7fff7986630a
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF798662FE 66FFC7            inc        di
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866301 0FB7C7            movzx      eax, di
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866304 4D392CC7          cmp        [r15+rax*8], r13
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF79866308 75F4              jnz        0x7fff798662fe
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00                 00007FFF7986630A 488B0DDF313800    mov        rcx, [rip+0x3831df]
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.249 2017.01.01 00:00:00   00: 0x00007FFF798662F9
2018.09.16 11:11:23.249 2017.01.01 00:00:00   01: 0x000000959D50C561
2018.09.16 11:11:23.249 2017.01.01 00:00:00   02: 0x0000000000CC0010
2018.09.16 11:11:23.249 2017.01.01 00:00:00   03: 0x000000958E540000
2018.09.16 11:11:23.249 2017.01.01 00:00:00   04: 0x000000959E354970
2018.09.16 11:11:23.249 2017.01.01 00:00:00   05: 0x0000009595F2D2C0
2018.09.16 11:11:23.249 2017.01.01 00:00:00   
2018.09.16 11:11:23.250 OnInit critical error

На реальных данных всё работает.

Juer
Juer | 16 сент. 2018 в 11:06
#property tester_library "wininet.dll"
#property tester_library "Kernel32.dll"
Вроде помогло
Juer
Juer | 16 сент. 2018 в 11:12
Juer:
Вроде помогло

Нет, не помогло.

Juer
Juer | 16 сент. 2018 в 11:21
#property tester_library "wininet.dll"
#property tester_library "Kernel32.dll"
Дурдом... после компиляции тестирование работает. При отладке в режиме тестирования не работает. А потом и просто при тестировании не работает.
Andrey Khatimlianskii
Andrey Khatimlianskii | 16 сент. 2018 в 20:16
Juer:
Дурдом... после компиляции тестирование работает. При отладке в режиме тестирования не работает. А потом и просто при тестировании не работает.

После запуска в дебаг-режиме ex-файл остается от этого режима. Видимо, будет работать только релизная версия.

MQL5 Wizard для "чайников" MQL5 Wizard для "чайников"
В начале 2011 года мы выпустили первую версию Визарда MQL5. Этот шаг обеспечил трейдеров простым и понятным инструментом для автоматического создания торговых роботов. Любой пользователь MetaTrader 5 получил возможность написать собственный эксперт, не умея программировать на MQL5.
3 метода ускорения индикаторов на примере линейной регрессии 3 метода ускорения индикаторов на примере линейной регрессии
Рассматриваются методы оптимизации вычислительных алгоритмов индикаторов. Каждый читатель найдет себе метод по душе: описан один простой метод, один требующий серьезных познаний в математике, и еще один, для которого нужна смекалка. Реализация большинства представленных методов задействует конструкционные особенности устройства индикаторов или терминала MetaTrader 5. При этом сами методы довольно универсальны - применимы не только для ускорения расчета линейной регрессии, но и для многих других индикаторов.
К вопросу о методах технического анализа и прогнозирования рынков К вопросу о методах технического анализа и прогнозирования рынков
Статья показывает возможности и потенциал хорошо известного математического метода в альянсе с образным мышлением и не совсем обычным взглядом на рынок. Материал призван, с одной стороны, привлечь внимание широкого круга читателей, поскольку способен привести творческих людей к переосмыслению самой парадигмы трейдинга. А с другой стороны - послужить импульсом к альтернативным разработкам и реализациям программного кода для инструментального арсенала анализа и прогнозов.
Плеер торговли на основе истории сделок Плеер торговли на основе истории сделок
Плеер торговли. Всего два слова и пояснения не нужны. В голове всплывают мысли об удобном ящичке с кнопками. Нажал одну кнопку - играет, передвинул рычажок - изменилась скорость воспроизведения. В реальности всё почти так и есть. В данной статье я хочу представить разработку, которая проигрывает торговую историю почти как в реал-тайме. В статье так же будут затронуты вопросы, проясняющие некоторые нюансы ООП, работу с индикаторами, управления чартами.