Using Standard Libraries
So we have finally made it to the Standard Library. This library comes together with the terminal, hence its name - Standard Library. It comprises functions that facilitate programming EAs and partially undertake complex processes, e.g. trade request generation.
Trade libraries (see also trade classes) are located in the following path: Include\Trade\ and can be added using the #include directive.
Example:
#include <Trade\Trade.mqh> #include <Trade\PositionInfo.mqh>
The above classes can be considered as the basic ones as the majority of Expert Advisors can be programmed using only these two classes (libraries). I call them libraries:
- The first one is designed to placed and modify orders.
- The second one serves to obtain information on already existing positions.
At times, another library can prove useful:
#include <Trade\OrderInfo.mqh>It contains functions for working with orders, if, say, our strategy requires the use of pending orders.Remember the trade request structure full of various parameters that require knowledge to be used properly?
Now, I will give you an example of a trade request made using the library:
CTrade m_Trade; m_Trade.Sell(lot,symbol_name,price,sl,tp,comment);
There is a total of 6 parameters here, only one of which is mandatory (the order size - that is the first parameter).
I will now specify each one of them:
- lot is the size of the order to be placed;
- symbol_name is the symbol (currency pair) the order applies to (if none is specified, the current symbol of the Expert Advisor is used);
- price is the opening price (since this is the function for opening an active order, its price might be unspecified in which case it will automatically be obtained directly from the price chart);
- sl is the price at which the order will close, should the price not be to our advantage (it may be left out if the strategy does not imply the use of stop loss);
- tp is the price at which the order will close, should the price take the required direction, i.e. it takes profit (it may be left out if the strategy does not imply the use of take profit);
- comment is the comment to the order, e.g. specifying the reason for placing the order.
There is a number of ways to close a position:
- to close the whole position
CPositionInfo m_Position; m_Position.Select(symbol_name); m_Trade.PositionClose(symbol_name);
- to close the position by placing a reverse order of the same size
CTrade m_Trade; m_Trade.Buy(lot,symbol_name,price,sl,tp,comment);
- by using a more complicated method whereby all open positions are first searched through to single out the one that meets the required parameters (symbol, type, magic number, position identifier, etc.) to be further closed.
I am not going to give any example of the above due to its difficulty for beginners.
Putting It All Together
It is high time now to put the newly-acquired knowledge into a single Expert Advisor.
//+------------------------------------------------------------------+ //| fast-start-example.mq5 | //| Copyright 2012, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2012, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> //include the library for execution of trades #include <Trade\PositionInfo.mqh> //include the library for obtaining information on positions int iMA_handle; //variable for storing the indicator handle double iMA_buf[]; //dynamic array for storing indicator values double Close_buf[]; //dynamic array for storing the closing price of each bar string my_symbol; //variable for storing the symbol ENUM_TIMEFRAMES my_timeframe; //variable for storing the time frame CTrade m_Trade; //structure for execution of trades CPositionInfo m_Position; //structure for obtaining information of positions //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { my_symbol=Symbol(); //save the current chart symbol for further operation of the EA on this very symbol my_timeframe=PERIOD_CURRENT; //save the current time frame of the chart for further operation of the EA on this very time frame iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE); //apply the indicator and get its handle if(iMA_handle==INVALID_HANDLE) //check the availability of the indicator handle { Print("Failed to get the indicator handle"); //if the handle is not obtained, print the relevant error message into the log file return(-1); //complete handling the error } ChartIndicatorAdd(ChartID(),0,iMA_handle); //add the indicator to the price chart ArraySetAsSeries(iMA_buf,true); //set iMA_buf array indexing as time series ArraySetAsSeries(Close_buf,true); //set Close_buf array indexing as time series return(0); //return 0, initialization complete } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(iMA_handle); //deletes the indicator handle and deallocates the memory space it occupies ArrayFree(iMA_buf); //free the dynamic array iMA_buf of data ArrayFree(Close_buf); //free the dynamic array Close_buf of data } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { int err1=0; //variable for storing the results of working with the indicator buffer int err2=0; //variable for storing the results of working with the price chart err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf); //copy data from the indicator array into the dynamic array iMA_buf for further work with them err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf); //copy the price chart data into the dynamic array Close_buf for further work with them if(err1<0 || err2<0) //in case of errors { Print("Failed to copy data from the indicator buffer or price chart buffer"); //then print the relevant error message into the log file return; //and exit the function } if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0]) //if the indicator values were greater than the closing price and became smaller { if(m_Position.Select(my_symbol)) //if the position for this symbol already exists { if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol); //and this is a Sell position, then close it if(m_Position.PositionType()==POSITION_TYPE_BUY) return; //or else, if this is a Buy position, then exit } m_Trade.Buy(0.1,my_symbol); //if we got here, it means there is no position; then we open it } if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0]) //if the indicator values were less than the closing price and became greater { if(m_Position.Select(my_symbol)) //if the position for this symbol already exists { if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol); //and this is a Buy position, then close it if(m_Position.PositionType()==POSITION_TYPE_SELL) return; //or else, if this is a Sell position, then exit } m_Trade.Sell(0.1,my_symbol); //if we got here, it means there is no position; then we open it } } //+------------------------------------------------------------------+
Second EA
//+------------------------------------------------------------------+
//| My_First_EA.mq5 |
//| Copyright 2010, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property version "1.00"
//--- input parameters
input int StopLoss=30; // Stop Loss
input int TakeProfit=100; // Take Profit
input int ADX_Period=8; // ADX Period
input int MA_Period=8; // Moving Average Period
input int EA_Magic=12345; // EA Magic Number
input double Adx_Min=22.0; // Minimum ADX Value
input double Lot=0.1; // Lots to Trade
//--- Other parameters
int adxHandle; // handle for our ADX indicator
int maHandle; // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
double maVal[]; // Dynamic array to hold the values of Moving Average for each bars
double p_close; // Variable to store the close value of a bar
int STP, TKP; // To be used for Stop Loss & Take Profit values
CPositionInfo m_Position;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Get handle for ADX indicator
adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
maHandle=iMA(_Symbol,_Period,MA_Period,0,MODE_EMA,PRICE_CLOSE);
//--- What if handle returns Invalid Handle
if(adxHandle<0 || maHandle<0)
{
Alert("Error Creating Handles for indicators - error: ",GetLastError(),"!!");
return(-1);
}
//--- Let us handle currency pairs with 5 or 3 digit prices instead of 4
STP = StopLoss;
TKP = TakeProfit;
if(_Digits==5 || _Digits==3)
{
STP = STP*10;
TKP = TKP*10;
}
return(0);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Release our indicator handles
IndicatorRelease(adxHandle);
IndicatorRelease(maHandle);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Do we have enough bars to work with
if(Bars(_Symbol,_Period)<60) // if total bars is less than 60 bars
{
Alert("We have less than 60 bars, EA will now exit!!");
return;
}
// We will use the static Old_Time variable to serve the bar time.
// At each OnTick execution we will check the current bar time with the saved one.
// If the bar time isn't equal to the saved time, it indicates that we have a new tick.
static datetime Old_Time;
datetime New_Time[1];
bool IsNewBar=false;
// copying the last bar time to the element New_Time[0]
int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
if(copied>0) // ok, the data has been copied successfully
{
if(Old_Time!=New_Time[0]) // if old time isn't equal to new bar time
{
IsNewBar=true; // if it isn't a first call, the new bar has appeared
if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here ",New_Time[0]," old time was ",Old_Time);
Old_Time=New_Time[0]; // saving bar time
}
}
else
{
Alert("Error in copying historical times data, error =",GetLastError());
ResetLastError();
return;
}
//--- EA should only check for new trade if we have a new bar
if(IsNewBar==false)
{
return;
}
//--- Do we have enough bars to work with
int Mybars=Bars(_Symbol,_Period);
if(Mybars<60) // if total bars is less than 60 bars
{
Alert("We have less than 60 bars, EA will now exit!!");
return;
}
//--- Define some MQL5 Structures we will use for our trade
MqlTick latest_price; // To be used for getting recent/latest price quotes
MqlTradeRequest mrequest; // To be used for sending our trade requests
MqlTradeResult mresult; // To be used to get our trade results
MqlRates mrate[]; // To be used to store the prices, volumes and spread of each bar
ZeroMemory(mrequest); // Initialization of mrequest structure
/*
Let's make sure our arrays values for the Rates, ADX Values and MA values
is store serially similar to the timeseries array
*/
// the rates arrays
ArraySetAsSeries(mrate,true);
// the ADX DI+values array
ArraySetAsSeries(plsDI,true);
// the ADX DI-values array
ArraySetAsSeries(minDI,true);
// the ADX values arrays
ArraySetAsSeries(adxVal,true);
// the MA-8 values arrays
ArraySetAsSeries(maVal,true);
//--- Get the last price quote using the MQL5 MqlTick Structure
if(!SymbolInfoTick(_Symbol,latest_price))
{
Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
return;
}
//--- Get the details of the latest 3 bars
if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
{
Alert("Error copying rates/history data - error:",GetLastError(),"!!");
ResetLastError();
return;
}
//--- Copy the new values of our indicators to buffers (arrays) using the handle
if(CopyBuffer(adxHandle,0,0,3,adxVal)<0 || CopyBuffer(adxHandle,1,0,3,plsDI)<0
|| CopyBuffer(adxHandle,2,0,3,minDI)<0)
{
Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
ResetLastError();
return;
}
if(CopyBuffer(maHandle,0,0,3,maVal)<0)
{
Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
ResetLastError();
return;
}
//--- we have no errors, so continue
//--- Do we have positions opened already?
bool Buy_opened=false; // variable to hold the result of Buy opened position
bool Sell_opened=false; // variables to hold the result of Sell opened position
if(PositionSelect(_Symbol)==true) // we have an opened position
{
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
{
Buy_opened=true; //It is a Buy
}
else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
{
Sell_opened=true; // It is a Sell
}
}
// Copy the bar close price for the previous bar prior to the current bar, that is Bar 1
p_close=mrate[1].close; // bar 1 close price
/*
1. Check for a long/Buy Setup : MA-8 increasing upwards,
previous price close above it, ADX > 22, +DI > -DI
*/
//--- Declare bool type variables to hold our Buy Conditions
bool Buy_Condition_1=(maVal[0]>maVal[1]) && (maVal[1]>maVal[2]); // MA-8 Increasing upwards
bool Buy_Condition_2 = (p_close > maVal[1]); // previuos price closed above MA-8
bool Buy_Condition_3 = (adxVal[0]>Adx_Min); // Current ADX value greater than minimum value (22)
bool Buy_Condition_4 = (plsDI[0]>minDI[0]); // +DI greater than -DI
//--- Putting all together
if(Buy_Condition_1 && Buy_Condition_2)
{
if(Buy_Condition_3 && Buy_Condition_4)
{
// any opened Buy position?
if(Buy_opened)
{
Alert("We already have a Buy Position!!!");
return; // Don't open a new Buy Position
}
ZeroMemory(mrequest);
mrequest.action = TRADE_ACTION_DEAL; // immediate order execution
mrequest.price = NormalizeDouble(latest_price.ask,_Digits); // latest ask price
mrequest.sl = NormalizeDouble(latest_price.ask - STP*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(latest_price.ask + TKP*_Point,_Digits); // Take Profit
mrequest.symbol = _Symbol; // currency pair
mrequest.volume = Lot; // number of lots to trade
mrequest.magic = EA_Magic; // Order Magic Number
mrequest.type = ORDER_TYPE_BUY; // Buy Order
mrequest.type_filling = ORDER_FILLING_FOK; // Order execution type
mrequest.deviation=100; // Deviation from current price
//--- send order
OrderSend(mrequest,mresult);
// get the result code
if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
{
Alert("A Buy order has been successfully placed with Ticket#:",mresult.order,"!!");
}
else
{
Alert("The Buy order request could not be completed -error:",GetLastError());
ResetLastError();
return;
}
}
}
/*
2. Check for a Short/Sell Setup : MA-8 decreasing downwards,
previous price close below it, ADX > 22, -DI > +DI
*/
//--- Declare bool type variables to hold our Sell Conditions
bool Sell_Condition_1 = (maVal[0]<maVal[1]) && (maVal[1]<maVal[2]); // MA-8 decreasing downwards
bool Sell_Condition_2 = (p_close <maVal[1]); // Previous price closed below MA-8
bool Sell_Condition_3 = (adxVal[0]>Adx_Min); // Current ADX value greater than minimum (22)
bool Sell_Condition_4 = (plsDI[0]<minDI[0]); // -DI greater than +DI
//--- Putting all together
if(Sell_Condition_1 && Sell_Condition_2)
{
if(Sell_Condition_3 && Sell_Condition_4)
{
// any opened Sell position?
if(Sell_opened)
{
Alert("We already have a Sell position!!!");
return; // Don't open a new Sell Position
}
ZeroMemory(mrequest);
mrequest.action=TRADE_ACTION_DEAL; // immediate order execution
mrequest.price = NormalizeDouble(latest_price.bid,_Digits); // latest Bid price
mrequest.sl = NormalizeDouble(latest_price.bid + STP*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(latest_price.bid - TKP*_Point,_Digits); // Take Profit
mrequest.symbol = _Symbol; // currency pair
mrequest.volume = Lot; // number of lots to trade
mrequest.magic = EA_Magic; // Order Magic Number
mrequest.type= ORDER_TYPE_SELL; // Sell Order
mrequest.type_filling = ORDER_FILLING_FOK; // Order execution type
mrequest.deviation=100; // Deviation from current price
//--- send order
OrderSend(mrequest,mresult);
// get the result code
if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
{
Alert("A Sell order has been successfully placed with Ticket#:",mresult.order,"!!");
}
else
{
Alert("The Sell order request could not be completed -error:",GetLastError());
ResetLastError();
return;
}
}
}
return;
}
//+------------------------------------------------------------------+

