MQL4: Как читать CSV из URL
Я использую это URL
получить некоторый контент с сайта Quandl:
https://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv?exclude_column_names=true&rows=1&api_key=my_api_key
Сервер Quandl возвращает в ответ на вышеуказанный запрос значение этого:
2016-08-01, 144598.0
Мне нужно использоватьзначение144598.0
в пределахMQL4
Script
, так:
Q1.Как я могу получить содержимое с URL-адреса выше для использования вMQL4
Сценарий?
Очень полезный пользователь из SO (https://stackoverflow.com/users/3666197/user3666197
) при условии следующегоscript
(оригинал найден на MQL4: чтение одного значения из CSV) (несколько частей, добавленных мной лично), чтобы помочь мне достичь этого, однако я не смог заставить его работать:
// Code created with the help of Stack Overflow question
// https://stackru.com/questions/39279634/mql4-read-single-value-from-csv/39284875#39284875
// Question by p.luck:
// https://stackoverflow.com/users/5551849/p-luck
// Answer by user3666197:
// https://stackoverflow.com/users/3666197/user3666197
void OnStart()
{
string cookie = NULL,
headers;
char post[],
result[];
int res;
/* TODO: *
* Must allow MT4 to access the server URL, *
* you should add URL "https://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv" *
* in the list of allowed URLs *
* ( MT4 -> Tools -> Options -> [Tab]: "Expert Advisors" ): */
string aDataSOURCE_URL = "https://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv";
string aDataSOURCE_API = "?exclude_column_names=true&rows=1&api_key=my_api_key";
//-- Create the body of the POST request for API specifications and API-authorization
ArrayResize( post,
StringToCharArray( aDataSOURCE_API, // string text |--> [in] String to copy.
post, // uchar &array[] <--| [out] Array of uchar type.
0, // int start = 0 |--> [in] Position from which copying starts. Default - 0.
WHOLE_ARRAY, // int count = -1 |--> [in] Number of array elements to copy. Defines length of a resulting string. Default value is -1, which means copying up to the array end, or till terminating '\0'. Terminating zero will also be copied to the recipient array, in this case the size of a dynamic array can be increased if necessary to the size of the string. If the size of the dynamic array exceeds the length of the string, the size of the array will not be reduced.
CP_UTF8 // uint cp = CP_ACP |--> [in] The value of the code page. For the most-used code pages provide appropriate constants.
)
- 1
);
//-- Reset the last error code
ResetLastError();
//-- Loading a html page from Quandl
int timeout = 5000; //-- Timeout below 1000 (1 sec.) is not enough for slow Internet connection
res = WebRequest( "POST", // const string method |--> [in] HTTP method.
aDataSOURCE_URL, // const string URL |--> [in] URL.
cookie, // const string cookie |--> [in] Cookie value.
NULL, // const string referrer |--> [in] Value of the Referer header of the HTTP request.
timeout, // int timeout |--> [in] Timeout in milliseconds.
post, // const char &data |--> [in] Data array of the HTTP message body
ArraySize( post ), // int data_size |--> [in] Size of the data[] array.
result, // char &result <--| [out] An array containing server response data.
headers // string &result_headers <--| [out] Server response headers.
);
//-- Check errors
if ( res == -1 )
{ Print( "WebRequest Error. Error code = ", GetLastError() ); //-- Perhaps the URL is not listed, display a message about the necessity to add the address
MessageBox( "Add the address '" + aDataSOURCE_URL + "' in the list of allowed URLs on tab 'Expert Advisors'", "Error", MB_ICONINFORMATION );
}
else //-- Load was successfull
{
PrintFormat( "The data has been successfully loaded, size = %d bytes.", ArraySize( result ) );
//-- parse the content ---------------------------------------
/*
"2016-08-01, 144598.0"
*/
//-- consume the content -------------------------------------
//...
}
}
Я добавилURL
изhttps://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv
к спискуallowed URLs
вMT4
,
Если я включуAutoTrading
и перетащитеscript
по имени (tutorial7
), на chart
изUSDCAD,M1
,
Я получаю эти сообщения в Experts
tab
:
Script tutorial7 USDCAD,M1: loaded successfuly
tutorial7 USDCAD,M1: initialized
tutorial7 USDCAD,M1: The data has been successfully loaded, size = 0 bytes
tutorial7 USDCAD,M1: uninit reason 0
Конечно, если "The data has successfully loaded
"это не должно сказать"size = 0 bytes
"?
Если этоscript
работать правильно, если я просто скопировать и вставить его прямо вMetaQuotes Language Editor
а также compile
Это?
Помимо добавленияURL
кallowed URLs
в MT4
и копировать и вставлять этот код в script
Что еще я должен сделать?
Если так, то как?
Я использую приведенный выше код какScript
не Expert Advisor
; это нормально?
Q2.Могу ли я установить выбранное значение 144598.0 в качестве переменной в моем скрипте?
Мне нужно сделать value
из 144598.0
переменная, чтобы ее можно было сравнить с другой value
,
Будет ли что-то вроде этой работы:
void OnStart()
{
... // above code which fetches the value from the .csv URL
double x = 155876.0 // value manually typed in
y = 144598.0 // value fetched from the .csv URL using the above code
// ignores column 1 consisting of 2016-08-01
if ( x > y ) {
// execute code
}
else {
// execute other code
}
}
1 ответ
A2:
ДА! Это самая легкая часть путешествия.
A1:
НО!
Как это работает на практике?
Как терминал MetaTrader на самом деле разговаривает с Quandl, чтобы его получить?
Позвольте мне сначала проиллюстрировать проблему удаленного, HttpServer
обработка.
Есть простая в прототипе программа curl
(Доступны версии для Linux и DOS), которые будут отображаться прямо в окне терминала (или Windows cmd
окно) как пульт HttpServer
У Quandl реагирует на различные композиции локально собранных запросов, передаваемых по HTTP-протоколу.
Обратите внимание, что только что перепечатанный URL-адрес создает всю историю доставки.
C:\>curl https://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv
DATE,VALUE
2016-08-01,144598.0
2016-07-01,144447.0
...
..
.
1939-03-01,30280.0
1939-02-01,30101.0
1939-01-01,29923.0
Как только мы добавим дополнительные параметры на равнине URL
, удаленная сторона (HttpServer
) меняет ответ только на одну интересующую нас строку:
C:\>curl -G --data rows=1 --data exclude_column_names=true https://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv
2016-08-01,144598.0
Круто, отлично смотрится, практически единственное значение, которое мы хотим!
Но здесь приходит волшебство.
Реальный обмен (диалог) между локальным процессом (curl
сейчас, но MetaTrader Terminal позже) выглядит так (используя --verbose
вариант в curl
командная строка):
C:\>curl --verbose -G --data rows=1 --data exclude_column_names=true https://www.quandl.com/api/v3/datasets/FRED/PAYEMS.csv
* Trying 54.174.87.84...
* Connected to www.quandl.com (54.174.87.84) port 443 (#0)
* schannel: SSL/TLS connection with www.quandl.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 70 bytes...
* schannel: sent initial handshake data: sent 70 bytes
* schannel: SSL/TLS connection with www.quandl.com port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with www.quandl.com port 443 (step 2/3)
* schannel: encrypted data buffer: offset 4096 length 4096
* schannel: encrypted data length: 4017
* schannel: encrypted data buffer: offset 4017 length 4096
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with www.quandl.com port 443 (step 2/3)
* schannel: encrypted data buffer: offset 4569 length 5041
* schannel: sending next handshake data: sending 318 bytes...
* schannel: SSL/TLS connection with www.quandl.com port 443 (step 2/3)
* schannel: encrypted data buffer: offset 51 length 5041
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with www.quandl.com port 443 (step 3/3)
* schannel: incremented credential handle refcount = 1
* schannel: stored credential handle in session cache
> GET /api/v3/datasets/FRED/PAYEMS.csv?rows=1&exclude_column_names=true HTTP/1.1
> Host: www.quandl.com
> User-Agent: curl/7.45.0
> Accept: */*
>
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 653
* schannel: encrypted data buffer: offset 653 length 17408
* schannel: decrypted data length: 623
* schannel: decrypted data added: 623
* schannel: decrypted data cached: offset 623 length 16384
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: decrypted data buffer: offset 623 length 16384
* schannel: schannel_recv cleanup
* schannel: decrypted data returned 623
* schannel: decrypted data buffer: offset 0 length 16384
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Disposition: attachment; filename=FRED-PAYEMS.csv
< Content-Transfer-Encoding: binary
< Content-Type: text/csv
< Date: Wed, 07 Sep 2016 12:47:20 GMT
< ETag: W/"adfdb97850c493cdd03e2036574bc404"
< Server: openresty
< Vary: Origin
< X-API-Version: 2015-04-09
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-Rack-CORS: preflight-hit; no-origin
< X-RateLimit-Limit: 50
< X-RateLimit-Remaining: 42
< X-Request-Id: c609e92d-22d2-40e7-b7d4-cacb07467c76
< X-Runtime: 0.023534
< X-XSS-Protection: 1; mode=block
< Content-Length: 20
< Connection: keep-alive
<
2016-08-01,144598.0
* Connection #0 to host www.quandl.com left intact
Обратите внимание на строку GET /api/v3/datasets/FRED/PAYEMS.csv?rows=1&exclude_column_names=true
Таким образом, магия заключается в том, чтобы заставить MetaTrader Terminal собирать то же самое вместе с разрешением URL-адреса в списке разрешенных в конфигурации (что вы уже сделали в другом посте).
Также, возможно, заметил, что HTTP GET
отправляет только <HttpServer_relative_part_of_the.URL>
Магия в создании MQL4
Код отправить тот же запрос, как было показано выше, и получить данные обратно.
WebRequest()
должен использовать HTTP GET
как квандл HttpServer
не отвечает на HTTP POST
версия того же примера запроса, возвращающая 0 байт (просто опустите -G
переключиться с curl
примеры выше).
Выполнение всех условий одновременно должно привести к получению 2016-08-01,144598.0
и используя:
int anAmountOfBytesRECVd = 0; // how many bytes Quandl sent
string headers_FromHttpSERVER; // stores as a string
char anAnswerFromHttpSERVER[]; // stores as a byte-array ( char[] )
double y_value = NULL;
anAmountOfBytesRECVd = WebRequest( "GET", // MUST use HTTP GET <- Quandl tested
...
anAnswerFromHttpSERVER,
headers_FromHttpSERVER
);
y_value = StrToDouble( CharArrayToString( anAnserFromHttpSERVER, // [2|0|1|6|-|0|8|-|0|1|,|1|4|4|5|98|.|0]
11, //-----------------------^_______________( -1 == TILL EndOfSTRING )
-1
)
);