Тестируем CGraphic - вопросы и предложения - страница 3

 

@Roman Konopelko

Вторая проблема, или может вы подскажете.

Пытаюсь создать линию с ценам Close. По Х соответсвтенно передаю массив времени. Но проблема - курва при создании сама добавляет промежутки. То есть она делает время равномерным и добавляет места где нет данных.

То есть я так понимаю что надо, чтоб вы сделали отдельный тип курвы - CURVE_TIMESERIES, она не должна находить автоматически никакие step и не добавлять промежутки между X точками.

Это аналогично как вы сделали создание курвы без передачи Х - и тогда все значения идут равномерно, всё привязано чисто к размеру массива Х (m_xmax = m_size-1; m_xmin = 0.0; ).

 
o_O:

@Roman Konopelko

Вторая проблема, или может вы подскажете.

Пытаюсь создать линию с ценам Close. По Х соответсвтенно передаю массив времени. Но проблема - курва при создании сама добавляет промежутки. То есть она делает время равномерным и добавляет места где нет данных.

То есть я так понимаю что надо, чтоб вы сделали отдельный тип курвы - CURVE_TIMESERIES, она не должна находить автоматически никакие step и не добавлять промежутки между X точками.

Это аналогично как вы сделали создание курвы без передачи Х - и тогда все значения идут равномерно, всё привязано чисто к размеру массива Х (m_xmax = m_size-1; m_xmin = 0.0; ).

Шаг по обеим осям рассчитывается автоматически встроенным алгоритмом. На сколько я понимаю вы хотите сами задавать max, min и step. Для этого вы можете перейти в ручной режим масштабирования осей:

   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:

Шаг по обеим осям рассчитывается автоматически встроенным алгоритмом. На сколько я понимаю вы хотите сами задавать max, min и step. Для этого вы можете перейти в ручной режим масштабирования осей

Еще нужно учитывать максимально допустимое число значений по оси MaxLabels, оно должно быть больше чем (Max-Min)/DefaultStep, иначе шаг будет изменен.


да, кое что получилось.

Но, как я вам и пояснял - у вас шкала равномерная.

Как ни крути - вы делаете по Х масштаб, и прицельно расчитываете координату в пикселях.

Так вот - этого при построении таймсерий делать нельзя.

Смотрите что получается






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

и вот как он делает, если не передавать ему время в Х

построение графически правильное



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


да, кое что получилось.

Но, как я вам и пояснял - у вас шкала равномерная.

Как ни крути - вы делаете по Х масштаб, и прицельно расчитываете координату в пикселях.

Так вот - этого при построении таймсерий делать нельзя.

Смотрите что получается

Скорее всего возможность изменения формата вывода значений для осей будет реализована, но пока точно не могу сказать в коком конкретно виде.

По поводу "Субботы и воскресенья" в вашем примере, которые образую прямую. Для поверки доработал ваш пример и добавил запись массивов в файл:

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

В аттаче на всякий случай выложил все файлы библиотеки.

По-поводу вашего сообщения в сервисдеск, да действительно в массиве 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.

Вы таки решили оставить все функции не virtual?

ок,

можно хотя бы ***Plot функции (HistogramPlot, LinesPlot и т.д) сделать virtual ?

Так как их "дизайнерских" возможностей не хватает для задачи (градиенты при заливке или несколько цветов в отрисовке).

 
o_O:

Бегло посмотрел файл Graphic.mqh.

Вы таки решили оставить все функции не virtual?

ок,

можно хотя бы ***Plot функции (HistogramPlot, LinesPlot и т.д) сделать virtual ?

Так как их "дизайнерских" возможностей не хватает для задачи (градиенты при заливке или несколько цветов в отрисовке).

Даже сделав их virtual вы не сможете делать нормальные перегрузки без полного доступа к членам класса CGraphics, следовательно их все(большинство) нужно объявлять как protected. Так же, не буду точно утверждать, но скорее всего оба аспекта будут реализованы.
Причина обращения: