Русский 中文 Español Deutsch 日本語 Português
preview
Using JSON Data API in your MQL projects

Using JSON Data API in your MQL projects

MetaTrader 5Trading systems | 11 July 2024, 15:40
6 877 21
Sara Sabaghi
Sara Sabaghi

Introduction and Background

Mixing external data could improve decision-making in algorithm trading. APIs enable data transfer between different systems and help traders access different data sources like real-time market data from other brokers and banks, access economic indicators not just economic calendars, access news feeds or social sentiment analysis, online artificial intelligence tools, online forecast system or anything you can imagine that are available in API services. In this article, we will show you how to use this tool in the best way.

Using API data in Expert Advisors (EA) can give you new and more insight into the trading market that helps you make informed decisions, create more dynamic trading strategies, and manage risks better. Using API data, traders can improve the accuracy of trading signals using advanced technical indicators and sophisticated charting tools. This integration extends the capabilities of platforms like MetaTrader and provides access to valuable market intelligence such as natural language processing (NLP) for market sentiment analysis and access to fundamental data and news.


Introduction to Ziwox API

Ziwox is a data analysis system in Forex that contain a free API services. This API provides traders with comprehensive market data including prices, technical indicators, sentiment analysis, and fundamental data. It supports major and minor forex pairs and provides important metrics such as fundamental currency bias, AI-based forecasts, retail trader statistics, COT reports, technical support and resistance, market sentiment (risk-on and risk-off), bond yields, and VIX index. This rich data set enables multi-faceted market analysis, combining technical, fundamental, and Sentiment insights to create game-changing tools.

The interesting part of this data is that beyond price and technical data, we will have access to data generated by artificial intelligence or real analysts. Some of that data included: Fundamental analysis for forex pairs by an analysts team, NLP (Natural Language Processing) system outputs as a forex news sentiment, Price forecast generated by AI.

The API is easy to use, requiring a simple sign-up to generate an API key and access data in JSON or text format. This accessibility, along with its extensive data coverage, makes it an invaluable tool for enhancing trading strategies and developing custom indicators or automated trading systems.

What is API?


Let's get a little more familiar: What is API?

APIs are mechanisms that enable two software components to communicate with each other using a set of definitions and protocols. For example, the weather bureau's software system contains daily weather data. The weather app on your phone “talks” to this system via an API and shows you the daily weather update on your phone.

API stands for Application Programming Interface. An interface can be thought of as a service contract between two applications. This contract defines how the two communicate with each other using requests and responses. Their API documentation contains information about how developers structure these requests and responses.

API architecture is usually described in terms of client and server. The program that sends the request is called the client and the program that sends the response is called the server. So in the weather example, the office's weather database is the server and the mobile app is the client.


API responses formats:

There are various formats for the responses or data exchange of an API. Depending on what purpose the API is made for, what other Applications is connected with, the format can change.

These responses could be in JSON, HTML, TEXT, XML or CSV standards format.

For a brief introduction to this standard model:

1. JSON: JSON is a lightweight, human-readable data interchange format that used in API responses due to its simplicity and flexibility. It represents data as key-value pairs, making it easy to parse and manipulate in various programming languages.

An example of  JSON  response:

{
  "id": 5687,
  "source": "oanda",
  "symbol": "EURUSD",
  "price": "1.08562",
  "high": "1.09211",
  "low": "1.08154"
}


2. XML: XML or "eXtensible Markup Language" is another widely accepted format for representing structured data in API responses. Unlike JSON, XML uses tags to define hierarchical data structures, providing a more precise but structured representation. Its like HTML tags in web design and web structures. While JSON is preferred for its simplicity and readability, XML remains relevant in certain areas such as enterprise systems and legacy integrations.

Example of XML in Forex Factory News API:

<event>
<title>German Trade Balance</title>
<country>EUR</country>
<date>
<![CDATA[ 07-07-2024 ]]>     </date>
<time>
<![CDATA[ 8:30am ]]>
</time>
<impact><![CDATA[ Low ]]></impact>

<forecast><![CDATA[ 19.9B ]]></forecast>
<previous><![CDATA[ 22.1B ]]></previous>
<url>
<![CDATA[ https://www.forexfactory.com/calendar/125-eur-german-trade-balance ]]>
</url>

</event>


3. Other Formats: Addition to JSON and XML, APIs may use other response formats, such as plain text, HTM, protocol buffers, or CSV file, depending on domain-specific requirements and conventions. Each format has its own advantages and uses, from efficiency and performance to human readability and adaptability.

The JSON format has become a popular choice in web development due to its simplicity, readability, and easy to use. Fortunately, the service in question also uses this model for data exchange.



Setting up your environment and developement

To set up an environment in MQL5 for using JSON APIs, you'll need to follow a few steps.

MQL5 is a programming language for creating trading robots, technical indicators, scripts, and function libraries for the MetaTrader 5 trading platform.

Here's a general guide on how to set up an environment to work with JSON APIs in MQL5:

  1. Understand MQL5 Basics: Make sure you have a good understanding of the basics of MQL5 programming language, as well as basic concepts related to trading and financial markets. Familiarize yourself with the MQL4 documentation and MQL5 Reference to understand language syntax and functions.
  2. Choose a JSON Library: MQL5 does not have native support for JSON parsing, so you'll need to use a third-party library. You can find these libraries on forums such as the MQL5 community or GitHub. JSON Serialization and JSON Parser.
  3. Download and Install the JSON Library: Download the chosen JSON library and follow the installation instructions provided by the library. This typically involves placing the library file (mqh or mq5) in the Include folder of your MetaTrader installation.
  4. Include the Library in Your Code: At the beginning of your MQL script or EA (Expert Advisor), include the JSON library using the #include directive:
  5. //Use this type of file include if the file is in MQL include follder
    #include <JAson.mqh>
    
    // Use this type of file include If this file is next to your EA file/follder
    #include "JAson.mqh" 
  6. Make HTTP Requests: To interact with JSON APIs, you'll need to make HTTP requests. Popular choices include WinHTTP or WebRequest. If you need other type of HTTP usage, Download and include an HTTP library that fits your needs.
  7. Save HTTP response to a file: Because most of these APIs are limited in terms of the number of requests, and concerned about the limit of API requests it is better to save the requested data in a file and use our saved file instead of repeated and unnecessary requests.
  8. Parse JSON Responses: Once you receive a response from the API, use the JSON library to parse the JSON data. The specific syntax will depend on the library you're using.
  9. Mixing: After classifying the JSON data, you can now combine the desired data with your program according to the model, strategy, or type.


An instruction for API functions code

MQL5 offers the WebRequest function for HTTP requests, enabling interaction with APIs.

You can read more about Webrequest documentation > Webrequest and HTTP data exchange

Below is an example of MQL code for requesting JSON data from an API address use GET method:

// Required variables
string cookie=NULL, headers="", apikey="your api key",
value1="value 1", value2="value 2";
char post[],result[];
int res;
string URL   =  "https://www.example.com/API?apikey="+apikey+"&data1=value1&data2="+value2; // Rest API address

ResetLastError(); // Reset ast error
// HTTP request via MQL Webrequest, GET method with apikey, value1, and value2 and 2000 millisecond timeout 
res=WebRequest("GET", URL, cookie, NULL, 2000, post, 0, result, headers);
if(res==-1) // WebRequest error handling
 {
    int error =  GetLastError();
    if(error==4060) Print("Webrequest Error ",error);
    else if(error==5203) Print("HTTP request failed!");
    else Print("Unknow HTTP request error("+string(error)+")! ");
    LastHTTPError=error;
 }
else if (res==200) // The HTTP 200 status response code indicates that the request has succeeded
 {
    Print("HTTP request successful!");

    // Use CharArrayToString to convert HTTP result array to a string
    string HTTP_Result = CharArrayToString(result, 0, 0, CP_UTF8); 
    Print(HTTP_Result);      

 }

This code sends a GET request to the specified API URL, demonstrating the simplicity of integrating API calls in MQL4.



Case Study: Successful MQL Expert Advisor with API Data Access

How to Use the Ziwox Forex Data API to Create an Auto Trade System by Using Fundamental and Real-time AI Forecast Data

In this article, we will explore how to use the Ziwox Forex Data API to build fundamental and real-time data-based tools in MetaQuotes Language (MQL). There are a lot of information on their API, But, we chose  AI forecast for our project.

The AI forecast system on Ziwox terminal, According to their information, is based on the aggregation of data such as news, economic calendar data, interest rates and their rate changes, monetary and economic policies of central banks, market sentiment, strength of forex currencies, COT data and the retail trader's data. As a result, the whole market is analyzed so that this prediction can be used as valuable data.

We'll walk through the process of obtaining API data, Saving JSON data  to a file, parsing JSON responses, and using this information to create an automated Expert Advisor (EA).

Our plan is  to make an Expert Advisor, use a simple MA strategy as our technical signal, and trade if the AI forecast is in our direction as an AI filter.

Let's do our best.


Step 1: Signing Up and Generating an API Key

To start using the Ziwox Forex Data API, follow these steps:

1. Sign up on the Ziwox Terminal HERE

Ziwox Sign UP 

2. Fill out the form with your information, read the terms and policies, and accept it, click on “I'm not a robot”, then click on “Create a new account”.

3. A verifying email is sent to your mailbox, verify your email.

3. Login to your account here, navigate to the profile page, API tab here, and generate your API key by clicking on green Generate button

Ziwox API generate

4. By generating an API key, now you get access to Ziwox API data. Copy that generated API code to use it on our project.

Ziwox API Key


Step 2: Understanding the API Structure

The API link structure is as follows:

https://ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&apikey={API_KEY}&apitype={REQUEST_TYPE}&pair={PAIR}

  • {API_KEY}: Your unique API key from last step
  • {REQUEST_TYPE}: The format of the response, either JSON or text.
  • {PAIR}: The desired Forex pair in a standard format, without prefix or suffix, like as EURUSD, USDJPY, GBPUSD, XAUUSD, WTI…


Step 3: Test your API structure

Now we want to check the API link structure and request a sample from Ziwox API. Simply, use the API link in Step 2, edit the parameters with your parameters, open your browser, enter the API link on the address bar and press enter.

If you edit the API link correctly, what we have on the HTTP response is like this:

Ziwox API response


With an incorrect API key, you have an error response like this:

{
"status": "error",
"desc": "invalid api key"
}

or if you enter the asset name incorrectly you may see this response:

{
"status": "error",
"desc": "invalid asset name!!"
}


Step 4: Implement an HTTP  API Request function 

If you succeed in step 3, now we are ready to implement a function to automate this part. Check this code:

datetime LastWebRequest = 0; // use this datetime var for limit failed request API

bool GetAPI(string symbolname, string apikey, string filename)

  {
   Print("Get API Update");
   bool NeedToUpdate =   false;

   // Check if the API data file available
   if(FileGetInteger(filename,FILE_EXISTS,true)>=0)
     {
      // Check the latest update time from file modify date time
      if(TimeLocal()-(datetime)FileGetInteger(filename,FILE_MODIFY_DATE,true)>900) // update data every 15 min becasue of API call rate limitation
         NeedToUpdate  = true;
     }
   else
      NeedToUpdate  =  true;


   if(NeedToUpdate && TimeLocal()-LastWebRequest>300)   // retry failed API request every 5 min to avoid firewall IP block
     {
      string   cookie=NULL,headers;
      char     post[],result[];
      int      res;
      string   URL   =  "https://www.ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&apikey="+apikey+"&apitype=json&pair="+symbolname;
      ResetLastError();
      int timeout=5000;
      res=WebRequest("GET", URL, cookie, NULL, timeout, post, 0, result, headers);
      if(res==-1)
        {
         LastWebRequest    =  TimeLocal();
         int error         =  GetLastError();
         if(error==4060)
            Print("API data Webrequest Error ",error, " Check your webrequest on Metatrader Expert option.");
         else  if(error==5203)
               Print("HTTP request for "+symbolname+" Data failed!");
            else
               Print("Unknow HTTP request error("+string(error)+")! "+symbolname+" Data");
         return(false);
        }
      else
         if(res==200)
           {
            LastWebRequest =  TimeLocal();
            string HTTPString = CharArrayToString(result, 0, 0, CP_UTF8);
            Print("HTTP request for "+symbolname+" Data successful!");
            Print(HTTPString);
	    
            if (StringFind(HTTPString,"invalid api key",0)!=-1) {
               Alert("invalid api key");
               return(false);
            }
            // Store the API data into a common folder file
            int filehandle=FileOpen(filename,FILE_READ|FILE_SHARE_READ|FILE_WRITE|FILE_SHARE_WRITE|FILE_BIN|FILE_COMMON);
            if(filehandle!=INVALID_HANDLE)
              {
               FileWriteArray(filehandle,result,0,ArraySize(result));
               FileClose(filehandle);
              }
           }
     }
   return(true);
  }

This function takes an authentication API key (apikey), assets name (symbolname) and a file name (filename) as inputs from you. It embeds "apikey" and "symbolname" into the url to prepair the API request link.

Then it uses the Webrequest function to makes an HTTP request similar to what you did in the previous step and finaly it gets a response from server and put the related information in a file with "filename" name.

We call the API function like this:

string APIfilename =  symbolname+"_API_Data.json"; // API store file name
string APIKey = "76thfd67a6f867df7"; // Our unic API Key, change it with your API Key
string SymbolRequest = "EURUSD"; // Symbol request, without prefix or suffix
string APIJSON[];
bool APIGET = GetAPI(SymbolRequest, APIKey,  APIfilename);


Step 5: Parsing JSON Data

As you remember in Step 3, the data received from the API contains an array of data. You can see the full explanation of this data in the table below.

JSON Object name Data type Description
Symbol string Return the same asset/symbol name
Last Price number Last price of asset
digits number Digits of asset price
Base string Base name of pair
Quote string Quote name of pair
Base Fundamental Bias string Base currency fundamental bias or fundamental outlook. It could be Bullish or Bearish
Base Fundamental Power string Base fundamental bias power. It could be Weak, Moderate or Strong
Quote Fundamental Bias string Quote currency fundamental bias or fundamental outlook. It could be Bullish or Bearish
Quote Fundamental Power string Quote fundamental bias power. It could be Weak, Moderate or Strong
Fundamental Bias string Asset Fundamental bias, or Long-Term fundamental outlook of assets. Bullish or Bearish
Fundamental Power string Asset Fundamental power. Weak, Moderate or Strong
Fundamental Driver string Same as the asset fundamental bias, it a number, 50=Neutral, Bigger than 50 is Bullish and lower than 50 is Bearish
AI Bullish Forecast Percentage Asset price bull movement Forecast, bigger number more Bullish
AI Bearish Forecast Percentage Asset price bear movement Forecast, bigger number more Bearish
Retail Long Ratio Percentage Retail traders Long percentage
Retail Long Lot number Retail traders Long lot (order volume)
Retail Long Pos number Number of Retail traders Long positions
Retail Short Ratio Percentage Retail traders Short percentage
Retail Short Lot number Retail traders Short lot (order volume)
Retail Short pos number Number of Retail traders Short positions
Base COT NET number COT net position of Base currency
Base COT change number COT net position changes (weekly) of Base currency
Quote COT NET number COT net position of Quote currency
Quote COT change number COT net position changes (weekly) of Quote currency
COT chng Ratio number Large speculators Net position change ratio, positive number = Long sentiment, Negative number = Short sentiment
Risk Sentiment string Market risk sentiment, It would be Risk-ON, Risk-OFF or MIX
D1 Trend string Technical data, Daily Trend, Buy or Sell trend
D1 RSI number Indicator data, Daily RSI indicator value
D1 Stoch number Indicator data, Daily Stochastic indicator value
cci numbers CCI indicator values and
cci signal string CCI indicator signal
supports numbers Asset supports levels
resistance numbers Asset resistance levels
pivot numbers Pivot point/levels of asset
VIX Value number VIX, volatility index value
VIX Direction number VIX sentiment direction, upside = Fear and risky market, downside = greed market
VIX Buy driver number Positive number =  greed  market 
VIX Sell driver number Negative number =  Fear and risky market
Base Bond number Bond yield value of Base currency
Base Bond chg number Base currency Bond yield value change
Quote Bond number Bond yield value of Quote currency
Quote Bond chg number Quote currency Bond yield value change
US10Y number Value of United States 10 years bond yield
US10Y chg number H1 US10Y value change
Yield Driver number Positive number, favor to the base, negative number favor to the Quote   
Allow To Trade boolean Ziwox Suggestion, trade ot better to stop trading
Stop Reason String If no trade is suggested, then you can see the reason here.
riskriversal number Value of Risk Reversal for this asset. Determine the PUT/CALL value
cesi number CESI value
yielddiff number Base currency yield value - Quote currency yield value 
banksposition number Bank institutions position ratio
macrofundamental number Macro economic value, a positive number is a bullish driver, a negative number is a bearish driver for asset
longtermsentiment number Long-term sentiment of asset, based on Economy, Politics...
seasonal Percentage The possibility of asset growth or decline in terms of seasonal data


In this Case Study/example, we like to use Bearish/Bullish AI forecast.  Now, to design this function, we read the data stored in the file (step 4) by the JSON library and extract what we need.

The function would be like this:

#include "JAson.mqh"  // include the JSON librery in our project
CJAVal JsonValue;


void JsonDataParse(string filename, string &_APIJSON[])

  {
   bool     UpdateData =   false;
   for (int arraIn=0; arraIn<ArraySize(APIJSON); arraIn++) APIJSON[arraIn]="";


   if(FileGetInteger(filename,FILE_EXISTS,true)>=0)
     {
      int   FileHandle =FileOpen(filename,FILE_READ|FILE_SHARE_READ|FILE_WRITE|FILE_SHARE_WRITE|FILE_BIN|FILE_COMMON);
      char  jsonarray[];
      FileReadArray(FileHandle,jsonarray);
      FileClose(FileHandle);

      JsonValue.Clear();
      JsonValue.Deserialize(CharArrayToString(jsonarray, 0, 0, CP_UTF8));


      _APIJSON[0]   =   JsonValue[0]["Symbol"].ToStr();
      _APIJSON[1]   =   JsonValue[0]["Fundamental Bias"].ToStr();
      _APIJSON[2]   =   JsonValue[0]["Fundamental Power"].ToStr();
      _APIJSON[3]   =   JsonValue[0]["AI Bullish Forecast"].ToStr();
      _APIJSON[4]   =   JsonValue[0]["AI Bearish Forecast"].ToStr();
      _APIJSON[5]   =   JsonValue[0]["Retail Long Ratio"].ToStr();
      _APIJSON[6]   =   JsonValue[0]["Retail Short Ratio"].ToStr();
      _APIJSON[7]   =   JsonValue[0]["Retail Short Lot"].ToStr();
      _APIJSON[8]   =   JsonValue[0]["Retail Short pos"].ToStr();
      _APIJSON[9]   =   JsonValue[0]["Base COT NET"].ToStr();
      _APIJSON[10]  =   JsonValue[0]["Base COT change"].ToStr();
      _APIJSON[11]  =   JsonValue[0]["Quote COT NET"].ToStr();
      _APIJSON[12]  =   JsonValue[0]["Quote COT change"].ToStr();
      _APIJSON[13]  =   JsonValue[0]["COT chng Ratio"].ToStr();
      _APIJSON[14]  =   JsonValue[0]["Risk Sentiment"].ToStr();
     }
  }

And we call the JSON function like this:

string APIfilename =  symbolname+"_API_Data.json"; // API store file name
string API_DATA[]; // define an array variable to store API details

JsonDataParse( APIfilename,API_DATA);


Step 6: Creating a Simple Moving Average Crossover Strategy

Using the extracted data, stored in “APIJSON” variable, we can now create automated trading strategies and mix our strategy with an AI forecast system. Here’s a basic example of how to use the data in an EA:

You can choose any strategy that you like, But in this article, we try to choose a simple strategy because our goal here is to guide and teach you how to use such a tool in your projects so that you can make it one step better.

A Moving Average Crossover strategy is a popular technique used by traders to identify potential buy and sell signals.

This strategy uses two moving averages. A short-term and a long-term to determine the market trend.

When the short-term MA crosses above the long-term MA, it signals a buy, and when it crosses below, it signals a sell.

Let's do that:

shortMA  = iMA(Symbol(), 0, shortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
longMA   = iMA(Symbol(), 0, longMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);


// Check for crossover signals
if ( int(APIJSON[3])>=60 ) // if bullish forecast is higher than 60%
   if (shortMA > longMA)   // BUY trend 
   { 
      if (OrdersTotal() == 0) {
         ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, 0, 0, "Buy Order", 0, 0, Green);
         if (ticket < 0) Print("Error opening buy order: ", GetLastError());
      }
   }

if ( int(APIJSON[4])>=60 ) // if bearish forecast is higher than 60%
   if (shortMA < longMA)   // Sell trend
   {
      if (OrdersTotal() == 0) 
      {
         ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, 0, 0, "Sell Order", 0, 0, Red);
         if (ticket < 0) Print("Error opening sell order: ", GetLastError());
      }
   }


Step 7: Using JSON Data for Signal Filtering

To improve the MA crossover strategy, we  use the JSON data, and AI forecast ratio from the Ziwox API to filter signals.

For example, if MA cross shows a buy trend, and if the AI forecast is over 50% that signs bullish/upward movement, it's a good idea to enter a buy. On the contrary, if the technical analysis ( MA  ) has a sell signal, we will only sell where the analytical and forecast data are in the same direction as the sell. In this way, the entry risk can be reduced and the win rate can be increased

Based on the arrangement of the JSON data in step 4, the AI Forecast, Bullish percentage is in 3rd/third element of our array and the Bearish Forecast is in the fourth  element.

The code may like this:

void OnTick()
  {
   if (!APIOK) return;
   double   shortMA, longMA;
   long     ticket = -1;

   if(IsNewCandle())
     {
      shortMA  = iMA(Symbol(), 0, shortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
      longMA   = iMA(Symbol(), 0, longMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
      
      // Check for crossover signals
      if ( int(APIJSON[3])>=60 ) // if bullish forecast is higher than 60%
         if (shortMA > longMA)   // BUY trend 
         { 
            if (OrdersTotal() == 0) {
               ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, 0, 0, "Buy Order", 0, 0, Green);
               if (ticket < 0) Print("Error opening buy order: ", GetLastError());
            }
         }
      if ( int(APIJSON[4])>=60 ) // if bearish forecast is higher than 60%
         if (shortMA < longMA)   // Sell trend
         {
            if (OrdersTotal() == 0) 
            {
               ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, 0, 0, "Sell Order", 0, 0, Red);
               if (ticket < 0) Print("Error opening sell order: ", GetLastError());
            }
         } 
     }
  }


Conclusion

Integrating API data with MQL4 empowers traders to create more adaptive and data-driven Expert Advisors. By leveraging real-time information from external sources, traders can enhance their strategies and make more informed trading decisions in dynamic market conditions. You can access data beyond raw market prices. This approach allows you to combine technical and fundamental analysis, increasing the effectiveness of your trading strategies.

Final Code is ready to download below.

I am here, Ready to answer any question, suggestion, or criticism.

Best regards and trade well.

Attached files |
APIExpert.mq4 (18.77 KB)
JAson.mqh (30.59 KB)
Last comments | Go to discussion (21)
Edgar Akhmadeev
Edgar Akhmadeev | 21 Jan 2025 at 13:18
Ney Borges #:
If necessary, you can use the JAson.mqh library, which can be found in the original code of our companion.

What a horrible way for google translator to work.

Without the JAson library, of course, it won't work.

The library is not in his code, it's here, and the author has specified that.

Ney Borges
Ney Borges | 21 Jan 2025 at 19:24
Sara Sabaghi #:

Yes, I completely understand it. Additionally, we are required to use this standard because nearly all financial data providers use this method.

Ney Borges #:
Hello, here it is, so what I asked for is for me to post it in the mql5 community =

Version for MQL5 METATRADER 5 I made changes to the code so that it would work in Metatrader 5. The changes were also made regarding the coding for better conditions in the current commercial situation. All the changes were to adapt the code to Metatrader 5. It is functional. And just download this file and run it. If necessary, the JAson.mqh library, which is found in the original code of our companion. My name is Ney Borges. I am from Brazil, state of Goiás, city of Caldas Novas, in the middle of the forest of Brazil. It was very difficult to learn alone without anyone to help, but here in the community I learned a lot. Thank you.

Version for MQL5 METATRADER 5 I made changes to the code so that it would work in Metatrader 5. The changes were also made regarding the coding for better conditions in the current commercial situation. All the changes were to adapt the code to Metatrader 5. It is functional. And just download this file and run it. If necessary, the JAson.mqh library, which is found in the original code of our companion. My name is Ney Borges. I am from Brazil, state of Goiás, city of Caldas Novas, in the middle of the forest of Brazil. It was very difficult to learn alone without anyone to help, but here in the community I learned a lot. Thank you.

Brasil - Goiás - Caldas Novas - Ney Borges

Fiz algumas correçoes ao codigo para funcionar no MQL5 gostaria que por gentilesa verificasse e retornar, obrigado -  Sara Sabaghi 

//+------------------------------------------------------------------+
//| Ney Borges versão mql5 de ZIWOX API and Technical Strategy.mq5 |
//|                                        Copyright 2024, ssabbaghi |
//|                          https://www.mql5.com/en/users/ssabbaghi |
//+------------------------------------------------------------------+
#property   copyright   "Sara Sabbaghi"
#property   link        "https://www.mql5.com/en/users/ssabbaghi"
#property   version     "1.0"
#property   strict
#property   description "Expert com funções de rede para ZIWOX API"

// Bibliotecas
#include <JAson.mqh>
CJAVal JsonValue;

// Propriedades do Expert para permitir funções de rede
//#property script_show_inputs
//#property script_show_confirm

//---- input parameters
input    string      APIKey         =  "sua Key aqui xxxxxxxx";      // Your unique API key
input    string      SymbolPrefix   =  "";      // Your Broker account symbol Prefix
input    string      SymbolSuffiex  =  "m";      // Your Broker account symbol Suffix
input    int         shortMAPeriod  =  50;      // Slow MA Period
input    int         longMAPeriod   =  200;     // Fast MA Period
input    double      Lots           =  0.01;    // Static Order volume
input    double      BullishThreshold = 60.0;   // Threshold for bullish forecast
input    double      BearishThreshold = 60.0;   // Threshold for bearish forecast
input    int         APICallInterval = 300;     // Interval between API calls in seconds (5 minutes)

string   OBJPREFIX      =  "ZXAPI",
         SymbolRequest  =  "",
         APIJSON[];
bool     APIOK          =  false;
datetime LastAPICallTime = 0; // Armazena o tempo da última chamada à API

//+------------------------------------------------------------------+
//| Função para testar conexão HTTP                                  |
//+------------------------------------------------------------------+
bool TestHTTPConnection()
{
   string cookie=NULL,headers;
   char post[],result[];
   string url="https://www.ziwox.com";
   
   ResetLastError();
   int timeout=5000; 
   
   int res=WebRequest("GET",url,cookie,NULL,timeout,post,0,result,headers);
   
   if(res==-1)
   { 
      int error=GetLastError();
      string msg = "Falha ao conectar, erro "+IntegerToString(error);
      
      // Se for erro de permissão, mostra mensagem específica
      if(error==4014)
         msg = "Adicione "+url+" em Ferramentas -> Opções -> Expert Advisors -> Permitir WebRequest";
         
      Print("DEBUG: ", msg);
      return(false);
   }
   
   Print("DEBUG: Conexão HTTP testada com sucesso");
   return(true);
}

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   Print("=== Iniciando Expert Advisor ===");
   
   // Verifica configurações básicas
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      Print("AVISO: Algorithmic Trading não está permitido");
      // Continua mesmo assim
   }
   
   if(!TerminalInfoInteger(TERMINAL_CONNECTED))
   {
      Print("AVISO: Terminal não está conectado à internet");
      // Continua mesmo assim
   }
   
   // Configura o EA
   EventSetTimer(30);
   ArrayResize(APIJSON, 15);
   SymbolRequest = PureSymbol(Symbol(), SymbolSuffiex, SymbolPrefix);
   
   // Prepara e mostra a URL que será usada
   string cleanSymbol = SymbolRequest;
   StringReplace(cleanSymbol, "m", "");
   string apiUrl = StringFormat("https://www.ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&amp;apikey=%s&apitype=json&pair=%s", 
                              APIKey, cleanSymbol);
   
   Print("URL configurada: ", apiUrl);
   Print("IMPORTANTE: Adicione a URL https://www.ziwox.com em:");
   Print("Ferramentas -> Opções -> Expert Advisors -> Permitir WebRequest");
   
   Comment("Iniciando EA...\n",
           "URL que será usada:\n",
           apiUrl,
           "\n\nIMPORTANTE: Configure a URL nas opções do Expert Advisor");
   
   // Testa conexão HTTP, mas não falha se der erro
   if(!TestHTTPConnection())
   {
      Print("AVISO: Teste de conexão HTTP falhou");
      Print("O EA continuará tentando conectar...");
      // Continua mesmo assim
   }
   
   Print("=== Inicialização concluída ===");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Comment("");
   ObjectsDeleteAll(0);
}

//+------------------------------------------------------------------+
//| Expert tick function    OnTick()                                 |
//+------------------------------------------------------------------+
void OnTick()
{
   if (!APIOK) return;
   
   double shortMA, longMA;
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   if (IsNewCandle())
   {
      shortMA = iMA(Symbol(),PERIOD_CURRENT, shortMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
      longMA = iMA(Symbol(),PERIOD_CURRENT, longMAPeriod, 0, MODE_SMA, PRICE_CLOSE);

      // Analisando dados JSON para decisões de negociação
      double aiBullishForecast = StringToDouble(APIJSON[3]); // Previsão de alta
      double aiBearishForecast = StringToDouble(APIJSON[4]); // Previsão de baixa

      // Check for crossover signals
      if (aiBullishForecast >= BullishThreshold && shortMA > longMA) // Se a previsão de alta for maior que o limite
      {
         if (OrdersTotal() == 0) {
            request.action = TRADE_ACTION_DEAL;
            request.symbol = _Symbol;
            request.volume = Lots;
            request.type = ORDER_TYPE_BUY;
            request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            request.deviation = 3;
            request.magic = 123456;
            request.comment = "Buy Order";
            request.type_filling = ORDER_FILLING_FOK;
            
            if(!OrderSend(request, result))
               Print("Error opening buy order: ", GetLastError());
         }
      }
      if (aiBearishForecast >= BearishThreshold && shortMA < longMA) // Se a previsão de baixa for maior que o limite
      {
         if (OrdersTotal() == 0) {
            request.action = TRADE_ACTION_DEAL;
            request.symbol = _Symbol;
            request.volume = Lots;
            request.type = ORDER_TYPE_SELL;
            request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            request.deviation = 3;
            request.magic = 123456;
            request.comment = "Sell Order";
            request.type_filling = ORDER_FILLING_FOK;
            
            if(!OrderSend(request, result))
               Print("Error opening sell order: ", GetLastError());
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Função para verificar se a URL está permitida                    |
//+------------------------------------------------------------------+
bool IsURLAllowed()
{
   string url = "https://www.ziwox.com";
   string cookie=NULL, headers;
   char post[], result[];
   ResetLastError();
   
   int res = WebRequest("GET", url, cookie, NULL, 5000, post, 0, result, headers);
   
   if(res == -1)
   {
      int error = GetLastError();
      if(error == 4014)
      {
         Comment("ATENÇÃO: URL não permitida\n",
                 "1. Vá em Ferramentas -> Opções -> Expert Advisors\n",
                 "2. Marque 'Permitir WebRequest para as URLs listadas abaixo'\n",
                 "3. Adicione a URL: ", url, "\n",
                 "4. Clique em OK");
         return false;
      }
   }
   return true;
}

//+------------------------------------------------------------------+
//| Expert OnTimer function                                          |
//+------------------------------------------------------------------+
void OnTimer()
{
   // Verifica se a URL está permitida antes de fazer a chamada
   if(!IsURLAllowed())
   {
      Print("DEBUG: URL não está permitida. Aguardando configuração...");
      return;
   }

   if (TimeCurrent() - LastAPICallTime >= APICallInterval)
   {
      string APIfilename = SymbolRequest + "_API_Data.json";
      
      // Prepara a URL para mostrar no comentário
      string cleanSymbol = SymbolRequest;
      StringReplace(cleanSymbol, "m", "");
      string apiUrl = StringFormat("https://www.ziwox.com/terminal/services/API/V1/fulldata.php?expn=ziwoxuser&amp;apikey=%s&apitype=json&pair=%s", 
                                 APIKey, cleanSymbol);
      
      // Mostra que está fazendo a chamada
      Comment("Fazendo chamada à API...\n",
              "URL: ", apiUrl,
              "\n\nAguarde...");
      
      APIOK = GetAPI(SymbolRequest, APIKey, APIfilename);
      
      if (APIOK) {
         JsonDataParse(APIfilename, APIJSON);
         Comment("=== API OK ===\n",
                 "URL: ", apiUrl, "\n",
                 "Última atualização: ", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), "\n",
                 "\nDados recebidos:",
                 "\nSymbol: ", APIJSON[0],
                 "\nÚltimo Preço: ", APIJSON[1],
                 "\nViés Fundamental: ", APIJSON[2],
                 "\nPrevisão de Alta: ", APIJSON[3], "%",
                 "\nPrevisão de Baixa: ", APIJSON[4], "%",
                 "\nPosições Compradas: ", APIJSON[5],
                 "\nPosições Vendidas: ", APIJSON[6],
                 "\nTendência D1: ", APIJSON[7],
                 "\nRSI D1: ", APIJSON[8],
                 "\nPermitido Operar: ", APIJSON[9]
                 );
      } else {
         Comment("=== FALHA NA API ===\n",
                 "URL tentada: ", apiUrl, "\n",
                 "Hora: ", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), "\n",
                 "\nVerifique:",
                 "\n1. Se a URL está permitida em Ferramentas -> Opções -> Expert Advisors -> WebRequest",
                 "\n2. Se sua conexão com a internet está funcionando",
                 "\n3. Se o símbolo está correto"
                 );
      }

      LastAPICallTime = TimeCurrent();
   }
}

//+------------------------------------------------------------------+
//| Função para verificar se é um novo candle                       |
//+------------------------------------------------------------------+
bool IsNewCandle()
{
   static datetime lastCandleTime = 0;
   datetime currentCandleTime = iTime(Symbol(), 0, 0);
   if (currentCandleTime != lastCandleTime)
   {
      lastCandleTime = currentCandleTime;
      return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| Pure symbol function                                             |
//+------------------------------------------------------------------+
string PureSymbol(string symbol, string suffiex, string prefix)
{
   string puresymbol = symbol;
   if (prefix != "" || suffiex != "")
   {
      StringReplace(puresymbol, suffiex, "");
      StringReplace(puresymbol, prefix, "");
   }
   return puresymbol;
}

//+------------------------------------------------------------------+
//| Função para verificar configuração do WebRequest                 |
//+------------------------------------------------------------------+
bool CheckWebRequestSettings()
{
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
   {
      Print("ERRO: DLLs não estão permitidas!");
      return false;
   }
   
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      Print("ERRO: Algorithmic Trading não está permitido!");
      return false;
   }
   
   if(!MQLInfoInteger(MQL_DLLS_ALLOWED))
   {
      Print("ERRO: DLLs não estão permitidas para este Expert!");
      return false;
   }
   
   return true;
}

//+------------------------------------------------------------------+
//| Função para verificar conexão com o servidor                     |
//+------------------------------------------------------------------+
bool CheckServerConnection()
{
   int socket = SocketCreate();
   
   if(socket != INVALID_HANDLE)
   {
      // Tenta conectar ao servidor da ZIWOX (porta 80 para HTTP)
      if(SocketConnect(socket, "www.ziwox.com", 80, 1000))
      {
         Print("DEBUG: Conexão com servidor testada com sucesso");
         // Verifica se está realmente conectado
         if(SocketIsConnected(socket))
         {
            SocketClose(socket);
            return true;
         }
      }
      else
      {
         Print("DEBUG: Falha ao conectar com o servidor: ", GetLastError());
      }
      SocketClose(socket);
   }
   else
   {
      Print("DEBUG: Falha ao criar socket: ", GetLastError());
   }
   return false;
}

//+------------------------------------------------------------------+
//| Função para obter dados da API                                   |
//+------------------------------------------------------------------+
bool GetAPI(string symbolname, string apikey, string filename)
{
   if(!TestHTTPConnection())
   {
      Print("DEBUG: Falha no teste de conexão HTTP");
      return false;
   }

   string headers = "Content-Type: application/json\r\nAccept: application/json\r\n";
   char post[], result[];
   string cookie=NULL;
   int res;
   
   // Remove o sufixo 'm' do símbolo para a API
   string cleanSymbol = symbolname;
   StringReplace(cleanSymbol, "m", "");
   
   string URL = "https://www.ziwox.com/terminal/services/API/V1/fulldata.php";
   string params = StringFormat("?expn=ziwoxuser&apikey=%s&apitype=json&pair=%s", 
                              apikey, cleanSymbol);
   
   Print("DEBUG: Preparando requisição...");
   Print("DEBUG: URL completa: ", URL + params);
   
   URL = URL + params;
   
   string body = StringFormat("{\"apikey\":\"%s\",\"pair\":\"%s\"}", apikey, cleanSymbol);
   StringToCharArray(body, post, 0, WHOLE_ARRAY, CP_UTF8);
   
   Print("DEBUG: Body da requisição: ", body);
   
   // Tenta fazer a requisição
   Print("DEBUG: Iniciando WebRequest...");
   res = WebRequest("GET", URL, cookie, NULL, 5000, post, 0, result, headers);
   Print("DEBUG: Código de resposta WebRequest: ", res);
   
   if(res == -1)
   {
      int error = GetLastError();
      Print("DEBUG: GetLastError retornou: ", error);
      return false;
   }
   
   if(res != 200)
   {
      Print("DEBUG: Resposta HTTP diferente de 200: ", res);
      return false;
   }
   
   string response = CharArrayToString(result, 0, WHOLE_ARRAY, CP_UTF8);
   
   // Remove a tag <pre> da resposta
   StringReplace(response, "<pre>", "");
   StringReplace(response, "</pre>", "");
   
   Print("DEBUG: Resposta recebida (primeiros 500 caracteres): ", StringSubstr(response, 0, 500));
   Print("DEBUG: Tamanho total da resposta: ", StringLen(response));
   
   if(StringFind(response, "invalid api key") >= 0)
   {
      Print("DEBUG: API Key inválida encontrada na resposta");
      Alert("Invalid API key");
      return false;
   }
   
   // Tenta salvar a resposta
   Print("DEBUG: Tentando salvar resposta no arquivo: ", filename);
   int filehandle = FileOpen(filename, FILE_WRITE|FILE_BIN|FILE_COMMON);
   if(filehandle != INVALID_HANDLE)
   {
      // Converte a resposta para array de caracteres
      char responseArray[];
      StringToCharArray(response, responseArray, 0, StringLen(response));
      
      // Salva no arquivo
      FileWriteArray(filehandle, responseArray);
      FileClose(filehandle);
      Print("DEBUG: Arquivo salvo com sucesso");
      return true;
   }
   
   Print("DEBUG: Falha ao salvar arquivo");
   return false;
}

//+------------------------------------------------------------------+
//| Função para analisar dados JSON                                   |
//+------------------------------------------------------------------+
void JsonDataParse(string filename, string &_APIJSON[])
{
   for (int arraIn = 0; arraIn < ArraySize(APIJSON); arraIn++) 
      APIJSON[arraIn] = "";

   if (FileGetInteger(filename, FILE_EXISTS, true) >= 0)
   {
      int FileHandle = FileOpen(filename, FILE_READ|FILE_BIN|FILE_COMMON);
      if(FileHandle != INVALID_HANDLE)
      {
         char jsonarray[];
         FileReadArray(FileHandle, jsonarray);
         FileClose(FileHandle);

         JsonValue.Clear();
         string jsonString = CharArrayToString(jsonarray, 0, WHOLE_ARRAY, CP_UTF8);
         Print("JSON Recebido: ", jsonString); // Debug
         
         if(JsonValue.Deserialize(jsonString))
         {
            _APIJSON[0] = JsonValue[0]["Symbol"].ToStr();
            _APIJSON[1] = JsonValue[0]["Last Price"].ToStr();
            _APIJSON[2] = JsonValue[0]["Base Fundamental Bias"].ToStr();
            _APIJSON[3] = JsonValue[0]["AI Bullish Forecast"].ToStr();
            _APIJSON[4] = JsonValue[0]["AI Bearish Forecast"].ToStr();
            _APIJSON[5] = JsonValue[0]["Retail Long Ratio"].ToStr();
            _APIJSON[6] = JsonValue[0]["Retail Short Ratio"].ToStr();
            _APIJSON[7] = JsonValue[0]["D1 Trend"].ToStr();
            _APIJSON[8] = JsonValue[0]["D1 RSI"].ToStr();
            _APIJSON[9] = JsonValue[0]["Allow To Trade"].ToStr();
            
            Print("Dados processados:");
            Print("Symbol: ", _APIJSON[0]);
            Print("Last Price: ", _APIJSON[1]);
Sara Sabaghi
Sara Sabaghi | 21 Jan 2025 at 20:33
Ney Borges #:

Fiz algumas correçoes ao codigo para funcionar no MQL5 gostaria que por gentilesa verificasse e retornar, obrigado -  Sara Sabaghi 

Hi dude

Thank you for sharing your code. Yeah, I tested it. It works fine

Ziwox Forex Data API

fxsaber
fxsaber | 22 Jan 2025 at 15:58
Nikolai Semko #:

Switched to binary. The size of the same data is now 1.2 Mb. Parsing into required arrays of structures now takes 5 milliseconds.

That's a bit too much for you. Here it takes 12 ms, but the data is 80 Mb.

BeeXXI Corporation
Nikolai Semko | 22 Jan 2025 at 16:55
fxsaber #:

That's a bit much. It's 12 ms here, but the data is 80 Mb.

No, everything with parsing is as optimal as possible. It's just that the data structure on the server is very suboptimal, which I couldn't influence. The parsing output is 5 arrays of structures, and the input (in the binary) is 2 arrays of structures. That is, 3 arrays of structures are nested in elements of 2 arrays of structures. That's why I had to copy element by element. The only thing I lied about was that I switched from JSON of 20 Mb to a binary of 2.2 Mb instead of 1.2 Mb.
Creating an Interactive Graphical User Interface in MQL5 (Part 2): Adding Controls and Responsiveness Creating an Interactive Graphical User Interface in MQL5 (Part 2): Adding Controls and Responsiveness
Enhancing the MQL5 GUI panel with dynamic features can significantly improve the trading experience for users. By incorporating interactive elements, hover effects, and real-time data updates, the panel becomes a powerful tool for modern traders.
MQL5 Wizard Techniques you should know (Part 27): Moving Averages and the Angle of Attack MQL5 Wizard Techniques you should know (Part 27): Moving Averages and the Angle of Attack
The Angle of Attack is an often-quoted metric whose steepness is understood to strongly correlate with the strength of a prevailing trend. We look at how it is commonly used and understood and examine if there are changes that could be introduced in how it's measured for the benefit of a trade system that puts it in use.
Price Driven CGI Model: Theoretical Foundation Price Driven CGI Model: Theoretical Foundation
Let's discuss the data manipulation algorithm, as we dive deeper into conceptualizing the idea of using price data to drive CGI objects. Think about transferring the effects of events, human emotions and actions on financial asset prices to a real-life model. This study delves into leveraging price data to influence the scale of a CGI object, controlling growth and emotions. These visible effects can establish a fresh analytical foundation for traders. Further insights are shared in the article.
Using PatchTST Machine Learning Algorithm for Predicting Next 24 Hours of Price Action Using PatchTST Machine Learning Algorithm for Predicting Next 24 Hours of Price Action
In this article, we apply a relatively complex neural network algorithm released in 2023 called PatchTST for predicting the price action for the next 24 hours. We will use the official repository, make slight modifications, train a model for EURUSD, and apply it to making future predictions both in Python and MQL5.