测试CGraphic--问题和建议 - 页 3

 

@罗曼-科诺佩尔科

第二个问题,或者你可以给我一个提示。

我正试图用Close价格创建一条线。在X上我相应地传递一个时间数组。但问题是,在创建曲线时,它自己会增加间隔。也就是说,它使时间统一,并增加了一个没有数据的地方。

所以,我理解你必须创建一个单独的曲线类型--CURVE_TIMESERIES--它不应该自动找到任何台阶,并且 不在X点之间添加间隙。

这类似于你在不传递X的情况下进行曲线创建--然后所有的值都是均匀的,一切都纯粹与数组X的大小挂钩(m_xmax = m_size-1; m_xmin = 0.0; )。

 
o_O:

@罗曼-科诺佩尔科

第二个问题,或者你可以给我一个提示。

我正试图创建一个带有Close价格的线。在X上我相应地传递一个时间数组。但问题是,在创建曲线时,它会增加间隔。也就是说,它使时间统一,并增加了一个没有数据的地方。

所以,我理解你必须创建一个单独的曲线类型--CURVE_TIMESERIES--它不应该自动找到任何台阶,并且 不在X点之间添加间隙。

这类似于你在不传递X的情况下进行曲线创建--然后所有的值都是均匀的,所有的东西都纯粹地被约束在数组X的大小上(m_xmax = m_size-1; m_xmin = 0.0; )。

两个轴上的步长是由内置算法自动计算的。据我所知,你想自己设置最大、最小和步长。要做到这一点,你可以切换到手动模式进行轴的缩放。

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

另外要考虑的是MaxLabels轴上允许的最大数值,它必须大于(Max-Min)/DefaultStep,否则将改变步长。

 
Roman Konopelko:

两个轴的步长是由内置算法自动计算的。据我所知,你想自己设置最大、最小和步长。要做到这一点,你可以切换到手动模式来调整轴的比例

你还需要考虑maxLabels轴,它必须大于(Max-Min)/DefaultStep,否则将改变步长。


是的,这很重要。

但正如我向你解释的那样--你的尺度是统一的。

无论你如何旋转它--你在做一个X比例,你在用像素来瞄准坐标。

嗯,你不能用时间序列来做这个。

看看你能得到什么






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

如果你不在X中传递时间,它就会这样做

结构图上是正确的



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


是的,我得到了一些东西。

但正如我向你解释的那样--你的刻度是平的。

无论你如何转动它--你按X缩放,并以像素为单位瞄准坐标。

嗯--在绘制时间序列时,你不能这样做。

看看你得到什么

最有可能的是,改变轴的输出格式的可能性将被实现,但我不能说具体是什么形式。

关于你的例子中的 "周六和周日",它们形成一条直线。为了验证你的例子,我修改了它,增加了将数组写进文件的内容。

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

并在OpenOffice中绘制了它。

这个图形也包含一条直线,所以它在数据中(X和Y数组)。为了制作评论 中描述的图表,你需要手动编辑你的输入数据(例如,删除周末)。

 
Roman Konopelko:

很可能会实现改变轴的输出格式的能力,但我不能确定具体以什么形式实现。

好消息,谢谢你。

正如我之前所说,你不必等待官方的构建,而是在这里发布测试的类。
 
o_O:

好消息,谢谢你。

正如我以前说过的,你不能等着建办公室,把课放在这里进行测试。
到目前为止,我正计划实现以三种格式设置轴的能力。
enum ENUM_AXIS_TYPE
  {
   AXIS_TYPE_DOUBLE,
   AXIS_TYPE_DATETIME,
   AXIS_TYPE_CUSTOM,
  };
  1. AXIS_TYPE_DOUBLE - 现在使用,将是默认设置
  2. AXIS_TYPE_DATETIME - 就像你问的那样,将基于TimeToString。
  3. AXIS_TYPE_CUSTOM - 将允许基于DoubleToStringFunction 的指针的任意输出。
    typedef string(*DoubleToStringFunction)(double);

为了以防万一,我把图书馆的所有文件都放在附件里。

关于你给servicedesk的信息,是的,确实在X阵列中没有星期六和星期日的日期。所以我没有正确地说,你需要修复数据。

但我们仍然可以解决你的问题,只要使用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();
  }
//+------------------------------------------------------------------+

结果。


附加的文件:
Graphic.mqh  86 kb
Curve.mqh  21 kb
Axis.mqh  12 kb
 
Roman Konopelko:

但你仍然可以通过使用AXIS_TYPE_CUSTOM来解决你的问题。

超级,很合适
 

我快速看了一下Graphic.mqh文件。

你是否决定让所有的功能都不是虚拟的

好的。

我们至少可以将***图函数(HistogramPlot,LinesPlot等)虚拟为

因为他们的 "设计 "能力不足以完成任务(填充时的梯度或渲染时的多种颜色)。

 
o_O:

我快速看了一下Graphic.mqh文件。

你是否决定让所有的功能都不是虚拟的

好的。

我们至少可以将***图函数(HistogramPlot,LinesPlot等)虚拟为

因为他们的 "设计 "能力不足以完成任务(填充时的梯度或渲染时的多种颜色)。

即使你把它们变成虚拟的 ,你也不能在没有完全访问 CGraphics类成员 的情况下进行正常的重载,所以它们都(大部分)需要被声明为保护的。另外,我不会肯定地说,但很可能这两个方面都会实施。