Testing CGraphic - questions and suggestions - page 3

 

@Roman Konopelko

Second problem, or maybe you can give me a hint.

I'm trying to create a line with Close prices. On X accordingly I am passing an array of time. But the problem is that when creating a curve, it adds intervals by itself. That is, it makes the time uniform and adds a place where there is no data.

So, I understand that you have to create a separate type of curve - CURVE_TIMESERIES - it shouldn't automatically find any step and not add gaps between X points.

This is analogous to how you made curve creation without passing X - and then all values go evenly, everything is tied purely to the size of array X (m_xmax = m_size-1; m_xmin = 0.0; ).

 
o_O:

@Roman Konopelko

Second problem, or maybe you can give me a hint.

I am trying to create a line with Close prices. On X accordingly I am passing an array of time. But the problem is that when creating a curve, it adds intervals. That is, it makes the time uniform and adds a place where there is no data.

So, I understand that you have to create a separate type of curve - CURVE_TIMESERIES - it shouldn't automatically find any step and not add gaps between X points.

This is analogous to how you made curve creation without passing X - and then all values go evenly, everything is bound purely to the size of array X (m_xmax = m_size-1; m_xmin = 0.0; ).

The step on both axes is calculated automatically by the built-in algorithm. As far as I understand, you want to set max, min and step yourself. To do that, you can switch to manual mode for scaling the axes:

   CAxis *xAxis = graphic.XAxis();  // получаем ось X
   xAxis.AutoScale(false);          // отключаем автомасштабирование
   xAxis.Min(0);                    // указываем минимальное значение по X
   xAxis.Max(10);                   // указываем максимальное значение по X
   xAxis.DefaultStep(1);            // указываем шаг по X

Another thing to consider is the maximum allowable number of values on the MaxLabels axis, it must be greater than (Max-Min)/DefaultStep, otherwise the step will be changed.

 
Roman Konopelko:

The step for both axes is calculated automatically by the built-in algorithm. As far as I understand, you want to set the max, min and step yourself. To do this, you can switch to manual mode for scaling the axes

You also need to consider the maxLabels axis, it must be greater than (Max-Min)/DefaultStep, otherwise the step will be changed.


Yes, that's something.

But as I explained to you - your scale is uniform.

No matter how you spin it - you're doing an X scale, and you're aiming the coordinate in pixels.

Well, you can't do that with a timeseries.

See what you get






#include <Graphics/Graphic.mqh>

//+------------------------------------------------------------------+
void OnStart()
{
        MqlRates rates[];
        CopyRates(Symbol(), Period(), 0, 100, rates);
        ArraySetAsSeries(rates, true);
        int size=ArraySize(rates);
        double arrY[], arrX[];
        ArrayResize(arrX, size); ArrayResize(arrY, size);
        for(int i=0; i<size; ++i) { arrX[i]=(double)rates[i].time; arrY[i]=rates[i].close; }
        
        CGraphic graphic;
        graphic.Create(0, "Rates", 0, 30, 30, 1600, 300);
        CCurve* curve=NULL;
        
        //curve=graphic.CurveAdd(arrY, CURVE_LINES, "Close");
        
        curve=graphic.CurveAdd(arrX, arrY, CURVE_LINES, "Close");
        CAxis *xAxis = graphic.XAxis();  // получаем ось X
        xAxis.AutoScale(false);          // отключаем автомасштабирование
        xAxis.Min(arrX[size-1]);                    // указываем минимальное значение по X
        xAxis.Max(arrX[0]);                 // указываем максимальное значение по X
        xAxis.DefaultStep(10*(arrX[0]-arrX[size-1])/size);            // указываем шаг по X
        xAxis.MaxLabels((arrX[0]-arrX[size-1])/xAxis.DefaultStep()+1);                          // число значений по оси MaxLabels должно быть больше чем (Max-Min)/DefaultStep
        
        curve.Visible(true);
        graphic.Redraw();
        graphic.Update();
}
 

and this is what it does if you don't pass it the time in X

the construction is graphically correct



#include <Graphics/Graphic.mqh>

//+------------------------------------------------------------------+
void OnStart()
{
        MqlRates rates[];
        CopyRates(Symbol(), Period(), 0, 100, rates);
        ArraySetAsSeries(rates, true);
        int size=ArraySize(rates);
        double arrY[];
        ArrayResize(arrY, size); ArraySetAsSeries(arrY, size);
        for(int i=0; i<size; ++i) arrY[i]=rates[i].close;
        
        CGraphic graphic;
        graphic.Create(0, "Rates", 0, 30, 30, 1600, 300);
        CCurve* curve=NULL;
        
        curve=graphic.CurveAdd(arrY, CURVE_LINES, "Close");
        curve.Visible(true);
        graphic.Redraw();
        graphic.Update();
}
 
o_O:


Yes, I got something.

But as I explained to you - your scale is flat.

No matter how you turn it - you scale by X, and aim the coordinate in pixels.

Well - you can't do this when plotting timeseries.

See what you get

Most likely the possibility to change the output format for axes will be implemented, but I can't say exactly in what form.

Regarding "Saturday and Sunday" in your example, which form a straight line. To verify your example, I modified it and added writing of arrays into file:

#include <Graphics/Graphic.mqh>
//+------------------------------------------------------------------+
void OnStart()
  {
   MqlRates rates[];
   CopyRates(Symbol(),Period(),0,100,rates);
   ArraySetAsSeries(rates,true);
   int size=ArraySize(rates);
   double arrY[],arrX[];
   datetime arrTime[];
   ArrayResize(arrX,size);
   ArrayResize(arrY,size);
   ArrayResize(arrTime,size);
   int handle=FileOpen("result.txt",FILE_WRITE|FILE_TXT);
   for(int i=0; i<size;++i)
     {
      arrTime[i]=rates[i].time;
      arrX[i]=(double)rates[i].time;
      arrY[i]=rates[i].close;
      string str=TimeToString(arrTime[i])+"\t"+DoubleToString(arrY[i],3)+"\n";
      FileWriteString(handle,str);

     }
   FileClose(handle);
   CGraphic graphic;
   graphic.Create(0,"Rates",0,30,30,1080,380);
   CCurve *curve=graphic.CurveAdd(arrX,arrY,CURVE_LINES,"Close");
   double min = arrX[ArrayMinimum(arrX)];
   double max = arrX[ArrayMaximum(arrX)];
   double step=(max-min)/10;
   CAxis *xAxis = graphic.XAxis();           // получаем ось X
   xAxis.AutoScale(false);                   // отключаем автомасштабирование
   xAxis.Min(min);                           // указываем минимальное значение по X
   xAxis.Max(max);                           // указываем максимальное значение по X
   xAxis.DefaultStep(step);                  // указываем шаг по X
   curve.Visible(true);
   graphic.Redraw();
   graphic.Update();
  }

And plotted it in OpenOffice:

This graph also contains a straight line, so it is in the data (arrays X and Y). To make the graph as described in comment , you'll need to manually edit your input data (e.g. remove weekends).

 
Roman Konopelko:

It is likely that the ability to change the output format for the axes will be implemented, but I can't say for sure in what form exactly.

Good news, thank you.

As I said before, you don't have to wait for the official build, but post classes for testing here.
 
o_O:

Good news, thank you.

As I said before, you can not wait for the build office and put classes for testing here.
So far I was planning to implement the ability to set the axis format in three formats:
enum ENUM_AXIS_TYPE
  {
   AXIS_TYPE_DOUBLE,
   AXIS_TYPE_DATETIME,
   AXIS_TYPE_CUSTOM,
  };
  1. AXIS_TYPE_DOUBLE - as used now, will be the default setting
  2. AXIS_TYPE_DATETIME - just what you asked will be based on TimeToString
  3. AXIS_TYPE_CUSTOM - will allow arbitrary output based on pointer to DoubleToStringFunction
    typedef string(*DoubleToStringFunction)(double);

In attache just in case I put all files of library.

Regarding your message to servicedesk, yes indeed there are no Saturday and Sunday dates in X array. So I didn't say correctly that you need to fix the data.

But still we can solve your problem, just using AXIS_TYPE_CUSTOM.

#include <Graphics/Graphic.mqh>
double arrX[];
double arrY[];
//---
string TimeFirmat(double x)
  {
   return(TimeToString((datetime)arrX[ArraySize(arrX)-(int)x-1]));
  }
//+------------------------------------------------------------------+
void OnStart()
  {
   MqlRates rates[];
   CopyRates(Symbol(),Period(),0,100,rates);
   ArraySetAsSeries(rates,true);
   int size=ArraySize(rates);
   ArrayResize(arrX,size);
   ArrayResize(arrY,size);
   for(int i=0; i<size;++i)
     {
      arrX[i]=(double)rates[i].time;
      arrY[i]=rates[i].close;
     }
   CGraphic graphic;
   graphic.Create(0,"Rates",0,30,30,780,380);
   CCurve *curve=graphic.CurveAdd(arrY,CURVE_LINES,"Close");
   CAxis *xAxis=graphic.XAxis();           // получаем ось X
   xAxis.AutoScale(false);
   xAxis.Type(AXIS_TYPE_CUSTOM);
   xAxis.ValuesFunctionFormat(TimeFirmat);
   xAxis.DefaultStep(20.0);
   curve.Visible(true);
   graphic.Redraw();
   graphic.Update();
  }
//+------------------------------------------------------------------+

Result:


Files:
Graphic.mqh  86 kb
Curve.mqh  21 kb
Axis.mqh  12 kb
 
Roman Konopelko:

But you can still solve your problem just by using AXIS_TYPE_CUSTOM.

super, that fits!
 

I took a quick look at the Graphic.mqh file.

Have you decided to leave all functions not virtual?

OK,

Can we at least ***Plot functions (HistogramPlot, LinesPlot, etc.) be virtual ?

As their "design" capabilities are not enough for the task (gradients when filling or multiple colours in rendering).

 
o_O:

I took a quick look at the Graphic.mqh file.

Have you decided to leave all functions not virtual?

OK,

Can we at least ***Plot functions (HistogramPlot, LinesPlot, etc.) be virtual ?

As their "design" capabilities are not enough for the task (gradients when filling or multiple colours in rendering).

Even if you make them virtual you won't be able to do normal overloading without full access to CGraphics class members, so they all (most) need to be declared as protected. Also, I won't say for sure, but most likely both aspects will be implemented.
Reason: