Programmatically equaling time on chart?

 

Greetings,

  Below I have a function intended to determine the intersection of 2 ('Object Trend') lines drawn on a chart.  The issue is that the 'intersection time' being reported does not seem to equal what I am seeing visually on the chart.  In the function the 'time' of the intersection is set as the variable for "x", while the 'price' at the intersection is set as the variable for "y".  The 'intersection time' is set as the variable "intersectionTime".  This problem might possibly be caused by some conversion error involving 'double' and 'datetime' variables in the MQL5 language...however I'm not exactly sure.  There also appear to be issues involving the comparison of "intersectionTime" and "lastTime" (is a direct comparison as I have written it possible in MQL5?) and possibly the display of the "y" variable for price.  Any suggestions greatly appreciated.


// Function to check if two lines intersect
bool DoLinesIntersect(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, int primary, int secondary) {

   // Get the index of the first visible bar on the chart
   long firstVisibleBar = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
   // Get the number of visible bars on the chart
   long visibleBars = ChartGetInteger(0, CHART_VISIBLE_BARS);
   // Calculate the index of the last visible bar
   long lastVisibleBar = MathAbs(firstVisibleBar - visibleBars) - 1;
   // Get the time of the last visible bar
   datetime lastTime = iTime(NULL, 0, lastVisibleBar);
    
    // Calculate slopes
    double m1 = (y2 - y1) / (x2 - x1);  
    double m2 = (y4 - y3) / (x4 - x3);

    // Check if lines are parallel
    if (m1 == m2) {
        return false;
    }

    // Calculate intersection point
    double x = (-m2 * x3 + y3 + m1 * x1 - y1) / (m1 - m2);
    double y = m1 * (x - x1) + y1;

    // Cast 'x' to datetime
    datetime intersectionTime = (datetime)x;
 Print("intersectionTime is: ", intersectionTime);   

    if ((intersectionTime <= lastTime) && (y >= MIN_PRICE) && (y <= MAX_PRICE)) {
    
        Print("Line Intersections Points Detected: X=", intersectionTime, " , Y=", (double)y, "...BAR #", primary, " intersects with BAR#", secondary);    
        return true;
            
    }  //'x' is BEFORE the TIME ENTRY of the LAST BAR ON THE RIGHT SIDE OF THE CHART...AND
       //'y' lies WITHIN the MAXIMUM and MINIMUM price values plotted on the chart.  
       //Therefore the 'intersection' occurs within the visible area of the chart.   

    
    return false; 
    
}

I thank you in advance for any assistance.

 

The X-axis is quantized by chosen time frame. For example in a H1 time frame you do not have 09:15.

Anywhere except those quantized points there is no valid data per trend line. Unless the trend lines are too large you get totally inaccurate results. If you choose a non-existing point on chart it rounds to nearest existing point which can be very different from what you expect.

 
Thanks for the reply, so if my chart is a 'Daily' (D1) then the 'rounding' could be significant I guess.  Any way to correct for that?
 
pangit68 #:
Thanks for the reply, so if my chart is a 'Daily' (D1) then the 'rounding' could be significant I guess.  Any way to correct for that?

Maybe temporarily switch to lowest possible time frame and do the calculations there.

 
pangit68:

Greetings,

  Below I have a function intended to determine the intersection of 2 ('Object Trend') lines drawn on a chart.  The issue is that the 'intersection time' being reported does not seem to equal what I am seeing visually on the chart.  In the function the 'time' of the intersection is set as the variable for "x", while the 'price' at the intersection is set as the variable for "y".  The 'intersection time' is set as the variable "intersectionTime".  This problem might possibly be caused by some conversion error involving 'double' and 'datetime' variables in the MQL5 language...however I'm not exactly sure.  There also appear to be issues involving the comparison of "intersectionTime" and "lastTime" (is a direct comparison as I have written it possible in MQL5?) and possibly the display of the "y" variable for price.  Any suggestions greatly appreciated.


I thank you in advance for any assistance.

You are calculating your slope with the count of bars, but you fail to convert the intersection result back from "count of bars" to actual time.

The cast operation you are doing is only changing the type of value, but it's not calculating the time of the bar you have identified to be the intersection.

You could use BarShift function to convert it back to time.
 

Thank you for the replies,

  So I should use the 'iBarShift' to convert 'intersectionTime' to the index of the bar corresponding to the specified time?  On a 'Daily' chart that might still be inaccurate, I would think...since the intersection time and price should be more precise than just a bar index. 

  Can the results of my calculations ('x' and 'y') in the example I provided be an considered accurate plot of intersection, or is it dependent upon the time period on the chart?

  This MQL5 language is extremely frustrating, is there any example someplace of code that will find line intersections and correctly log X and Y coordinates, and/or plot graphical objects on the chart AT THE POINT OF THE INTERSECTION accurately?  Thank you in advance.


Regards

 

In your code (x1, x2) can be non-existent points on chart. Better to round them to existing ones in M1 time frame. Then find the intersection (what your code is doing is fine about this). 

//round x1 and x2 to closest existing M1 bar on chart
x1=iTime(_Symbol, PERIOD_M1, iBarShift(_Symbol, PERIOD_M1, x1, false));
x2=iTime(_Symbol, PERIOD_M1, iBarShift(_Symbol, PERIOD_M1, x2, false));
//Now call your function
bool DoLinesIntersect(x1, y1, x2, y2... )
 

Thanks for the reply Yashar,

  So I should revise my computations before calling the "DoLinesIntersect" function?  I had previously been passing information similar to the following:

            double xA1 = (double)ObjectGetInteger(0, "TopOpen_" + IntegerToString(bar1), OBJPROP_TIME, 0);
            double yA1 = ObjectGetDouble(0, "TopOpen_" + IntegerToString(bar1), OBJPROP_PRICE, 0);
            double xA2 = (double)ObjectGetInteger(0, "TopOpen_" + IntegerToString(bar1), OBJPROP_TIME, 1);
            double yA2 = ObjectGetDouble(0, "TopOpen_" + IntegerToString(bar1), OBJPROP_PRICE, 1);

            (DoLinesIntersect(xA1, yA1, xA2, yA2, ...)

  And instead I should modify as you posted so as to return the closest bar on the minute chart...?  As so:

           //round x1 and x2 to closest existing M1 bar on chart
           x1=iTime(_Symbol, PERIOD_M1, iBarShift(_Symbol, PERIOD_M1, xA1, false));
           x2=iTime(_Symbol, PERIOD_M1, iBarShift(_Symbol, PERIOD_M1, xA2, false));

  And this is done for the purpose of establishing the most accurate intersection return (as rounded to the minute) regardless of the chart timeframe used?  Thank you again.


Regards 

 
Your originally calculated value is most accurate but to match it with what you see on chart I think you should switch to M1. However rounding endpoints to nearest existing points also helps you to see closer results to what you calculate.
Note: I think we should not complicate it further. All you need to do is load the visual trend lines in lower time frame to see the accuracy of your calculation.
 

Thanks Yashar I will attempt your idea later when I have the opportunity.  I will see about converting the starting and ending points of the object lines into M1 calculations, thanks for your input (and to Dominik as well).


Regards

 


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {

   long x1 = ObjectGetInteger(ChartID(), "TREND1", OBJPROP_TIME, 0);
   long x2 = ObjectGetInteger(ChartID(), "TREND1", OBJPROP_TIME, 1);
   long x3 = ObjectGetInteger(ChartID(), "TREND2", OBJPROP_TIME, 0);
   long x4 = ObjectGetInteger(ChartID(), "TREND2", OBJPROP_TIME, 1);

   double y1 = ObjectGetDouble(ChartID(), "TREND1", OBJPROP_PRICE, 0);
   double y2 = ObjectGetDouble(ChartID(), "TREND1", OBJPROP_PRICE, 1);
   double y3 = ObjectGetDouble(ChartID(), "TREND2", OBJPROP_PRICE, 0);
   double y4 = ObjectGetDouble(ChartID(), "TREND2", OBJPROP_PRICE, 1);


   double m1 = (y2 - y1) / (x2 - x1);
   double m2 = (y4 - y3) / (x4 - x3);

   if(m1 != m2)
     {
      double x = (-m2 * x3 + y3 + m1 * x1 - y1) / (m1 - m2);
      double y = m1 * (x - x1) + y1;
      datetime intersectionTime = (datetime)x;
      Print(intersectionTime);
     }
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+