Understanding order placement in MQL5
Introduction
In any trading system, we need to deal with orders and their operations such as opening positions, placing stop-loss and profit-taking, and modifying orders. Therefore, it is very important to understand how to handle order operations in mql5 when creating a trading system for MetaTrader5. The objective of this article is to provide you a simple guidance for most of the order and position operations to be able to deal with everything about this topic effectively. We will cover in this article the following topics:
- Orders, positions, and deals terms
- OrderSend()
- OrderSend() application
- CTrade class
- CTrade class application
- Conclusion
I hope that you will find this article useful and valuable to develop your MetaTrader5 trading system smoothly regarding order placement. All applications in this article, you must test them before using to make sure that they are profitable or suitable for your trading because the main purpose of mentioning them is only to give an example to create a trading system using two different methods regarding working with order, deal, and position operations.
Orders, Positions, and Deals terms
In this part, we will talk about important terms to understand how to deal with orders effectively. We'll understand the differences between three related terms to orders in the MetaTrader 5. These terms are order, deal, and position, we can consider these terms as steps to execute the trade.
Order: is a request received by the trading server to open a buy or sell trade with a specific lot or volume at a specific price. There are two types of orders, the market order and the pending order.
- Market order: an order that can be executed immediately at the current market price.
- Pending order: an order that executes the trade at predetermined conditions concerning the price to execute the trade at its level and the time to execute the trade.
These pending orders can be one of the following:
- Buy stop: Place a buy pending order at a specific price that is above the current price in the market.
- Buy limit: Place a buy pending order at a specific price that is below the current price in the market.
- Sell stop: Place a sell pending order at a specific price that is below the current price in the market.
- Sell limit: Place a sell pending order at a specific price that is above the current price in the market.
Once the order placed, regardless of whether it is a market or pending order, it can be found in the Trade tab of the Toolbox in the MetaTrader 5. The following is an example:
When the order is closed or canceled without execution, we can find them in the History tab of the Toolbox.
When we want to modify a current position by MQL5, we need to deal with these orders the same as we will see later when handling order modifying.
Deal: It is the result when the trade order is executed or filled. We can find it as in and out actions based on the execution of the trade. Let’s say that there is a buy order of one lot executed. After that, we closed a partial of the position 0.5 lots, then closed the remaining 0.5 lots. So, deals will be the same as the following:
- 1 buy in
- 0.5 sell out
- 0.5 sell out
We can find these deals in the History tab of the Toolbox of the MetaTrader 5 by appearing deals data by right-clicking and choosing them.
Position: It is the net of deals of long or short based on buying or selling the financial asset. We can find it in the Trade tab as an active trade or the History tab if we choose positions to appear.
It is good to mention that the executable price of the buy order is the Ask price, and the executable price when closing is the Bid price. On the other hand, the executable price of the sell order is the Bid price and the executable price when closing is the Ask price.
OrderSend()
After understanding important terms about trade execution in MetaTrader 5, we need to learn how we should execute orders automatically in MQL5. Firstly, you can check about Trade Functions in the MQL5 reference for more information about functions intended for managing activities.
We will discuss the OrderSend() function, which can be used to execute trade operations by sending requests to a trade server. In other words, it can be used to place, modify, and close orders.
The following is the format of this function:
bool OrderSend( MqlTradeRequest& request, MqlTradeResult& result );
As we can see the function has two parameters:
- MqlTradeRequest structure: It contains the order parameters and all the necessary fields or variables to perform trade deals. Objects passed by reference as per the ampersands. The TradeRequest is the method for interaction between the client terminal and the trade server to execute orders.
- MqlTradeResult structure: The TradeResult returns the results of the order request. Objects passed by reference also.
The MqlTradeRequest structure:
The structure is a set of related data of different types. We can find the MqlTradeRequest structure definition the same as the following:
struct MqlTradeRequest { ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type ulong magic; // Expert Advisor ID (magic number) ulong order; // Order ticket string symbol; // Trade symbol double volume; // Requested volume for a deal in lots double price; // Price double stoplimit; // StopLimit level of the order double sl; // Stop Loss level of the order double tp; // Take Profit level of the order ulong deviation; // Maximal possible deviation from the requested price ENUM_ORDER_TYPE type; // Order type ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type ENUM_ORDER_TYPE_TIME type_time; // Order expiration type datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type) string comment; // Order comment ulong position; // Position ticket ulong position_by; // The ticket of an opposite position };
If we want to declare an MqlTradeRequest object, we can do so through the following line of code:
MqlTradeRequest request;
Then, we can assign the trade parameters to the variables of the created request object by adding a dot (.) after the object, as shown in the following example:
request.symbol = _Symbol; request.volume = 0.01; request.type = ORDER_TYPE_BUY;
The following is a list of all members or variables of the MqlTradeRequest structure, along with their accepted values for assignment.
Variable | Description | Accepted value for assignment |
---|---|---|
action | It represents the type of trade operation | One of the ENUM_TRADE_REQUEST_ACTIONS (TRADE_ACTION_DEAL, TRADE_ACTION_PENDING, TRADE_ACTION_SLTP, TRADE_ACTION_MODIFY, TRADE_ACTION_REMOVE, TRADE_ACTION_CLOSE_BY) |
magic | It represents the expert advisor ID for identifying orders placed by a certain expert advisor | Any ulong value |
order | It represents the order ticket. It is required when using TRADE_ACTION_MODIFY or TRADE_ACTION_REMOVE in the action variable | Any ulong value |
symbol | The specified symbol or the instrument to trade.the (_SYMBOL) refers to the current one | Any string symbol |
volume | It specify trade volume or lots | Any allowed double value |
price | The opening price | Double value |
stoplimit | The opening price of limit pending order. The action must be TRADE_ACTION_PENDING and the type variable must be ORDER_TYPE_BUY_STOP_LIMIT or ORDER_TYPE_SELL_STOP_LIMIT and it is required for stop limit orders | Double valuue |
sl | The stop loss price of the trade | Double value |
tp | The take profit price of the trade | Double value |
deviation | The maximal price deviation in points | ulong value |
type | The order type | One of the ENUM_ORDER_TYPE (ORDER_TYPE_BUY, ORDER_TYPE_SELL, ORDER_TYPE_BUY_STOP, ORDER_TYPE_SELL_STOP, ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT, ORDER_TYPE_SELL_STOP_LIMIT) |
type_filling | Order execution type or the filling policy of the order | One of the ENUM_ORDER_TYPE_FILLING (ORDER_FILLING_FOK, ORDER_FILLING_IOC, ORDER_FILLING_BOC, ORDER_FILLING_RETURN) |
type_time | The type of the pending order expiration | One of the ENUM_ORDER_TYPE_TIME (ORDER_TIME_GTC, ORDER_TIME_DAY, ORDER_TIME_SPECIFIED, ORDER_TIME_SPECIFIED_DAY) |
expiration | The pending order expiration time. It is required when the type_time is ORDER_TIME_SPECIFIED | datetime value |
comment | The order comment | string value |
position | The ticket of a position. It is required when a position is modified or closed to identify it | ulong value |
position_by | The ticket of an opposite position. It is used when the position is closed by an opposite open one in the opposite direction for the same symbol | ulong value |
Now, we will mention some important actions that we need to use when placing orders in MQL5.
- Market order
- Adding stop-loss and take-profit
- Pending order
- Pending order modifying
- Remove pending order
Market Order:
In this type of action, we need to place a market order which means the order will be placed at the current market price, we will use the (TRADE_ACTION_DEAL) action. If the order is a buy order, the order will be placed at the current ask price or if the order is a sell order, the order will be placed at the current bid price. Here is how to do that:
After declaring MqlTradeRequest and MqlTradeResult objects, we can assign the following values to following variables:
request.action = TRADE_ACTION_DEAL; &nbsthe p; //market order palcement request.type = ORDER_TYPE_BUY; //type of order is buy request.symbol = _Symbol; //applied for the cuurrent symbol request.volume = 0.1; //the lot size request.type_filling = ORDER_FILLING_FOK; //the filling policy fill or kill request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); //the price is the current ask for buy request.sl = 0; //stop loss is 0 request.tp = 0; //take profit is 0 request.deviation = 50; //slippage is 50 OrderSend(request, result); //calling the OrderSend function
As we can see in the previous code, we did not add stop loss and take profit values. We can add their values to the code along with the other variables, or we can add them through another action, as we will see in the next point.
Adding stop-loss and take-profit:
When we need to add stop-loss and take-profit, we assign the TRADE_ACTION_SLTP to the variable action as shown in the following example.
request.action = TRADE_ACTION_SLTP; //adding sl and tp request.symbol = _Symbol; //applied for the cuurrent symbol request.sl = 1.07000; //sl price request.sl = 1.09000; //tp price OrderSend(request, result); //calling the OrderSend function
Pending order:
If we want to place a pending order, we can use another action (TRADE_ACTION_PENDING). Then, we determine the type of order. We can set the time if we need an expiration time for the pending order.
request.action = TRADE_ACTION_PENDING; //pending order placement request.type = ORDER_TYPE_BUY_STOP; //type of order is buy stop request.symbol = _Symbol; //applied for the cuurrent symbol request.volume = 0.1; //the lot size request.price = 1.07000; //opening price request.sl = 1.06950; //stop loss request.tp = 1.07100; //take profit request.type_time = ORDER_TIME_SPECIFIED; //to set an expiration time request.expiration = D'2023.08.31 00.00'; //expiration time - datetime constant request.type_filling = ORDER_FILLING_FOK; //the filling policy fill or kill request.stoplimit = 0; //for stoplimit order only OrderSend(request, result); //calling the OrderSend function
Pending order modifying:
If we need to modify the pending order, we need to get the order ticket number of the pending order that we need to modify. We can use the OrderGetTicket function to get the order ticket. This function returns the ticket of the corresponding order, which we can use to select the order and work with it.
ulong OrderGetTicket( int index // Number in the list of orders );
Let's consider that we have a variable named (ticket) that holds the order ticket number. We can use this variable to assign the order ticket number to the order variable of the request object. We can then modify the order using the action (TRADE_ACTION_MODIFY), the same as the following example.
request.action = TRADE_ACTION_MODIFY; //pending order modyfying request.order = ticket; //ticket variable that holds the pending order ticket to modify request.price = 1.07050; //new opening price request.sl = 1.07000; //new stop loss request.tp = 1.07150; //new take profit request.type_time = ORDER_TIME_SPECIFIED; //to set an expiration time request.expiration = D'2023.09.01 00.00'; //new expiration time - datetime constant OrderSend(request, result); //calling the OrderSend function
Remove Pending Order:
If we need to remove the pending order, we can do that using the action of (TRADE_ACTION_REMOVE). We also need the ticket number of the pending order that we need to remove. We can use the variable ticket assuming that it holds the needed ticket number.
request.action = TRADE_ACTION_REMOVE; //pending order remove request.order = ticket; //ticket variable that holds the pending order ticket to remove OrderSend(request, result); //calling the OrderSend function
The MqlTradeResult structure:
The MqlTradeResult structure returns the result of whether or not the order was successful once an order has been placed by the OrderSend() function. It contains trade information from the trade server, such as the ticket number, the volume, and the price.
The following is the definition of the MqlTradeResult structure:
struct MqlTradeResult { uint retcode; // Operation return code ulong deal; // Deal ticket, if it is performed ulong order; // Order ticket, if it is placed double volume; // Deal volume, confirmed by broker double price; // Deal price, confirmed by broker double bid; // Current Bid price double ask; // Current Ask price string comment; // Broker comment to operation (by default it is filled by description of trade server return code) uint request_id; // Request ID set by the terminal during the dispatch int retcode_external; // Return code of an external trading system };
We can declare an object named result to pass it as a second parameter after the first one (request) to the OrderSend() function call.
MqlTradeResult result;
As we can see in the variables of the MqlTradeResult structure, the retcode variable is very important because it returns the code from the trade server to indicate whether or not the request was successful.
If the trade is not placed, the return code indicates an error state. You can check the list of return codes from the MQL5 reference for more information. It is crucial to include a code in our trading system to report if there is an error returned or not, such as the following example:
if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) { Print("Trade Placed Successfully"); } else { Print("Trade Not Placed, Error ", result.retcode); }
As we can see in the previous code, it will print a message with the result after the request and fill in the result variables. If the trade was placed, it'll send us a message with that, or if there is a problem, it will print a message that there was an error and return the error code to help navigate the issue.
OrderSend() Application
We need to create a simple trading system that can execute trades by using the OrderSend() function. The trading system that we need to create is a simple moving average crossover and the action is placing a market order only.
The objective here is to understand the differences when creating the same trading system using the OrderSend() and the CTrade class. The following are steps to create this MA crossover using the OrderSend() function.
In the global scope create two integer variables (simpleMA, barsTotal) without assignment and they will be assigned later in the OnInit part.
int simpleMA; int barsTotal;
The simpleMA will be assigned to the iMA function that returns the handle of the moving average technical indicator. Its parameters are:
- symbol: To specify the symbol name, the _Symbol refers to the current instrument.
- period: To specify the time frame, we will use PERIOD_H1 which refers to the one-hour time frame.
- ma_period: the period of the moving average, we will 50.
- ma_shift: to specify the needed horizontal shift.
- ma_method: To specify the moving average type, we will specify the simple one.
- applied_price: To specify the type of price that will be used in the MA calculation, we will set the closing price.
The barsTotal will be assigned to the iBars function that returns the number of bars. Its parameters are:
- symbol: The symbol name
- timeframe: the time frame period
simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1);
In the OnTick part, we will create two arrays one for price using the MqlRates type which stores information about price, volume, and spread and the other for the moving average using double variable type
MqlRates priceArray[]; double mySMAArray[];
Defining the ask and bid prices
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
Creating two objects for the OrderSend() function one is for request using the MqlTradeReuest and the other for the result using the MqlTradeResult, then resetting the request variable by reference
ZeroMemory(request);
Setting the AS_SERIES flag to these two created arrays priceArray and mySMAArray by using the ArraySetAsSeries function. Its parameters:
- array[]: To specify the needed array
- flag: Array indexing direction.
ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true);
Getting historical data of MqlRates by using the CopyRates function. Its parameters are:
- symbol: the symbol name or the _Symbol for the current symbol or instrument.
- time frame: time frame period or _period for the current time frame.
- start position: the position to start from.
- count: data count to copy.
- rates_array: the target array to copy.
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
Getting the indicator data buffer by using the CopyBuffer function. Its parameters:
- indicator_handle: To specify the indicator handle, the MA.
- buffer_num: To specify the indicator buffer number.
- start_pos: the starting position to count from.
- count: amount to copy.
- buffer[]: the target array.
CopyBuffer(simpleMA,0,0,3,mySMAArray);
Defining last, previous closing prices, last, and previous SMA values
double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
Create an integer bars variable and assign it to the iBars
int bars=iBars(_Symbol,PERIOD_H1);
Checking bars, if the barsTotal is not equal to the bars variable
if(barsTotal != bars)
Updating barsTotal value to equal to the bars if they are not equal to each other
barsTotal=bars;
Checking the condition of the strategy to open a trade, if the last close is greater than the last SMA value after the previous close was less than the previous SMA value
if(prevClose<prevSMAVal && lastClose>SMAVal)
Opening a market buy order using suitable variables related to the MqlTradeRequest function
request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.sl = Ask-(500*_Point); request.tp = Ask+(1000*_Point); request.deviation = 50; OrderSend(request, result);
Checking the condition of the strategy to open a sell trade, if the last close is less than the last SMA value after the previous close was greater than the previous SMA value
if(prevClose>prevSMAVal && lastClose<SMAVal)
Opening a market sell order using suitable variables related to the MqlTradeRequest function request.type = ORDER_TYPE_SELL; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); request.sl = Bid+(500*_Point); request.tp = Bid-(1000*_Point); request.deviation = 50; OrderSend(request, result);
The following is the full code in one block to create this type of trading system using the OrderSend() function
//+------------------------------------------------------------------+ //| OrderSend_Trading_system.mq5 | //+------------------------------------------------------------------+ int simpleMA; int barsTotal; int OnInit() { simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1); return(INIT_SUCCEEDED); } void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,PERIOD_H1); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.sl = Ask-(500*_Point); request.tp = Ask+(1000*_Point); request.deviation = 50; OrderSend(request, result); } if(prevClose>prevSMAVal && lastClose<SMAVal) { request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_SELL; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); request.sl = Bid+(500*_Point); request.tp = Bid-(1000*_Point); request.deviation = 50; OrderSend(request, result); } } }
CTrade class
After learning how we can place orders by OrderSend() function, we have an easy method to access trade functions. We can use the CTrade ready-made class provided by MQL5, or we can create our own class for more personal preferences. Now, we will mention how we can use the CTrade ready-made class in the MQL5. You can check all about CTrade class from MQL5 reference for more information.
First, we can find the include file of the CTrade class in the Trade folder in the include folder in the MetaTrader 5 installation files. All we need is to include this file in the expert advisor for calling and using all trade functions the same as the following:
#include <Trade\Trade.mqh>
Create an object from the CTrade class
CTrade trade;
After that we'll be able to use all trade functions in the CTrade class by using trade before the dot(.) and the desired function. We can use all functions of operations with orders, operations with positions, access to the last request parameters, access to the last request checking results, access to the last request execution results, and others.
We will mention some important functions the same as we did with OrderSend() to understand the differences between the two methods. We will understand how to do the following:
- Market order
- Adding stop-loss and take-profit
- Pending order
- Pending order modifying
- Remove pending order
Market order:
After creating our trade object we can use the PositionOpen function to place a market order, its parameters are:
- symbol: to specify the needed symbol
- order_type: to specify the order type to open a position
- volume: to specify the lot size
- price: to specify the price of the position opening
- sl: to specify the stop loss price
- tp: to specify the ttake profit price
- comment: to specify a comment or NULL
The following is an example of that:
trade.PositionOpen( _Symbol, //to be applied for the current symbol ORDER_TYPE_BUY, //to place buy order 0.1, //lot size or volume Ask, //opening price of the order - current ask Ask-(500*_Point), //sl Ask+(1000*_Point), //tp NULL //NULL );
We can also use the additional methods in the CTrade like Buy, Sell instead of PositionOpen to open a market order.
Adding stop-loss and take-profit:
We can modify position by symbol or ticket number using the PositionModify function. Its parameters are:
- symbol or ticket: to specify the position we need to modify, if modifying by symbol we will specify the symbol name or if modifying by ticket we will specify the ticket number.
- sl: the new stop loss price
- tp: the take profit price
Example for modifying by symbol:
trade.PositionModify( EURUSD, //the symbol name 1.06950, //the new sl 1.07100, //the new tp );
Example for modifying by ticket:
trade.PositionModify( ticket, //the ticket variable that holds the needed ticket number to modify 1.06950, //the new sl 1.07100, //the new tp );
Pending order:
If we need to place a pending order using the CTrade class we can use the OrderOpen function. Its parameters are:
- symbol: the determine the symbol name
- order_type: to determine the pending order type
- volume: to specify the lot size
- limit_price: to specify the stop limit price
- price: to specify the execution price of the pending order
- sl: to specify the stop loss
- tp: to specify the take Profit price
- type_time: to specify the type by expiration
- expiration: to specify the expiration datetime variable
- comment: to specify a comment if needed
The following example is for placing a buy limit pending order using the OrderOpen function
trade.OrderOpen( "EURUSD", // symbol ORDER_TYPE_BUY_LIMIT, // order type 0.1, // order volume 0, // StopLimit price 1.07000, // execution price 1.06950, // Stop Loss price 1.07100, // Take Profit price ORDER_TIME_SPECIFIED, // type by expiration D'2023.08.31 00.00', // expiration "" // comment );
Pending order modifying:
If we need to modify the placed pending order we can do that using the CTrade class by the OrderModify function. Its parameters are:
- ticket: to specify the pending order ticket to modify
- price: the new execution price
- sl: the new stop Loss price
- tp: the new take Profit price
- type_time: to specify the type by expiration
- expiration: to specify the expiration datatime variable
- stoplimit : to determine the limit order price
The following is an example of pending order modifying
trade.OrderModify( ticket, // ticket number of the pending order to modify 1.07050, // execution price 1.07000, // Stop Loss price 1.07150, // Take Profit price ORDER_TIME_SPECIFIED, // type by expiration D'2023.08.31 00.00', // expiration 0, // StopLimit price );
Delete pending order:
If you need to delete a pending order you can do that by using the OrderDelete function and it needs the ticket number of the pending order to be deleted. The following is an example of that function.
trade.OrderDelete(
ticket, // tick number of the pending order to delete
);
CTrade class Application
We need to create the same trading system that we created using the OrderSend(). We will use the CTrade class to understand the differences in how functions work in both of them.
The following are the only different steps to create this trading system using the CTrade class, and the remaining steps are the same as we did before.
Including the Trade include file using the preprocessor #include
#include <Trade\Trade.mqh>
Create the trade object from the CTrade class
CTrade trade;
When the buy condition is met we can use the PositionOpen and the order type will be ORDER_TYPE_BUY or the additional buy method the same as the following code
trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL);
When the sell condition is met, we can use the PositionOpen along with the order type ORDER_TYPE_SELL or the additional sell method the same as the following code
trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL);
The following is the full code to create the trading system using the CTrade class:
//+------------------------------------------------------------------+ //| CTrade_Trading_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> int simpleMA; int barsTotal; CTrade trade; int OnInit() { simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1); return(INIT_SUCCEEDED); } void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,PERIOD_H1); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL); } if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL); } } }
Conclusion
If you have completed reading this article, it is supposed that understand how orders, positions, and deals work in MQL5. In addition to understanding how we can create a trading system smoothly using the two methods of trade operations, the OrderSend method and the CTrade method.
We identified how we place market orders and pending orders, add stop-loss and take-profit, modify pending orders, and remove or delete pending orders using the two methods.
It is supposed that you understood how to apply all of the previous to create an application because we provided two simple applications to create the same moving average crossover trading system using the two methods.
- OpenSend_Trading_System
- CTrade_Trading_System
The objective of mentioned applications is only to understand the differences between them practically so, take care, you must test them before using them in any live account to make sure they are profitable and suitable for your trading.
I believe that you released how easy it is to use the ready-made CTrade class when working with trade operations because it saves a lot of time and effort. In addition to other features when using classes in programming generally.
If you want to learn more about that and the object-oriented programming in MQL5 you can read my previous article Understanding MQL5 Object-Oriented Programming (OOP), I hope that you find it useful. MQL5 made a lot of appreciated work and effort to provide us with tools to develop and create trading software smoothly and easily.
I hope that you found this article useful and got many useful insights to understand and do your work easily after these insights. If you want to read more articles for me, you can check my publication for many articles about how to create trading systems using the most popular technical indicators and others and I hope that you will find them useful.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
hello,
great text, tyvm.
I have found 1 small bug:
in the box under TRADE_ACTION_SLTP you have written twice request.sl, the second one should be request.tp, as indicated in the comment at the end of the line.
Best Regards,
Gunther
hello,
great text, tyvm.
I have found 1 small bug:
in the box under TRADE_ACTION_SLTP you have written twice request.sl, the second one should be request.tp, as indicated in the comment at the end of the line.
Best Regards,
Gunther
Hello,
Thanks for your kind comment. You are correct, it is a mistake and it will be considered.
Regards,