240 lines
19 KiB
Plaintext
240 lines
19 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| Histogram.mqh |
|
|
//| Copyright 2018, DNG® |
|
|
//| http://www.mql5.com/en/users/dng |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2018, DNG®"
|
|
#property link "http://www.mql5.com/en/users/dng"
|
|
#property version "1.00"
|
|
//---
|
|
#include "PlotBase.mqh"
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
enum ENUM_HISTOGRAM_ORIENTATION
|
|
{
|
|
HISTOGRAM_VERTICAL, //Markert Profile
|
|
HISTOGRAM_HORIZONTAL //Classic
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CHistogram : public CPlotBase
|
|
{
|
|
private:
|
|
ENUM_HISTOGRAM_ORIENTATION e_orientation;
|
|
uint i_cells;
|
|
|
|
public:
|
|
CHistogram();
|
|
~CHistogram();
|
|
//---
|
|
bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int size, ENUM_HISTOGRAM_ORIENTATION orientation=HISTOGRAM_HORIZONTAL);
|
|
bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2, ENUM_HISTOGRAM_ORIENTATION orientation=HISTOGRAM_HORIZONTAL);
|
|
int AddTimeserie(const double ×erie[]);
|
|
bool UpdateTimeserie(const double ×erie[],uint timeserie=0);
|
|
bool SetCells(uint value) { if(i_cells<=1) return (false); i_cells=value; return (true);}
|
|
|
|
protected:
|
|
// virtual void HistogramPlot(CCurve *curve);
|
|
bool CalculateHistogramArray(const double &data[],double &intervals[],double &frequency[],
|
|
double &maxv,double &minv);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CHistogram::CHistogram() : e_orientation(HISTOGRAM_HORIZONTAL),
|
|
i_cells(10)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CHistogram::~CHistogram()
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CHistogram::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int size,ENUM_HISTOGRAM_ORIENTATION orientation=1)
|
|
{
|
|
int x2=x1+size;
|
|
int y2=y1+size;
|
|
return Create(chart,name,subwin,x1,y1,x2,y2,orientation);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CHistogram::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2,ENUM_HISTOGRAM_ORIENTATION orientation=1)
|
|
{
|
|
e_orientation=orientation;
|
|
if(!CGraphic::Create(chart,name,subwin,x1,y1,x2,y2))
|
|
return false;
|
|
m_chart_id=chart;
|
|
m_subwin=subwin;
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate frequencies for data set |
|
|
//+------------------------------------------------------------------+
|
|
bool CHistogram::CalculateHistogramArray(const double &data[],double &intervals[],double &frequency[],
|
|
double &maxv,double &minv)
|
|
{
|
|
int size=ArraySize(data);
|
|
if(size<(int)i_cells*10) return (false);
|
|
minv=data[ArrayMinimum(data)];
|
|
maxv=data[ArrayMaximum(data)];
|
|
double range=maxv-minv;
|
|
double width=range/i_cells;
|
|
if(width==0) return false;
|
|
ArrayResize(intervals,i_cells);
|
|
ArrayResize(frequency,i_cells);
|
|
//--- set the interval centers
|
|
for(uint i=0; i<i_cells; i++)
|
|
{
|
|
intervals[i]=minv+(i+0.5)*width;
|
|
frequency[i]=0;
|
|
}
|
|
//--- fill in the interval fitting frequencies
|
|
for(int i=0; i<size; i++)
|
|
{
|
|
uint ind=int((data[i]-minv)/width);
|
|
if(ind>=i_cells) ind=i_cells-1;
|
|
frequency[ind]++;
|
|
}
|
|
//--- normalize frequencies into percentage
|
|
for(uint i=0; i<i_cells; i++)
|
|
frequency[i]*=(100.0/(double)size);
|
|
return (true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
int CHistogram::AddTimeserie(const double ×erie[])
|
|
{
|
|
CCurve *curve=CGraphic::CurveAdd(timeserie,CURVE_HISTOGRAM);
|
|
if(curve==NULL)
|
|
return -1;
|
|
//--- Set width of histogram
|
|
int total=CurvesTotal();
|
|
int width=fmax((e_orientation==HISTOGRAM_HORIZONTAL ? m_width-m_right-m_left : m_height-m_up-m_down)/((int)(i_cells)*(total+1)),1);
|
|
for(int i=0;i<total;i++)
|
|
{
|
|
curve=CurveGetByIndex(i);
|
|
if(curve==NULL)
|
|
continue;
|
|
curve.HistogramWidth(width);
|
|
}
|
|
//--- Return index of new timeserie
|
|
return (total-1);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CHistogram::UpdateTimeserie(const double ×erie[], uint timeserie_number=0)
|
|
{
|
|
if((int)timeserie_number>=m_arr_curves.Total())
|
|
return false;
|
|
if(ArraySize(timeserie)==0)
|
|
return false;
|
|
//---
|
|
CCurve *curve=m_arr_curves.At(timeserie_number);
|
|
if(CheckPointer(curve)==POINTER_INVALID)
|
|
return false;
|
|
//---
|
|
curve.Update(timeserie);
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// CHistogram::HistogramPlot(CCurve *curve)
|
|
// {
|
|
// double data[],intervals[],frequency[];
|
|
// double max_value, min_value;
|
|
// curve.GetY(data);
|
|
// if(!CalculateHistogramArray(data,intervals,frequency,max_value,min_value))
|
|
// return;
|
|
// //--- historgram parametrs
|
|
// int histogram_width=fmax(curve.HistogramWidth(),2);
|
|
// //--- check
|
|
// if(ArraySize(frequency)==0 || ArraySize(intervals)==0)
|
|
// return;
|
|
// //---
|
|
// switch(e_orientation)
|
|
// {
|
|
// case HISTOGRAM_HORIZONTAL:
|
|
// m_y.AutoScale(false);
|
|
// m_x.Min(intervals[ArrayMinimum(intervals)]);
|
|
// m_x.Max(intervals[ArrayMaximum(intervals)]);
|
|
// m_x.MaxLabels(3);
|
|
// m_x.ValuesFormat("%.0f");
|
|
// m_y.Min(0);
|
|
// m_y.Max(frequency[ArrayMaximum(frequency)]);
|
|
// m_y.ValuesFormat("%.2f");
|
|
// break;
|
|
// case HISTOGRAM_VERTICAL:
|
|
// m_x.AutoScale(false);
|
|
// m_y.Min(intervals[ArrayMinimum(intervals)]);
|
|
// m_y.Max(intervals[ArrayMaximum(intervals)]);
|
|
// m_y.MaxLabels(3);
|
|
// m_y.ValuesFormat("%.0f");
|
|
// m_x.Min(0);
|
|
// m_x.Max(frequency[ArrayMaximum(frequency)]);
|
|
// m_x.ValuesFormat("%.2f");
|
|
// break;
|
|
// }
|
|
// //---
|
|
// CalculateXAxis();
|
|
// CalculateYAxis();
|
|
// //--- calculate original of y
|
|
// int originalY=m_height-m_down;
|
|
// int originalX=m_width-m_right;
|
|
// int yc0=ScaleY(0.0);
|
|
// int xc0=ScaleX(0.0);
|
|
// //--- gets curve color
|
|
// uint clr=curve.Color();
|
|
// //--- draw
|
|
// for(uint i=0; i<i_cells; i++)
|
|
// {
|
|
// //--- check coordinates
|
|
// if(!MathIsValidNumber(frequency[i]) || !MathIsValidNumber(intervals[i]))
|
|
// continue;
|
|
// if(e_orientation==HISTOGRAM_HORIZONTAL)
|
|
// {
|
|
// int xc=ScaleX(intervals[i]);
|
|
// int yc=ScaleY(frequency[i]);
|
|
// int xc1 = xc - histogram_width/2;
|
|
// int xc2 = xc + histogram_width/2;
|
|
// int yc1 = yc;
|
|
// int yc2 = (originalY>yc0 && yc0>0) ? yc0 : originalY;
|
|
// //---
|
|
// if(yc1>yc2)
|
|
// yc2++;
|
|
// else
|
|
// yc2--;
|
|
// //---
|
|
// m_canvas.FillRectangle(xc1,yc1,xc2,yc2,clr);
|
|
// }
|
|
// else
|
|
// {
|
|
// int yc=ScaleY(intervals[i]);
|
|
// int xc=ScaleX(frequency[i]);
|
|
// int yc1 = yc - histogram_width/2;
|
|
// int yc2 = yc + histogram_width/2;
|
|
// int xc1 = xc;
|
|
// int xc2 = (originalX>xc0 && xc0>0) ? xc0 : originalX;
|
|
// //---
|
|
// if(xc1>xc2)
|
|
// xc2++;
|
|
// else
|
|
// xc2--;
|
|
// //---
|
|
// m_canvas.FillRectangle(xc1,yc1,xc2,yc2,clr);
|
|
// }
|
|
// }
|
|
// //---
|
|
// }
|
|
//+------------------------------------------------------------------+
|