Download MetaTrader 5

Are you learning MQL5 and want to have a couple of very simple EAs? Here you have my two micro robots!

To add comments, please log in or register
MQL5 Reference is available in 8 languages. Learn MQL5 in the language that suits you best!
Jordi Bassaganas
3528
Jordi Bassaganas 2012.12.28 14:33 

Hello there,

I share with you my two first EAs tought for learning purposes! Any feedback from experts is welcome. How would you improve them?

The first one is RSIExpectator, the very simple EA that works exclusively on RSI. The results calculated by this robot give an idea of the effectiveness of RSI understood as an overbought/oversold indicator. In other words, this EA tries to refute the popular a priori reasoning which states that RSI itself is an overbought/oversold indicator. I mean, it answers the question Can you get rich by selling an asset when RSI equals 80, buy it when equals 20, and so on?

Here it is RSIExpectator.mq5:

#property copyright     "Author: laplacianlab, CC Attribution-Noncommercial-No Derivate 3.0"
#property link          "https://www.mql5.com/en/forum/ea"
#property version       "1.00"
#property description   "RSIExpectator is a very simple EA that works exclusively on the RSI."

#include <Trade\Trade.mqh>

//+------------------------------------------------------------------+
//| Input block                                                      |
//+------------------------------------------------------------------+

// General inputs

input string pair = "EURUSD";
input ENUM_TIMEFRAMES timeframe = PERIOD_M15;

// RSI inputs

input int overboughtLimit = 80;                       // RSI overbought limit
input int oversoldLimit = 20;                         // RSI oversold limit
input int RSI_period = 14;                            // RSI period

// Monetary management strategy inputs

input int stopLoss = 300;                             // Stop loss in pips
input double size = 0.1;                              // The size of the operation
   
enum ENUM_RISK_BENEFIT                                // Let's enum some risk-benefit ratios to make the user's life easier!
  {
   five,    // 1/5
   four,    // 1/4
   three,   // 1/3
   two,     // 1/2
   one      // 1/1
  };
                            
input ENUM_RISK_BENEFIT riskBenefitRatio = two;      // Risk-benefit ratio


//+------------------------------------------------------------------+
//| Var block                                                        |
//+------------------------------------------------------------------+

int RSIHandle;
double RSIValues[];
int takeProfit;                                       // 'takeProfit' will be calculated according to 'stopLoss' and 'riskBenefitRatio'.
string flag;                                          // 'flag' is 'buy' when we want the robot to buy and 'sell' when we want it to sell. 

int OnInit()
  {  
   
   switch(riskBenefitRatio)
     {  
      case five:
      
         takeProfit = (int)(stopLoss * 5);
      
         break;
         
      case four:
      
         takeProfit = (int)(stopLoss * 4);
      
         break;
         
      case three:
      
         takeProfit = (int)(stopLoss * 3);
      
         break;
         
      case two:
      
         takeProfit = (int)(stopLoss * 2);
      
         break;
         
      case one:
      
         takeProfit = stopLoss;
      
         break;
     
     }
  
   SymbolSelect(pair, true);    
   RSIHandle = iRSI(Symbol(), timeframe, RSI_period, PRICE_CLOSE);   
   ArraySetAsSeries(RSIValues, true);   
   flag = "buy";
   
   return(0);   
  }
  
void OnDeinit(const int reason)
  {
   IndicatorRelease(RSIHandle);
   ArrayFree(RSIValues);
  }

void OnTick()
  {    
 
   CTrade trade; 
   MqlTick tick;

   SymbolInfoTick(_Symbol, tick);
         
   if(CopyBuffer(RSIHandle, 0, 0, 1, RSIValues) > 0) { 
   
      if (RSIValues[0] >= overboughtLimit && flag == "sell") {   
                 
         double sl = tick.ask + stopLoss * _Point; 
         double tp = tick.bid - takeProfit * _Point;
         
         trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, size, tick.bid, sl, tp);
      
         flag = "buy";
   
      }
   
      else if (RSIValues[0] <= oversoldLimit && flag == "buy") {
            
         double tp = tick.ask + takeProfit * _Point;
         double sl = tick.bid - stopLoss * _Point;    
      
         trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, size, tick.ask, sl, tp);
      
         flag = "sell";
   
      }
   
   }

  }

The second one is MACDWaterlineCrossExpectator. This is the classical trading system which consists in buying when MACD crosses above the waterline line and selling when crosses below it. This EA works, as the previous one, along with a monetary management system which has a positive mathematical expectation.

Here it is MACDWaterlineCrossExpectator.mq5:

#property copyright     "Author: laplacianlab, CC Attribution-Noncommercial-No Derivate 3.0"
#property link          "https://www.mql5.com/en/forum/ea"
#property version       "1.00"
#property description   "This is a basic trading system which consists in buying when MACD crosses above the waterline line and selling when crosses below it. This EA works along with a monetary management system which has a positive mathematical expectation."

#include <Trade\Trade.mqh>

//+------------------------------------------------------------------+
//| Input block                                                      |
//+------------------------------------------------------------------+

// General inputs

input string pair = "EURUSD";
input ENUM_TIMEFRAMES timeframe = PERIOD_M15;

// MACD inputs

input int fastEMAPeriod = 12;                      // Fast EMA period
input int slowEMAPeriod = 26;                      // Slow EMA period
input int signalPeriod = 9;                        // Difference period

// Monetary management strategy inputs

input int stopLoss = 300;                          // Stop loss in pips
input double size = 0.1;                           // The size of the operation
   
enum ENUM_RISK_BENEFIT                             // Let's enum some risk-benefit ratios to make the user's life easier!
  {
   ONE_FIVE,   // 1/5
   ONE_FOUR,   // 1/4
   ONE_THREE,  // 1/3
   ONE_TWO,    // 1/2
   ONE         // 1/1
  };
                            
input ENUM_RISK_BENEFIT riskBenefitRatio = ONE_TWO;   // Risk-benefit ratio


//+------------------------------------------------------------------+
//| Var block                                                        |
//+------------------------------------------------------------------+

int MACDHandle;
double MACDValues[];
int takeProfit;      // 'takeProfit' will be calculated according to 'stopLoss' and 'riskBenefitRatio'.
string flag;         // 'flag' is 'buy' when we want the robot to buy and 'sell' when we want it to sell. 

int OnInit()
  {  
   
   switch(riskBenefitRatio)
     {  
      case ONE_FIVE:
      
         takeProfit = (int)(stopLoss * 5);
      
         break;
         
      case ONE_FOUR:
      
         takeProfit = (int)(stopLoss * 4);
      
         break;
         
      case ONE_THREE:
      
         takeProfit = (int)(stopLoss * 3);
      
         break;
         
      case ONE_TWO:
      
         takeProfit = (int)(stopLoss * 2);
      
         break;
         
      case ONE:
      
         takeProfit = stopLoss;
      
         break;
     
     }
  
   SymbolSelect(pair, true);    
   MACDHandle = iMACD(Symbol(), timeframe, fastEMAPeriod, slowEMAPeriod, signalPeriod, PRICE_CLOSE);   
   ArraySetAsSeries(MACDValues, true);   
   flag = "buy";
   
   return(0);   
  }
  
void OnDeinit(const int reason)
  {
   IndicatorRelease(MACDHandle);
   ArrayFree(MACDValues);
  }

void OnTick()
  {    
 
   CTrade trade; 
   MqlTick tick;

   SymbolInfoTick(_Symbol, tick);
         
   if(CopyBuffer(MACDHandle, 1, 0, 2, MACDValues) > 0) { 
   
      if (MACDValues[0] < 0 && MACDValues[1] > 0 && flag == "sell") {   
                 
         double sl = tick.ask + stopLoss * _Point; 
         double tp = tick.bid - takeProfit * _Point;
         
         trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, size, tick.bid, sl, tp);
         
         flag = "buy";
   
      }
   
      else if (MACDValues[0] > 0 && MACDValues[1] < 0 && flag == "buy") {
            
         double tp = tick.ask + takeProfit * _Point;
         double sl = tick.bid - stopLoss * _Point;    
      
         trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, size, tick.ask, sl, tp);
         
         flag = "sell";
   
      }
   
   }

  }
phi nuts
2184
phi nuts 2012.12.31 04:54  

Your code is much better than the last one.

Here's some error, though ;(

1. This is the same error like the last one, you use input for symbol, and yet you don't use it 

input string pair = "EURUSD";

2. Try not comparing string

if (... flag == "sell")
else if (... flag == "buy")

There's nothing wrong comparing string, but string takes much more memory, and processor have to compare each character in a string. So in your code, use directive #define with integer value on top of your code.

#define  FLAG_BUY 1
#define  FLAG_NO_TRADE 0
#define  FLAG_SELL -1

And change the type of variable flag from string to integer and use it like this

if (... flag == FLAG_SELL || flag == FLAG_NO_TRADE)
else if (... flag == FLAG_BUY || flag == FLAG_NO_TRADE)

3. You Risk-Reward-Ratio (3R) calculation is incorrect. Your 3R is based on calculation of SL and TP and also not changing lot size. Your 3R should change the lot size based calculation of SL, and Margin call (see AccountInfoDouble) . I'll explain this another time, coz it will be long explanation and calculation.

4. Your lot calculation is also incorrect - and this is a fatal error which makes your EA may will only open buy. In MT5, there's only one position for each symbol, and opening opposite symbol will close the other symbol (see it here buy and sel another cancel each other). In your code, if you have 1 lot buy, and then open 1 lot sell, you will have no trade at all, yet you flag it as opened sell. If buy position exist and you want to open sell position with the same lot as buy position, then you have to send open sell with twice lot size than open buy , or close that buy position first (using CTrade::PositionCLose) then open sell with same lot as previous buy. 

Use this code to check the lot size of current opened position

  int pos, total_position;
  
  total_position = PositionsTotal();
  flag = FLAG_NO_TRADE;
  
  for (pos = 0; pos < total_position; pos ++)
      {
      if (PositionGetSymbol (pos) == _Symbol)
         {
         if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            {
            flag = FLAG_BUY;
            size = PositionGetDouble(POSITION_VOLUME);
            break;
            }
            else
            {
            flag = FLAG_SELL;
            size = PositionGetDouble(POSITION_VOLUME);
            break;
            }
         }
      }

5. Your code does NOT using CheckResult to check if order send is successful or not,

6. You should not use SL and TP to stop your position. In MT5, we should use opposite type pending order with the same lot as opened position to stop our positions (for buy position use sell limit as TP and sell stop as SL with the same lot as that buy position and vice versa). That because MT5 is a position based trade platform, and so, SL and TP may not be well executed (there's plenty report about that in forum) and SL and TP may will be deleted if we open new position with the same type with the previous one. 

So after order send is successful (which you don't check - see number 5), immediately send opposite pending orders with the same lot as opened position, as SL and TP, using CTrade::OrderOpen.

7. Have fun. 

Jordi Bassaganas
3528
Jordi Bassaganas 2012.12.31 12:56  
phi.nuts:

Your code is much better than the last one.

Here's some error, though ;(

1. This is the same error like the last one, you use input for symbol, and yet you don't use it 

2. Try not comparing string

There's nothing wrong comparing string, but string takes much more memory, and processor have to compare each character in a string. So in your code, use directive #define with integer value on top of your code.

And change the type of variable flag from string to integer and use it like this

3. You Risk-Reward-Ratio (3R) calculation is incorrect. Your 3R is based on calculation of SL and TP and also not changing lot size. Your 3R should change the lot size based calculation of SL, and Margin call (see AccountInfoDouble) . I'll explain this another time, coz it will be long explanation and calculation.

4. Your lot calculation is also incorrect - and this is a fatal error which makes your EA may will only open buy. In MT5, there's only one position for each symbol, and opening opposite symbol will close the other symbol (see it here buy and sel another cancel each other). In your code, if you have 1 lot buy, and then open 1 lot sell, you will have no trade at all, yet you flag it as opened sell. If buy position exist and you want to open sell position with the same lot as buy position, then you have to send open sell with twice lot size than open buy , or close that buy position first (using CTrade::PositionCLose) then open sell with same lot as previous buy. 

Use this code to check the lot size of current opened position

5. Your code does NOT using CheckResult to check if order send is successful or not,

6. You should not use SL and TP to stop your position. In MT5, we should use opposite type pending order with the same lot as opened position to stop our positions (for buy position use sell limit as TP and sell stop as SL with the same lot as that buy position and vice versa). That because MT5 is a position based trade platform, and so, SL and TP may not be well executed (there's plenty report about that in forum) and SL and TP may will be deleted if we open new position with the same type with the previous one. 

So after order send is successful (which you don't check - see number 5), immediately send opposite pending orders with the same lot as opened position, as SL and TP, using CTrade::OrderOpen.

7. Have fun. 

That's the answer I was waiting for! Thanks so much phi.nuts, you are the best! I have a very busy week but I'll try to correct these errors and send back my "EAs". 
Fred Uche Elechi
19
Fred Uche Elechi 2015.03.14 06:19  

I will like to discuss EA project with you mail me at executivef@gmail.com. Thanks

Mahmoud Farajpour
233
Mahmoud Farajpour 2015.12.17 13:41  

hello dear I'm writing an EA as an amature...

here is my problem

this EA dont care about charts.. it just open a file an read trade signals from, and open/modify them

so it should select a symbol each time a new signal arrive to open a trade on

how do i exactly select a symbol by SymbolSelect() ?

i tried this but that doesnt work

 string pair="CADJPY";

 SymbolSelect(pair,true);

Alert (Symbol());

please help me by writing  the exactly code which select for example EURUSD

please note that im writing in mql4

To add comments, please log in or register