Files
2025-02-07 19:13:59 +03:30

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 &timeserie[]);
bool UpdateTimeserie(const double &timeserie[],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 &timeserie[])
{
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 &timeserie[], 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);
// }
// }
// //---
// }
//+------------------------------------------------------------------+