Transcript for:
Creating a Trade Copier for Metatrader 5

Hey this is Rene, welcome back for another video on this channel and today we will write a trade copier program for the Metatrader 5. This was requested so often and I always rejected this but there were so many requests so I will just get this done and you can or whenever I get the question in the future I can just link this video. So what we will do is we will write a program that you can use on your pc locally if you have for example two Metatrader terminals like I have them here. And then it is important that on one terminal you have one account and on the other terminal you have another account.

And the idea is to use the program, like the same program, on both of these Metatrader terminals. And one of these terminals will function as the master and one will function as the slave. And whenever the master says something like open a trade or close a position, the slave will react and will do the same.

Actually, I'm not really sure if these master and slave wordings are still state-of-the-art in the modern century, but in programming, these are the terms that I use. So don't cancel me for this. Okay, so what we will do is we will work in this ICMarkets metatrader that I have here, and then we will copy to the JFT Brokers metatrader. But it doesn't matter.

You can use this with any Metatrader. So first of all, we will have to write the program now. So let's go to the Metacodes language editor.

And in this tutorial, I will not explain like the complete basics, like variables and stuff. If you are interested how this works, check out the other videos on the channel. Also, if you want to learn everything in a structured course, make sure to check out the link.

in the bio of this video and you will find a complete course for Metatrader 5 programming where I teach everything you need to know like all the basics but also advanced stuff like working with files what we will do in this video. So first of all let's create a new program it will be an expert advisor and I can name this trade copier youtube for example you can choose anyone any name you like then click on next next and finish and this is the program that is created for us I will delete the comments and the properties at the top and the comments in the code here. Then we will delete the onTick function because we don't work with the onTick function in this case and I like to rearrange my brackets like this. So I will try to code this from top to bottom because this was also requested before in a comment on YouTube and I want to want to see if this works out. So first of all let's create another define.

and we will call this file name because as i said before the we will use files to transfer the information from one terminal to another terminal and there is a concept in like in metatrader or working with the metatrader which is a shared folder so if we go to file in the common data folder if we go to file in the metacourse language editor then you can go to open common data folder And this is a folder that is shared by all of the Metatrader terminals. So you can see the path is somewhere, yeah, it should look somehow like this. It's a MetaQuotes-like major folder, and then we have a common folder.

And this folder is shared by all the Metatrader terminals. So for example, this terminal has access to the common folder, but also this one. So this is the location where we want to store a file. So the file name, it will be mqlinfo string, for example, and then we can say mql program name. And then we will just add.bin for binary file because we will work with a binary file.

This is the fastest file, so to say. So this makes sense in this case, I think. Then we will include some things.

So let's already include the trail.mqh file because we will, of course. use this later on if you want to open, modify and close positions. Then I also want to include an array file, which will be the array long MQH file. Erase like this.

And then it should work. Because we will use erase to store the tickets of the original account later on on the slave Metatrader so we don't open the the positions multiple times, only once. So next we will create a enumeration for the mode.

And here we will have the master mode, mode master. master and we'll have mode slave and then of course we will need a input variable for this of type enum mode and this will be named mode and by default let's say it's a slave mode. So don't forget to compile from time to time so you will see quickly if you made any mistakes in your code.

Okay, so now we have the input variable. Now let's also use the Ctrade class that we include here to create a global variable of type Ctrade. Then since we don't use the onTick function, we will need some frequent event handler.

And here we will use event set timer and yeah, you can also use millisecond timer, whatever you like. Let's use the millisecond one maybe. And then in the onD init you use event kill timer. What this does is it will initialize your program or set up your onTimer function.

And the onTimer function can be added here. We just say onTimer, then add empty parentheses and the brackets. And this function will now be processed or executed every 500 milliseconds. This is because we set the event timer to 500 milliseconds. And then in the onD init you should kill this timer.

And this is just a proper programming habits. And then in the onTimer function, this is where we want to add our code. So first of all, we want to check if the mode is mode master or if it is mode slave like this.

First of all, let's add the code block for the master. So if we run this program on the master, On the master terminal we want to loop through all the open trades and save them in this external file So let's get this file up and running first We will use the file open function for this and then we will open or create a new file with this file name It comes from this define here. So this will be the name of the file.

We will see this in a second Then we need several flags. Oh, it's a file write because we want to write then it's file bin for binary and it's also file common this is important because otherwise the second terminal will not be able to find this file so if we open this file we can then check if file is unequal invalid handle so if we are able to find or open this file then we want to go here so what we want to do next is we want to check if positions total is greater than zero or no let's check if it is zero in this account because in this case what i want to do is i want to say file delete if we do not have any trades in our master account we just want to delete the file so we will provide the file name this is the file that we want to delete and in this case um yeah that that's fine like this and then oh also you Yeah, no, that's fine. Okay, so if we have open positions in the account, we want to do something else.

In this case, we want to loop through all the open positions. And this is like the standard for loop that we always use for this purpose. Nothing special, nothing interesting really. And then we will use the C position info class, which is a class that makes working with positions easier. And here we can now use the position object and say position select by index and we will use the index i.

So if we find a position at index i we will get into this if statements body. And what we want to do here is we want to write all of the position properties to this specific file. So let's start with file write long with a position ticket. So you will always use these fileWriteLong, fileWriteInteger, fileWriteDouble, fileWriteString, whatever functions. Then you have to provide the file handle where you want to write to.

And this is a file handle here, which is returned by the fileOpen function. So you can see here this fileOpen function, it will return a handle. And we can now use this handle so the computer knows what file we want to write to. And then we just have to provide the value that we want to write.

In this case, it's of course the position ticket. And we can now get this ticket easily using this position object variable. So next, we want to write the symbol, but it's not that easy.

We cannot just write strings to a binary file because we have to define how long this string will be. So first of all, we will have to get the length. So what we want to do here is we want to say length and it's string len. And then we say position symbol.

This will give us the length of this symbol. Like EURUSD, for example, would be 6. DE40 would be 4. US30 would be 4. So just the length of the symbol. And now we can write this length as an integer to the file, like this.

And next, we want to write the string. And here we also write to the file, and we just write position symbol. And yeah, we could specify the length here, but it's not really needed.

And now we have the length and the symbol text in the file. This will be important when we read from the file on the slave terminal. So next we want to write what else we need the volume. It's a double of course position volume.

So the amount of lots. Then file write integer. We need the position type. Position type like this which is either buy or sell and then we need all the other properties. File position price open.

We won't even use this but it doesn't really matter. Let's just write it to the file. Maybe you want to adjust the program later on and add orders and stuff then you might use this.

So we also write the stop loss and the take profit. Yeah the order is not really relevant here. And then position take profit. Okay like this.

And after we did all of this, after we did this loop and everything or when we deleted the file, we then want to close this file. So we will do this here, file close. This is also important because when you open a file you always need to close it later on.

So this of course only necessary if we were able to open the file because otherwise the handle is not Filled with a useful value anyways, but if we are able to open or create the file Then we want to close it later on so if another program tries to access this file It's not blocked and there's a wrong parameter count because the file close needs the handle of the file that you need to close Okay, that that's it. That's actually the code for our master already. So let me show you this quickly in the Metatrader 5 Like when you compile this correctly, you can go to the MetaTrader 5. And in the MetaTrader 5, you can go to your navigator and to expert advisors. And here you should find the trade copier YouTube or whatever name you chose program.

You can just drag and drop it on any chart. And then you will see the settings here in the inputs tab. We will, of course, use mode master instead of mode slave. And then we will click on OK.

So what happens now? Let's go to the meta editor again. Let's go to file open common data folder and then go to Files here and we will see there's a trade copier youtube.binary file This is because the trade copier youtube.mq or the executable created this file Still we can see that this file is not really big.

There are two zero kilobytes. So it's pretty much empty So we can change this if we open a position. Let's go ahead and open a byte position with one lots maybe.

And then if we go back to our file here in the folder, now it's one kilobyte. So the program actually saved some data in this binary file. We can try to open this file, but it's not really a good idea because since this is a binary file, we are not able to read a lot.

Actually, we can read the symbol, but that's it. So. Binary files are not really made for us as a human to read it But the computer is really good at reading these files and it's really quickly So let's now go back to a meter editor and let's work on the slave part. So this first Master part is already finished like this if statement is filled with all the data or Information that we need like this is for the master and now we will add the block for the slave here So let me zoom in again And let's add the block for the slave. So what we want to do here is, first of all, we want to create an array.

So we will use the C array long class. This is possible because we included this file up here. And then we will create an array, which is called...

Array for example, so this is our array also make sure to use the sort function on this array Because we want to search in this array later on then after creating this array And this is just an array where we can put double sorry long values inside So we will store position tickets in this in this area. So next we want to get a file handle again So let's use file open then we will use the file name file name then we use the The flex and in this case we will use file Read because we want to read from the file then use this one Vertical line again separator and then we will use file binary again or bin and file common So we will access the same file next we check if file Oh, we just check a file is unequal invalid handle. Well, this took me some while and then we will check if we find a file or a handle like this, then we want to loop through this file. And here we'll use a while loop.

This is one of the rare occasions where while loop is necessary in MetaTrader programming. So as long as file is not ending, and we can use this exclamation mark at the beginning to negate this return value of the function, we'll use the file is ending on the file. a handle and as long as file is not ending, we want to do something.

So what do we want to do? First of all, we want to get all of the information for our position. So you can see, like you can view, have a view on this binary file. Like it's just a file where all the data is put side by side. So when we add more and more data, it just put...

side by side. So it's just like there's pretty much like one line in this binary file, if you want to say so. And if you put a value in this file, it's put at the first position.

If you put another value, it's put next to it. If you put another value, it's put next to the previous value, and so on and so on. And if we would put, for example, 100 positions or 100 properties of positions inside of this binary file, it's just getting longer and longer.

And this is why we can use this while loop and loop through this file as long as we are not at the end of the file. And here what we want to do next is we want to read from the file and the important part is that it has to be in the exact same order as we put it here. Because as I said it's just put next to each other. So if we want to start reading from the file we will of course start with a long value which is the position ticket.

So what we want to do is we want to create this position ticket unsigned long variable and then we say file read long because we know the first value in this file is for sure a long value. And then we just have to provide the file handle so the program knows what file we are reading from. Then now next we get the or we want to read the string. Whenever you work with strings in binary files you always have to store the length. first and then read the length first and then read the string.

So you know how many letters you want to read for the string. So what we do here, first of all, we'll get the length again, file read integer, this integer value, and then we want to get the string. So position symbol is equal to file read string.

And now you can see we have the file and the length. Then next we want to read, wait, what's next in the order the symbol is here so next is the position volume so read the next double value of course. Then we have enum position type we will get the position type next and this is of type enum position type so we will typecast it to this but in the file it is a integer so we will read the integer from the file and then I think we just have the open the stop loss and the take profit left so just go with position price open file read double of course not daytime double and then file then double position stop loss or just sl file read double file not daytime this is something you have to be careful with because the autocomplete often just puts daytime instead of double and then you are wondering why your code is not working and then last but not least we will read the take profit okay so now When we enter this file on the slave... Terminal we will just read all of this data from the file and now we have all of the relevant information for our first position That we were reading from the file what we want to do next is we want to loop all the trades on the on the On the slave terminal and then we want to check if we find this position already So let's get a position info object again. Let's select the position.

Select by index. This is just the same process. We will just select every single position in the slave or on the slave terminal.

And what we want to do here is we want to check if string get integer string get wait string to integer and we will use the position comment so we will get whatever is stored in the position comment for this position on the slave terminal and we will check if it is the same as the position ticket of the position that we just got from the from the master terminal from the file and if this is the same this will mean in the end that the position is already open on the slave terminal because you for every position that this EA opens on the slave terminal, we will just take the position ticket from the master terminal and store it as a comment for the position in the slave terminal. And this is a way of comparing the values here so we know that a position is already opened on the slave terminal. So what we want to do here is we want to say if array search first. We want to search inside of our array here for this specific position ticket. And if this is not available in the array, make sure to use search first.

And this only works if you sorted the array before, otherwise you will get problems. So if this is not in the array, then we will just put it inside of the array. And here we will use insert sort.

So we will just put the position ticket inside of this array. So, um... Also, when we found a position, this means that we now found a position on the slave terminal, which is also open on the master terminal.

But also, we will get the access to the stop loss and the take profit of the position on the master terminal. So we want to check if this is different than the stop loss and take profit on the slave terminal. So what we want to check is we want to check the position stop loss.

This is from the slave terminal, like the position on the slave terminal. And here we want to compare this. or check if this is different than the position stop loss that is coming from the master terminal.

Or if the position take profit, slave terminal, is different than the position TP master terminal. So if there's a difference, we just want to modify our position, so we would use the trade position modify function from the trade object variable, and we will apply it to the position ticket on the slave terminal. and we will use the position stop loss that is coming from the master terminal and the position TP that's coming from the master terminal. That's pretty much it. Also, if we found a position already, which is safe if we are inside of this if statement, we can break from this loop here.

This will stop this loop because we found the position. And after breaking from this loop, we'll then continue with the next trade coming from the master terminal. But before we do this we want to check if we have to open this position on the slave terminal because this is something that We didn't do yet. So after we process this loop here We will either have the position ticket of this position from the master terminal stored in the array array or not So after this loop which ends down here you can highlight the oh, no, it ends down here So after this for loop we want to check if the array, search first, if it contains the position ticket variable, so if this is smaller than zero, so if we do not have it in our array here yet, this means that the position is currently not open. So in this case, we want to open it.

So we check if the position type, wait. Why don't I get recommendations here? Daytime to double. Oh, there's another mistake.

I use Read double here, not date time to get the position volume. And then let's go on here. So if we do not find the position on the slave terminal, we want to open it. So we check if the position type is equal to position type by.

And yeah, make sure to not forget that this is the position type of the position coming from the file. And if this is not a by position, then it has to be a cell position. So if we have a buy position coming from the master terminal and we want to open this, yeah we just use trade buy and then we would say the volume is position volume, then we have the symbol it's position symbol, then we have the price, position price open or since we are using market func openings here, market positions, we will just add zero. And then we use the position stop loss coming from the master terminal and the position TP.

And then the comment is something we don't take from the master terminal. And this is really important because here we will use integer to string and return the position ticket to a string that is then stored as the comment for our trade on the slave term. Next we want to check if trade result red code is equal to trade red code done which means that the operation was sent successfully. Then we want to say array insert sort and then we want to sort the position ticket in our array here. We will do the same thing of course if it is a sell position that we have to open so we will go trade sell.

And then we say position volume, position symbol, like the rest is pretty much the same because all of this information is just coming from the, from the master. Integer to string, position ticket. So we're just copying everything.

And while I'm saying this, yeah, I just realized that since it is the same anyways, we can just use it like this. We can just move this outside of the if statement and then just put it here. And yeah, that's pretty much how it should also work.

Okay, so this will make sure that if you don't have open positions on the slave terminal, and we find a new open position coming from the master terminal, we will just open it. So now let me zoom out a little bit. Now this was all inside of this while loop here. So as long as there are still positions in the file that we can read, we will do this kind of stuff.

But this while loop has a ending point somewhere. And you can just move your cursor here at the beginning curly brackets and it should highlight the ending curly bracket. And I want you to go after the ending curly bracket and add some code here because after the ending curly bracket, we are still not really done. I mean, of course, we want to read everything from this file, but we still have to make sure when we read everything from the file, at this point, all of the positions coming from the file should be stored in the array. And now what we want to do next is we want to loop all the positions on the slave terminal and check if these positions are still in the array because if they are not, then we kind of want to close these positions, right?

So what we want to do, we want to loop through all the trades again. So same procedure as every time, nothing special here. Let's just use the C position info again. Let's try to select something.

Select by index at I. And if we find a position on the slave terminal, what we want to do is we want to check if we can find the comment. in our array here.

Search first and we would search for um string to int and we will use the position comment and yeah close all of these brackets and if we find the position um oh wait no we want to search if we do not find the position. So if we are searching for this in the array and we do not find it, it will return a value smaller than zero minus one. In this case we will just close the position.

Position close and we will close the position with a position dot ticket. ticket and that's pretty much it I think. So we can compile this.

There should be no errors and this should be a fully functioning trade copier. There are still one or two things that I want to adjust and improve for this project. So first thing that I realized is that in this slave or in the slave mode here we do not really close the file. So whenever I open a file and find an invalid handle, we should at the end of this bracket here, we should say file close.

Or actually we can already do it here because the rest of these operations like this loop where we just loop through the trades on the slave account, we don't really need the file anymore. So we can close it here already. So this is something we should do. And then, oh yeah, of course we close the file.

Also. What I want to change is that if we do not find a position on the master account, we don't want to delete the file. We'll just do nothing, which means that if we open a file on the master account and we only write here and we do not find a position, it will still create a file or manage a file, but this file will then be empty.

So this is another thing that I want to do. And also here, the event timer. I think, I mean, you can use whatever you want, but I think I would just set it to one second because the less times you execute the timer event, it will take less resources from your PC. And I think it's not really necessary for most strategies to do it on a millisecond basis.

But if you apply these changes, we can then start our first test on the connection between master and slave terminal. So we would go on our master terminal where... wrote this code or just where you wrote this code you can click open the containing folder where you can then find the trade copier youtube program and i will just copy it from here and then i will go to my slave terminal and here i will go to file open data folder then we go to mql5 then we will go to experts and here you just want to paste your file you So I will just paste it here.

Okay, pasted it here. I had to replace it. For you, you probably don't have to replace it if it's the first time that you put it here. And then I can close this, auto close this. So now I have the trade copy up on both of my terminals.

On the right side, you see the master terminal. On the left side, the slave terminal where I copy the trades to. And...

On the right side, you can see the trade copier is already active in the chart. And here it is running in the master mode, of course. On the left side, we have the trade copier in the terminal now. You can just refresh your expert advisors and you should find it in the slave terminal now too.

So here I can also drag and drop it on any chart. Doesn't really matter. It's just important that it's running on slave mode here. So I can click on OK. And now the program is running on both of my terminals.

Of course, I want to do the trading operations on the master terminal. So, for example, if I just buy one lot USD Japanese Yen on the master terminal, it works just fine and the slave terminal reacts. Also, you can see the comment for this trade is the trade ID of the trade on the master terminal.

I can open another trade with a different lot size. I can open a third trade, which could be a sell trade. I can also go ahead and change the...

symbol. I can also go with GBPUS dollar and you can see the slave is just doing what the master is Yeah, like like saying or however you want to tell it. I want to name it so You can see like everything is Working kind of smoothly Of course I can also close positions on the master terminal and it will open the position close the position on the On the slave terminal it just takes like a second or so for the slave to react But this is a really easy and simple example for a slave and master trade copier. And we can now also go ahead and say, for example, for GBPUS dollar for the sell position, I want to have a take profit. So on the master account, I change the take profit or I add a take profit.

And the slave account will react and also use this take profit. If I change the take profit, the slave should also react. And it does. And I can also, of course, put a stop loss. And this will also work if I open another buy position, USD, Japanese Yen maybe.

And if I now go ahead and add ATP here. and a stop loss it will also be transferred to the slave and yeah that's pretty much how you can do it of course this program is not perfect that's not what i'm saying because for example if i would open other positions um in the slave account like for example if i open a position in the slave account without using the master and this position will be closed by the program because it's not in the array list because it didn't came from the master. Also, if I try to close positions on the slave account, it will just open it again because it's still active on the master. So you can see, if you want to have a slave or a trade copier that copies the trades to the slave account, but is still able to trade independently from the master, you will have to make modifications. Also, of course, if you want to work with orders and stuff and not only market positions, you will also have to modify the program and make adjustments.

But this is like the really easy program that I used to explain you or introduce you to the concept of trade copying using the common shared folder for files in the Metatrader. So let me talk you through the code one last time. And this is to just finish off the video. So here we have the whole source code for the trade copier.

We define a name first for our file that we use to share the trades. Then we include two files, the trade.mkh file and the array-long.mkh file. We use these files, first of all, for the C trade class and then for the C array-long class that we use to store the position tickets in.

Then we have a mode. We need the mode for the master and the slave. You could add more input variables.

For example, you could have a lot factor. If you say, for example, on the slave, you only want to trade 0.5% of the lots or the double amount of lots. You can do all of this kind of stuff if you just modify the program. But this is just a basic program. Then in the onInit function, we set the timer.

Yeah, I mean... I would not really recommend to set a millisecond timer of like 100 milliseconds because it will just eat up a lot of your resources on your PC and in most cases is not necessary. In the onD init don't forget to kill the timer and then in the onTimer function this is where the main code is.

Like for the master mode, we just make sure that we open the file it's important that we open it in write mode and here we then write to the common file in the shared folder. So we first of all check if we were able to open this file, if it's free for processing. And then we check if we have an open position.

So we can do it like this, if positions total is equal to zero. Or otherwise we do this. We can also say we just want to do anything if positions total is greater than zero.

And then we can delete this part. And then we say if we have positions in this account, we want to loop through all the positions. We use the C position info class to get access to the position properties because we can use this position object to just select positions. And then we write all of the position properties that we might need later on to this binary file.

For this reason, we can use the file write long, integer, string, double, whatever function. whatever value we want to store. And in the end, do not forget to close the file if you have finished your processing. Then in the slave mode, we want to first of all create an array for the tickets that we took from the master account.

And so we declare this object variable of type C array long. We sort it. This is important because otherwise we cannot search on this array.

And then we open the file again. This time in read mode, still from the comment folder. Then if we are able to open this file, this is only possible if the master is not writing right now, then we can say while file is not ending, then we want to loop through this file and we want to just read the properties for one position.

And then if we have all these properties stored in variables, we can then loop through all the positions on the slave account. We select every position on the slave account and then we check. if this position is, or if the comment of this position is the same as the position ticket of the position that's coming from the master account. And if this is true, then we know that we found a position from the master account. We put this position in our array so we don't open another position.

And then we just check if TP and SL is still valid and correct. And if not, we update TP and SL. And yeah, if we find a position, we can break from this loop and process the next steps. The next steps are, for example, checking if this array contains the position ticket. Because if we did not edit here, it means that this position is not in the account right now.

And then we want to open the position. So we check the position type and then open a buy or sell position. And then we check. if this position opening operation was successfully sent.

If yes, we put the position ticket into our array. After doing this, don't forget to close the file if you are done with the file operations. Then the last part is the simple for loop here, just a normal standard for loop where we just loop through all the positions again on the slave account.

And here we're just checking if these positions are still part of... the array and if not we just close it. So this is a super simple example for a trade copier you can see here this was like really smooth and easy just 99 lines of code at least less than 100 and yeah you can use this as an idea as a basic program and make any adjustments you like. Of course you could also have all of this kind of stuff stored or running over a server for example, there are easy functions in MQL5, so you can put this file on a FTP server for example, so you could create a trade copier that works on different Metatrader terminals, even if they are not on the same PC.

All of this kind of stuff is possible. This was just a small introduction. And again, if you like content like this, Make sure to subscribe. Do not forget this because I will upload more programming tutorials and talk a lot about automated trading and how to be successful with automated trading. Also, if you want to learn more about MQL5, like in a detailed and structured course, check out the link in the video description.

Yeah, but that's it for this video. Thanks for watching. Have a great time.

Good trades. Bye.