Download MetaTrader 5

Problem writing an EA to perform similar functions as a custom indicator. - page 2

To add comments, please log in or register
Fernando Carreiro
3391
Fernando Carreiro  
DrBeardface: As it happens that particular book is available through the university library as an eBook. I read the section on iCustom, and the only thing I can see is different to how I've laid out the code is that the "shift" parameter is set to 1 instead of 0. But I still can't see why that would mean that one if statement would work but the other one wouldn't. 

You are not suppose to just read one section! That is the same as reading that section of reference documentation. The purpose of the book is for it to be read from start to finish, as it builds up your ability to code in MQL4 step by step, from basics to advanced.

It is obvious, that you still do not know the basics, so you cannot expect to start "running" when you can barely "crawl"!

If you have the book it in your library (hopefully it is the 2014 edition and not the 2010 one which is no longer valid or compatible), then you cannot state that you cannot afford it when you have it freely available.

What you can state, is that you lack the discipline to actually follow through in your research and learning, in a structured and ordered fashion, and just want to skip to the end and have the finished product.

It does not work that way, and that is why a mentioned the "required mindset for a trader". Unfortunately, most people of the younger generations, are living in an "instant" world where they want everything "here & now" in an "instant" - it is just "me, me, me", "want, want, want", "now, now, now"!

The real world, does not work that way! It takes time to learn, to gain a skill, to perfect and to improve! In needs discipline, dedication, commitment and these require time and most importantly, effort.

EDIT: As for bugs in the book, the link I referenced also has a download of all the source code with corrections and errata for the book!


DrBeardface
37
DrBeardface  
Ok, thanks for your input and opinions about the world. I'm here asking for help because I can't ask a book for help. If you're not willing to provide help that doesn't involve telling me to read a book then maybe you shouldn't be on a coding help forum. Research isn't just about reading, it's also about asking questions of people that know better, which is what I'm on here to do. 
mrluck1
739
mrluck1  

if you read mql4 book, its free on mql4 site, i leaned from there, anyone can and its for free, about your problem where is ordersend function

DrBeardface
37
DrBeardface  
mrluck1:

if you read mql4 book, its free on mql4 site, i leaned from there, anyone can and its for free, about your problem where is ordersend function

It's not there yet. I wanted to make sure that the information from the iCustom function was being correctly imported first so I set up a simple printed output to show that it was doing that before moving on. And I'm glad I did because it's not. It's responding to the Sell signal from the indicator but not the Buy signal. The code in the indicator is correctly generating the signal, but the EA isn't responding to it correctly. I think the problem is with the if statements, but I'm not familiar enough with this language to spot the problem. 
mrluck1
739
mrluck1  

have you tried if ( spread >= 0) ?

i think its best to  use == or >= on if functions, never only > or < 

DrBeardface
37
DrBeardface  
mrluck1:

have you tried if ( spread >= 0) ?

i think its best to  use == or >= on if functions, never only > or < 

I did try that, and it didn't work. If it had it would have raised more questions though. The main problem I have here is that one of the nested if statements works fine, but the other one just won't no matter what I do. I've even tried removing the working one from code so that there's only on nested if statement, but it still won't do anything. Here's the code as it stands now:

#include <stdlib.mqh>
#include <stderror.mqh>


//External Inputs for Indicator
extern double EntryThreshold=11;
extern int MagicNumber=12345;
extern double Lots=1;
extern double StopLoss=15;
extern double TakeProfit=50;
extern int Slippage=3;
extern int Expiration=14400;

//External Input for Trailing Stop
extern int TrailingStop=15;

//Variable Declaration
double PointValue = 0;
double Spread = 0;
double Trigger = 0; // 0 = None, 1 = Buy, 2 = Sell
//+-------------------------+
//| Expert Advisor Function |
//+-------------------------+

int start()
   {
      PointValue = (Point*10);
      NormalizeDouble(PointValue,Digits);
      Spread = (MarketInfo(Symbol(), MODE_SPREAD)/10);
      NormalizeDouble(Spread,1);
      Trigger = iCustom(NULL,0,"Turtle",4,0);
      if (Spread >= 0)
      {
      if(Trigger == 1)
         {
         Print("Buy @ ",Bid);
         Print("Trigger = ",Trigger);
         }
      else if(Trigger == 2)
         {
         Print("Sell @ ",Bid);
         Print("Trigger = ",Trigger);
         }
      }
   }

It also doesn't work if I remove the first if statement (if (Spread >= 0) and just have the nested if statements on their own.


Just to cover all bases, here is the Indicator code. This works perfectly and does seem to generate the correct signals to pass along to the EA via iCustom:

#include <stdlib.mqh>
#include <stderror.mqh>

#property indicator_chart_window
#property indicator_buffers 4

#property indicator_type1 DRAW_ARROW
#property indicator_width1 5
#property indicator_color1 0x00FF00
#property indicator_label1 "Buy"

#property indicator_type2 DRAW_ARROW
#property indicator_width2 5
#property indicator_color2 0x0000FF
#property indicator_label2 "Sell"

#property indicator_type3 DRAW_ARROW
#property indicator_width3 5
#property indicator_color3 0x00FF00
#property indicator_label3 "Exit Long"

#property indicator_type4 DRAW_ARROW
#property indicator_width4 5
#property indicator_color4 0x0000FF
#property indicator_label4 "Exit Short"

//Buffers
double Buffer1[];
double Buffer2[];
double Buffer3[];
double Buffer4[];
double Trigger[];

//Variable Declaration
datetime time_alert; 
bool Send_Email = true;
bool Audible_Alerts = true;
int inShort = 0;
int inLong = 0;
double Entry = 0;

//External Inputs

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | Trending Indicator @ "+Symbol()+","+Period()+" | "+message);
     }
   else if(type == "indicator")
     {
     if(Audible_Alerts) Alert(type+" | Trending Indicator @ "+Symbol()+","+Period()+" | "+message);
     if(Send_Email) SendMail(""+Symbol()+"" " | "+message, "");
     }
  }
  
void  ChartRedraw(
   long  chart_id=0      // Chart ID
   );

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   IndicatorBuffers(5);
   SetIndexBuffer(0, Buffer1);
   SetIndexEmptyValue(0, 0);
   SetIndexArrow(0, 241);
   SetIndexBuffer(1, Buffer2);
   SetIndexEmptyValue(1, 0);
   SetIndexArrow(1, 242);
   SetIndexBuffer(2, Buffer3);
   SetIndexEmptyValue(2, 0);
   SetIndexArrow(2, 251);
   SetIndexBuffer(3, Buffer4);
   SetIndexEmptyValue(3, 0);
   SetIndexArrow(3, 251);
   SetIndexBuffer(4, Trigger);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
   int limit = rates_total - prev_calculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(Buffer1, true);
   ArraySetAsSeries(Buffer2, true);
   ArraySetAsSeries(Buffer3, true);
   ArraySetAsSeries(Buffer4, true);
   ArraySetAsSeries(Trigger, true);
   if(prev_calculated < 1)
     {
      ArrayInitialize(Buffer1, 0);
      ArrayInitialize(Buffer2, 0);
      ArrayInitialize(Buffer3, 0);
      ArrayInitialize(Buffer4, 0);
      ArrayInitialize(Trigger, 0);
     }
   else
      limit++;
   


   for(int i = limit-1; i >= 0; i--)
     {
      if (i >= MathMin(5000-1, rates_total-1-50)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   

      //Indicator Buy Signal
      if(Open[i] > iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i)
      && Open[i+1] < iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i+1) //Candlestick Open crosses below Moving Average
      && inLong == 0
      )
        {
         Buffer1[i] = High[i]; //Set indicator value at Candlestick Low
         Trigger[i] = 1;
         inShort = 0;
         inLong = 1;
         Entry = Bid + ((Point*10)*11);
         if(i == 0 && Time[0] != time_alert){myAlert("indicator", "Open Buy @ " +Entry); time_alert = Time[0]; } //Instant alert, only once per bar
        }
      else
        {
         Buffer1[i] = 0;
         //Trigger[i] = 0;
        } 
         
      //Indicator Sell Signal
      if(Open[i] < iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i)
      && Open[i+1] > iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i+1) //Candlestick Open crosses below Moving Average
      && inShort == 0
      )
        {
         Buffer2[i] = Low[i]; //Set indicator value at Candlestick Low
         Trigger[i] = 2;
         inShort = 1;
         inLong = 0;
         Entry = Bid - ((Point*10)*11);
         if(i == 0 && Time[0] != time_alert) { myAlert("indicator", "Open Sell @ " +Entry); time_alert = Time[0]; } //Instant alert, only once per bar
        }
      else
        {
         Buffer2[i] = 0;
         Trigger[i] = 0;
        }
        
      //Indicator Exit Long
      if(Open[i] < iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_LOW, i)
      && Open[i+1] > iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_LOW, i+1) //Candlestick Open crosses below Moving Average
      && inLong == 1
      )
        {
         Buffer3[i] = High[i]; //Set indicator value at Candlestick High
         inLong = 0;
         if(i == 0 && Time[0] != time_alert) { myAlert("indicator", "Close Buy"); time_alert = Time[0]; } //Instant alert, only once per bar
        }
      else
        {
         Buffer3[i] = 0;
        }
        
      //Indicator Exit Short
      if(Open[i] > iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_HIGH, i)
      && Open[i+1] < iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_HIGH, i+1) //Candlestick Open crosses above Moving Average
      && inShort == 1
      )
        {
         Buffer4[i] = Low[i]; //Set indicator value at Candlestick Low
         inShort = 0;
         if(i == 0 && Time[0] != time_alert) { myAlert("indicator", "Close Sell"); time_alert = Time[0]; } //Instant alert, only once per bar
        }
      else
        {
         Buffer4[i] = 0;
        }

     }
   return(rates_total);
  }

So if you see anything that is obviously wrong please feel free to point it out. Thanks!!


Regards,

Nik

Amir Yacoby
1256
Amir Yacoby  
DrBeardface:

I did try that, and it didn't work. If it had it would have raised more questions though. The main problem I have here is that one of the nested if statements works fine, but the other one just won't no matter what I do. I've even tried removing the working one from code so that there's only on nested if statement, but it still won't do anything. Here's the code as it stands now:

It also doesn't work if I remove the first if statement (if (Spread >= 0) and just have the nested if statements on their own.


Just to cover all bases, here is the Indicator code. This works perfectly and does seem to generate the correct signals to pass along to the EA via iCustom:

So if you see anything that is obviously wrong please feel free to point it out. Thanks!!


Regards,

Nik

Just by glancing the code - not by trying:
You are running a script - not an ea (OnStart is for scripts).
Scripts run once the OnStart - and quit running - and in the code you check the current bar (0) of the indicator buffer Buffer4 (the 4th buffer in the indicator).
Looking at the buffer4 in the indicator you gave, there are sometimes you set it to 0 and sometimes you set a value.
Your If statement checks Trigger variable against values 1 or 2 - but it is probably zero for the current bar (0) and that's why you are not entering.

Lorentzos Roussos
14456
Lorentzos Roussos  
The issue was in your indicator , 
The new sell section had an "else" statement so basically , 
lets assume a buy signal was valid , then the code would check for a sell signal and if it was not valid it would trigger the else function 
and zero out the Trigger[i].

I placed zeroing out of Trigger Buffer1 Buffer2 before the checks .

#include <stdlib.mqh>
#include <stderror.mqh>

#property indicator_chart_window
#property indicator_buffers 5

#property indicator_type1 DRAW_ARROW
#property indicator_width1 5
#property indicator_color1 0x00FF00
#property indicator_label1 "Buy"

#property indicator_type2 DRAW_ARROW
#property indicator_width2 5
#property indicator_color2 0x0000FF
#property indicator_label2 "Sell"

#property indicator_type3 DRAW_ARROW
#property indicator_width3 5
#property indicator_color3 0x00FF00
#property indicator_label3 "Exit Long"

#property indicator_type4 DRAW_ARROW
#property indicator_width4 5
#property indicator_color4 0x0000FF
#property indicator_label4 "Exit Short"
#property strict
//Buffers
double Buffer1[];
double Buffer2[];
double Buffer3[];
double Buffer4[];
double Trigger[];

//Variable Declaration
datetime time_alert; 
bool Send_Email = true;
bool Audible_Alerts = true;
int inShort = 0;
int inLong = 0;
double Entry = 0;

//External Inputs

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | Trending Indicator @ "+Symbol()+","+Period()+" | "+message);
     }
   else if(type == "indicator")
     {
     if(Audible_Alerts) Alert(type+" | Trending Indicator @ "+Symbol()+","+Period()+" | "+message);
     if(Send_Email) SendMail(""+Symbol()+"" " | "+message, "");
     }
  }
  
void  ChartRedraw(
   long  chart_id=0      // Chart ID
   );

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   IndicatorBuffers(5);
   SetIndexBuffer(0, Buffer1);
   SetIndexEmptyValue(0, 0);
   SetIndexArrow(0, 241);
   SetIndexBuffer(1, Buffer2);
   SetIndexEmptyValue(1, 0);
   SetIndexArrow(1, 242);
   SetIndexBuffer(2, Buffer3);
   SetIndexEmptyValue(2, 0);
   SetIndexArrow(2, 251);
   SetIndexBuffer(3, Buffer4);
   SetIndexEmptyValue(3, 0);
   SetIndexArrow(3, 251);
   SetIndexBuffer(4, Trigger);
   SetIndexEmptyValue(4,0);
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
   int limit = rates_total - prev_calculated;
  


   for(int i = limit-1; i >= 0; i--)
     {
      if (i >= MathMin(5000-1, rates_total-1-50)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
      Buffer1[i]=0;
      Buffer2[i]=0;
      Trigger[i]=0;
      //Indicator Buy Signal
      if(Open[i] > iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i)
      && Open[i+1] < iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i+1) //Candlestick Open crosses below Moving Average
      && inLong == 0
      )
        {
         Buffer1[i] = High[i]; //Set indicator value at Candlestick Low
         Trigger[i] = 1;
         inShort = 0;
         inLong = 1;
         Entry = Bid + ((Point*10)*11);
         if(i == 0 && Time[0] != time_alert){myAlert("indicator", "Open Buy @ " +Entry); time_alert = Time[0]; } //Instant alert, only once per bar
        }        
      //Indicator Sell Signal
      if(Open[i] < iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i)
      && Open[i+1] > iMA(NULL, PERIOD_CURRENT, 40, 0, MODE_SMA, PRICE_LOW, i+1) //Candlestick Open crosses below Moving Average
      && inShort == 0
      )
        {
         Buffer2[i] = Low[i]; //Set indicator value at Candlestick Low
         Trigger[i] = 2;
         inShort = 1;
         inLong = 0;
         Entry = Bid - ((Point*10)*11);
         if(i == 0 && Time[0] != time_alert) { myAlert("indicator", "Open Sell @ " +Entry); time_alert = Time[0]; } //Instant alert, only once per bar
        }
        
      //Indicator Exit Long
      if(Open[i] < iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_LOW, i)
      && Open[i+1] > iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_LOW, i+1) //Candlestick Open crosses below Moving Average
      && inLong == 1
      )
        {
         Buffer3[i] = High[i]; //Set indicator value at Candlestick High
         inLong = 0;
         if(i == 0 && Time[0] != time_alert) { myAlert("indicator", "Close Buy"); time_alert = Time[0]; } //Instant alert, only once per bar
        }
      else
        {
         Buffer3[i] = 0;
        }
        
      //Indicator Exit Short
      if(Open[i] > iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_HIGH, i)
      && Open[i+1] < iMA(NULL, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_HIGH, i+1) //Candlestick Open crosses above Moving Average
      && inShort == 1
      )
        {
         Buffer4[i] = Low[i]; //Set indicator value at Candlestick Low
         inShort = 0;
         if(i == 0 && Time[0] != time_alert) { myAlert("indicator", "Close Sell"); time_alert = Time[0]; } //Instant alert, only once per bar
        }
      else
        {
         Buffer4[i] = 0;
        }

     }
   return(rates_total);
  }
DrBeardface
37
DrBeardface  
Lorentzos Roussos:
The issue was in your indicator , 
The new sell section had an "else" statement so basically , 
lets assume a buy signal was valid , then the code would check for a sell signal and if it was not valid it would trigger the else function 
and zero out the Trigger[i].

I placed zeroing out of Trigger Buffer1 Buffer2 before the checks .

Can't believe I missed that. Thanks a lot, it works perfectly now!!
12
To add comments, please log in or register