Expert Advisor: Order Placement
Bid, Ask & Spread
As a Forex trader, you’re probably already familiar with the Bid and Ask prices. 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 Ask price is generally just a few pips above the Bid 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, stop and limit orders.
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.” When this is checked, you can then
specify the maximum deviation in pips. 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. Note that ECN/STP brokers do not use a slippage
setting, and will always open market orders at the current price.
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.
The Order Placement Process
The process of placing an order in MQL involves several steps. 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.
OrderSend()
The OrderSend() function is used to place orders in MQL. The syntax is as follows:
int OrderSend(string Symbol, int Type, double Lots, double Price,
int Slippage, double StopLoss, double TakeProfit, string Comment = NULL,
int MagicNumber = 0, datetime Expiration = 0, color Arrow = CLR_NONE);
• Symbol – A string representing the currency pair to trade, for example GBPUSD. The
Symbol() function is used for the current chart’s currency pair.
• Type – The type of order to place: buy or sell; market, stop or limit. This is an integer value,
represented by the following constants:
◦ OP_BUY – Buy market order (integer value 0).
◦ OP_SELL – Sell market order (integer value 1).
◦ OP_BUYSTOP – Buy stop order (integer value 2).
◦ OP_SELLSTOP – Sell stop order (integer value 3).
◦ OP_BUYLIMIT – Buy limit order (integer value 4).
◦ OP_SELLLIMIT – Sell limit order (integer value 5).
• Lots – The number of lots to trade. You can specify mini lots (0.1) or micro lots (0.01) if your
broker supports it.
• 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 -1.
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. We’ll assume that the variables LotSize, Slippage,
BuyStopLoss, BuyTakeProfit and MagicNumber have already been calculated or assigned and are
valid.
OrderSend(Symbol(),OP_BUY,LotSize,Ask,Slippage,BuyStopLoss,BuyTakeProfit,
“Buy Order”,MagicNumber,0,Green);
The Symbol() function returns the current chart symbol. We will be placing orders on the current
chart pair 99% of the time. OP_BUY indicates that this is a buy market order. 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. If your broker offers 3 and 5 digit quotes however, then 1 point would
be 0.1 pips. 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:
OrderSend(Symbol(),OP_SELL,LotSize,Bid,Slippage,SellStopLoss,SellTakeProfit,
“Sell Order”,MagicNumber,0,Red);
We use OP_SELL as the order type, to specify a sell market order. We use Bid as the order opening
price, to reflect the fact that sell orders open at the Bid price. “Sell Order” is our order comment,
and we use Red as the arrow color to differentiate from buy orders.
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. We’ll assume that
BuyStopLoss and BuyTakeProfit have been correctly calculated relative to PendingPrice. Here’s
an example of a buy stop order placement:
OrderSend(Symbol(),OP_BUYSTOP,LotSize,PendingPrice,Slippage,BuyStopLoss,
BuyTakeProfit,”Buy Stop Order”,MagicNumber,0,Green);
Note that we use OP_BUYSTOP to indicate a buy stop order, and PendingPrice for our order opening
price. 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:
OrderSend(Symbol(),OP_SELLSTOP,LotSize,PendingPrice,Slippage,SellStopLoss,
SellTakeProfit,”Sell Stop Order”,MagicNumber,Expiration,Red);
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:
OrderSend(Symbol(),OP_BUYLIMIT,LotSize,PendingPrice,Slippage,BuyStopLoss,
BuyTakeProfit,”Buy Limit Order”,MagicNumber,0,Green);
Note that we used OP_BUYLIMIT to indicate 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:
OrderSend(Symbol(),OP_SELLLIMIT,LotSize,PendingPrice,Slippage,SellStopLoss,
SellTakeProfit,”Sell Limit Order”,MagicNumber,Expiration,Red);
Calculating Stop Loss & Take Profit
There are several ways of calculating stop loss and take profit prices. 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:
extern int StopLoss = 50;
extern int TakeProfit = 100;
In this example, we’ve entered a stop loss of 50 pips, and a take profit of 100 pips. 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.50. For all other pairs, it’s 0.0050.
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
the number of decimal places. For a 4 decimal place currency pair, the point is 0.0001. For a Yen pair,
it’s 0.01.
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.
double OpenPrice = Ask;
if(StopLoss > 0) double BuyStopLoss = OpenPrice – (StopLoss * Point);
// 1.4600 – (50 * 0.0001) = 1.4550
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.0001, if the order opening price
is 1.4600, and our stop loss is 50 pips, then the stop loss price for the buy order will be 1.4600 –
(0.0050) = 1.4550.
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.00001.
If we use a point value of 0.00001 in our stop loss calculation example above, the stop loss would be
calculated as 5 pips from the opening price, instead of 50 pips. This poses a problem. To get the
correct value, we would have to add an extra zero to our stop loss setting – i.e. StopLoss = 500.
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.01 or 0.0001, regardless of whether or not the broker uses fractional pips. We’ll call this function PipPoint,
because it will always return the point value that is equal to one pip.
double PipPoint(string Currency)
{
int CalcDigits = MarketInfo(Currency,MODE_DIGITS);
if(CalcDigits == 2 || CalcDigits == 3) double CalcPoint = 0.01;
else if(CalcDigits == 4 || CalcDigits == 5) CalcPoint = 0.0001;
return(CalcPoint);
}
The string argument Currency is the symbol of the currency pair that we want to retrieve the point
for. The MarketInfo() function with the MODE_DIGITS parameter returns the number of decimal
places (digits) for that pair. The if-else statement assigns the appropriate point value to the
CalcPoint variable, depending on the number of digits.
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.
double UsePoint = PipPoint(Symbol());
Here’s a set of examples using specific pairs:
double UsePoint = PipPoint(EURUSD);
// Result is 0.0001
double UsePoint = PipPoint(USDJPY);
// Result is 0.01
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.
This function will automatically set the slippage parameter to the number of pips specified by the
external Slippage parameter:
int GetSlippage(string Currency, int SlippagePips)
{
int CalcDigits = MarketInfo(Currency,MODE_DIGITS);
if(CalcDigits == 2 || CalcDigits == 4) double CalcSlippage = SlippagePips;
else if(CalcDigits == 3 || CalcDigits == 5) CalcSlippage = SlippagePips * 10;
return(CalcSlippage);
}
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 10. Here is how we use this function
in OrderSend():
// External parameters
extern int Slippage = 5;
// Order placement
OrderSend(Symbol(),OP_BUY,LotSize,Ask,GetSlippage(Symbol(),Slippage),BuyStopLoss,
BuyTakeProfit,”Buy Order”,MagicNumber,0,Green);
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:
// Global variables
double UsePoint;
int UseSlippage;
int init()
{
UsePoint = PipPoint(Symbol());
UseSlippage = GetSlippage(Symbol(),Slippage);
}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. This will be the case 98% of the time,
but if you’re creating an expert advisor that places orders on multiple currencies (or on a currency
other than the current chart), you’ll need to use the PipPoint() and GetSlippage() functions every
time you need to calculate these values.
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:
double MarketInfo(string Symbol, int RequestType);
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. For other symbols, you’ll need to
specify the currency symbol, such as EURJPY.
RequestType is an integer constant, representing the information that you are requesting from the
function. Here’s a list of the most useful MarketInfo() constants. A complete list can be found in the
MQL Reference, under Standard Constants – MarketInfo.
• MODE_POINT – The point value. For example, 0.01 or 0.00001.
• MODE_DIGITS – The number of decimal places in the price. Will be 2 or 3 for Yen pairs, and 4
or 5 for all other pairs.
• MODE_SPREAD – The current spread. For example, 3 pips (or 30 for a fractional pip broker).
• MODE_STOPLEVEL – The stop level. 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:
• MODE_BID – The current bid price of the selected symbol.
• MODE_ASK – The current ask price of the selected symbol.
• MODE_LOW – The low of the current bar of the selected symbol.
• MODE_HIGH – The high of the current bar of the selected 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:
double OpenPrice = Ask;
if(StopLoss > 0) double BuyStopLoss = OpenPrice – (StopLoss * UsePoint);
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:
double OpenPrice = Bid;
if(StopLoss > 0) double SellStopLoss = OpenPrice + (StopLoss * UsePoint);
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:
if(TakeProfit > 0) double BuyTakeProfit = OpenPrice + (TakeProfit * UsePoint);
if(TakeProfit > 0) double SellTakeProfit = OpenPrice – (TakeProfit * UsePoint);
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[0] is the low of the
current bar, Low[1] 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:
double BuyStopLoss = Low[0] – (2 * UsePoint);
So if the low of the bar is 1.4760, the stop loss will be placed at 1.4758.
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. iLowest() returns the shift value indicating the bar with
the lowest value in a specified time range. 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:
int CountBars = 10;
int LowestShift = iLowest(NULL,0,MODE_LOW,CountBars,0);
double BuyStopLoss = Low[LowestShift];
The first parameter of iLowest() is the currency symbol – NULL means that we’re using the current
symbol. Many functions in MQL use the string constant NULL to refer to the current chart symbol. The
second parameter is the chart period – 0 refers to the current chart frame.
MODE_LOW is an integer constant that specifies the low price series array. In other words, we’re
looking for the lowest low of the last CountBars. If we wanted to find the lowest close, for example,
we would use MODE_CLOSE. You can find all of the series array constants in the MQL Reference under
Standard Constants – Series Arrays.
CountBars is the number of bars we want to search, in this case 10. Finally, the last parameter is our
starting location. 0 is the current bar. 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[6].
If you wanted to calculate a stop loss for a sell order using this method, the iHighest() function
works the same way. Referencing the example above, you would use MODE_HIGH for your series array
parameter.
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:
double BuyStopLoss = MA;
If the moving average line is currently at 1.6894, then that will be our stop loss.
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:
bool OrderSelect(int Index, int Select, int Pool = MODE_TRADES)
• 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:
◦ SELECT_BY_TICKET – The value of the Index parameter is an order ticket number.
◦ SELECT_BY_POS – The value of the Index parameter is an order pool position.
Pool – An optional constant indicating the order pool: pending/open orders, or closed orders.
◦ MODE_TRADES – By default, we are examining the pool of currently opened orders.
◦ MODE_HISTORY – Examines the closed order pool (the order history).
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:
OrderSelect(Ticket,SELECT_BY_TICKET);
After the OrderSelect() function has been called, we can use any of the order information functions
to retrieve information about that order. A complete listing of functions that can be used with
OrderSelect() can be found in the MQL Reference under Trading Functions. 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: buy or sell; market, stop or limit. The
return value is an integer corresponding to the order type constants on page 22.
• 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
through the order pool with the SELECT_BY_POS parameter.
• OrderMagicNumber() – The magic number of the selected order. When cycling through
orders, you’ll need to use this to identify orders placed by your EA.
• OrderComment() – The comment that was placed with the order. This can be used as a
secondary order identifier.
OrderClosePrice() – The closing price of the selected order. The order must already be
closed (i.e. present in the order history pool).
• OrderOpenTime() – The opening time of the selected order.
• OrderCloseTime() – The closing time of the selected order.
• OrderProfit() – Returns the profit (in the deposit currency) for 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. 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:
bool OrderClose(int Ticket, double Lots, double Price, int Slippage, color Arrow);
• 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.00, and you want to close half of the trade, then specify 1 lot for the Lots
argument. 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.00
lot each, then simply close one of the orders when you want to close out half of the position. In this
book, we will always be closing out the full order.
The following example closes a buy market order:
OrderSelect(CloseTicket,SELECT_BY_TICKET);
if(OrderCloseTime() == 0 && OrderType() == OP_BUY)
{
double CloseLots = OrderLots();
double ClosePrice = Bid;
bool Closed = OrderClose(CloseTicket,CloseLots,ClosePrice,UseSlippage,Red);
}
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. If it’s a buy market order,
indicated by OP_BUY, we’ll continue closing the order.
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.
To close a sell market order, all you need to do is change the order type to OP_SELL and assign the
current Ask price to ClosePrice:
if(OrderCloseTime() == 0 && OrderType() == OP_SELL)
{
double CloseLots = OrderLots();
double ClosePrice = Ask;
bool Closed = OrderClose(CloseTicket,CloseLots,ClosePrice,UseSlippage,Red);
}
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:
OrderSelect(CloseTicket,SELECT_BY_TICKET);
if(OrderCloseTime() == 0 && OrderType() == OP_BUYSTOP)
{
bool Deleted = OrderDelete(CloseTicket,Red);
}
As we did with the OrderClose() function above, we need to check the order type to be sure it is a
pending order. The pending order type constants are OP_BUYSTOP, OP_SELLSTOP, OP_BUYLIMIT and
OP_SELLLIMIT. 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.