EXPERT ADVISOR PROGRAMMING FOR METATRADER 4 PDF
Expert Advisor Programming Creating Automated Trading Systems in MQL for wildlifeprotection.info Pages · · MB · 2, Programming Embedded Systems Second Edition Page 4 experience. The beginner is interested. Expert Advisor Programming - Creating Automated Trading System in MQL for Metatrader 4 - Free ebook download as PDF File .pdf), Text File .txt) or read. READ PDF Expert Advisor Programming for MetaTrader 4. Creating automated trading systems in the MQL4 language By Andrew R. Young.
|Language:||English, Spanish, Japanese|
|ePub File Size:||17.32 MB|
|PDF File Size:||16.86 MB|
|Distribution:||Free* [*Regsitration Required]|
The Initializing Wisard of the Expert Advisor will ask you for entering All variables to be used in the expert program must be defined according to the syntax of. To read Expert Advisor Programming for Metatrader 4: Creating Automated the Mql4 Language PDF, remember to click the button listed below and save the. The use of its embedded programming language, MQL4, lifts traders to a new An Expert Advisor (EA) can work on a 24/7 basis without any intervention - track Development of applications for MetaTrader 4 Client Terminal requires the.
We specify an external variable by adding extern in front of the variable. This specifies that the variable will appear in the Expert Properties dialog, and will be viewable and adjustable by the user.
Be sure that the identifier for your external variable is descriptive of what it actually does. You have 31 characters to describe your variable, so make the most of it. The default value for your variable will also be the default for that parameter, so choose a logical default value.
Global Variables We declare any global variables at the top of our source code file, generally after the external variables. The location does not matter, as long as both the global and external variables are placed outside of and before any functions. A global variable is one that is available to any function in the program. As long as the program is running, the global variable and it's value stays in memory, and can be referenced and changed by any function in the program.
Technically, external variables are global as well, but the global variables we're discussing in this section are internal, which means they are not viewable or changeable by the user. Special Functions MQL has 3 built-in functions to control program execution: The init function is comprised of code that is run once, when the EA is first started. The init function is optional, and can be left out if you're not using it. The deinit function consists of code that is run once, when the EA is stopped.
This function is also optional, and it's unlikely you will need to use it in an expert advisor. The start function contains the main program code, and is required in your EA. Every time the start function is run, your trading conditions are checked, and orders are placed or closed depending on how those conditions are evaluated.
The start function is run on every tick. A tick is a price movement, or change in the Bid or Ask price for a currency pair. During active markets, there may be several ticks per second. During slow markets, minutes can pass by without a tick. Other Functions Any other functions that your EA may use should be declared after the start function.
These functions will be called from the start , init or deinit functions, or from other functions that are called from the main program. We'll cover custom functions later in the book. But you might not be aware of their role in order placement. It is very important to use the correct price when opening or closing orders. The Bid price is what you see on the MetaTrader charts. It is usually what we think of when we think of the "current price.
The difference between the Bid and the Ask is the the spread, which is the broker's commission for placing the order. The Ask price is where we open buy orders, and close sell orders. The Bid price is where we open sell orders, and close buy orders. You'll need to indicate the correct price when opening a market order, or when closing an order at market, so remember the difference between the two.
Order Types There are three types of orders that can be placed in MetaTrader: Market orders are the most common. A market order opens a position immediately at the prevailing Bid or Ask price.
When placing a market order in MQL, we must specify an opening price generally the latest Bid or Ask quote. If the specified opening price is outdated, due to a fast moving market or a delay in program execution, the terminal will attempt to place the order at the current market price, provided it is within the maximum slippage.
If you place a market order using the New Order dialog in MetaTrader, you'll see a setting at the bottom labeled "Enable maximum deviation from quoted price. This is the maximum slippage. If the current price falls outside of our specified opening price, plus or minus the slippage, a requote error will occur and the order will not be placed.
You may have noticed this when attempting to place a market order during a fast moving market. A stop order is a type of pending order. Pending orders are a request to open a market order at a certain price. A buy stop order is placed above the current price, while a sell stop order is placed below the current price.
The expectation is that the price will eventually rise or fall to that level and continue in that direction, resulting in a profit.
A limit order is the opposite of a stop order. A buy limit order is placed below the current price, while a sell limit order is placed above the current price. The expectation is that the price will rise or fall to that level, triggering the order, and then reversing.
Limit orders are not used very often in automated trading. An expiration time can be set for pending orders. If the order is not filled by the expiration time, the order is automatically deleted. Not all brokers support trade expiration. We must determine the following before placing the order: The type of order to be placed buy or sell; stop, market or limit.
The currency pair to trade generally the chart that the EA is attached to. The lot size. This can either be a fixed lot size, or one that is calculated using a money management routine. The order opening price. For market orders, this will be the current Bid or Ask price. For pending orders, the opening price must be a minimum distance from the current price, and should be above or below the current price as required by the order type.
The stop loss price. The stop loss can be a predetermined price, an indicator value, a fixed number of pips from the order opening price, or it can be dynamically calculated using a risk management routine. The stop loss can be placed with the order, or it can be added to the order afterward. The take profit price. This is generally a fixed number of pips from the order opening price, although it can be calculated using other methods as well.
The take profit can be placed with the order, or it can be added to the order afterward.
Order identifiers such as an order comment, or a "magic number" that identifies an order as being placed by a specific expert advisor. An optional expiration price for pending orders, if the broker supports it. The syntax is as follows: The Symbol function is used for the current chart's currency pair. Type The type of order to place: This is an integer value, represented by the following constants: Lots The number of lots to trade.
You can specify mini lots 0. Price The price at which to open the order. For a buy market order, this will be the Ask. For a sell market order, this will be the Bid. For pending orders, this will be any valid price that is above or below the current price. Slippage The maximum slippage in points. Use a sufficiently large setting when auto trading. Brokers that do not use slippage will ignore this parameter.
StopLoss The stop loss price. For a buy order, the stop loss price is below the order opening price, and for a sell order, above. If set to 0, no stop loss will be used. TakeProfit The take profit price. For a buy order, the take profit is above the order opening price, and for a sell order, below. If set to 0, no take profit will be used. Comment An optional string that will serve as an order comment. Comments are shown under the Trade tab in the Terminal window. Order comments can also be used as an order identifier.
MagicNumber An optional integer value that will identify the order as being placed by a specific expert advisor. It is highly recommended that you use this. Expiration An optional expiration time for pending orders. Not all brokers accept trade expiration times for these brokers, an error will result if an expiration time is specified.
Arrow An optional color for the arrow that will be drawn on the chart, indicating the opening price and time. If no color is specified, the arrow will not be drawn. The OrderSend function returns the ticket number of the order that was just placed. If no order was placed, due to an error condition, the return value will be We can save the order ticket to a global or static variable for later use. If the order was not placed due to an error condition, we can analyze the error and take appropriate action based on the returned error code.
Placing A Market Order Here's an example of a buy market order. The Symbol function returns the current chart symbol. Ask is a predefined variable in MQL that stores the most recent Ask quote. Remember that buy orders open at the Ask price! The Slippage is set using an external variable.
The slippage parameter is an integer, indicating the number of points to allow for price slippage. If your broker uses 4 digit quotes 2 for Yen pairs , 1 point would be equal to 1 pip.
PDF Expert Advisor Programming: Creating Automated Trading Systems in MQL for MetaTrader 4
If your broker offers 3 and 5 digit quotes however, then 1 point would be 0. In this case, you'd need to add an additional zero to the end of your Slippage setting.
We've added the generic comment "Buy Order" to this order. Since there is no expiration for market orders, the Expiration parameter is 0. Finally, we specify the color constant Green to draw a green arrow on the chart.
Here is an example of a sell market order, using the same parameters as above:. We use Bid as the order opening price, to reflect the fact that sell orders open at the Bid price.
Placing a Pending Stop Order The difference between pending orders and market orders is that the order opening price will be something other than the current market price. The stop loss and take profit values must be calculated relative to the pending order opening price. In these examples, we will use the variable PendingPrice for our pending order price.
It can be calculated based on our trading algorithm, or it can be set as an external parameter. For a buy stop order, PendingPrice must be greater than the current Ask price. Here's an example of a buy stop order placement: No expiration time has been indicated for this order.
For a sell stop order, PendingPrice must be less than the current Bid price. In this example, we'll add an order expiration time, using the variable Expiration. The expiration time must be greater than the current server time. Here's an example of a sell stop order placement: Placing a Pending Limit Order Limit orders are similar to stop orders, except that the pending order price is reversed, relative to the current price and the order type. For buy limit orders, the pending order price must be less than the current Bid price.
Here's an example of a buy limit order:. Otherwise, our parameters are identical to those for stop orders. For a sell limit order, the pending order price must be greater than the current Ask price. Here's an example of a sell limit order: The most common method is to specify the number of pips away from the order opening price to place your stop.
For example, if we have a stop loss setting of 50 pips, that means that the stop loss price will be 50 pips away from our order opening price. We can also use an indicator value, an external parameter or some other type of price calculation. All we will need to do then is verify that the stop loss or take profit price is valid. Calculating in Pips For this, the most common method of calculating stops, we will use an external variable in which the user specifies the number of pips for the stop loss and take profit.
We then calculate the stops relative to the order opening price. For buy market orders, the opening price will be the Ask, and for sell market orders, the opening price will be the Bid.
For pending stop and limit orders, we assign a a valid opening price that is something other than the current market price. We will assign the appropriate price to the variable OpenPrice. Here are the external variables we'll use for our stop loss and take profit settings: You've likely seen settings similar to these in the EAs you've used. To calculate our stop loss, we need to add or subtract 50 pips from our order opening price.
First, we need to convert the integer value of 50 to the fractional value we'll use to add or subtract from the opening price. For Yen pairs, 50 pips is equal to 0. For all other pairs, it's 0. To convert an integer to the appropriate fractional value, we need to multiply our external StopLoss variable by the Point.
Point Point is a predefined variable in MQL that returns the smallest price unit of a currency, depending on. For a 4 decimal place currency pair, the point is 0. For a Yen pair, it's 0. Let's calculate the stop loss for a buy market order. We'll assign the current Ask price to OpenPrice, and use that as our order opening price. We'll check to see if our StopLoss setting is greater than zero. If so, we'll multiply the StopLoss by the Point. Then we'll subtract that from OpenPrice.
The result will be stored in the variable BuyStopLoss. If StopLoss is not greater than zero, then BuyStopLoss is initialized with a value of 0, and no stop loss will be placed with the order. Assuming that Point is equal to 0. Recently, many brokers have been moving towards fractional pip price quotes, with 3 decimal places for Yen pairs and 5 decimal places for all other pairs.
If our broker uses fractional pip quotes, then in our example above, Point would be equal to 0. If we use a point value of 0. This poses a problem. To get the correct value, we would have to add an extra zero to our stop loss setting i. Instead of requiring the user to add an additional zero to their stop loss and take profit settings every time they trade on a fraction pip broker, we'll create a function that will always return 0.
We'll call this function PipPoint, because it will always return the point value that is equal to one pip. The string argument Currency is the symbol of the currency pair that we want to retrieve the point for. The if-else statement assigns the appropriate point value to the CalcPoint variable, depending on the number of digits.
Essentials of Ecology
Here's an example of the usage of this function. You will be using the current chart pair the vast majority of the time, so we will pass the Symbol function as the argument.
This will return the point for the current chart. Here's a set of examples using specific pairs: We will be using this function to find the single pip point value for the remainder of this book.
As we've demonstrated, the Point variable won't work correctly on fractional pip brokers when calculating the value of a single pip. You can never assume that the EA will only be used on a 2 and 4 digit broker, so it is necessary to automatically determine the point value of a single pip using PipPoint. Slippage and Point Let's digress for a minute and create a function to resize the slippage parameter properly.
As mentioned earlier in this chapter, on a broker with fractional pip quotes, the slippage parameter for the OrderSend function will need to be increased by a factor of 10 to get the correct slippage value.
We pass the currency symbol and the external slippage parameter as arguments. If the currency uses 2 or 4 digit quotes, we use the unchanged SlippagePips argument as our slippage setting. If the currency uses 3 or 5 digit quotes, we multiply SlippagePips by Here is how we use this function in OrderSend: The slippage in this example will be 5 pips, and the slippage parameter will be automatically adjusted based on the number of digits in the currency quote.
Slippage and Point as Global Variables The disadvantage of using a function to return the point or slippage value is the extra typing required for the function arguments.
We'll create global variables that will hold the appropriate point and slippage values for our currency pair, and we'll use those anytime we need to reference those values. Since these values will never change during program execution, we'll calculate these values in the init function. We'll assume that the external integer variable Slippage is already present: From now on, we'll use UsePoint and UseSlippage to refer to these values. The above code assumes that your EA is placing orders on one currency only.
MarketInfo We used the MarketInfo function above to retrieve the Point value and the number of digits in the currency quote. The MarketInfo function has many uses, and you will be using it to retrieve necessary price information in your programs.
Here is the syntax for the MarketInfo function: The Symbol argument is simply the currency symbol that you want to retrieving the information for. For the current chart symbol, the Symbol function can be used. RequestType is an integer constant, representing the information that you are requesting from the. Here's a list of the most useful MarketInfo constants. For example, 0. Will be 2 or 3 for Yen pairs, and 4.
For example, 3 pips or 30 for a fractional pip broker. These request identifiers are generally used when checking price information on another currency, or anywhere where the symbol may be anything other than the current chart symbol: Calculating the Stop Loss Now that we've determined the proper point value, it's time to calculate our stop loss.
For buy orders, the stop loss will be below the order opening price, and for sell orders, the stop loss will be above the order opening price.
Here's our buy order stop loss calculation from earlier, with the UsePoint variable added. Note that we've assigned the Ask price to the OpenPrice variable: And here's the calculation for a sell order. Note that we've assigned the Bid price to OpenPrice, and that we are simply adding instead of subtracting: For pending orders, the stop loss will be calculated relative to the pending order price.
In this case, use the variable OpenPrice to store the pending order price instead of the current market price. The logic will be identical to the examples above. Calculating the Take Profit Calculating the take profit price is similar to calculating the stop loss, except we'll be reversing addition and subtraction. For a buy order, the take profit price will be above the order opening price, and for a sell order, the take profit price will be below the order opening price.
We'll assume that the appropriate price has been assigned to OpenPrice: Alternate Stop Loss Methods There are other ways of determining stop loss and take profit prices. For example, a recent high or low, or an indicator value could be used to determine a stop loss.
Let's demonstrate how we could calculate these. Let's say we're using a trading system that places the stop loss 2 pips below the low of the current bar. We use the predefined price array Low to retrieve the low of a bar. Low is the low of the current bar, Low is the low of the previous bar, and so on. Once we've determined the low of the current bar, we multiply 2 by UsePoint to get a decimal value, and subtract that from our low: So if the low of the bar is 1.
But maybe you want to place your stop loss at the lowest low of the last x number of bars. There's a function built into MetaTrader just for that. We can use high, low, open or close values. Here's an example of how we would use iLowest to find the lowest low of the last 10 bars: The first parameter of iLowest is the currency symbol NULL means that we're using the current symbol. The second parameter is the chart period 0 refers to the current chart frame.
In other words, we're. CountBars is the number of bars we want to search, in this case Finally, the last parameter is our. To start at a previous bar, count backward from the current bar the previous bar is 1, the bar before that is 2, etc. The output of the iLowest function is an integer indicating the backward shift of the bar with the lowest value in the price series.
In the example above, if iLowest returns a 6, that means that the lowest low is 6 bars back. We store that value in the variable LowestShift. To find the actual price, we simply retrieve the price value of Low[LowestShift], or in other words, Low.
Here's an example using an indicator. Let's say we have a moving average, and we want to use the moving average line as our stop loss. We'll use the variable MA to represent the moving average value for the current bar. All you need to do is assign the current moving average value to the stop loss: If the moving average line is currently at 1.
These are simply the most common methods of determining a stop loss or take profit price. Other methods can be developed using your knowledge of technical analysis or your imagination. Retrieving Order Information Once we've successfully placed an order, we'll need to retrieve some information about the order if we want to modify or close it.
We do this using the OrderSelect function. To use OrderSelect , we can either use the ticket number of the order, or we can loop through the pool of open orders and select each of them in order. Once we've selected an order using OrderSelect , we can use a variety of order information functions to return information about the order, including the current stop loss, take profit, order opening price, closing price and more.
OrderSelect Here is the syntax for the OrderSelect function: Index This is either the ticket number of the order that we want to select, or the position in the order pool. The Select parameter will indicate which of these we are using. Select A constant indicating whether the Index parameter is a ticket number or an order pool position: Pool An optional constant indicating the order pool: If the OrderSelect function locates the order successfully, the return value will be true, otherwise, the return value will be false.
Here's an example of the OrderSelect function using an order ticket number. The Ticket variable should contain a valid order ticket: After the OrderSelect function has been called, we can use any of the order information functions to retrieve information about that order.
Here's a list of the most commonly used order information functions: OrderSymbol The symbol of the instrument that the selected order was placed on. OrderType - The order type of the selected order: OrderOpenPrice The opening price of the selected order.
OrderLots The lot size of the selected order. OrderStopLoss The stop loss price of the selected order. OrderTakeProfit The take profit price of the selected order. OrderTicket The ticket number of the selected order. Generally used when cycling. OrderMagicNumber The magic number of the selected order.
When cycling through. OrderComment The comment that was placed with the order. This can be used as a. OrderClosePrice The closing price of the selected order. The order must already be. OrderOpenTime The opening time of the selected order. OrderCloseTime The closing time of the selected order.
We'll need to use OrderSelect before closing or modifying an order. Let's illustrate how we use OrderSelect to close an order. Closing Orders When we close a market order, we are exiting the trade at the current market price.
Expert Advisor Programming – The Old Way to Create Forex Robots
For buy orders, we close at the Bid price, and for sell orders, we close at the Ask. For pending orders, we simply delete the order from the trade pool. OrderClose We close market orders using the OrderClose function.
Here is the syntax: Ticket The ticket number of the market order to close. Lots The number of lots to close. Most brokers allow partial closes. Price The preferred price at which to close the trade. For buy orders, this will be the current Bid price, and for sell orders, the current Ask price. Slippage The allowed slippage from the closing price, in pips.
Color A color constant for the closing arrow. If no color is indicated, no arrow will be drawn. You can close part of a trade by specifying a partial lot size. For example, if you have a trade open with a lot size of 2.
Note that not all brokers support partial closes. It is recommended that if you need to close a position in several parts, you should place multiple orders instead of doing partial closes. Using the example above, you would place two orders of 1. In this book, we will always be closing out the full order. The following example closes a buy market order: The CloseTicket variable is the ticket number of the order we wish to close.
The OrderSelect function selects the order, and allows us to retrieve the order information. We use OrderCloseTime to check the order closing time to see if the order has already been closed.
If OrderCloseTime returns 0, then we know the order has not been closed yet. We also need to check the order type, since the order type determines the closing price for the order. The OrderType function returns an integer indicating the order type.
Next, we retrieve the order lot size using OrderLots , and store that value in CloseLots. We assign the current Bid price to ClosePrice.
Then we call the OrderClose function to close out our order. We specify our Slippage setting with UseSlippage, and indicate a Red arrow to be printed on the chart. A boolean return value is stored in the variable Closed. If the order has been closed successfully, the value of Closed will be true, otherwise false. OrderDelete There is a separate function for closing pending orders.
OrderDelete has two arguments, the ticket number and the arrow color. No closing price, lot size or slippage is required. Here is the code to close a pending buy stop order:. As we did with the OrderClose function above, we need to check the order type to be sure it is a pending order. To close other types of pending orders, simply change the order type. If the order has been filled, then it is now a market order, and must be closed using OrderClose instead.
A Simple Expert Advisor Let's see how the code we've discussed so far would work in an expert advisor. This is a simple moving average cross system. A buy order is opened when the 10 period moving average is greater than the 20 period moving average. When the 10 period moving average is less than the 20 period moving average, a sell order is opened. This EA will alternate between opening buy and sell orders.
Orders will be closed when an order is opened in the opposite direction, or by stop loss or take profit. We will use the global variables BuyTicket and SellTicket to store the last order ticket. When a new order is opened, the last order ticket is cleared. This prevents multiple consecutive orders from opening. We start with our property copyright preprocessor directive that identifies the code as belonging to us. The external variables are next, and should be self-explanatory.
We declare BuyTicket and SellTicket as global variables this way the order ticket is stored between program executions. We could also have declared them as static variables within the start function.
We add UsePoint and UseSlippage as global variables we'll calculate the value of these next. Our init function is run first. We call the PipPoint and GetSlippage functions declared at the We'll use these when referencing point or slippage values in the rest of our expert advisor. Next is the start function, our main program execution.
We've left out deinit , since we have no use for it here. Everything else is set to default a no shift, simple moving average calculated on the close price. We use the if operator to define our order opening conditions.
If the current 10 period moving average the FastMA is greater than the 20 period moving average the SlowMA , and if BuyTicket is equal to 0, we will open a buy order.
Before we open the buy order, we will close the current sell order, if it exists. We use OrderSelect to retrieve the current SellTicket. If the order close time is 0 indicating that the order has not yet been closed , and the SellTicket is greater than 0 indicating that the SellTicket is likely valid , we will go ahead and close the sell order.
We retrieve the lot size of the sell order and the current Ask price, which will be the closing price for the sell order. Then, we close the sell order using OrderClose.
Next, we assign the current Ask price to the OpenPrice variable this will be the opening price of our buy order. We calculate our stop loss and take profit relative to the opening price, checking first to make sure that we have specified a StopLoss or TakeProfit value in the settings.
Then, we place the order using the OrderSend function, and store the order ticket in BuyTicket. Lastly, we clear the value of SellTicket, allowing the placement of another sell order when the order condition becomes valid. The sell order block follows the same logic as the buy order block. The stop loss and take profit calculations are reversed. The start function ends with a return operator.
Our custom PipPoint and GetSlippage functions are defined at the end after the start function. We will include these functions in every example in this book. We'll use stop orders in this example. When the fast moving average is greater than the slow moving average, we will place a buy stop order 10 pips. When the opposite is true, we'll place a sell stop order 10 pips below the current low.
Let's declare an external variable to adjust this setting, called PendingPips. We're adding the OrderDelete function to our buy and sell order block to close any unfilled pending orders. We need to check the order type of the order indicated by SellTicket to ensure that we are using the correct function to close the order.
We use OrderType to check whether the selected sell order is a market order or a stop order. If it's a market order, we close it using OrderClose. If it's a pending order, we close it using OrderDelete.
Here's our pending order price calculation. We simply convert PendingPips to a fractional value with UsePoint, and add it to the current Close price. We'll store this value in the PendingPrice variable. Next, we calculate the stop loss and take profit relative to our pending order price. Finally, we place our pending order using OrderSend , storing the trade result in the variable BuyTicket: The code below shows the changes for the sell stop order block: Chapter 3 Advanced Order Placement ECN Compatibility As the order placement examples in the last chapter show, the default method of placing a stop loss and take profit with a market order is to place them using the OrderSend function.
In this case, we'll need to place the stop loss and take profit after the order has been placed, using the OrderModify function. This only applies to market orders for pending orders, you can still place the stop loss and take profit with the OrderSend function. Order Modification After placing an order, you can modify the take profit, stop loss, pending order price or expiration time using the OrderModify function. To use OrderModify , we'll need the ticket number of the order that we wish to modify.
Here is the syntax for the OrderModify function: Ticket The ticket number of the order to modify.
Price The new pending order price. StopLoss The new stop loss price. TakeProfit The new take profit price. Expiration The new expiration time for pending orders. Arrow A optional color for the arrow to indicate a modified order.
If not indicated, no arrow will be displayed. If the order modification is successful, OrderModify will return a boolean value of true. If the order modification failed, the return value will be false.
When modifying orders, we must be sure that the values we are passing to the function are valid. For example, the order must still be open we cannot modify a closed order. When modifying pending orders with the Price parameter, the order must not have already been filled i.
The modified order price also must not be too close to the current Bid or Ask price. We should also check to make sure that the stop loss and take profit are valid. We can do this using the price verification routines that we will cover later in this chapter.
If we are not modifying a particular parameter, we must pass the original value to the OrderModify function. For example, if we are modifying only the stop loss for a pending order, then we must retrieve the current order price and take profit using OrderSelect , and pass those values to the OrderModify function. If you attempt to modify an order without specifying any changed values, you'll get an error 1: You should verify why your code is passing unchanged values to the function, but otherwise this error is harmless and can be safely ignored.
We do this by examining the return value of the OrderSend function, which is the ticket number of the order that was just placed. If the order was not placed due to an error condition, the ticket number will be equal to Next, we use the OrderSelect function to retrieve the information for the order that was just placed. Finally, we'll use OrderModify to add the stop loss and take profit to the order. Here's an example where we set the stop loss and take profit for a buy order using the OrderModify function.
We've moved the stop loss and take profit calculation after the OrderSend function, so that it is calculated before we modify the order: The OrderSend function is identical to our earlier example, except that we use a value of 0 for the stop loss and take profit parameters. A value of zero means that there is no stop loss or take profit being placed with the order. The BuyTicket variable stores the ticket number of the order.
We use an if statement to check that the BuyTicket number is valid i. If so, we call the OrderSelect function using our BuyTicket number. We retrieve the opening price for the order using OrderOpenPrice , and assign that to the OpenPrice variable. Next, we calculate the stop loss and take profit, relative to the opening price of the order we just placed. We check first to see if the StopLoss and TakeProfit external variables are greater than zero.
Finally, we call the OrderModify function to add our stop loss and take profit to the order. If we attempt to modify the order with unchanged values, we'll get an error code 1 from the OrderModify function. The first parameter for OrderModify is our BuyTicket number. We could also use OrderTicket as well. The second parameter is the new order price. Since we are not modifying the order price, we use the OrderOpenPrice function, to indicate that the order price is unchanged.
Remember that we can only modify order prices for pending orders. If we are modifying a market order, we can pass any value for the Price parameter, since you cannot change the order price of a market order. But we cannot assume that we will always be modifying market orders, so we will always use OrderOpenPrice. If you plan on using order expiration times for your pending orders, you can use OrderExpiration as the unchanged Expiration parameter.
Otherwise, just use 0. Although this method adds a few extra steps, we recommended that you use this method of placing stop losses and take profits for market orders in your expert advisors to ensure that they are compatible with all brokers. This method also has the advantage of allowing us to place accurate stop loss and take profit prices without the effects of slippage.
Modifying a Pending Order Price OrderModify can also be used to modify the order price of a pending order. If the pending order. We'll use the variable NewPendingPrice to represent our changed order price. We'll assume the price has already been calculated and is valid. Here's how we modify a pending order price: As always, we retrieve the order information using OrderSelect.
This way we can pass the unchanged stop loss and take profit prices to the OrderModify function.
Before modifying the order, we'll check to make sure that our new pending order price is not the same as the current pending order price.
We're not using an expiration time for this order, so we use 0 for the expiration parameter. Verifying Stops and Pending Order Prices Stop loss, take profit and pending order prices must be a minimum distance away from the Bid and Ask prices.
If a stop or pending order price is too close to the current price, an error will result, and the order will not be placed. This is one of the most common trading errors, and it can easily be prevented if the trader is careful to set their stops and pending orders a sufficient distance from the price. But during periods of rapid price movement, valid stop loss prices can be made invalid by widening spreads.
Different brokers have varying stop levels, so a stop loss that is valid on one broker may be too close for another. Some trading systems will set stops and pending order prices based on indicator values, highs or lows, or some other method of calculation where a minimum distance is not guaranteed. We verify this by checking the currency's stop level. Stop Levels The stop level is the number of pips away from the current Bid or Ask price that all stops and pending orders must be placed.
For most brokers, the stop level is approximately pips. ECN brokers generally have very tight stop levels, while other brokers such as Alpari have wider stop levels at least 8 pips. Figure 3. Think of the price as not being just a single value such as the Bid , but rather a thick line the width of the spread. On either side of that price line are boundaries, indicated by the stop levels. All stop loss, take profit and pending orders must be placed outside of these boundaries. The stop level is expressed as a whole number, and will need to be converted to a fractional value using Point.
For a 5 digit currency with a stop level of 3 pips, MarketInfo will return 30, due to the extra decimal place. Here's the code for retrieving the stop level and converting it to a decimal value: Note that we use the predefined Point variable, instead of the PipPoint function we created earlier.
This is because we need to multiply the stop level by the actual point value. For a 4 digit currency, the Point will be 0. If the stop level is 3 pips as demonstrated above, then the fractional value will be 0. Now that we've figured out how to find the stop level, we need to calculate the minimum and maximum values for our stop loss, take profit and pending order prices.
We do this by adding or subtracting the stop level from our current Bid and Ask prices.
This code will calculate the minimum allowed price for a buy take profit, sell stop loss, buy stop order, or sell limit order. We'll use the StopLevel value we calculated above. If our Ask price is 1. If we are placing a buy take profit with this order, then it must be above this price. We'll call this the UpperStopLevel, since it is above the price. This code will calculate the maximum allowed price for a sell take profit, buy stop loss, sell stop order or sell limit order.
Note that we are simply using the Bid instead of the Ask, and subtracting instead of adding. We'll call this the LowerStopLevel, since it is below the price.
Before placing an order, use the UpperStopLevel and LowerStopLevel values above to verify your stop loss, take profit and pending order prices. Keep in mind that prices can change rapidly, and you'll want your actual stops, profits and pending orders to be well outside these levels.
Verifying Stop Loss and Take Profit Prices The minimum take profit in pips will be equal to the order opening price, plus or minus the stop level. If the stop level is 3 pips, and the order opening price is 1. The minimum stop loss in pips for a market order, however, will include the current spread, so the minimum stop loss will be larger than the minimum take profit.
For example, if the stop level is 3 pips, the spread is 2 pips, and the order opening price is 1. This doesn't apply for pending orders, so when verifying a stop loss for a pending order, it's not necessary to figure in the spread.
So if you're placing a pending order at 1. Here's an example where we check the stop loss and take profit for a buy order to make sure the prices are valid. If the stop loss or take profit price is not valid, we will automatically adjust it so that it is several pips outside of the stop level. The variable MinStop adds or subtracts 5 pips from the stop level, to ensure that our validated prices do not become invalid due to slippage.
The second line compares our stop loss to our LowerStopLevel. If the stop loss is greater than our lower stop level, we know that the stop loss is invalid. In that case, we adjust the stop loss to be just a few pips below our stop level. The third line does the same for our take profit. To check the stop loss and take profit for a sell order, we simply reverse the calculations: Instead of automatically adjusting an invalid price, you could also display an error message and halt program execution.
This way the user would be required to readjust their stop loss or take profit setting before continuing. Here's an example of how to do this: If the calculated stop loss is above the stop level, and thus too close to the price, the Alert function will display a pop-up message to the user. The return operator exits the current function and assures that the order will not be placed. In this book, we will be automatically adjusting invalid prices, with the assumption that is is better to place a corrected order than to not place one at all.
It may be useful to document when this happens by printing a message to the log: Verifying Pending Order Prices Here's how we verify the pending order price for a buy stop or sell limit order. The PendingPrice variable stores our pending order price: Notice that the logic here is identical to the code above that checks our buy take profit and sell stop loss prices. And here's the code to check the pending order price for a sell stop or buy limit order: Calculating Lot Size Aside from choosing suitable stop loss and take profit levels, using an appropriate lot size is one of the best risk management tools you have.
Specifying a lot size can be as simple as declaring an external variable and using a fixed lot size for every order. In this section, we'll explore a more sophisticated method that calculates the lot size based on the maximum amount you're willing to lose per trade.
Over-leveraging is one of the big killers of forex traders. Using lot sizes that are too large in relation to your equity can wipe out your account just as easily as it can produce big gains. Money Management To calculate the lot size using this method, we need to specify a percentage of equity to use and the stop loss in pips. We'll use the external variable EquityPercent to set the percentage of equity to use.
We'll assume a stop loss of 50 pips is used. First, we need to calculate the amount of equity specified by EquityPercent. We divide EquityPercent by to give us a fractional value 0. Then, we multiply that by AccountEquity to calculate the amount of equity to use.
Next, we have to find the tick value. This is the profit per pip if we were trading one lot of the desired currency. The tick value must be in pips, so if we are trading on a fractional pip broker 3 or 5 decimal places , we must multiply the tick value by This will be stored in the TickValue variable.
If this is a fractional pip broker, then TickValue will be 1. We will need to multiply this by 10 to make it equivalent to one pip. If the Point variable indicates that the currency is 3 or 5 decimal places, then TickValue will be multiplied by 10 to make it equal to a 2 or 4 decimal place value. The next step is to calculate our lot size. First, we divide the RiskAmount by the StopLoss setting. An indicator is a technical analysis tool that calculates price data to give an interpretation of market activity.
An indicator draws lines or objects on the chart. Indicators cannot place, modify or close orders. Examples of indicators include the moving average and stochastics.
A script is a simplified expert advisor that performs a single task, such as placing a pending order or closing all orders on a chart. A few useful scripts are included with MetaTrader. File Formats Files with the. These are the files we edit in MetaEditor. When an. Files with the. These are the files we run in MetaTrader. These files cannot be opened in MetaEditor. If you only have the. These files contain user-created functions that are referenced in an.
During compilation, the compiler "includes" the contents of the. We'll learn more about include files later. While these files can be opened in MetaTrader, the file type is not associated with the program in Windows.
An Introduction to MQL You can create your own templates if you wish, but we will not be covering template creation in this book.
The MetaTrader documentation will tell you all you need to know about creating templates. Indicators, expert advisors, libraries and scripts all share the. The only way to tell them apart is either by their save location, or by opening the file and examining them.
By the time you finish this book, you should be able to identify the difference between program types just by looking at the source code. File Locations All MetaEditor files are stored inside the experts folder.
These will be useful for debugging your expert advisors. It includes useful reference, search and auto-complete tools that makes coding in MQL a lot easier. The Editor window allows you to have multiple files open at once.
You can minimize, maximize and tab between several open windows. The Navigator window offers useful file-browsing and reference features.The string argument Currency is the symbol of the currency pair that we want to retrieve the point for. The pending order placement functions will place the stop loss and take profit with the pending order, so no separate order modification function is required. The rapid development of Internet and performance of modern computers opened up new vistas in many fields of human activities.
Different brokers have varying stop levels, so a stop loss that is valid on one broker may be too close for another. For example, a recent high or low, or an indicator value could be used to determine a stop loss. The stop loss can be a predetermined price, an indicator value, a fixed number of pips from the order opening price, or it can be dynamically calculated using a risk management routine.
We will assign the appropriate price to the variable OpenPrice.
The textbook is designed in such a method that to make learning MQL4 as convenient and consequent as possible. Place, modify and close market and pending orders. In this example, we are assigning the return value of OpenBuyOrder to the variable GetTicket, which the ticket number of the order we just placed.