Problem when adding Indicator to Template

 

Hey Guys,

short question: I've written a custom indicator (see below) just drawing 3 trendlines. Everything works just fine. However, when adding the indicator to my template and apllying this template to a different currency pair the lines are not drawn. Then, when i open the indicator list clicking edit on my custom indicator and ok the lines are drawn -.- Any ideas? Thanks in advance :)


EDIT: It might have something to do with my check variable? Like it is still set to true when loading the template or something like this? No idea ...

#property indicator_chart_window
//--- input parameters
extern int       DaysOfInterest=1;
extern color     LineColorHigh=DarkBlue,LineColorLow=Red, LineColorOpen=Green;
extern int       LineStyleHigh=1,LineStyleLow=1,LineStyleOpen=1,FontSize=10;

double           high,low,open;
datetime         time,timeToday,period;
int              ObjIdx;
string           ObjName,TextName;
int              TYPE_HIGH=0,TYPE_LOW=1,TYPE_OPEN=2;
bool             check=false;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   for(int i=1;i<=ObjIdx;i++){
      ObjectDelete("Line"+DoubleToStr(i,0));
      ObjectDelete("HighLowText"+DoubleToStr(i,0));
   }
   check=false;
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   if(!check){
      period=iTime(Symbol(),Period(),0);
      for(int y=1;y<=DaysOfInterest;y++){   
         high = iHigh(Symbol(),PERIOD_D1,y);
         low = iLow(Symbol(),PERIOD_D1,y);
         open = iOpen(Symbol(),PERIOD_D1,y-1);
         time = iTime(Symbol(),PERIOD_D1,y);
         timeToday = iTime(Symbol(),PERIOD_D1,y-1);
         TrendLine(time,high,time+(60*PERIOD_D1*20),high,LineColorHigh,LineStyleHigh,TYPE_HIGH,y);
         TrendLine(time,low,time+(60*PERIOD_D1*20),low,LineColorLow,LineStyleLow,TYPE_LOW,y);
         TrendLine(timeToday,open,timeToday+(60*PERIOD_D1*21),open,LineColorOpen,LineStyleOpen,TYPE_OPEN,y);       
         check=true;
      }  
   }
   //new bar or new period - move text
   if(period!=iTime(Symbol(),Period(),0)){
      moveText();
      period=iTime(Symbol(),Period(),0);
   }
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Draws a Trendline                                                |
//+------------------------------------------------------------------+
void TrendLine(datetime x1, double y1, datetime x2, double y2, color col, int style,int type, int day)
   {
   ObjIdx++;
   
   if(type==TYPE_HIGH){
      ObjName="Line" + DoubleToStr(ObjIdx,0);
      TextName="HighLowText"+DoubleToStr(ObjIdx,0);   
      ObjectCreate(ObjName, OBJ_TREND, 0, x1, y1, x2, y2);
      ObjectSet(ObjName,OBJPROP_COLOR,col);
      ObjectSet(ObjName,OBJPROP_RAY,0);    
      ObjectSet(ObjName,OBJPROP_STYLE,style);
      ObjectCreate(TextName,OBJ_TEXT,0,iTime(Symbol(),Period(),0)+(150*Period()),y1,iTime(Symbol(),Period(),0)+(150*Period()),y1);
      ObjectSetText(TextName,StringConcatenate("High (-",day,")"),FontSize,"Arial",Black);
      
      }
   if(type==TYPE_LOW){
      ObjName="Line" + DoubleToStr(ObjIdx,0);
      TextName="HighLowText"+DoubleToStr(ObjIdx,0);   
      ObjectCreate(ObjName, OBJ_TREND, 0, x1, y1, x2, y2);
      ObjectSet(ObjName,OBJPROP_COLOR,col);
      ObjectSet(ObjName,OBJPROP_RAY,0);    
      ObjectSet(ObjName,OBJPROP_STYLE,style);
      ObjectCreate(TextName,OBJ_TEXT,0,iTime(Symbol(),Period(),0)+(150*Period()),y1,iTime(Symbol(),Period(),0)+(150*Period()),y1);
      ObjectSetText(TextName,StringConcatenate("Low (-",day,")"),FontSize,"Arial",Black);
     
      }
   if(type==TYPE_OPEN){
      ObjName="Line" + DoubleToStr(ObjIdx,0);
      TextName="HighLowText"+DoubleToStr(ObjIdx,0);   
      ObjectCreate(ObjName, OBJ_TREND, 0, x1, y1, x2, y2);
      ObjectSet(ObjName,OBJPROP_COLOR,col);
      ObjectSet(ObjName,OBJPROP_RAY,0);    
      ObjectSet(ObjName,OBJPROP_STYLE,style);
      ObjectCreate(TextName,OBJ_TEXT,0,iTime(Symbol(),Period(),0)+(150*Period()),y1,iTime(Symbol(),Period(),0)+(150*Period()),y1);
      ObjectSetText(TextName,StringConcatenate("OOpen (-",day,")"),FontSize,"Arial",Black);
      
      }
 }
 
 void moveText()
  {
   for(int i=1;i<=ObjIdx;i++){
      ObjectSet("HighLowText"+DoubleToStr(i,0),OBJPROP_TIME1, iTime(Symbol(),Period(),0)+(150*Period()));
      ObjectSet("HighLowText"+DoubleToStr(i,0),OBJPROP_TIME2, iTime(Symbol(),Period(),0)+(150*Period()));
      
   }
   return(0);
  }
 

Do your Objects already exist in the template ?

Check the return value from your ObjectCreate . . . if it is false check the error, it is probably 4200 "ERR_OBJECT_ALREADY_EXISTS" when you change timeframes deinit is called which deletes the Objects . . .

 

Hi,

thanks for your answer. You were right: when I'm changing timeframes the lines and corresponding text appears. However, when the template is freshly loaded the objects are created (I can see them in the object list) but not visible (even if I click on "Show" in the object list)...I'm a bit clueless here..


EDIT: As I'm new to MQL - is there something like a command line to output errors. Or at least a log or something?

 
TJmclovin:

Hi,

thanks for your answer. You were right: when I'm changing timeframes the lines and corresponding text appears. However, when the template is freshly loaded the objects are created (I can see them in the object list) but not visible (even if I click on "Show" in the object list)...I'm a bit clueless here..


EDIT: As I'm new to MQL - is there something like a command line to output errors. Or at least a log or something?

You have probably created the Template on a different pair, so the trendlines will be off screen on a different pair . . . for example GBPUSD vs USDJPY.

If you want to log stuff just use Print(); it outputs to the Journal tab if you are using the Strategy Tester and to the Experts tab if you are running in Demo or Live (and also in the corresponding log files in tester/logs and experts/logs).

 
Ah okay. Cheers. I thought whenever I load a template containing indicators it will run as a new instance ... So there is no way to avoid this? Is a template always bound to a specific pair?
 
TJmclovin:
Ah okay. Cheers. I thought whenever I load a template containing indicators it will run as a new instance ... So there is no way to avoid this? Is a template always bound to a specific pair?

What is making your issue a problem is partly because your Indicator is using Objects not Indicator buffers and Indicator lines, you can get round this in a number of ways :

  • make sure the trendlines are not on the chart when you save the template
  • delete the trendline Objects within init()

but really what you should do is use ObjectFind to determine if the trendline objects exist before you try to create them again . . . if they do exist then just use ObjectSet to change their position or other attributes, if they don't exist then go ahead and create them.

 
Thanks! This helped me a lot!!
 
When you created your template, the objects existed, thus your ObjectCreate fails. I always code it move or create.
void TLine( string name, datetime T0, double P0, datetime T1, double P1,
            color clr, double V0=INF, double V1=INF, bool ray=false){
    if (!Show.Objects)  return;                 #define WINDOW_MAIN 0
    if      (ObjectMove( name, 0, T0, P0 ))     ObjectMove(name, 1, T1, P1);
    else if (!ObjectCreate( name, OBJ_TREND, WINDOW_MAIN, T0, P0, T1, P1 ))
        Alert("ObjectCreate(",name,",TREND) failed: ", GetLastError() );
    else if (!ObjectSet( name, OBJPROP_RAY, ray ))
        Alert("ObjectSet(", name, ",Ray) failed: ", GetLastError());
    if (!ObjectSet(name, OBJPROP_COLOR, clr )) // Allow color change
        Alert("ObjectSet(", name, ",Color) [4] failed: ", GetLastError());
    if (V0 == INF || V0 == P0){
        string  P0t = PriceToStr(P0);           if (MathAbs(P0 - P1) >= Point)
                P0t = StringConcatenate(P0t, " to ", PriceToStr(P1));       }
    else if (V0 == V1)  P0t = StringConcatenate(V0,""); // Suppress trailing to
    else                P0t = StringConcatenate(V0, " to ", V1);
    if (!ObjectSetText(name, P0t, 10))
        Alert("ObjectSetText(",name,") [2] failed: ", GetLastError());
}
// V0, V1 is used only for price overlays
 
Thank you very much guys. I quick fixed it and now it's working. Next time I'll definitely go with indicator buffers. Otherwise I'll get a huge headache if I use more and more indicators and thus objects.
Reason: