Чтение новостей в формате RSS средствами MQL4
Вступление
В данной статье рассматриватся пример чтения RSS разметки средствами MQL4, используя функции из статьи "Разбор HTML средствами MQL4". Предполагается, что читатель читал статью или хотя бы имеет общее понимание изложенных в ней идей.
Что такое RSS и зачем он нам в MQL4?
RSS - это XML-формат, предназначенный для передачи различного рода информации от одного источника к другому.
Очень широкое распостранение RSS получил в интернете на сайтах новостных агентств, компаний, да и просто на различных информационных сайтах.
RSS может быть собран (или прочитан) различными специальными программами (читалками) и доставлен пользователю в удобном для него виде. В этой статье мы попытаемся сделать заготовку, на базе которой можно будет сделать, например, новостной индикатор или просто RSS-читалку, только на языке MQL4. Какая информация нас интересует в RSS? Это, конечно же, новости.
Как уже было сказано выше, RSS - это по сути XML-документ. Что же такое XML?
Xml (eXtensible Markup Language - расширяемый язык разметки) - текстовый формат, предназначенный для хранения структурированных данных. Визуально структура может быть представлена в виде дерева элементов. Элементы XML описываются тегами.
Пример простого XML-документа:
<!--?xml version="1.0" encoding="windows-1252"?--> <weeklyevents> <event> <title>Rightmove HPI m/m</title> <country>GBP</country> <date><!--[CDATA[05-15-2011]]--></date> <time><!--[CDATA[23:01]]--></time> <impact><!--[CDATA[Medium]]--></impact> <forecast> <previous><!--[CDATA[1.7%]]--></previous> </forecast></event> </weeklyevents>
Реализация
Как мы видим из примера выше, XML чем-то напоминает HTML. Поэтому, чтобы не "изобретать велосипед", мы воспользуемся кодом из статьи "Разбор HTML средствами MQL4".
Первое что нам необходимо, это подключить функции разбора HTML к нашему проекту (индикатору). Для этого скачаем файл ReportHTMLtoCSV-2.mq4 и положим его в папочку experts/include. Поскольку файл мы будем использовать как функциональную библиотеку, в нем нужно закомментировать функцию start().
Также предлагаю переименовать файл (например в HTMLTagsLib.mq4) просто для наглядности.
Файл готов, подключаем его к индикатору (файл заготовки для индикатора можно будет скачать в приложении к статье):
#include <htmltagslib.mq4>
Теперь нам нужно подключить стандартную библиотеку Windows "wininet.dll" для работы со ссылками:
#include <winuser32.mqh> #import "wininet.dll" int InternetAttemptConnect(int x); int InternetOpenA(string sAgent, int lAccessType, string sProxyName = "", string sProxyBypass = "", int lFlags = 0); int InternetOpenUrlA(int hInternetSession, string sUrl, string sHeaders = "", int lHeadersLength = 0, int lFlags = 0, int lContext = 0); int InternetReadFile(int hFile, int& sBuffer[], int lNumBytesToRead, int& lNumberOfBytesRead[]); int InternetCloseHandle(int hInet); #import
Для чтения URL будем использовать функцию ReadWebResource(string url). Работа этой функции не является темой для данной статьи, поэтому мы не будем на ней останавливаться.
Нас интересуют только входные и выходные аргументы. Функции передается ссылка, которую нужно прочитать, возвращает функция содержимое ресурса в виде строки.
Для анализа тегов мы будем использовать две функции из файла HTMLTagsLib.mq4: FillTagStructure() и GetContent(). Работа этих функций подробно описана в статье "Разбор HTML средствами MQL4". Следует отметить, что входные данные для анализа передаются в виде массива, поэтому после получения данных их нужно преобразовать в массив при помощи функции ReadWebResource(string url).
В этом нам поможет функция ArrayFromString():
//+------------------------------------------------------------------+ int ArrayFromString(string & webResData[], string inputStr, string divider) { if (inputStr == "") { Print ("Не задана входная строка"); return(0); } if (divider == "") { Print ("Не задан разделитель"); return(0); } int i, stringCounter = 0; string tmpChar, tmpString, tmpArr[64000]; int inputStringLen = StringLen(inputStr); for (i = 0; i < inputStringLen; i++ ) { tmpChar = StringSubstr(inputStr, i, 1); tmpString = tmpString + tmpChar; tmpArr[stringCounter] = tmpString; if (tmpChar == divider) { stringCounter++; tmpString = ""; } } if (stringCounter > 0) { ArrayResize(webResData, stringCounter); for (i = 0; i < stringCounter; i++) webResData[i] = tmpArr[i]; } return (stringCounter); }
На вход функции передаются три аргумента. Первый - это ссылка на массив, в котором будет храниться результат работы функции, второй - строка, которую нужно преобразовать в массив, и третий - разделитель, по которому будет происходить разделение строки. Функция возвращает количество рядов в результирующем массиве.
Теперь наши данные подготовлены для анализа.
В следующем фрагменте мы анализируем данные и выводим значения тегов title и country в консоль терминала:
string webRss = ReadWebResource(rssUrl); int i, stringsCount = ArrayFromString(webResData, webRss, ">"); string tags[]; // массив для хранения тегов int startPos[][2];// координаты начала тега int endPos[][2]; // координатры конца тега FillTagStructure(tags, startPos, endPos, webResData); int tagsNumber = ArraySize(tags); string text = ""; string currTag; int start[1][2]; int end[1][2]; for (i = 0; i < tagsNumber; i++) { currTag = tags[i]; if (currTag == "<weeklyevents>") { Print("Начало блока новостей;"); } if (currTag == "<event>") { text = ""; start[0][0] = -1; start[0][1] = -1; } if (currTag == "<title>") {// координаты начальной позиции для выборки содержимого между тегами start[0][0] = endPos[i][0]; start[0][1] = endPos[i][1]; } if (currTag == "</title>") {// координаты конечной позиции для выборки содержимого между тегами end[0][0] = startPos[i][0]; end[0][1] = startPos[i][1]; text = text + GetContent(webResData, start, end) + ";"; } if (currTag == "<country>") {// координаты начальной позиции для выборки содержимого между тегами start[0][0] = endPos[i][0]; start[0][1] = endPos[i][1]; } if (currTag == "</country>") {// координаты конечной позиции для выборки содержимого между тегами end[0][0] = startPos[i][0]; end[0][1] = startPos[i][1]; text = text + GetContent(webResData, start, end) + " ;"; } if (currTag == "</event>") { Print(text); } if (currTag == "</weeklyevents>") { Print("конец новостей;"); } }
С помощью функции FillTagStructure() мы получаем количество и структуру тегов, а с помощью функции GetContent() - их значение.
Результат работы скрипта:
Рис 1. Результат работы скрипта NewsRss
В результатах работы мы видим название новости и символ валюты страны, к которой данная новость относится.
Выводы
В статье рассмотрен способ чтения RSS средствами MQL4 с использованием функций анализа HTML-тегов. О недостатках данного способа достаточно сказано в статье "Разбор HTML средствами MQL4". От себя хочу добавить, что к недостаткам реализации можно отнести некоторое "неудобство" использования функций в коде, в отличии от других стандартных библиотек для чтения XML.
После написания данной статьи и скрипта я задумался о подключении внешней библиотеки для работы с XML. К плюсам я бы отнес быстроту реализации.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
И могла бы быть довольно полезной, если бы не проблема устаревших страниц.
Старые RSS новости нам, извините, не нужны...
запустил пример - выдает "Ошибка при вызове InternetOpenUrlA()"
url взят из примера: http://www.forexfactory.com/ffcal_week_this.xml
в настройках "Разрешить WebRequest" установлен "http://forexfactory.com" и с ним исправно работает другой советник
разрешить импорт DLL - установлен
в чем глюк?
заранее спасибо
запустил пример - выдает "Ошибка при вызове InternetOpenUrlA()"
url взят из примера: http://www.forexfactory.com/ffcal_week_this.xml
в настройках "Разрешить WebRequest" установлен "http://forexfactory.com" и с ним исправно работает другой советник
разрешить импорт DLL - установлен
в чем глюк?
заранее спасибо
запустил пример - выдает "Ошибка при вызове InternetOpenUrlA()"
url взят из примера: http://www.forexfactory.com/ffcal_week_this.xml
в настройках "Разрешить WebRequest" установлен "http://forexfactory.com" и с ним исправно работает другой советник
разрешить импорт DLL - установлен
в чем глюк?
Статья очень старая, после чего язык сильно менялся и теперь все строки юникодные. Поэтому нужно использовать InternetOpenUrlW вместо InternetOpenUrlA.
Но еще лучше использовать штатный WebRequest и никаких DLL не надо будет.
У меня аналогично. Решили проблему ?
Статья очень старая, после чего язык сильно менялся и теперь все строки юникодные. Поэтому нужно использовать InternetOpenUrlW вместо InternetOpenUrlA.
Но еще лучше использовать штатный WebRequest и никаких DLL не надо будет.