Teste CGraphic - perguntas e sugestões - página 3

 

@Roman Konopelko

Segundo problema, ou talvez você possa me dar uma dica.

Estou tentando criar uma linha com preços próximos. Em X de acordo com isso, estou passando um período de tempo. Mas o problema é que ao criar uma curva, ela acrescenta intervalos por si só. Isto é, torna o tempo uniforme e acrescenta um lugar onde não há dados.

Portanto, entendo que é preciso criar um tipo separado de curva - CURVE_TIMESERIES - ela não deve encontrar automaticamente nenhum passo e não deve acrescentar espaços entre X pontos.

Isto é análogo a como você fez a criação de curvas sem passar por X - e então todos os valores vão uniformemente, tudo é ligado puramente ao tamanho da matriz X (m_xmax = m_size-1; m_xmin = 0,0; ).

 
o_O:

@Roman Konopelko

Segundo problema, ou talvez você possa me dar uma dica.

Estou tentando criar uma linha com preços próximos. Em X de acordo com isso, estou passando um período de tempo. Mas o problema é que ao criar uma curva, ela acrescenta intervalos. Isto é, torna o tempo uniforme e acrescenta um lugar onde não há dados.

Portanto, entendo que é preciso criar um tipo separado de curva - CURVE_TIMESERIES - ela não deve encontrar automaticamente nenhum passo e não deve acrescentar espaços entre X pontos.

Isto é análogo a como você fez a criação de curvas sem passar por X - e então todos os valores vão uniformemente, tudo é ligado puramente ao tamanho da matriz X (m_xmax = m_size-1; m_xmin = 0,0; ).

A etapa em ambos os eixos é calculada automaticamente pelo algoritmo incorporado. Tanto quanto eu entendo, você quer definir o máximo, o mínimo e o próprio passo. Para fazer isso, você pode mudar para o modo manual para escalonar os eixos:

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

Outra coisa a considerar é o número máximo permitido de valores no eixo MaxLabels, ele deve ser maior que (Max-Min)/DefaultStep, caso contrário, o passo será alterado.

 
Roman Konopelko:

A etapa para ambos os eixos é calculada automaticamente pelo algoritmo incorporado. Tanto quanto eu entendo, você quer definir o máximo, o mínimo e o próprio passo. Para fazer isso, você pode mudar para o modo manual para escalonar os eixos

Você também precisa considerar o eixo maxLabels, ele deve ser maior que (Max-Min)/DefaultStep, caso contrário, o passo será alterado.


Sim, isso é alguma coisa.

Mas como lhe expliquei - sua escala é uniforme.

Não importa como você gire - você está fazendo uma escala X, e você está apontando a coordenada em pixels.

Bem, não se pode fazer isso com uma série de tempos.

Veja o que você recebe






#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 isto é o que faz se você não passar o tempo em X

a construção está graficamente correta



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


Sim, eu tenho algo.

Mas como lhe expliquei - sua escala é plana.

Não importa como você gire - você escala por X, e aponta a coordenada em pixels.

Bem - você não pode fazer isso quando se traça uma série de horários.

Veja o que você recebe

Muito provavelmente a possibilidade de alterar o formato de saída dos eixos será implementada, mas não posso dizer exatamente sob que forma.

Quanto ao "sábado e domingo" em seu exemplo, que formam uma linha reta. Para verificar seu exemplo, eu o modifiquei e acrescentei a escrita de matrizes em arquivo:

#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 a traçou em OpenOffice:

Este gráfico também contém uma linha reta, portanto, está nos dados (arrays X e Y). Para fazer o gráfico como descrito no comentário , você precisará editar manualmente seus dados de entrada (por exemplo, remover fins de semana).

 
Roman Konopelko:

É provável que a capacidade de alterar o formato de saída dos eixos seja implementada, mas não posso dizer ao certo de que forma exatamente.

Boas notícias, obrigado.

Como eu disse antes, não é preciso esperar pela construção oficial, mas aulas de pós-teste aqui.
 
o_O:

Boas notícias, obrigado.

Como eu disse antes, você não pode esperar pelo escritório de construção e colocar aulas para testes aqui.
Até agora, eu planejava implementar a capacidade de definir o formato do eixo em três formatos:
enum ENUM_AXIS_TYPE
  {
   AXIS_TYPE_DOUBLE,
   AXIS_TYPE_DATETIME,
   AXIS_TYPE_CUSTOM,
  };
  1. AXIS_TYPE_DOUBLE - como usado agora, será a configuração padrão
  2. AXIS_TYPE_DATETIME - exatamente o que você pediu será baseado no TimeToString
  3. AXIS_TYPE_CUSTOM - permitirá uma saída arbitrária baseada no ponteiro para DoubleToStringFunction
    typedef string(*DoubleToStringFunction)(double);

Em anexo, para o caso de colocar todos os arquivos da biblioteca.

Com relação à sua mensagem para o Servicedesk, sim, de fato não há datas de sábado e domingo na matriz X. Então eu não disse corretamente que você precisa consertar os dados.

Mas ainda assim podemos resolver seu problema, usando apenas 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:


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

Mas você ainda pode resolver seu problema apenas usando o AXIS_TYPE_CUSTOM.

super, serve!
 

Dei uma rápida olhada no arquivo Graphic.mqh.

Você decidiu deixar todas as funções não virtuais?

OK,

Podemos pelo menos as funções ***Plot (HistogramPlot, LinesPlot, etc.) ser virtuais ?

Como suas capacidades de "design" não são suficientes para a tarefa (gradientes ao preencher ou múltiplas cores na renderização).

 
o_O:

Dei uma rápida olhada no arquivo Graphic.mqh.

Você decidiu deixar todas as funções não virtuais?

OK,

Podemos pelo menos as funções ***Plot (HistogramPlot, LinesPlot, etc.) ser virtuais ?

Como suas capacidades de "design" não são suficientes para a tarefa (gradientes ao preencher ou múltiplas cores na renderização).

Mesmo que você os torne virtuais , você não poderá fazer uma sobrecarga normal sem acesso total aos membros da classe CGraphics, então todos eles (a maioria) precisam ser declarados como protegidos. Também não vou dizer com certeza, mas o mais provável é que ambos os aspectos sejam implementados.
Razão: