Trend Line class

 

Hi ..  I have coded a new class for defining and saving trend line as below:

class TrendLine
  {
public:
   datetime          time1,time2;
   double            price1,price2;

                     TrendLine(void){};
                     TrendLine(datetime t1,double p1,datetime t2,double p2)
     { time1=t1; price1=p1; time2=t2; price2=p2;};
                    ~TrendLine(void){};
   double            getvaluebytime(datetime t)
     {
      double price;
      double angle=MathAbs((price1-price2)/(time1-time2));
      price=angle*MathAbs(t-time1)+price1;
      return price;
     }
   void              setanchorpoint(int ind,datetime t,double p)
     {               if(ind==1) {time1=t; price1=p;} else if(ind==2) {time2=t; price2=p; } return;}
  };



 

but when I use  getvaluebytime function it does not return a correct value !!

I write a test expert and you can see the value that trend line class's method returns is different from the metatrader's TL object

please help me and say what is wrong with my code

TrendLine tl;
   double p1,p2;
   string object_name;
   int obj_total=ObjectsTotal();
   for(int j=0; j<obj_total; j++)
     {
      object_name=ObjectName(j);
      if(ObjectGetInteger(0,object_name,OBJPROP_TYPE,0)==OBJ_TREND)
        {
         p1=ObjectGetValueByTime(0,object_name,TimeCurrent(),0);
         
         tl.setanchorpoint(1,ObjectGetInteger(0,object_name,OBJPROP_TIME,0), ObjectGetDouble(0,object_name,OBJPROP_PRICE,0));
         tl.setanchorpoint(1,ObjectGetInteger(0,object_name,OBJPROP_TIME,1), ObjectGetDouble(0,object_name,OBJPROP_PRICE,1));


        }
     }
   p2=tl.getvaluebytime(TimeCurrent());
   Comment("\n\n get from object = ",p1,"\n\n get from class = ",p2);
Documentation on MQL5: Constants, Enumerations and Structures / Objects Constants / Object Types
Documentation on MQL5: Constants, Enumerations and Structures / Objects Constants / Object Types
  • www.mql5.com
When a graphical object is created using the ObjectCreate() function, it's necessary to specify the type of object being created, which can be one of the values of the ENUM_OBJECT enumeration. Further specifications of object properties are possible using functions for working with graphical objects.
 
Please edit your post and
use the code button (Alt+S) when pasting code
 
  1. Please edit your (original) post and use the CODE button (Alt-S)! (For large amounts of code, attach it.)
              General rules and best pratices of the Forum. - General - MQL5 programming forum 2019.05.06
              Messages Editor

  2. double angle=MathAbs((price1-price2)/(time1-time2));

    There is no angle from 2 anchor points. An angle requires distance divided by distance; a unit-less number. A chart has price and time. What is the angle of going 30 miles in 45 minutes? Meaningless!

  3. Slope can be rising or falling; the MathAbs is wrong. You can get the slope from a trendline: m=ΔPrice÷ΔTime. Changing the price scale, bar width, or window size, changes the apparent angle, the slope is constant. Angle is meaningless.

  4. You can create an angled line using one point and setting the angle (Object Properties - Objects Constants - Standard Constants, Enumerations and Structures - MQL4 Reference.) The line is drawn that angle in pixels. Changing the axes scales does NOT change the angle (and thus is meaningless.)

  5. If you insist, take the two price/time coordinates, convert them to pixel coordinates and then to apparent angle with arctan.
              How to get the angle of a trendline and place a text object to it? - Trend Indicators - MQL4 programming forum - Page 2

  6. Mehrdad Sarrafi: I write a test expert and you can see the value that trend line function return  is different from the metatrader TL object
    tl.setanchorpoint(1,ObjectGetInteger(0,object_name,OBJPROP_TIME,0), ObjectGetDouble(0,object_name,OBJPROP_PRICE,0));
    tl.setanchorpoint(1,ObjectGetInteger(0,object_name,OBJPROP_TIME,1), ObjectGetDouble(0,object_name,OBJPROP_PRICE,1));
    
    Try setting two (2) anchor points, not one twice.
 

Try this .

Remember if you intend to represent stuff visually the chart may have gaps .For instance , the weekend is missing from most charts .

Also you had one anchor point 

#property copyright "Thread In Mql5.com"
#property link      "https://www.mql5.com/en/forum/351166"
#property description "Telegram  : https://t.me/lorentzor\nInstagram : @rlorentzo\nTwitter : @lorentzo_r\nLinkedIn : https://www.linkedin.com/in/lorentzor\nYoutube : https://www.youtube.com/channel/UCM0Lj06cAJagFWvSpb9N5zA\nFacebook  : @LorentzoR"
/* 
ways to connect .> : 
Telegram  : https://t.me/lorentzor
Instagram : https://www.instagram.com/rlorentzo /OR/ @rlorentzo
Twitter   : https://twitter.com/lorentzo_r /OR/ @lorentzo_r
LinkedIn  : https://www.linkedin.com/in/lorentzor
Youtube   : https://www.youtube.com/channel/UCM0Lj06cAJagFWvSpb9N5zA
Facebook  : https://www.facebook.com/LorentzoR /OR/ @LorentzoR
Mql5.com  : https://www.mql5.com/en/users/lorio
*/
#property version   "1.00"
#property strict
class trend_line
{
bool valid;
string object;
long chartid;
double price_a,price_b,step_per_bar;
datetime time_a,time_b;
int subwindow,bar_a,bar_b,bar_distance;
void reset(bool del_obj){bar_distance=0;valid=false;bar_a=-1;bar_b=-1;if(del_obj&&object!=NULL){ObjectDelete(chartid,object);}object=NULL;chartid=NULL;}
public:
trend_line(void){reset(true);}
trend_line(long chart_id,int sub_w,string obj_name)
 {
 reset(true);
 ResetLastError();
 int errors=0;
 Print("Object "+obj_name+" is = "+IntegerToString(ObjectGetInteger(chart_id,obj_name,OBJPROP_TYPE)));
 //if object is trend
 if(ObjectGetInteger(chart_id,obj_name,OBJPROP_TYPE)!=OBJ_TREND){Print(__FUNCTION__+"::: Object Not Trend");}
 if(ObjectGetInteger(chart_id,obj_name,OBJPROP_TYPE)==OBJ_TREND)
 {
 object=obj_name;
 //get specs from object 
   price_a=ObjectGetDouble(chart_id,obj_name,OBJPROP_PRICE1);errors+=GetLastError();
   price_b=ObjectGetDouble(chart_id,obj_name,OBJPROP_PRICE2);errors+=GetLastError();
   time_a=(datetime)ObjectGetInteger(chart_id,obj_name,OBJPROP_TIME1);errors+=GetLastError();
   time_b=(datetime)ObjectGetInteger(chart_id,obj_name,OBJPROP_TIME2);errors+=GetLastError();
   chartid=chart_id;
   subwindow=sub_w;
   //find bars 
     bar_a=iBarShift(_Symbol,_Period,time_a,true);errors+=GetLastError();
     bar_b=iBarShift(_Symbol,_Period,time_b,true);errors+=GetLastError();
   //find bars 
     if(errors==0){
     bar_distance=bar_a-bar_b;//because series
     valid=true;
     }
 }
 //if object is trend 
 }
~trend_line(void){reset(true);}
double GetPriceByTime(datetime time,bool exact)
{
double price=0;
//is it valid ?
  if(valid)
  {
  //is the time valid ?
    if(time>=time_a&&time<=time_b)
    {
    //this time corresponds to a bar 
    int time_bar=iBarShift(_Symbol,_Period,time,exact);
    if(time_bar!=-1){
      //we acquire the bars again because they might have changed bar index 
        int errors=0;
        ResetLastError();
        int new_bar_a=iBarShift(_Symbol,_Period,time_a,true);errors+=GetLastError();
        int new_bar_b=iBarShift(_Symbol,_Period,time_b,true);errors+=GetLastError();
        //if no errors 
          if(errors==0)
          {
          bar_a=new_bar_a;bar_b=new_bar_b;bar_distance=bar_a-bar_b;
          //step 
          step_per_bar=(price_b-price_a)/((double)bar_distance);
          price=price_a+step_per_bar*((double)(bar_a-time_bar));
          price=NormalizeDouble(price,Digits());
          }
        //if no errors 
      }
    }
  //is the time valid ? ends here 
  }
//is it valie ? ends here 
return(price);
}
};
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
trend_line *tr;
int OnInit()
  {

  ObjectsDeleteAll(ChartID(),"TESTS_");
  ObjectCreate(ChartID(),"TEST_TREND",OBJ_TREND,0,Time[20],High[20],Time[1],Low[1]);
  tr=new trend_line(ChartID(),0,"TEST_TREND");
  double price=tr.GetPriceByTime(Time[5],true);
  Print("Price Found : "+DoubleToString(price,Digits()));
  ObjectCreate(ChartID(),"TEST_MARK",OBJ_TEXT,0,Time[5],price);
  ObjectSetInteger(ChartID(),"TEST_MARK",OBJPROP_ANCHOR,ANCHOR_CENTER);
  ObjectSetString(ChartID(),"TEST_MARK",OBJPROP_TEXT,"-O-");
  ObjectSetInteger(ChartID(),"TEST_MARK",OBJPROP_FONTSIZE,25);
  ObjectSetString(ChartID(),"TEST_MARK",OBJPROP_FONT,"Arial Black");
  ObjectSetInteger(ChartID(),"TEST_MARK",OBJPROP_COLOR,clrDodgerBlue);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  delete tr;
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }
//+------------------------------------------------------------------+
Reason: