Introduction to MQL5 (Part 37): Mastering API and WebRequest Function in MQL5 (XI)
Introduction
Welcome back to Part 37 of the Introduction to MQL5 series! In the previous article, we introduced the basics of API signatures and explored how secure requests are created in MQL5 using hashing and HMAC-based techniques. We focused on why signatures are necessary, how they protect sensitive requests, and how MQL5 handles signature generation at a conceptual level.
This article builds on that foundation by taking the next useful step. Here, we will write an MQL5 script that retrieves account balance data for every asset that is accessible by sending authenticated API queries to Binance. This will compile all the previously discussed topics, such as using WebRequest, handling timestamps, creating signatures, and interacting with private API endpoints. You will have a firm grasp of how to safely interact with Binance and retrieve actual account information straight from MQL5 at the end of this article.
Fetching the Binance Server Timestamp for Signed Requests
A message and a secret key are the two essential components needed to create a safe signature for Binance, as we covered in the last post. The message in this instance is the timestamp, which needs to reflect the current time on the Binance server rather than the time on your local computer. To secure your requests, the timestamp is essential. Repeated attacks are prevented by ensuring that each signed request is distinct and cannot be utilized by another party. The timestamp captures the precise moment the request is made because it is continually changing. Binance allows for accurate verification by providing the timestamp in milliseconds. When contacting private endpoints, such as checking balances or making trades, using the appropriate server time ensures that your signature will be valid.
We must submit an API request to Binance to obtain this server time. The server timestamp is the official reference that Binance uses for all authorized requests, in contrast to local time, which can vary according to your computer's clock or time zone. This means that before creating the signature, our MQL5 software needs to get in touch with Binance to obtain the server time. Any signature we make without this step would be rejected since the timestamp wouldn't fit Binance's expectations. To obtain the current server time, a GET request must be sent to a certain Binance endpoint. We can freely access this endpoint since it doesn't require authentication. The current server time in milliseconds is contained in a JSON object that Binance provides in response to our request. After that, our script will take this value out of the response and use it as the message while the signature is being created.
We make sure that every subsequent API call we make is in sync with Binance's server clock by properly constructing our request, managing the response, and interpreting the timestamp. Although it may seem insignificant, this step is crucial because without a precise timestamp, neither a private request nor a signature would be successful. We must first become proficient at reliably collecting the server time before we can combine this timestamp with the secret key to generate a properly signed request later in the article. Although I've said this before, I think it's worth saying again. You must enable WebRequest to Binance in the platform settings before your MQL5 script may do so. Add https://api.binance.com to the list of permitted URLs in the Expert Advisors section after pressing Ctrl+O to access the options. This is a prerequisite before we send any signed API requests because it guarantees that your script may interact with Binance servers without being blacklisted.
Example://+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- string url_t = "https://api.binance.com/api/v3/time"; string headers_t = ""; char result_t[]; string response_headers_t; char data_t[]; int status_t = WebRequest("GET", url_t, headers_t, 5000, data_t, result_t, response_headers_t); string time = CharArrayToString(result_t); Print(time); }
Output:

Explanation:
The script starts by defining the URL of the Binance endpoint that gives the server time right now. Our MQL5 software will submit a request to this URL to retrieve the official Binance timestamp. Utilizing the server time is essential since it guarantees that any signed requests we subsequently submit are in sync with Binance's clock, preventing mistakes or rejections brought on by inconsistent timestamps. The script then creates a blank string for headers. The headers can stay blank because there is no requirement for authentication because this request is to a public API. On the other hand, headers including your API key or other credentials would be needed for private queries. However, it is acceptable to leave the headers empty when retrieving the server timestamp.
Additionally, arrays are declared by the script to hold the request content and the response. Since a GET request does not include any data, the array designated for the request body stays empty while the array intended for the response will contain the raw data returned from the server. Any headers the server returns are stored in a different variable. Although optional, this can be useful for debugging or verifying further data that Binance has returned. The GET request is then sent to Binance via the WebRequest function. The request type, URL, headers, timeout period in milliseconds, request content, array for response storage, and variable for returning headers are among the parameters that this function accepts. A status code indicating whether the request was successful is returned by the function. Usually, a successful request yields a status code of 200.
The raw byte array is transformed into a readable string once the server answer has been received. This conversion enables us to extract the data in a manner that is usable by humans. The timestamp is sent by the Binance server as a series of bytes in JSON format. To verify that the request was successful and that we have the current Binance server time in milliseconds, the script lastly prints the timestamp.
Analogy:
Let's say you want to see what time it is in a friend's city before setting up a call. To ensure that your letter reaches them, you must first provide their address. This is comparable to how the script specifies the Binance endpoint URL, which instructs the program on the precise location to submit the request. It instructs your MQL5 program on the precise location to submit the request to obtain the official server time. It's crucial to use this server time since it guarantees that your timing will coincide with Binance's clock when you plan actions later. Your plans may change, and Binance may reject your request if you utilize your own local clock instead.
Then consider the possibility that your envelope might contain more instructions or notes. The headers of the WebRequest are similar to these. You don't need any further notes for this specific request, which is for the server time, since Binance already understands what you're asking for. Similar to putting an API key in the headers, you might need to include a secret code or identity for other kinds of requests, such as transferring sensitive data.
Imagine the reply as a package that Binance returns. The response array in the script serves as a place to catch and store the package. The request body is blank since you are merely posing a query and not providing any additional information. If you would like further information about how the response was sent, you can review the returned headers, which are essentially additional notes about the package. Using the WebRequest function is comparable to sending the letter. You indicate where the returned letter should be deposited, the type of mail, the destination, and how long the post office should attempt before giving up. The status code functions as a delivery receipt when the letter is returned, indicating whether the request was fulfilled. A 200 code verifies that everything was completed successfully.
The information is finally found inside the package when you open it; however, it can first be written in a code that you can’t decipher. Translating that secret communication into ordinary language is similar to turning the byte array into a readable text. Printing the timestamp, which displays the precise server time in milliseconds, is similar to reading the notice from Binance. Knowing that your time coincides with Binance's clock allows you to confidently plan your next course of action. We can observe that the server response is in JSON format from the WebRequest's output. The response includes structured keys and values in addition to raw numbers. The JSON object for this specific endpoint has a single key named serverTime, whose value indicates the server timestamp as of right now in milliseconds. Extracting the timestamp is simple due to the response format.
When creating our API signature, we will utilize the value associated with serverTime as the message, so that is all we need. We can make sure that our ensuing signed requests are in sync with Binance's server time and hence approved by the private endpoints by isolating this numerical value.
Example://+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- string url_t = "https://api.binance.com/api/v3/time"; string headers_t = ""; char result_t[]; string response_headers_t; char data_t[]; int status_t = WebRequest("GET", url_t, headers_t, 5000, data_t, result_t, response_headers_t); string time = CharArrayToString(result_t); string pattern = "{\"serverTime\":"; int pattern_lenght = StringFind(time,pattern); pattern_lenght += StringLen(pattern); int end = StringFind(time,"}",pattern_lenght + 1); string server_time = StringSubstr(time,pattern_lenght,end - pattern_lenght); Print(server_time); }
Explanation:
The first line defines a string called "pattern" that contains "serverTime." The JSON object that the Binance server returned had this exact beginning. By recognizing this pattern, we may ascertain the start of the real timestamp value within the entire JSON response. The first line defines a string called "pattern" that contains "serverTime." The JSON object that the Binance server returned had this exact beginning. By recognizing this pattern, we may ascertain the start of the real timestamp value within the entire JSON response.
The next step is to find this pattern among the string of answers. The function gives back the pattern's initial index in the response. We append the pattern's length to this location since we are interested in the value that follows the pattern. This provides the server timestamp of the string's beginning.
Analogy:
Imagine receiving a tiny box with a note from a buddy. The note starts with a header that reads "serverTime:" followed by a lengthy number. The header and any further material are not relevant to you; only the number is. Finding the header in the JSON response is the initial step, much like finding server time. Once located, you ignore the header in favor of concentrating on the number itself, which contains the necessary information. The closing brace in the JSON object indicates the end of the integer, which you then search for. This is comparable to locating the note's end within the package. You may carefully remove just the number, omitting the header and any other characters, now that you know precisely where the number begins and finishes.
Lastly, you either jot down the number or read it aloud to yourself. This translates to extracting the substring in the code that alone contains the numerical server time. Printing it is similar to putting the number on paper so you can use it for your next assignment. In the same manner that you would utilize the precise time your friend wrote on the note to plan an activity, you can isolate the number in this way and use it directly as the message when constructing your API signature.
Generating Your Binance API Key and Secret Key
An API key and a secret key are required to communicate with Binance via MQL5 and submit authenticated queries. Your program can safely connect with Binance and carry out tasks on your account, like checking balances or making trades, thanks to these two keys, which function as a username and password. While the secret key is used to provide secure signatures to demonstrate that the requests actually originate from you, the API key identifies your account. Actually, the secret key is precisely what our MQL5 scripts will use to create the signature.
You must first log into your Binance account to generate these keys. Go to your profile after logging in, then choose API Management. The option to generate a new API key is displayed here. Binance will ask you to name or label it. Select a descriptive name, such as "MQL5 Trading Bot," so that you can quickly recognize it in the future, particularly if you generate several API keys. Binance will create the secret key and API key after naming the key. The secret key is only displayed once; however, the API key will be exposed right away.
It is essential to save the secret key safely because Binance won't show it again. It can be kept in a secure password manager or a secured file. Never share your private key with outside parties or include it in scripts that other people could see. When the keys are generated, you also need to set up permissions for the API key. You usually need to enable Read Info to retrieve account balances and send queries from MQL5. If your bot is going to make trades, you must also enable trading. To prevent money from being transferred out of your account, you should never enable withdrawals unless essential.
Your MQL5 program can create signatures and send secure requests to Binance after you have both the secret key and the API key. Because it is used with the message, along with the date, to create a unique signature, the secret key is very significant. This protects your requests from intervention and ensures that only your software can access your account.
Creating Binance API Signatures in MQL5
The next step is to create a signature since we now understand how to use an API GET request to obtain the Binance server time and have successfully created an API key and secret key. A signature is a safe technique to demonstrate that requests issued to Binance are genuine and unaltered, as we covered in the last post. The distinction is that we are creating the signature using the precise parameters needed for Binance's secret API this time. We create a unique signature by combining the secret key with the current server timestamp in milliseconds. By adding this signature to the API request, Binance can verify the request's legitimacy and the integrity of the data.
Because Binance will reject any queries to private endpoints that are unsigned or improperly signed, creating the signature is an essential step. You may be sure that your MQL5 script can effectively and safely communicate with Binance by carefully following the instructions and using the server timestamp in addition to your secret key. Declaring two string variables will be the initial step in our MQL5 program. The Binance server time that we previously obtained using the API request will be stored in one of these variables. When we generate the signature, the message will be this server time, expressed in milliseconds. The private key created on the Binance dashboard will be kept in the second string variable. Because it is the crucial element used to demonstrate that the request actually is yours, this secret key is private and needs to be kept safe.
The next stage is to transform both values into character arrays after they have been stored as strings. Before we can create a signature, this translation is required since MQL5's cryptographic algorithms operate at the byte level rather than directly with strings. During this conversion, we employ UTF-8 encoding to guarantee consistency and prevent encoding problems. By using UTF-8, you can be sure that the message and the secret key are represented in a standard manner that the Binance server and your MQL5 program would understand in the same way. We prepare both the server time and the secret key for hashing and signing by transforming them from strings to character arrays using UTF-8 encoding.
Example:
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- string url_t = "https://api.binance.com/api/v3/time"; string headers_t = ""; char result_t[]; string response_headers_t; char data_t[]; int status_t = WebRequest("GET", url_t, headers_t, 5000, data_t, result_t, response_headers_t); string time = CharArrayToString(result_t); string pattern = "{\"serverTime\":"; int pattern_lenght = StringFind(time,pattern); pattern_lenght += StringLen(pattern); int end = StringFind(time,"}",pattern_lenght + 1); string server_time = StringSubstr(time,pattern_lenght,end - pattern_lenght); string message = "timestamp=" + server_time; string secrete_key = "ABCDER2y8VAzqopxzLVEhVYABCDEV2AxIYLueComud3aSEez8Z8fvgHPZTXABCDE"; uchar uMsg[], uSKey[]; StringToCharArray(message, uMsg, 0, StringLen(message), CP_UTF8); StringToCharArray(secrete_key, uSKey, 0, StringLen(secrete_key), CP_UTF8); }
Explanation:
At this point, we start by specifying the message that will be signed. The server time value that we previously extracted from the Binance API response is combined with the string timestamp= to form the message. Because Binance requires signed requests to adhere to a rigid parameter syntax, adding this prefix is required. Raw numbers are not signed by the server. Key-value pairs are signed by it. The produced signature will not match what Binance calculates on its end, and the request will be denied if we attempt to utilize only the server time value without specifying timestamp=. For this reason, the message must be worded precisely as the Binance API specification specifies.
The secret key is then stored in a string variable that we specify. This value, which is the private key produced by the Binance dashboard, is to be kept safe at all times. Binance never receives the private key as part of the request. Rather, the signature is created directly within the MQL5 application. Because Binance already has a copy of this key, it may generate the same signature on its end to validate the request. We declare two character arrays after specifying the message and the secret key as strings. The secret key and the message's byte-level representation will be kept in these arrays. This conversion step is necessary before creating the signature since MQL5's cryptographic procedures operate with bytes rather than plain strings.
Next, UTF-8 encoding is used to transform the message string into a character array. This guarantees a consistent and predictable format for each character in the message. The secret key undergoes the same conversion procedure. Because it ensures that the byte representation used in MQL5 matches the one used by Binance when executing the same signature calculation, using UTF-8 encoding is crucial.
Analogy:
Let's say you wish to send a registered letter to a security office that only accepts letters in a particular format. You start by writing the letter's content. The time is the content in this instance. Nevertheless, a simple number printed on paper is not accepted by the office. It anticipates that the time will be clearly marked, such as by stating "timestamp equals this time." The office will reject the letter since it does not adhere to the necessary format if you send just the number without the label. For this reason, it is necessary to put timestamp= before the server time. The proposal will never be approved without it.
Next, visualize the secret key as a personal stamp that you alone possess. This stamp was never placed into the envelope. Rather, you utilize it at your workstation to annotate the letter before sending it. The office can verify that the mail actually originated from you thanks to this stamp. The office will know right away that your letter is fraudulent if someone else tries to reproduce it without the stamp. Imagine for a moment that handwritten letters are not read by the office. Only text written with a certain keyboard layout is understood by it. As a result, you have to use this same format when rewriting the message and the secret stamp information. To ensure that there is no confusion when the letter is read, the message and secret key are converted into character arrays using UTF-8, which is similar to typing everything on the authorized keyboard.
Example:
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- string url_t = "https://api.binance.com/api/v3/time"; string headers_t = ""; char result_t[]; string response_headers_t; char data_t[]; int status_t = WebRequest("GET", url_t, headers_t, 5000, data_t, result_t, response_headers_t); string time = CharArrayToString(result_t); string pattern = "{\"serverTime\":"; int pattern_lenght = StringFind(time,pattern); pattern_lenght += StringLen(pattern); int end = StringFind(time,"}",pattern_lenght + 1); string server_time = StringSubstr(time,pattern_lenght,end - pattern_lenght); string message = "timestamp=" + server_time; string secrete_key = "ABCDER2y8VAzqopxzLVEhVYABCDEV2AxIYLueComud3aSEez8Z8fvgHPZTXABCDE"; uchar uMsg[], uSKey[]; StringToCharArray(message, uMsg, 0, StringLen(message), CP_UTF8); StringToCharArray(secrete_key, uSKey, 0, StringLen(secrete_key), CP_UTF8); int blockSize = 64; uchar ipad[], opad[]; ArrayResize(ipad, blockSize); ArrayResize(opad, blockSize); for(int i = 0; i < blockSize; i++) { ipad[i] = uSKey [i] ^ 0x36; opad[i] = uSKey [i] ^ 0x5C; } uchar innerData[], innerHash[]; ArrayCopy(innerData, ipad); ArrayCopy(innerData, uMsg, blockSize); CryptEncode(CRYPT_HASH_SHA256, innerData, uSKey, innerHash); uchar outerData[], finalHash[]; ArrayCopy(outerData, opad); ArrayCopy(outerData, innerHash, blockSize); CryptEncode(CRYPT_HASH_SHA256, outerData, uSKey, finalHash); string signature = ""; for(int i = 0; i < ArraySize(finalHash); i++) signature += StringFormat("%02x", finalHash[i]); Print(signature); }
Explanation:
First, we set the block size to 64 bytes. The hashing algorithm's requirements determine this value. Using the appropriate block size ensures that the data we provide properly matches the algorithm's expectations because the algorithm operates with fixed-size pieces of data. Two byte arrays are then declared. The inner pad is represented by one, and the outer pad by the other. To fit the block size, both arrays are shrunk. These arrays are currently empty containers with a capacity of precisely 64 bytes each. These pads are essential for dividing the inner and outer hashing processes, and they will soon be filled with values obtained from the secret key.
The pads are actually prepared in the loop that comes after. From the first byte until the sixty-fourth byte, the loop is executed. An exclusive OR operation is used to combine a byte from the secret key with a fixed constant for each place. The inner pad uses one constant, whereas the outer pad uses a different constant. This process modifies the secret key in a uniform and regulated manner. The outcome is two distinct key versions, one for the outside hashing step and one for the interior hashing stage. This division is crucial for security and contributes to the signature's resistance to manipulation.
Preparing the data for the inner hashing stage comes next when the pads are ready. The inner pad is copied into a new byte array that is built to store the combined data. The message bytes are then inserted, beginning at the block size position. This produces a single continuous byte array with the message after the inner pad. The cryptographic hashing algorithm then receives this combined data and generates a hash. The initial transformation of the message using the secret key is represented by this result, which is called the inner hash.
The procedure proceeds to the outer hashing stage following the creation of the inner hash. The outside pad is copied into a new byte array. This array is then added to the inner hash. The outer pad and the outcome of the first hash are combined to form a new sequence of bytes. The final hash is created by running this data through the hashing process once more. At the byte level, this final hash represents the actual signature output.
The signature is still in the form of raw bytes at this point; therefore, it cannot be utilized directly in an API call. An empty string is constructed to make it usable. The resultant hash's bytes are then iterated over via a loop. The byte is appended to the signature string after being transformed into a two-character hexadecimal representation throughout each cycle. Until every byte has been digested, this process is repeated.
The final signature is represented by a single hexadecimal string after the loop is finished. We may use this value directly in an API request and confirm the output by printing it. This string is given to Binance as evidence that the request is legitimate, properly formed, and produced with the right secret key.
Analogy:
Let's say you are making a strong wax seal for a crucial document. This seal needs to demonstrate two things. Firstly, that you actually wrote the document. Secondly, that no changes were made to the document during delivery. Creating a fixed-size mold for the seal is the first step in the process. No matter how long your message or secret phrase is, this mold is always the same size. Because the sealing technique was created to work with that size, the mold size is set. The block size indicates this. It establishes the area where the sealing procedure takes place.
You then get two unique sheets of wax ready. Your secret word is used to create both, but they are handled differently. A first standard component is combined with one sheet, while a second standard ingredient is combined with the other. The secret phrase is slightly changed in two different ways by this mixing phase. The end product is two distinct wax sheets that have different functions in the sealing process but come from the same secret. The inner and outer pads are these.
You proceed to the initial sealing step once the wax sheets are prepared. After inserting the first wax sheet into the mold, place your paper on top of it. They come together to form a single merged stack. An intermediate seal is created by pressing this stack using a stamping machine. The final seal is not this one. It is merely a transient outcome that will be utilized in the subsequent phase. The second sealing stage then starts. You insert the second sheet of wax into the mold. The intermediate seal is then applied on top of it. The same stamping machine is used to press this fresh stack once more. The final wax seal is the outcome of this second press. Both your document and your secret phrase are uniquely represented by this seal, and even a slight alteration to either would result in an entirely different seal.
The seal is now in an unprocessed physical state that makes it difficult to send or digitally attach to a document. You meticulously translate the seal into a written code with two characters for each component to make it usable. Until the complete seal is represented as a single readable string, you walk through the entire seal piece by piece and write down its coded form. Lastly, you examine and confirm the finished code. You attach this code to your document when you email it. The recipient uses their copy of your secret phrase to repeat the identical sealing procedure after receiving the document. They can be certain that the document is genuine and unaltered if their seal precisely matches yours.
Sending Authenticated Requests to the Binance API
Sending an authenticated request to the Binance API is the next step after learning how to build API signatures in MQL5. While account-related endpoints, such as getting your balance, require authentication, public endpoints can be visited without any extra protection. This is where the server time, the signature you created, and the API key come together. A signed request must be sent to a private endpoint to retrieve your account balance for each asset on Binance. The request headers contain your API key, while the parameters contain the timestamp and signature. To make sure the request is authentic and the data hasn't been altered, Binance checks these details.
The server replies with a JSON object that includes information about every asset in your account, including the available balance and locked balance, after the request has been properly sent. You can then extract and handle the necessary balance data from this response within your MQL5 software. At this stage, your code transitions from being ready to actually interacting with your Binance account.
Example://+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- string url_t = "https://api.binance.com/api/v3/time"; string headers_t = ""; char result_t[]; string response_headers_t; char data_t[]; int status_t = WebRequest("GET", url_t, headers_t, 5000, data_t, result_t, response_headers_t); string time = CharArrayToString(result_t); string pattern = "{\"serverTime\":"; int pattern_lenght = StringFind(time,pattern); pattern_lenght += StringLen(pattern); int end = StringFind(time,"}",pattern_lenght + 1); string server_time = StringSubstr(time,pattern_lenght,end - pattern_lenght); string message = "timestamp=" + server_time; string secrete_key = "ABCDER2y8VAzqopxzLVEhVYABCDEV2AxIYLueComud3aSEez8Z8fvgHPZTXABCDE"; uchar uMsg[], uSKey[]; StringToCharArray(message, uMsg, 0, StringLen(message), CP_UTF8); StringToCharArray(secrete_key, uSKey, 0, StringLen(secrete_key), CP_UTF8); int blockSize = 64; uchar ipad[], opad[]; ArrayResize(ipad, blockSize); ArrayResize(opad, blockSize); for(int i = 0; i < blockSize; i++) { ipad[i] = uSKey [i] ^ 0x36; opad[i] = uSKey [i] ^ 0x5C; } uchar innerData[], innerHash[]; ArrayCopy(innerData, ipad); ArrayCopy(innerData, uMsg, blockSize); CryptEncode(CRYPT_HASH_SHA256, innerData, uSKey, innerHash); uchar outerData[], finalHash[]; ArrayCopy(outerData, opad); ArrayCopy(outerData, innerHash, blockSize); CryptEncode(CRYPT_HASH_SHA256, outerData, uSKey, finalHash); string signature = ""; for(int i = 0; i < ArraySize(finalHash); i++) signature += StringFormat("%02x", finalHash[i]); Print(signature); string query_string = ""; query_string += "&signature=" + signature; string time_stamp = "timestamp=" + server_time; string url = "https://api.binance.com/api/v3/account?"+ time_stamp + query_string; string API_KEY = "ABcdeviQHg3LD9ncT0mabcdepfz2a3qkNvrI0abcdeIZYU5umZgeowabcdeMbq8A"; string headers = "X-MBX-APIKEY: " + API_KEY + "\r\n"; char result[]; string response_headers; char datas[]; int status = WebRequest("GET", url, headers, 5000, datas, result, response_headers); string server_result = CharArrayToString(result); Print(server_result); }
Explanation:
The query parameters that Binance requires for an authenticated request are prepared in the first section of the code. The signature is appended to an empty string that is constructed to store additional query values. The signature must never be supplied inside the headers or body, but rather as part of the URL query. Separately, the server time you previously obtained from Binance is used to prepare the timestamp in the proper format. This timestamp helps Binance defend against replay attacks and demonstrates that the request was made recently. The final request URL that will be sent to Binance is then created by combining the date and the signature with the base endpoint URL.
After that, the API key is ready. The API key is not appended to the URL like the signature is. Rather, it is inserted using the unique header name that Binance mandates inside the request headers. The signature verifies that the request was approved using the correct secret key, and this header indicates to Binance whose account is submitting the request. WebRequest requires headers to adhere to correct HTTP syntax, so the line break at the end of the header string is crucial.
Variables are then declared to receive the response from the server. These consist of an additional character array used internally by the WebRequest function, a string to record response headers supplied by the server, and a character array to store the response content. After processing the request, MetaTrader uses these variables as containers to store anything Binance delivers back. Since retrieving the account balance does not require sending data in the request body, the WebRequest function is then called using the GET method. The function receives the final URL, a timeout value, and headers with the API key. Binance reviews the request, confirms the signature and timestamp, and returns your account information if everything is correct.
To make it easier to read and process within MQL5, the raw response that was received as a character array is finally transformed into a string. You may view the complete JSON response from Binance, which contains balance details for every asset in your account, by printing this result. You can subsequently extract particular data, such as the free balance, the locked balance, or the specifics of each asset, from this output.
Analogy:
Let's say you wish to verify all of your account balances by sending a secure letter to a bank. The bank demands that each request be authentic and unaltered, so you can't just stroll in and ask. You start by writing a personalized note to attach to your letter. A timestamp and a signature are two crucial pieces of information in this note. The timestamp, which displays the precise time you penned the letter, functions similarly to a postmark. It guarantees that the bank is aware that the letter is current and not an outdated one that someone is attempting to use again.
The signature serves as proof that you are the only person with permission to transmit this message, much like a personal wax seal. When the bank gets your request, both are combined and affixed to the envelope for verification. You then prepare an ID card that serves as a representation of your API key for the bank. To let the bank know which account the request is for, this is included within the envelope in a visible slot. The bank can see your ID, but since it doesn't know your secret stamp, it cannot fake your signature.
You now give the envelope to a reliable courier. The WebRequest function in MQL5 is represented by this courier. After delivering your mail to the bank, the courier waits for a response. After verifying your identity and checking the timestamp and wax seal, the bank writes a response that includes the balance of all the assets in your account. You open the envelope when the courier comes back. Like a message recorded in a secret ledger format (JSON), the response is coded. To easily see the balances, you transform it into legible language. Printing it from your program is similar to setting up the ledger on your desk so you can review each entry.
The data must then be saved in a file when the request has been sent and the server has responded. You can debug the result, preserve a permanent record of your account balances, or process the response later without making repeated queries to Binance by saving the response. Standard file functions in MQL5 can be used to write the server response to a file.
Example:
string filename = "Binace_Balance.txt"; int handle = FileOpen(filename, FILE_WRITE|FILE_TXT|FILE_SHARE_READ|FILE_ANSI); if(handle != INVALID_HANDLE) { FileWrite(handle, server_result); FileClose(handle); Print("EA successfully wrote the data to " + filename); } else { Print("Error opening file for writing. Error code: ", + GetLastError()); }
Explanations:
Imagine getting a formal letter outlining all of your balances from your bank. You decide to save it for later, so you pick a notebook and clearly label the cover. When you need it again, you can quickly identify it thanks to that label. Selecting a descriptive file name for the server response is comparable to this. After that, you open the notebook to a blank page, making sure it is readable and prepared for writing. Similarly, your program opens a file with the appropriate settings so that readable text may be stored correctly.
You copy the contents of the letter onto the page while the notebook is open. You close the notebook after writing everything down to preserve its contents. By closing it, you may be sure that your notes are secure. Closing the file in your software accomplishes the same thing by guaranteeing that the response is preserved accurately. If you cannot open the notebook, write the reason so that it can be resolved. Similarly, an error code that helps you comprehend and fix a file opening failure is returned.
Conclusion
In this article, we took the next big step in working with the Binance API in MQL5. We learned how to send authenticated requests to retrieve your account balance for all assets using the API key, secret key, server time, and the signature we generated. We also covered how to handle the server response and store it safely in a file for future use or further processing.
Warning: All rights to these materials are reserved by MetaQuotes Ltd. Copying or reprinting of these materials in whole or in part is prohibited.
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.
Creating Custom Indicators in MQL5 (Part 6): Evolving RSI Calculations with Smoothing, Hue Shifts, and Multi-Timeframe Support
The MQL5 Standard Library Explorer (Part 6): Optimizing a generated Expert Advisor
Larry Williams Market Secrets (Part 8): Combining Volatility, Structure and Time Filters
Data Science and ML (Part 48): Are Transformers a Big Deal for Trading?
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use