Download MetaTrader 5

Need help with drawing arrows, I think I'm having a problem getting the name to re-write?

To add comments, please log in or register
gagebrk
66
gagebrk  

Ok ! I'm having a problem being able to draw multiple arrows! Basically, if there's a higher high or higher close candle, then one of two functions will be run in the Draw Arrows functions area. I'm trying to add a number to the name of the arrow, so I can have multiple names draw multiple on the chart.

In order to do this I'm trying to concatenate a growing "counter" variable into the name of the arrow so that I can draw multiple. I think this is where I'm having the problem. The code as it stands will draw one of each kind of arrow as the rules are met, but then will not draw another arrow. I can't figure out where I'm going wrong with the re-naming, as that's where I think I'm going wrong.

Also, I know it's a mess with changing from integer to string and whatnot, but it runs. I know that the logic for the alert is right, because the alert goes off when the rules are met, but when it goes to run either of those draw functions, the function only draws an arrow one time.


Any help would be greatly appreciated!!! Also, I know I can clean those functions up, so any advice on that would also be great. Thanks for taking the time, guys :)

Also, if this is in the wrong forum, I apologize!


//--- input parameters
input color    LLLC_Color=clrRed;
input color    HHHC_Color=clrLime;



//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- draw arrow functions

//---
   return(INIT_SUCCEEDED);
  }
  
//+------------------------------------------------------------------+
//| Draw Arrows functions                        |
//+------------------------------------------------------------------+

void DrawUpArrow()
   {
   int counter = 10000;
   counter = IntegerToString(counter);
   string name = StringConcatenate("LLLCArrow " + counter);
   
   ObjectCreate(name,OBJ_ARROW_UP,0,iTime(NULL,0,1), Low[1]); 
      ObjectSet(name,OBJPROP_COLOR,LLLC_Color);
      ObjectSet(name,OBJPROP_STYLE,STYLE_DASH);
      ObjectSet(name,OBJPROP_WIDTH,1);
      ObjectSet(name,OBJPROP_ANCHOR,ANCHOR_UPPER);
      
   counter = StringToInteger(counter);
   counter += 1;
   
         
   }
   
void DrawDownArrow()
   { 
   int counter = 10000;
   counter = IntegerToString(counter);
   string name = StringConcatenate("HHHCArrow " + counter); 
   
   ObjectCreate(name,OBJ_ARROW_DOWN,0,iTime(NULL,0,1),High[1]);
      ObjectSet(name,OBJPROP_COLOR,HHHC_Color);
      ObjectSet(name,OBJPROP_STYLE,STYLE_DASH);
      ObjectSet(name,OBJPROP_WIDTH,1);
      ObjectSet(name,OBJPROP_ANCHOR,ANCHOR_LOWER);
      
   counter = StringToInteger(counter);
   counter += 1;   
   }
   
  
  
//+------------------------------------------------------------------+
//| 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[])
  {
   static datetime last_bar = 0;
   datetime this_bar = Time[0];
   if(last_bar != this_bar)
      {
      //Do stuff here once per bar
       if (Close[1]<Low[2])
         {
          Alert (Symbol() + " LLLC");
          DrawUpArrow();
          last_bar = this_bar;
         }
         
       if (Close[1]>High[2])
         {
          Alert (Symbol() + " HHHC");
          DrawDownArrow();
          last_bar = this_bar;
         }
      }
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,"LLLCArrow");
   ObjectsDeleteAll(0,"HHHCArrow");
  }
gagebrk
66
gagebrk  

UPDATE:

I changed

int counter = 10000;

to

int counter = MathRand();
and the it works! So I know the logic is right. I really don't want to be using a random number though, so if you guys can help me get that counter working, that would be great :)
Alain Verleyen
Moderator
33502
Alain Verleyen  

Use :

   static int counter = 10000;
gagebrk
66
gagebrk  
Alain Verleyen:

Use :

*smacks head against the wall*

Ohhhh boy. Dummy move right there, I didn't see that. Thank you!

whroeder1
16104
whroeder1  

Why are you creating objects? Why don't you create a arrow buffer?

gagebrk
66
gagebrk  
whroeder1:

Why are you creating objects? Why don't you create a arrow buffer?

Frankly, because I've only done one other little indicator, and that's just how I did it the last time, by creating objects. What would the pros of a buffer be, and what are the cons of creating objects like I am? The code works splendidly as it stands, but if there's a way to make it better, I'm all ears! :)
whroeder1
16104
whroeder1  
gagebrk What would the pros of a buffer be, and what are the cons of creating objects like I am?
  1. Can be read by iCustom. No naming problems. Creation/deletion/movement by buffer element value.
  2. Can't. Naming problems. Multiple calls to create/move. CPU and memory intensive for the terminal.
gagebrk
66
gagebrk  

This is the updated code. I added a few more things like being able to select a price zone, instead of just showing all the arrows all the time. I had originally wanted to just draw a rectangle, but I was having a hard time getting the rectangle to draw into a future time on the chart. I just have it draw H lines now, until I get that figured out. I also threw some stuff into functions to help clean it up.


//--- input parameters
input color    LLLC_Color=clrRed;
input color    HHHC_Color=clrLime;
input color    Zone_Color=clrLightSkyBlue;

input bool BuyOnly = False;
input bool SellOnly = False;
input bool SellInZone = False;
input bool BuyInZone = False;
input double Zone1Top = 0.0;
input double Zone1Bottom = 0.0;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 
   if (Zone1Bottom != 0.0 && Zone1Top != 0.0)
      DrawLines();

//---
   return(INIT_SUCCEEDED);
  }
  
//+------------------------------------------------------------------+
//| Functions                        |
//+------------------------------------------------------------------+

void DrawUpArrow()
   {
   static int counter = 10000;
   counter = IntegerToString(counter);
   string name = StringConcatenate("LLLCArrow " + counter);
   
   ObjectCreate(name,OBJ_ARROW_UP,0,iTime(NULL,0,1), Low[1]); 
      ObjectSet(name,OBJPROP_COLOR,LLLC_Color);
      ObjectSet(name,OBJPROP_STYLE,STYLE_DASH);
      ObjectSet(name,OBJPROP_WIDTH,1);
      //ObjectSet(name,OBJPROP_ANCHOR,ANCHOR_UPPER);
      ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_TOP);
      
   counter = StringToInteger(counter);
   counter = counter += 1;
   }
   
void DrawDownArrow()
   { 
   static int counter = 10000;
   counter = IntegerToString(counter);
   string name = StringConcatenate("HHHCArrow " + counter); 
   
   ObjectCreate(name,OBJ_ARROW_DOWN,0,iTime(NULL,0,1),High[1]);
      ObjectSet(name,OBJPROP_COLOR,HHHC_Color);
      ObjectSet(name,OBJPROP_STYLE,STYLE_DASH);
      ObjectSet(name,OBJPROP_WIDTH,1);
      //ObjectSet(name,OBJPROP_ANCHOR,ANCHOR_LOWER);
      ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
      
   counter = StringToInteger(counter);
   counter = counter += 1; 
     
   }
   
//This still needs to be implemented. 
//void DrawRectangle() 
//   { 
//   static int counter = 10000;
//   counter = IntegerToString(counter);
//   string name = StringConcatenate("Zone " + counter); 
//   
//   ObjectCreate(name,OBJ_RECTANGLE,0,iTime(NULL,0,1),Zone1Top,Time[0] + (Period() * 60),Zone1Bottom);
//      ObjectSet(name,OBJPROP_COLOR,Zone_Color);
//      ObjectSet(name,OBJPROP_STYLE,STYLE_DASH);
//      ObjectSet(name,OBJPROP_WIDTH,1);
//     
//      
//   counter = StringToInteger(counter);
//   counter = counter += 1; 
//     
//   }
   
void DrawLines()
   {
   ObjectCreate("ZoneTop",OBJ_HLINE,0,Time[0],Zone1Top);
      ObjectSet("ZoneTop",OBJPROP_COLOR,Zone_Color);
      ObjectSet("ZoneTop",OBJPROP_STYLE,STYLE_DASH);
      ObjectSet("ZoneTop",OBJPROP_WIDTH,1);
   
   ObjectCreate("ZoneBottom",OBJ_HLINE,0,Time[0],Zone1Bottom);
      ObjectSet("ZoneBottom",OBJPROP_COLOR,Zone_Color);
      ObjectSet("ZoneBottom",OBJPROP_STYLE,STYLE_DASH);
      ObjectSet("ZoneBottom",OBJPROP_WIDTH,1);
   }
   
void ShowBuys()
   {
      if (Close[1]>High[2])
            {
             Alert (Symbol() + " HHHC");
             DrawDownArrow();
             
            } 
   }

void ShowSells()
   {
      if (Close[1]<Low[2])
            {
             Alert (Symbol() + " LLLC");
             DrawUpArrow();
            }
   
   }
  
//+------------------------------------------------------------------+
//| 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[])
  {
   static datetime last_bar = 0;
   datetime this_bar = Time[0];
   if(last_bar != this_bar)
      {
      //Do stuff here once per bar
       if (BuyOnly == True && SellOnly == False) //No Zone, show buys
            {
             ShowBuys();
             last_bar = this_bar;
            } 
            
       if (BuyOnly == False && SellOnly == True) //No Zone, show sells 
            {
             ShowSells();
             last_bar = this_bar;
            }
            
       if (BuyInZone == False && SellInZone == False) //No Zone, show all
            {
             ShowBuys();
             last_bar = this_bar;
             ShowSells();
             last_bar = this_bar;
            }
            
       if (SellInZone == True && BuyInZone == False) //Sell only
          if (Ask > Zone1Bottom && Ask < Zone1Top) //if in zone
               {
                ShowSells();
                last_bar = this_bar;
               }
               
       if (BuyInZone == True && SellInZone == False) //Buy only
          if (Ask > Zone1Bottom && Ask < Zone1Top) //if in zone
               {
                ShowBuys();
                last_bar = this_bar;
               }     
       if (BuyInZone == True && SellInZone == True) //Buy and Sell
          if (Ask > Zone1Bottom && Ask < Zone1Top) //if in zone
             if (Close[1]<Low[2])
            {
              ShowBuys();
              last_bar = this_bar;
              ShowSells();
              last_bar = this_bar;
            }
            
         
      }
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,"LLLCArrow");
   ObjectsDeleteAll(0,"HHHCArrow");
   ObjectsDeleteAll(0,"Zone");
  }
gagebrk
66
gagebrk  
whroeder1:
  1. Can be read by iCustom. No naming problems. Creation/deletion/movement by buffer element value.
  2. Can't. Naming problems. Multiple calls to create/move. CPU and memory intensive for the terminal.

Looks like we posted at the same time!

Awesome! I'll go dig into the documentation and see if I can figure it out!

Edit: Also just saw that I should be checking if Close[1] is in the zone, not the Ask. Gonna change that real quick.

gagebrk
66
gagebrk  
whroeder1:

Why are you creating objects? Why don't you create a arrow buffer?


Ok... So I've been trying to get this figured. I've been reading everything I can about using buffers, but I'm having a problem figuring out how the buffers draw on the chart.

I've got the buffers setup:

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Green
#property indicator_color2 Red

double arrowUp[],arrowDown[];


//--- input parameters
input color    LLLC_Color=clrRed;
input color    HHHC_Color=clrLime;
input color    Zone_Color=clrLightSkyBlue;

and I've got the indexes setup:

int OnInit()
  {
//--- 

   SetIndexBuffer(0,arrowUp);       
   SetIndexStyle (0,DRAW_ARROW);
   SetIndexArrow (0,241);
   SetIndexBuffer(1,arrowDown);  
   SetIndexStyle (1,DRAW_ARROW);
   SetIndexArrow (1,242);
   return(0);                         

but I'm having a problem with figuring out how to actually utilize these buffers based on a criteria... Seems like everything I've seen, people are using a for loop to iterate over all the candles, in order to draw something on the chart.

Really, I have the logic for when I want these to be printed, but I'm not sure how to have the buffer draw using the individual candles that are found using my criteria.

 I think I have to have the buffer tied into my drawing functions (yanking out the CreateObject stuff), but the more I try to get it figured out the more confused I'm getting. I'm definitely missing something here.

I'm NOT asking someone to code this whole thing for me, I really want to learn how this works, but I could definitely use some guidance and a push in the right direction. Where do I actually want to be calling for these buffers I've made?

Marco vd Heijden
Moderator
5671
Marco vd Heijden  

Dear Garagebrk there are many examples in code base for you to examine and even the standard indicators that come with the platform can be analyzed.

Here is a good example:

//+------------------------------------------------------------------+
//| 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[])
  {
//--- check for rates
   if(rates_total<InpChannelPeriod) return(0);
//--- preliminary calculations
   if(prev_calculated==0) limit=InpChannelPeriod;
   else limit=prev_calculated;
//--- the main loop of calculations
   for(i=limit;i<rates_total && !IsStopped();i++)
     {
      start=i-InpChannelPeriod;
      ExtHighBuffer[i]=high[ArrayMaximum(high,start,InpChannelPeriod)];
      ExtLowBuffer[i]=low[ArrayMinimum(low,start,InpChannelPeriod)];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
The full code can be viewed here https://www.mql5.com/en/code/viewcode/1601/128511/donchian_channel.mq5
12
To add comments, please log in or register