Prueba CGraphic - preguntas y sugerencias - página 3

 

@Roman Konopelko

Segundo problema, o tal vez puedas darme una pista.

Estoy tratando de crear una línea con precios cercanos. En X en consecuencia estoy pasando un array de tiempo. Pero el problema es que al crear una curva, añade intervalos por sí mismo. Es decir, uniformiza el tiempo y añade un lugar donde no hay datos.

Por lo tanto, entiendo que usted tiene que crear un tipo separado de la curva - CURVE_TIMESERIES - no debe encontrar automáticamente cualquier paso y no añadir espacios entre los puntos X.

Esto es similar a la creación de una curva sin pasar X - y entonces todos los valores van uniformemente, todo está ligado puramente al tamaño de la matriz X (m_xmax = m_size-1; m_xmin = 0.0; ).

 
o_O:

@Roman Konopelko

Segundo problema, o tal vez puedas darme una pista.

Estoy tratando de crear una línea con los precios de Close. En X en consecuencia estoy pasando un array de tiempo. Pero el problema es que al crear una curva, añade intervalos. Es decir, uniformiza el tiempo y añade un lugar donde no hay datos.

Por lo tanto, entiendo que usted tiene que crear un tipo separado de la curva - CURVE_TIMESERIES - no debe encontrar automáticamente cualquier paso y no añadir espacios entre los puntos X.

Esto es análogo a cómo se hizo la creación de la curva sin pasar X - y entonces todos los valores van uniformemente, todo está ligado puramente al tamaño de la matriz X (m_xmax = m_size-1; m_xmin = 0.0; ).

El paso en ambos ejes es calculado automáticamente por el algoritmo incorporado. Por lo que tengo entendido, quieres establecer tú mismo el máximo, el mínimo y el paso. Para ello, puede cambiar al modo manual para escalar los ejes:

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

Otra cosa a tener en cuenta es el número máximo permitido de valores en el eje MaxLabels, debe ser mayor que (Max-Min)/DefaultStep, de lo contrario el paso será cambiado.

 
Roman Konopelko:

El paso para ambos ejes es calculado automáticamente por el algoritmo incorporado. Por lo que tengo entendido, quieres establecer tú mismo el máximo, el mínimo y el paso. Para ello, puede cambiar al modo manual para escalar los ejes

También hay que tener en cuenta el eje maxLabels, debe ser mayor que (Max-Min)/DefaultStep, de lo contrario el paso se cambiará.


Sí, eso es algo.

Pero, como le expliqué, su escala es uniforme.

No importa cómo lo hagas: estás haciendo una escala X, y estás apuntando la coordenada en píxeles.

Bueno, eso no se puede hacer con una serie temporal.

Vea lo que obtiene






#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();
}
 

y esto es lo que hace si no le pasas el tiempo en X

la construcción es gráficamente correcta



#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:


Sí, tengo algo.

Pero como te expliqué, tu escala es plana.

No importa cómo lo gires: escalas por X, y apuntas la coordenada en píxeles.

Pues bien, no se puede hacer esto cuando se trazan series temporales.

Vea lo que obtiene

Lo más probable es que se implemente la posibilidad de cambiar el formato de salida de los ejes, pero no puedo decir exactamente de qué forma.

En cuanto a los "sábados y domingos" de tu ejemplo, que forman una línea recta. Para comprobarlo, he modificado tu ejemplo y he añadido la escritura de arrays en el archivo:

#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();
  }

Y lo he trazado en OpenOffice:

Este gráfico también contiene una línea recta, por lo que está en los datos (matrices X e Y). Para hacer el gráfico como se describe en el comentario , tendrá que editar manualmente sus datos de entrada (por ejemplo, eliminar los fines de semana).

 
Roman Konopelko:

Es probable que se implemente la posibilidad de cambiar el formato de salida de los ejes, pero no puedo asegurar de qué forma exactamente.

Buenas noticias, gracias.

Como he dicho antes, no hay que esperar a la compilación oficial, sino publicar las clases para probarlas aquí.
 
o_O:

Buenas noticias, gracias.

Como he dicho antes, no se puede esperar a la oficina de construcción y poner las clases para las pruebas aquí.
Hasta ahora estaba planeando implementar la capacidad de establecer el formato del eje en tres formatos:
enum ENUM_AXIS_TYPE
  {
   AXIS_TYPE_DOUBLE,
   AXIS_TYPE_DATETIME,
   AXIS_TYPE_CUSTOM,
  };
  1. AXIS_TYPE_DOUBLE - tal como se utiliza ahora, será la configuración por defecto
  2. AXIS_TYPE_DATETIME - justo lo que pidió se basará en TimeToString
  3. AXIS_TYPE_CUSTOM - permitirá una salida arbitraria basada en el puntero a DoubleToStringFunction
    typedef string(*DoubleToStringFunction)(double);

En adjunto por si acaso pongo todos los archivos de la biblioteca.

En cuanto a tu mensaje a servicedesk, sí, efectivamente no hay fechas de sábado y domingo en la matriz X. Así que no he dicho correctamente que haya que arreglar los datos.

Pero aún así podemos resolver su problema, simplemente usando 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();
  }
//+------------------------------------------------------------------+

Resultado:


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

Pero aún puede resolver su problema simplemente utilizando AXIS_TYPE_CUSTOM.

¡Super, eso encaja!
 

He echado un vistazo al archivo Graphic.mqh.

¿Ha decidido dejar todas las funciones no virtuales?

DE ACUERDO,

¿Podemos por lo menos ***Las funciones de los gráficos (HistogramPlot, LinesPlot, etc.) ser virtuales ?

Ya que sus capacidades de "diseño" no son suficientes para la tarea (gradientes al rellenar o múltiples colores en el renderizado).

 
o_O:

He echado un vistazo al archivo Graphic.mqh.

¿Ha decidido dejar todas las funciones no virtuales?

DE ACUERDO,

¿Podemos por lo menos ***Las funciones de los gráficos (HistogramPlot, LinesPlot, etc.) ser virtuales ?

Ya que sus capacidades de "diseño" no son suficientes para la tarea (gradientes al rellenar o múltiples colores en el renderizado).

Incluso si los haces virtuales no podrás hacer una sobrecarga normal sin acceso completo a los miembros de la clase CGraphics, por lo que todos (la mayoría) deben ser declarados como protegidos. Además, no lo diré con seguridad, pero lo más probable es que se apliquen ambos aspectos.
Razón de la queja: