Test CGraphic - domande e suggerimenti - pagina 3

 

@Roman Konopelko

Secondo problema, o forse puoi darmi un suggerimento.

Sto cercando di creare una linea con i prezzi Close. Su X di conseguenza sto passando un array di tempo. Ma il problema è che quando si crea una curva, aggiunge gli intervalli da solo. Cioè, rende il tempo uniforme e aggiunge un posto dove non ci sono dati.

Quindi, capisco che devi creare un tipo di curva separato - CURVE_TIMESERIES - non dovrebbe trovare automaticamente nessun passo e non aggiungere spazi vuoti tra i punti X.

Questo è analogo a come avete fatto la creazione di curve senza passare X - e allora tutti i valori vanno in modo uniforme, tutto è legato puramente alla dimensione dell'array X (m_xmax = m_size-1; m_xmin = 0.0; ).

 
o_O:

@Roman Konopelko

Secondo problema, o forse puoi darmi un suggerimento.

Sto cercando di creare una linea con i prezzi Close. Su X di conseguenza sto passando un array di tempo. Ma il problema è che quando si crea una curva, aggiunge degli intervalli. Cioè, rende il tempo uniforme e aggiunge un posto dove non ci sono dati.

Quindi, capisco che devi creare un tipo di curva separato - CURVE_TIMESERIES - non dovrebbe trovare automaticamente alcun passo e non aggiungere spazi vuoti tra i punti X.

Questo è analogo a come avete fatto la creazione di curve senza passare X - e allora tutti i valori vanno in modo uniforme, tutto è legato puramente alla dimensione dell'array X (m_xmax = m_size-1; m_xmin = 0.0; ).

Il passo su entrambi gli assi è calcolato automaticamente dall'algoritmo integrato. Per quanto ho capito, vuoi impostare tu stesso max, min e step. Per farlo, potete passare alla modalità manuale per scalare gli assi:

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

Un'altra cosa da considerare è il numero massimo ammissibile di valori sull'asse MaxLabels, deve essere maggiore di (Max-Min)/DefaultStep, altrimenti il passo sarà cambiato.

 
Roman Konopelko:

Il passo per entrambi gli assi è calcolato automaticamente dall'algoritmo integrato. Per quanto ho capito, vuoi impostare tu stesso il massimo, il minimo e il passo. Per fare questo, si può passare alla modalità manuale per scalare gli assi

Devi anche considerare l'asse maxLabels, deve essere maggiore di (Max-Min)/DefaultStep, altrimenti il passo sarà cambiato.


Sì, è qualcosa.

Ma come ti ho spiegato - la tua scala è uniforme.

Non importa come la giri - stai facendo una scala X, e stai puntando le coordinate in pixel.

Beh, non puoi farlo con una serie temporale.

Vedi cosa ottieni






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

e questo è ciò che fa se non si passa il tempo in X

la costruzione è graficamente corretta



#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ì, ho qualcosa.

Ma come ti ho spiegato - la tua scala è piatta.

Non importa come lo giri - si scala per X, e si punta la coordinata in pixel.

Beh - non si può fare questo quando si tracciano le serie temporali.

Vedi cosa ottieni

Molto probabilmente la possibilità di cambiare il formato di output per gli assi sarà implementata, ma non posso dire esattamente in quale forma.

Per quanto riguarda "sabato e domenica" nel tuo esempio, che formano una linea retta. Per verificare il tuo esempio, l'ho modificato e ho aggiunto la scrittura degli array nel 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();
  }

E lo ha tracciato in OpenOffice:

Questo grafico contiene anche una linea retta, quindi è incorporato nei dati (array X e Y). Per fare il grafico come descritto nel commento , dovrai modificare manualmente i tuoi dati di input (ad esempio rimuovere i fine settimana).

 
Roman Konopelko:

È probabile che la capacità di cambiare il formato di output per gli assi sarà implementata, ma non posso dire con certezza in quale forma esattamente.

Buone notizie, grazie.

Come ho detto prima, non dovete aspettare la build ufficiale, ma postate qui le classi da testare.
 
o_O:

Buone notizie, grazie.

Come ho detto prima, non si può aspettare l'ufficio costruzione e mettere le classi per i test qui.
Finora avevo intenzione di implementare la possibilità di impostare il formato dell'asse in tre formati:
enum ENUM_AXIS_TYPE
  {
   AXIS_TYPE_DOUBLE,
   AXIS_TYPE_DATETIME,
   AXIS_TYPE_CUSTOM,
  };
  1. AXIS_TYPE_DOUBLE - come usato ora, sarà l'impostazione predefinita
  2. AXIS_TYPE_DATETIME - proprio quello che hai chiesto sarà basato su TimeToString
  3. AXIS_TYPE_CUSTOM - permetterà un'uscita arbitraria basata sul puntatore a DoubleToStringFunction
    typedef string(*DoubleToStringFunction)(double);

In allegato solo nel caso in cui ho messo tutti i file della libreria.

Per quanto riguarda il tuo messaggio a servicedesk, sì, effettivamente non ci sono date di sabato e domenica nell'array X. Quindi non ho detto correttamente che bisogna correggere i dati.

Ma possiamo comunque risolvere il tuo problema, semplicemente 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();
  }
//+------------------------------------------------------------------+

Risultato:


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

Ma potete ancora risolvere il vostro problema semplicemente usando AXIS_TYPE_CUSTOM.

super, che si adatta!
 

Ho dato un'occhiata veloce al file Graphic.mqh.

Avete deciso di lasciare tutte le funzioni non virtuali?

OK,

Possiamo almeno ***Plot funzioni (HistogramPlot, LinesPlot, ecc.) essere virtuali ?

Poiché le loro capacità di "design" non sono sufficienti per il compito (gradienti durante il riempimento o colori multipli nel rendering).

 
o_O:

Ho dato un'occhiata veloce al file Graphic.mqh.

Avete deciso di lasciare tutte le funzioni non virtuali?

OK,

Possiamo almeno ***Plot funzioni (HistogramPlot, LinesPlot, ecc.) essere virtuali ?

Poiché le loro capacità di "design" non sono sufficienti per il compito (gradienti durante il riempimento o colori multipli nel rendering).

Anche se li rendete virtuali non sarete in grado di fare il normale sovraccarico senza un accesso completo ai membri della classe CGraphics, quindi tutti (la maggior parte) devono essere dichiarati come protetti. Inoltre, non lo dico con certezza, ma molto probabilmente entrambi gli aspetti saranno implementati.