MobinMQL/Include/Graphics/Curve.mqh
2025-07-22 14:47:41 +03:00

700 lines
22 KiB
MQL5

//+------------------------------------------------------------------+
//| Curve.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
#include <Canvas\Canvas.mqh>
//--- forward declaration
class CGraphic;
//--- fucntion for represent custom plot method
typedef void(*PlotFucntion)(double &x[],double &y[],int size,CGraphic *graphic,CCanvas *canvas,void *cbdata);
//--- function for represent curve
typedef double(*CurveFunction)(double);
//--- drawing type
enum ENUM_CURVE_TYPE
{
CURVE_POINTS,
CURVE_LINES,
CURVE_POINTS_AND_LINES,
CURVE_STEPS,
CURVE_HISTOGRAM,
CURVE_CUSTOM,
CURVE_NONE
};
//--- type for the various point shapes that are available
enum ENUM_POINT_TYPE
{
POINT_CIRCLE,
POINT_SQUARE,
POINT_DIAMOND,
POINT_TRIANGLE,
POINT_TRIANGLE_DOWN,
POINT_X_CROSS,
POINT_PLUS,
POINT_STAR,
POINT_HORIZONTAL_DASH,
POINT_VERTICAL_DASH
};
//+------------------------------------------------------------------+
//| Structure CPoint2D |
//| Usage: 2d point on graphic in Cartesian coordinates |
//+------------------------------------------------------------------+
struct CPoint2D
{
double x;
double y;
};
//+------------------------------------------------------------------+
//| Class CCurve |
//| Usage: class to represent the one-dimensional curve |
//+------------------------------------------------------------------+
class CCurve : public CObject
{
private:
uint m_clr;
double m_x[];
double m_y[];
double m_xmin;
double m_xmax;
double m_ymin;
double m_ymax;
int m_size;
ENUM_CURVE_TYPE m_type;
string m_name;
//--- lines
ENUM_LINE_STYLE m_lines_style;
ENUM_LINE_END m_lines_end_style;
int m_lines_width;
bool m_lines_smooth;
double m_lines_tension;
double m_lines_step;
//--- points
int m_points_size;
ENUM_POINT_TYPE m_points_type;
bool m_points_fill;
uint m_points_clr;
//--- steps
int m_steps_dimension;
//--- histogram
int m_hisogram_width;
//--- custom
PlotFucntion m_custom_plot_func;
void *m_custom_plot_cbdata;
//--- general property
bool m_visible;
//--- trend line property
uint m_trend_clr;
bool m_trend_visible;
protected:
bool m_trend_calc;
double m_trend_coeff[];
public:
CCurve(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name);
CCurve(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name);
CCurve(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name);
CCurve(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name);
~CCurve(void);
//--- gets the general properties
void GetX(double &x[]) const { ArrayCopy(x,m_x); }
void GetY(double &y[]) const { ArrayCopy(y,m_y); }
double XMax(void) const { return(m_xmax); }
double XMin(void) const { return(m_xmin); }
double YMax(void) const { return(m_ymax); }
double YMin(void) const { return(m_ymin); }
int Size(void) const { return(m_size); }
//--- update
void Update(const double &y[]);
void Update(const double &x[],const double &y[]);
void Update(const CPoint2D &points[]);
void Update(CurveFunction function,const double from,const double to,const double step);
//--- gets or sets general options
uint Color(void) const { return(m_clr); }
int Type(void) const { return(m_type); }
string Name(void) const { return(m_name); }
bool Visible(void) const { return(m_visible); }
void Color(const uint clr) { m_clr=clr; }
void Type(const int type) { m_type=(ENUM_CURVE_TYPE)type; }
void Name(const string name) { m_name=name; }
void Visible(const bool visible) { m_visible=visible; }
//--- gets or sets the lines properties
ENUM_LINE_STYLE LinesStyle(void) const { return(m_lines_style); }
ENUM_LINE_END LinesEndStyle(void) const { return(m_lines_end_style); }
int LinesWidth(void) const { return(m_lines_width); }
bool LinesSmooth(void) const { return(m_lines_smooth); }
double LinesSmoothTension(void) const { return(m_lines_tension); }
double LinesSmoothStep(void) const { return(m_lines_step); }
void LinesStyle(ENUM_LINE_STYLE style) { m_lines_style=style; }
void LinesEndStyle(ENUM_LINE_END end_style) { m_lines_end_style=end_style; }
void LinesWidth(const int width) { m_lines_width=width; }
void LinesSmooth(const bool smooth) { m_lines_smooth=smooth; }
void LinesSmoothTension(const double tension) { m_lines_tension=tension; }
void LinesSmoothStep(const double step) { m_lines_step=step; }
//--- gets or sets the points properties
int PointsSize(void) const { return(m_points_size); }
ENUM_POINT_TYPE PointsType(void) const { return(m_points_type); }
bool PointsFill(void) const { return(m_points_fill); }
uint PointsColor(void) const { return(m_points_clr); }
void PointsSize(const int size) { m_points_size=size; }
void PointsType(ENUM_POINT_TYPE type) { m_points_type=type; }
void PointsFill(const bool fill) { m_points_fill=fill; }
void PointsColor(const uint clr) { m_points_clr=clr; }
//--- gets or sets the steps properties
int StepsDimension(void) const { return(m_steps_dimension); }
void StepsDimension(const int dimension) { m_steps_dimension=dimension; }
//--- gets or sets the histogram properties
int HistogramWidth(void) const { return(m_hisogram_width); }
void HistogramWidth(const int width) { m_hisogram_width=width; }
//--- gets or sets the custom properties
PlotFucntion CustomPlotFunction(void) const { return(m_custom_plot_func); }
void *CustomPlotCBData(void) const { return(m_custom_plot_cbdata); }
void CustomPlotFunction(PlotFucntion func) { m_custom_plot_func=func; }
void CustomPlotCBData(void *cbdata) { m_custom_plot_cbdata=cbdata; }
//--- gets or sets the trend line properties
bool TrendLineVisible(void) const { return(m_trend_visible); }
uint TrendLineColor(void) const { return(m_trend_clr); }
void TrendLineVisible(const bool visible) { m_trend_visible=visible; }
void TrendLineColor(const uint clr) { m_trend_clr=clr; }
void TrendLineCoefficients(double &coefficients[]);
protected:
virtual void CalculateCoefficients(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CCurve::CCurve(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name)
: m_name(name),
m_clr(clr),
m_type(type),
m_visible(false),
m_lines_style(STYLE_SOLID),
m_lines_end_style(LINE_END_ROUND),
m_lines_width(1),
m_lines_smooth(false),
m_lines_tension(0.5),
m_lines_step(1.0),
m_points_size(6),
m_points_type(POINT_CIRCLE),
m_points_fill(false),
m_points_clr(clr),
m_steps_dimension(0),
m_hisogram_width(1),
m_custom_plot_func(NULL),
m_custom_plot_cbdata(NULL),
m_trend_visible(false),
m_trend_clr(clr),
m_trend_calc(false)
{
//--- keep y array
m_size=ArraySize(y);
ArrayResize(m_x,m_size);
ArrayCopy(m_y,y);
m_xmax = m_size-1;
m_xmin = 0.0;
m_ymax = 0.0;
m_ymin = 0.0;
bool yvalid=false;
//--- find min and max values
for(int i=0; i<m_size; i++)
{
m_x[i]=i;
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax=m_y[i];
m_ymin= m_y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<y[i])
m_ymax=y[i];
else
if(m_ymin>y[i])
m_ymin=y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CCurve::CCurve(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name)
: m_name(name),
m_clr(clr),
m_type(type),
m_visible(false),
m_lines_style(STYLE_SOLID),
m_lines_end_style(LINE_END_ROUND),
m_lines_width(1),
m_lines_smooth(false),
m_lines_tension(0.5),
m_lines_step(1.0),
m_points_size(6),
m_points_type(POINT_CIRCLE),
m_points_fill(false),
m_points_clr(clr),
m_steps_dimension(0),
m_hisogram_width(1),
m_custom_plot_func(NULL),
m_custom_plot_cbdata(NULL),
m_trend_visible(false),
m_trend_clr(clr),
m_trend_calc(false)
{
//--- keep x and y array
ArrayCopy(m_x,x);
ArrayCopy(m_y,y);
m_size = ArraySize(x);
m_xmax = 0.0;
m_xmin = 0.0;
m_ymax = 0.0;
m_ymin = 0.0;
bool yvalid=false;
bool xvalid=false;
//--- find min and max values
for(int i=0; i<m_size; i++)
{
if(MathIsValidNumber(m_x[i]))
{
if(!xvalid)
{
m_xmax = x[i];
m_xmin = x[i];
xvalid=true;
}
else
{
//--- find max and min of x
if(m_xmax<x[i])
m_xmax=x[i];
else
if(m_xmin>x[i])
m_xmin=x[i];
}
}
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax = y[i];
m_ymin = y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<y[i])
m_ymax=y[i];
else
if(m_ymin>y[i])
m_ymin=y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CCurve::CCurve(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name)
: m_name(name),
m_clr(clr),
m_type(type),
m_visible(false),
m_lines_style(STYLE_SOLID),
m_lines_end_style(LINE_END_ROUND),
m_lines_width(1),
m_lines_smooth(false),
m_lines_tension(0.5),
m_lines_step(1.0),
m_points_size(6),
m_points_type(POINT_CIRCLE),
m_points_fill(false),
m_points_clr(clr),
m_steps_dimension(0),
m_hisogram_width(1),
m_custom_plot_func(NULL),
m_custom_plot_cbdata(NULL),
m_trend_visible(false),
m_trend_clr(clr),
m_trend_calc(false)
{
//--- preliminary calculation
m_size=ArraySize(points);
ArrayResize(m_x,m_size);
ArrayResize(m_y,m_size);
m_xmax = 0.0;
m_xmin = 0.0;
m_ymax = 0.0;
m_ymin = 0.0;
bool xvalid=false;
bool yvalid=false;
//--- keep x and y array
for(int i=0; i<m_size; i++)
{
m_x[i] = points[i].x;
m_y[i] = points[i].y;
if(MathIsValidNumber(m_x[i]))
{
if(!xvalid)
{
m_xmax = m_x[i];
m_xmin = m_x[i];
xvalid=true;
}
else
{
//--- find max and min of x
if(m_xmax<m_x[i])
m_xmax=m_x[i];
else
if(m_xmin>m_x[i])
m_xmin=m_x[i];
}
}
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax = m_y[i];
m_ymin = m_y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<m_y[i])
m_ymax=m_y[i];
else
if(m_ymin>m_y[i])
m_ymin=m_y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CCurve::CCurve(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name)
: m_name(name),
m_clr(clr),
m_type(type),
m_visible(false),
m_lines_style(STYLE_SOLID),
m_lines_end_style(LINE_END_ROUND),
m_lines_width(1),
m_lines_smooth(false),
m_lines_tension(0.5),
m_lines_step(1.0),
m_points_size(6),
m_points_type(POINT_CIRCLE),
m_points_fill(false),
m_points_clr(clr),
m_steps_dimension(0),
m_hisogram_width(1),
m_custom_plot_func(NULL),
m_custom_plot_cbdata(NULL),
m_trend_visible(false),
m_trend_clr(clr),
m_trend_calc(false)
{
//--- preliminary calculation
m_size=(int)((to-from)/step)+1;
ArrayResize(m_x,m_size);
ArrayResize(m_y,m_size);
m_xmax = to;
m_xmin = from;
m_ymax = 0.0;
m_ymin = 0.0;
bool yvalid=false;
//--- keep x and y array
for(int i=0; i<m_size; i++)
{
m_x[i]=from+(i*step);
m_y[i]=function(m_x[i]);
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax=m_y[i];
m_ymin=m_y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<m_y[i])
m_ymax=m_y[i];
else if(m_ymin>m_y[i])
m_ymin=m_y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CCurve::~CCurve(void)
{
}
//+------------------------------------------------------------------+
//| Update x and y coordinates of curve |
//+------------------------------------------------------------------+
void CCurve::Update(const double &y[])
{
m_trend_calc=false;
ArrayFree(m_y);
int size=ArraySize(y);
//--- keep y array
if(m_size!=size)
{
m_size=size;
ArrayResize(m_x,m_size);
}
ArrayCopy(m_y,y);
m_xmax = m_size-1;
m_xmin = 0.0;
m_ymax = 0.0;
m_ymin = 0.0;
bool yvalid=false;
//--- find min and max values
for(int i=0; i<m_size; i++)
{
m_x[i]=i;
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax=m_y[i];
m_ymin= m_y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<y[i])
m_ymax=y[i];
else
if(m_ymin>y[i])
m_ymin=y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Update x and y coordinates of curve |
//+------------------------------------------------------------------+
void CCurve::Update(const double &x[],const double &y[])
{
m_trend_calc=false;
ArrayFree(m_x);
ArrayFree(m_y);
//--- keep x and y array
ArrayCopy(m_x,x);
ArrayCopy(m_y,y);
m_size = ArraySize(x);
m_xmax = 0.0;
m_xmin = 0.0;
m_ymax = 0.0;
m_ymin = 0.0;
bool yvalid=false;
bool xvalid=false;
//--- find min and max values
for(int i=0; i<m_size; i++)
{
if(MathIsValidNumber(m_x[i]))
{
if(!xvalid)
{
m_xmax = x[i];
m_xmin = x[i];
xvalid=true;
}
else
{
//--- find max and min of x
if(m_xmax<x[i])
m_xmax=x[i];
else
if(m_xmin>x[i])
m_xmin=x[i];
}
}
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax = y[i];
m_ymin = y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<y[i])
m_ymax=y[i];
else
if(m_ymin>y[i])
m_ymin=y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Update x and y coordinates of curve |
//+------------------------------------------------------------------+
void CCurve::Update(const CPoint2D &points[])
{
m_trend_calc=false;
int size=ArraySize(points);
//--- preliminary calculation
if(size!=m_size)
{
m_size=size;
ArrayResize(m_x,m_size);
ArrayResize(m_y,m_size);
}
m_xmax = 0.0;
m_xmin = 0.0;
m_ymax = 0.0;
m_ymin = 0.0;
bool xvalid=false;
bool yvalid=false;
//--- keep x and y array
for(int i=0; i<m_size; i++)
{
m_x[i] = points[i].x;
m_y[i] = points[i].y;
if(MathIsValidNumber(m_x[i]))
{
if(!xvalid)
{
m_xmax = m_x[i];
m_xmin = m_x[i];
xvalid=true;
}
else
{
//--- find max and min of x
if(m_xmax<m_x[i])
m_xmax=m_x[i];
else
if(m_xmin>m_x[i])
m_xmin=m_x[i];
}
}
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax = m_y[i];
m_ymin = m_y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<m_y[i])
m_ymax=m_y[i];
else
if(m_ymin>m_y[i])
m_ymin=m_y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Update x and y coordinates of curve |
//+------------------------------------------------------------------+
void CCurve::Update(CurveFunction function,const double from,const double to,const double step)
{
m_trend_calc=false;
int size=(int)((to-from)/step)+1;
//--- preliminary calculation
if(size!=m_size)
{
m_size=size;
ArrayResize(m_x,m_size);
ArrayResize(m_y,m_size);
}
m_xmax = to;
m_xmin = from;
m_ymax = 0.0;
m_ymin = 0.0;
bool yvalid=false;
//--- keep x and y array
for(int i=0; i<m_size; i++)
{
m_x[i]=from+(i*step);
m_y[i]=function(m_x[i]);
if(MathIsValidNumber(m_y[i]))
{
if(!yvalid)
{
m_ymax=m_y[i];
m_ymin=m_y[i];
yvalid=true;
}
else
{
//--- find max and min of y
if(m_ymax<m_y[i])
m_ymax=m_y[i];
else if(m_ymin>m_y[i])
m_ymin=m_y[i];
}
}
}
//---
}
//+------------------------------------------------------------------+
//| Gets the coefficients for trend line |
//+------------------------------------------------------------------+
void CCurve::TrendLineCoefficients(double &coefficients[])
{
if(!m_trend_calc)
{
CalculateCoefficients();
m_trend_calc=true;
}
ArrayCopy(coefficients,m_trend_coeff);
}
//+------------------------------------------------------------------+
//| Calculate coefficients |
//+------------------------------------------------------------------+
void CCurve::CalculateCoefficients(void)
{
//--- simple linear resgression
ArrayResize(m_trend_coeff,2);
double xmean=0.0;
double ymean=0.0;
double sum_xy=0.0;
double sum_xx=0.0;
//--- primary calculate
for(int i=0; i<m_size; i++)
{
xmean+=m_x[i];
ymean+=m_y[i];
sum_xy+=m_x[i]*m_y[i];
sum_xx+=m_x[i]*m_x[i];
}
xmean/=m_size;
ymean/=m_size;
//--- calculate intercept
m_trend_coeff[0]=(sum_xy -(m_size*xmean*ymean))/(sum_xx -(m_size*xmean*xmean));
//--- calculate slope
m_trend_coeff[1]=ymean-m_trend_coeff[0]*xmean;
}
//+------------------------------------------------------------------+