Communicating with an api/custom server using a HTTP request inside of .mq5 indicator code

 

Hello I have a .mq5 indicator and I have a custom flask python server running on local host (0.0.0.0:80) 

I'm trying to setup a system where the indicator (inside of OnInit()) would send a HTTP POST request to the server with some information and then the server would return a message back based on the information that was sent. 

I've been going down some rabbit holes. I found webrequest but this is not supported within indicator code, only EA/scripts from my understanding. 

I found XML-rpc and using winlet.dll but both of these code articles are 10-11 years old. I made attempts at using both of them (connecting to a localhost python server on port 80) but was unable to be successful after spending several hours with both libraries. I had hard time debugging them since I wasn't sure if the code was just out of date or if I was missing something in the code. For the XML-RPC I couldn't even get a simple connection to my python server using the following code 

void OnInit(){
   CXMLRPCServerProxy s("0.0.0.0:80");
   if(s.isConnected()==true) {
        Print("Hello");
        }
}

What I'm now considering is writing my own .dll to send the POST request. I'm just sending a few string arguments in the POST request, it's nothing super complex like downloading files. I was considering using something like curl or https://github.com/elnormous/HTTPRequest, compiling the DLL, and then importing into .mq5. 

I'm more so making this post to hopefully gain some helpful insight or ideas from the community. Is there something really easy that I'm missing and there is an easier way to do what I trying to accomplish? Is what I'm trying to do even possible? I really appreciate anyone taking the time to read through this and give me insight/ideas. Thanks!  

MQL5-RPC. Remote Procedure Calls from MQL5: Web Service Access and XML-RPC ATC Analyzer for Fun and Profit
MQL5-RPC. Remote Procedure Calls from MQL5: Web Service Access and XML-RPC ATC Analyzer for Fun and Profit
  • www.mql5.com
This article describes MQL5-RPC framework that enables Remote Procedure Calls from MQL5. It starts with XML-RPC basics, MQL5 implementation and follows with two real usage examples. First example is using external web service and the second one is a client to simple XML-RPC ATC 2011 Analyzer service. If you are interested on how to implement and analyze different statistics from ATC 2011 in real time, this article is just for you.
 
You can use MT5 Services to run background tasks and communicate with it from indicators using global variables.

 
thatguy1429:

Hello I have a .mq5 indicator and I have a custom flask python server running on local host (0.0.0.0:80) 

I'm trying to setup a system where the indicator (inside of OnInit()) would send a HTTP POST request to the server with some information and then the server would return a message back based on the information that was sent. 

I've been going down some rabbit holes. I found webrequest but this is not supported within indicator code, only EA/scripts from my understanding. 

I found XML-rpc and using winlet.dll but both of these code articles are 10-11 years old. I made attempts at using both of them (connecting to a localhost python server on port 80) but was unable to be successful after spending several hours with both libraries. I had hard time debugging them since I wasn't sure if the code was just out of date or if I was missing something in the code. For the XML-RPC I couldn't even get a simple connection to my python server using the following code 

What I'm now considering is writing my own .dll to send the POST request. I'm just sending a few string arguments in the POST request, it's nothing super complex like downloading files. I was considering using something like curl or https://github.com/elnormous/HTTPRequest, compiling the DLL, and then importing into .mq5. 

I'm more so making this post to hopefully gain some helpful insight or ideas from the community. Is there something really easy that I'm missing and there is an easier way to do what I trying to accomplish? Is what I'm trying to do even possible? I really appreciate anyone taking the time to read through this and give me insight/ideas. Thanks!  


Did you try WinInet.dll ?


https://www.mql5.com/en/articles/73

Using WinInet.dll for Data Exchange between Terminals via the Internet
Using WinInet.dll for Data Exchange between Terminals via the Internet
  • www.mql5.com
This article describes the principles of working with the Internet via the use of HTTP requests, and data exchange between terminals, using an intermediate server. An MqlNet library class is presented for working with Internet resources in the MQL5 environment. Monitoring prices from different brokers, exchanging messages with other traders without exiting the terminal, searching for information on the Internet – these are just some examples, reviewed in this article.
 
Amine Abed #:


Did you try WinInet.dll ?


https://www.mql5.com/en/articles/73

Yeah the third link I have in my post https://www.mql5.com/en/articles/276 is using winlet. I tried doing this but was unable to get a request to send successfully. I couldn't get the request to go through and show up on the server side. Had a hard time debugging the library and figuring out what was wrong. I thought it could be an issue with hosting the server on localhost and was toying with the idea of hosting it online using something like NGROK. Indicator code: 

void OnInit(){
   // open session
        if (!INet.Open("0.0.0.0", 80, "", "", INTERNET_SERVICE_HTTP)){
           Alert("Can't connect to server.");
           return;
        }
        
        string Head="Content-Type: application/x-www-form-urlencoded"; // header
        string Path="/index"; // path to the page
        string Data ="hello=test";                                              
   	string resp="";
        tagRequest req; // initialization of parameters 
        req.Init("POST", Path, Head, Data, false, resp, false);

        bool test = INet.Request(req); // send the request to the server
        Print(test);
        Print(req.stOut);

Python flask server code: 

import os 
from flask import Flask, request, Response

app = Flask(__name__)


@app.route('/index', methods=['POST'])
def respond():

    return Response(status=200)

app.run(host="0.0.0.0", port=80)

So I was toying with the idea of just using winlet or using something like curl in a C++ .dll and then importing the .dll into .mq5 code 

Using WinInet in MQL5. Part 2: POST Requests and Files
Using WinInet in MQL5. Part 2: POST Requests and Files
  • www.mql5.com
In this article, we continue studying the principles of working with Internet using HTTP requests and exchange of information with server. It describes new functions of the CMqlNet class, methods of sending information from forms and sending of files using POST requests as well as authorization on websites under your login using Cookies.
 
Soewono Effendi #:
You can use MT5 Services to run background tasks and communicate with it from indicators using global variables.

Dumb question but can you elaborate at a high level how you would do this? 

I think I understand the concept of global variables but having hard time understanding how you would send http requests with these global variables

 
thatguy1429 #:

Dumb question but can you elaborate at a high level how you would do this? 

I think I understand the concept of global variables but having hard time understanding how you would send http requests with these global variables

There is a reason why WebRequest is not supported on Indicators. It is because all the Indicators run together on the same thread and if you use networking calls (which block), you will lock-up all indicators and the chart itself too.

So, don't use networking functionality in your indicator. Instead, create a separate MQL5 program and run it as a MQL5 service (see below), which runs on a separate dedicated thread.

You can then have that service use WebRequest to gather the data, and then send custom chart events to the Indicator with EventChartCustom() to communicate with it.

Program Running

Each script, each service and each Expert Advisor runs in its own separate thread. All indicators calculated on one symbol, even if they are attached to different charts, work in the same thread. Thus, all indicators on one symbol share the resources of one thread.

All other actions associated with a symbol, like processing of ticks and history synchronization, are also consistently performed in the same thread with indicators. This means that if an infinite action is performed in an indicator, all other events associated with its symbol will never be performed.

When running an Expert Advisor, make sure that it has an actual trading environment and can access the history of the required symbol and period, and synchronize data between the terminal and the server. For all these procedures, the terminal provides a start delay of no more than 5 seconds, after which the Expert Advisor will be started with available data. Therefore, in case there is no connection to the server, this may lead to a delay in the start of an Expert Advisor.

The below table contains a brief summary of MQL5 programs:

Program

Running

Note

Service

A separate thread, the number of threads for services is equal to the number of services

A looped service cannot break running of other programs

Script

A separate thread, the number of threads for scripts is equal to the number of scripts

A looped script cannot break running of other programs

Expert Advisor

A separate thread, the number of threads for Expert Advisors is equal to the number of Expert Advisors

A looped Expert Advisor cannot break running of other programs

Indicator

One thread for all indicators on a symbol. The number of threads is equal to the number of symbols with indicators

An infinite loop in one indicator will stop all other indicators on this symbol

 
Fernando Carreiro #:

There is a reason why WebRequest is not supported on Indicators. It is because all the Indicators run together on the same thread and if you use networking calls (which block), you will lock-up all indicators and the chart itself too.

So, don't use networking functionality in your indicator. Instead, create a separate MQL5 program and run it as a MQL5 service (see below), which runs on a separate dedicated thread.

You can then have that service use WebRequest to gather the data, and then send custom chart events to the Indicator with EventChartCustom() to communicate with it.

I appreciate the help and this makes sense to me. I'm trying to create a remote licensing server since my indicator is a subscription based business model. I'm worried that having a MQL service communicate with the indicator using global variables or EvenChartCustom() function calls that the user will be able to access some of these parameters that I don't want them to be able to see. I'm trying to figure out what the best solution is to having the license of the indicator remotely managed via a server based on a monthly subscription business model 
 
Fernando Carreiro #:

There is a reason why WebRequest is not supported on Indicators. It is because all the Indicators run together on the same thread and if you use networking calls (which block), you will lock-up all indicators and the chart itself too.

So, don't use networking functionality in your indicator. Instead, create a separate MQL5 program and run it as a MQL5 service (see below), which runs on a separate dedicated thread.

You can then have that service use WebRequest to gather the data, and then send custom chart events to the Indicator with EventChartCustom() to communicate with it.

Many thank  Fernando Carreiro,

Because of " Services are unloaded immediately after completing their work " , is there any way to trigger service from Indicator? 

 
Minh Truong Pham #: Many thank  Fernando Carreiro, Because of " Services are unloaded immediately after completing their work " , is there any way to trigger service from Indicator? 

You are misinterpreting that phrase. A Service will usually not return immediately and instead have a loop to keep it running indefinitely until some condition signals it to end its execution.

 
Fernando Carreiro #:

You are misinterpreting that phrase. A Service will usually not return immediately and instead have a loop to keep it running indefinitely until some condition signals it to end its execution.

1. Sorry if i wrong but when i try thi simply code:

//+------------------------------------------------------------------+
//| Service program start function                                   |
//+------------------------------------------------------------------+
void OnStart()
{
//---
   Print("service execute!");
}
//+------------------------------------------------------------------+

when i run this service. console show that just run one and stop (icon from test2 service change to stop - red).

So i think service just run once when enable this.

In my case, indicator have to send message to service and service have to forward message to other api. I think about two way solve this case are:

1- indicator execute service directly to send message.

2- indicator write to file and every time file created or change, service "know" and do their job.

My question is: is how to execute service from indicator or ea?

Thanks for your time!

 
Minh Truong Pham #: 1. Sorry if i wrong but when i try thi simply code: when i run this service. console show that just run one and stop (icon from test2 service change to stop - red). So i think service just run once when enable this. In my case, indicator have to send message to service and service have to forward message to other api. I think about two way solve this case are: 1- indicator execute service directly to send message. 2- indicator write to file and every time file created or change, service "know" and do their job. My question is: is how to execute service from indicator or ea? Thanks for your time!

Yes, but did I not say "... instead have a loop to keep it running indefinitely until some condition signals it to end its execution "?

When you code a service, you have to use a "loop" to keep it running. In essence a service and a script behave basically the same, but to keep a service alive and running you have to use a loop.

// Script/Service main function.
   void OnStart() {
      while( !IsStopped() ) {
         // Do Something
      };
   };

Unfortunately, I don't know of any example of a service in the CodeBase in order to provide you with an example.

As for "how to execute service from indicator or ea", you can't as far as I know, unless you use DLL calls to the Windows API.