Add files via upload
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Axis.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
typedef string(*DoubleToStringFunction)(double,void*);
|
||||
//--- Various axis types
|
||||
enum ENUM_AXIS_TYPE
|
||||
{
|
||||
AXIS_TYPE_DOUBLE,
|
||||
AXIS_TYPE_DATETIME,
|
||||
AXIS_TYPE_CUSTOM,
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CAxis |
|
||||
//| Usage: class for create axes on a two-dimensional graphics |
|
||||
//+------------------------------------------------------------------+
|
||||
class CAxis
|
||||
{
|
||||
private:
|
||||
double m_min;
|
||||
double m_max;
|
||||
double m_step;
|
||||
uint m_clr;
|
||||
string m_name;
|
||||
int m_name_size;
|
||||
int m_values_size;
|
||||
int m_values_width;
|
||||
string m_values_format;
|
||||
string m_values_fontname;
|
||||
uint m_values_fontflags;
|
||||
uint m_values_fontangle;
|
||||
bool m_auto_scale;
|
||||
double m_zero_lever; // this number is used to determine when an axis scale range should be extended to include the zero value.
|
||||
double m_default_step; // length of the default step
|
||||
double m_max_labels; // the maximum number of marks
|
||||
double m_min_grace; // "grace" value applied to the minimum data range
|
||||
double m_max_grace; // "grace" value applied to the maximum data range
|
||||
int m_values_dt_mode;
|
||||
DoubleToStringFunction m_values_func;
|
||||
void *m_values_cbdata;
|
||||
ENUM_AXIS_TYPE m_type;
|
||||
|
||||
public:
|
||||
CAxis(void);
|
||||
~CAxis(void);
|
||||
//--- properties
|
||||
double Step(void) const { return(m_step); }
|
||||
double Min(void) const { return(m_min); }
|
||||
void Min(const double min) { m_min=min; }
|
||||
double Max(void) const { return(m_max); }
|
||||
void Max(const double max) { m_max=max; }
|
||||
string Name(void) const { return(m_name); }
|
||||
void Name(const string name) { m_name=name; }
|
||||
ENUM_AXIS_TYPE Type(void) const { return(m_type); }
|
||||
void Type(ENUM_AXIS_TYPE type) { m_type=type; }
|
||||
//--- default properties
|
||||
uint Color(void) const { return(m_clr); }
|
||||
void Color(const uint clr) { m_clr=clr; }
|
||||
bool AutoScale(void) const { return(m_auto_scale); }
|
||||
void AutoScale(const bool auto) { m_auto_scale=auto; }
|
||||
int ValuesSize(void) const { return(m_values_size); }
|
||||
void ValuesSize(const int size) { m_values_size=size; }
|
||||
int ValuesWidth(void) const { return(m_values_width); }
|
||||
void ValuesWidth(const int width) { m_values_width=width; }
|
||||
string ValuesFormat(void) const { return(m_values_format); }
|
||||
void ValuesFormat(const string format) { m_values_format=format; }
|
||||
int ValuesDateTimeMode(void) const { return(m_values_dt_mode); }
|
||||
void ValuesDateTimeMode(const int mode) { m_values_dt_mode=mode; }
|
||||
DoubleToStringFunction ValuesFunctionFormat(void) const { return(m_values_func); }
|
||||
void ValuesFunctionFormat(DoubleToStringFunction func) { m_values_func=func; }
|
||||
void *ValuesFunctionFormatCBData(void) const { return(m_values_cbdata); }
|
||||
void ValuesFunctionFormatCBData(void *cbdata) { m_values_cbdata=cbdata; }
|
||||
string ValuesFontName(void) const { return(m_values_fontname); }
|
||||
void ValuesFontName(const string fontname) { m_values_fontname=fontname; }
|
||||
uint ValuesFontAngle(void) const { return(m_values_fontangle); }
|
||||
void ValuesFontAngle(const uint fontangle) { m_values_fontangle=fontangle; }
|
||||
uint ValuesFontFlags(void) const { return(m_values_fontflags); }
|
||||
void ValuesFontFlags(const uint fontflags) { m_values_fontflags=fontflags; }
|
||||
int NameSize(void) const { return(m_name_size); }
|
||||
void NameSize(const int size) { m_name_size=size; }
|
||||
double ZeroLever(void) const { return(m_zero_lever); }
|
||||
void ZeroLever(const double value) { m_zero_lever=value; }
|
||||
double DefaultStep(void) const { return(m_default_step); }
|
||||
void DefaultStep(const double value) { m_default_step=value; }
|
||||
double MaxLabels(void) const { return(m_max_labels); }
|
||||
void MaxLabels(const double value) { m_max_labels=value; }
|
||||
double MinGrace(void) const { return(m_min_grace); }
|
||||
void MinGrace(const double value) { m_min_grace=value; }
|
||||
double MaxGrace(void) const { return(m_max_grace); }
|
||||
void MaxGrace(const double value) { m_max_grace=value; }
|
||||
//--- method for auto scaling
|
||||
void SelectAxisScale(void);
|
||||
|
||||
private:
|
||||
//--- additional methods for axis autoscaling
|
||||
void ExtensionBoundaries(void);
|
||||
double CalcStepSize(const double range,const double steps);
|
||||
double Mod(const double x,const double y);
|
||||
double CalcBoundedStepSize(const double range,const double max_steps);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CAxis::CAxis(void) : m_auto_scale(true),
|
||||
m_zero_lever(0.25),
|
||||
m_default_step(25.0),
|
||||
m_max_labels(15),
|
||||
m_min_grace(0.01),
|
||||
m_max_grace(0.01),
|
||||
m_clr(clrBlack),
|
||||
m_name_size(0),
|
||||
m_values_size(12),
|
||||
m_values_fontname("arial"),
|
||||
m_values_fontflags(0),
|
||||
m_values_fontangle(0),
|
||||
m_values_func(NULL),
|
||||
m_values_cbdata(NULL),
|
||||
m_values_dt_mode(TIME_MINUTES),
|
||||
m_type(AXIS_TYPE_DOUBLE),
|
||||
m_values_width(30)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CAxis::~CAxis(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Rounds a maximum, minimum values and defines step size. |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAxis::SelectAxisScale(void)
|
||||
{
|
||||
if(m_min>m_max)
|
||||
m_max=m_min;
|
||||
if(!m_auto_scale)
|
||||
{
|
||||
if(m_max<=m_min)
|
||||
ExtensionBoundaries();
|
||||
m_step=((m_max-m_min)>m_default_step && m_default_step>0) ? m_default_step : m_max-m_min;
|
||||
return;
|
||||
}
|
||||
ExtensionBoundaries();
|
||||
//--- test for trivial condition of range = 0 and pick a suitable default
|
||||
if(m_max-m_min<1.0e-30)
|
||||
{
|
||||
m_max=m_max+0.2 *(m_max==0 ? 1.0 : MathAbs(m_max));
|
||||
m_min=m_min-0.2 *(m_min==0 ? 1.0 : MathAbs(m_min));
|
||||
}
|
||||
//--- this is the zero-lever test. If m_min is within the zero lever fraction of the data range,then use zero.
|
||||
if(m_min>0 && m_min/(m_max-m_min)<m_zero_lever)
|
||||
m_min=0;
|
||||
//--- repeat the zero-lever test for cases where the m_max is less than zero
|
||||
if(m_max<0 && MathAbs(m_max/(m_max-m_min))<m_zero_lever)
|
||||
m_max=0;
|
||||
//--- calculate the new m_step size
|
||||
double target_step=(m_default_step!=0) ? m_default_step : m_max-m_min;
|
||||
//--- Calculate the m_step size based on target steps
|
||||
m_step=CalcStepSize(m_max-m_min,target_step);
|
||||
double labels=MathCeil((m_max-m_min)/m_step);
|
||||
if(m_max_labels<labels && m_max_labels>0)
|
||||
m_step=CalcBoundedStepSize(m_max-m_min,m_max_labels);
|
||||
else
|
||||
m_step=CalcBoundedStepSize(m_max-m_min,labels);
|
||||
//--- calculate the scale minimum
|
||||
m_min=m_min-Mod(m_min,m_step);
|
||||
//--- calculate the scale maximum
|
||||
m_max=Mod(m_max,m_step)==0.0 ? m_max : m_max+m_step-Mod(m_max,m_step);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expands the boundaries to the left and right. |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAxis::ExtensionBoundaries(void)
|
||||
{
|
||||
double range=m_max-m_min;
|
||||
//--- do not let the grace value extend the axis below zero when all the values were positive
|
||||
if(m_min<0 || m_min-m_min_grace*range>=0.0)
|
||||
m_min=m_min-m_min_grace*range;
|
||||
//--- do not let the grace value extend the axis above zero when all the values were negative
|
||||
if(m_max>0 || m_max+m_max_grace*range<=0.0)
|
||||
m_max=m_max+m_max_grace*range;
|
||||
//--- calculate new min and max values if they equal
|
||||
if(m_max==m_min)
|
||||
{
|
||||
if(MathAbs(m_max)>1e-100)
|
||||
{
|
||||
m_max *= (m_min < 0 ? 0.95 : 1.05 );
|
||||
m_min *= (m_min < 0 ? 1.05 : 0.95 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_max = 1.0;
|
||||
m_min = -1.0;
|
||||
}
|
||||
}
|
||||
//---
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate a m_step size based on a data range. |
|
||||
//+------------------------------------------------------------------+
|
||||
double CAxis::CalcStepSize(const double range,const double steps)
|
||||
{
|
||||
//--- calculate an initial guess at m_step size
|
||||
double temp=range/steps;
|
||||
//--- get the magnitude of the m_step size
|
||||
double mag=MathFloor(MathLog10(temp));
|
||||
double magPow=MathPow(10.0,mag);
|
||||
//--- calculate most significant digit of the new m_step size
|
||||
double magMsd=NormalizeDouble(temp/magPow+.5,0);
|
||||
//--- promote the MSD to either 1, 2, or 5
|
||||
if(magMsd>5.0)
|
||||
magMsd=10.0;
|
||||
else
|
||||
if(magMsd>2.0)
|
||||
magMsd=5.0;
|
||||
else
|
||||
if(magMsd>1.0)
|
||||
magMsd=2.0;
|
||||
//--- return step
|
||||
return(magMsd * magPow);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate the modulus (remainder) in a safe manner so that divide|
|
||||
//| by zero errors are avoided |
|
||||
//+------------------------------------------------------------------+
|
||||
double CAxis::Mod(const double x,const double y)
|
||||
{
|
||||
//--- check
|
||||
if(y==0)
|
||||
return(0);
|
||||
//--- calculate modulus
|
||||
return (x>0)? MathMod(x,y): MathMod(x,y)+y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate a m_step size based on a data range, limited to a max |
|
||||
//| number of steps. |
|
||||
//+------------------------------------------------------------------+
|
||||
double CAxis::CalcBoundedStepSize(const double range,const double max_steps)
|
||||
{
|
||||
//--- calculate an initial guess at m_step size
|
||||
double temp=range/max_steps;
|
||||
//--- get the magnitude of the m_step size
|
||||
double mag=MathFloor(MathLog10(temp));
|
||||
double magPow=MathPow((double) 10.0,mag);
|
||||
//--- calculate most significant digit of the new m_step size
|
||||
double magMsd=MathCeil(temp/magPow);
|
||||
//--- promote the MSD to either 1, 2, or 5
|
||||
if(magMsd>5.0)
|
||||
magMsd=10.0;
|
||||
else
|
||||
if(magMsd>2.0)
|
||||
magMsd=5.0;
|
||||
else
|
||||
if(magMsd>1.0)
|
||||
magMsd=2.0;
|
||||
//--- return step
|
||||
return(magMsd * magPow);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,74 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ColorGenerator.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CColorGenerator |
|
||||
//| Usage: class to generate the default colors |
|
||||
//+------------------------------------------------------------------+
|
||||
class CColorGenerator
|
||||
{
|
||||
private:
|
||||
int m_index;
|
||||
bool m_generate;
|
||||
uint m_current_palette[20];
|
||||
const static uint s_default_palette[20];
|
||||
|
||||
public:
|
||||
CColorGenerator(void);
|
||||
~CColorGenerator(void);
|
||||
//--- gets the next color
|
||||
uint Next(void);
|
||||
//--- reset generator
|
||||
void Reset(void);
|
||||
};
|
||||
const uint CColorGenerator::s_default_palette[20]=
|
||||
{
|
||||
0x3366CC,0xDC3912,0xFF9900,0x109618,0x990099,
|
||||
0x3B3EAC,0x0099C6,0xDD4477,0x66AA00,0xB82E2E,
|
||||
0x316395,0x994499,0x22AA99,0xAAAA11,0x6633CC,
|
||||
0xE67300,0x8B0707,0x329262,0x5574A6,0x3B3EAC
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CColorGenerator::CColorGenerator(void): m_index(0),
|
||||
m_generate(false)
|
||||
{
|
||||
ArrayCopy(m_current_palette,s_default_palette);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CColorGenerator::~CColorGenerator(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gets or generates the following color from the palette |
|
||||
//+------------------------------------------------------------------+
|
||||
uint CColorGenerator::Next(void)
|
||||
{
|
||||
//--- check the array out of range
|
||||
if(m_index==20)
|
||||
{
|
||||
m_index=0;
|
||||
if(!m_generate)
|
||||
m_generate=true;
|
||||
}
|
||||
//--- check the default palette is over
|
||||
if(m_generate)
|
||||
m_current_palette[m_index]=(m_index==19 ? (m_current_palette[m_index]^m_current_palette[0]):(m_current_palette[m_index]^m_current_palette[m_index+1]));
|
||||
//--- return next color
|
||||
return(m_current_palette[m_index++]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resets all the new colors, set the index to 0 |
|
||||
//+------------------------------------------------------------------+
|
||||
void CColorGenerator::Reset(void)
|
||||
{
|
||||
m_index=0;
|
||||
m_generate=false;
|
||||
ArrayCopy(m_current_palette,s_default_palette);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,700 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Curve.mqh |
|
||||
//| Copyright 2000-2024, 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;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,761 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BillWilliams.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Indicator.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiAC. |
|
||||
//| Purpose: Class of the "Accelerator Oscillator" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiAC : public CIndicator
|
||||
{
|
||||
public:
|
||||
CiAC(void);
|
||||
~CiAC(void);
|
||||
//--- method of creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
//--- methods of access to data of indicator
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_AC); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAC::CiAC(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAC::~CiAC(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Accelerator Oscillator" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAC::Create(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iAC(symbol,period);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- idicator successfully created
|
||||
if(!Initialize(symbol,period))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAC::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAC::Initialize(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="AC";
|
||||
m_status="("+symbol+","+PeriodDescription()+") H="+IntegerToString(m_handle);
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to the buffer of "Accelerator Oscillator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiAC::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiAlligator. |
|
||||
//| Purpose: Class of the "Alligator" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiAlligator : public CIndicator
|
||||
{
|
||||
protected:
|
||||
int m_jaw_period;
|
||||
int m_jaw_shift;
|
||||
int m_teeth_period;
|
||||
int m_teeth_shift;
|
||||
int m_lips_period;
|
||||
int m_lips_shift;
|
||||
ENUM_MA_METHOD m_ma_method;
|
||||
int m_applied;
|
||||
|
||||
public:
|
||||
CiAlligator(void);
|
||||
~CiAlligator(void);
|
||||
//--- methods of access to protected data
|
||||
int JawPeriod(void) const { return(m_jaw_period); }
|
||||
int JawShift(void) const { return(m_jaw_shift); }
|
||||
int TeethPeriod(void) const { return(m_teeth_period); }
|
||||
int TeethShift(void) const { return(m_teeth_shift); }
|
||||
int LipsPeriod(void) const { return(m_lips_period); }
|
||||
int LipsShift(void) const { return(m_lips_shift); }
|
||||
ENUM_MA_METHOD MaMethod(void) const { return(m_ma_method); }
|
||||
int Applied(void) const { return(m_applied); }
|
||||
//--- method of creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied);
|
||||
//--- methods of access to data of indicator
|
||||
double Jaw(const int index) const;
|
||||
double Teeth(const int index) const;
|
||||
double Lips(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_ALLIGATOR); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAlligator::CiAlligator(void) : m_jaw_period(-1),
|
||||
m_jaw_shift(-1),
|
||||
m_teeth_period(-1),
|
||||
m_teeth_shift(-1),
|
||||
m_lips_period(-1),
|
||||
m_lips_shift(-1),
|
||||
m_ma_method(WRONG_VALUE),
|
||||
m_applied(-1)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAlligator::~CiAlligator(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Alligator" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAlligator::Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iAlligator(symbol,period,jaw_period,jaw_shift,teeth_period,teeth_shift,lips_period,lips_shift,ma_method,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- idicator successfully created
|
||||
if(!Initialize(symbol,period,jaw_period,jaw_shift,teeth_period,teeth_shift,lips_period,lips_shift,ma_method,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAlligator::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,
|
||||
(int)params[2].integer_value,(int)params[3].integer_value,
|
||||
(int)params[4].integer_value,(int)params[5].integer_value,
|
||||
(ENUM_MA_METHOD)params[6].integer_value,(int)params[7].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAlligator::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,3))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="Alligator";
|
||||
m_status="("+symbol+","+PeriodDescription()+","+
|
||||
IntegerToString(jaw_period)+","+IntegerToString(jaw_shift)+","+
|
||||
IntegerToString(teeth_period)+","+IntegerToString(teeth_shift)+","+
|
||||
IntegerToString(lips_period)+","+IntegerToString(lips_shift)+","+
|
||||
MethodDescription(ma_method)+","+PriceDescription(applied)+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_jaw_period =jaw_period;
|
||||
m_jaw_shift =jaw_shift;
|
||||
m_teeth_period=teeth_period;
|
||||
m_teeth_shift =teeth_shift;
|
||||
m_lips_period =lips_period;
|
||||
m_lips_shift =lips_shift;
|
||||
m_ma_method =ma_method;
|
||||
m_applied =applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("JAW_LINE");
|
||||
((CIndicatorBuffer*)At(0)).Offset(jaw_shift);
|
||||
((CIndicatorBuffer*)At(1)).Name("TEETH_LINE");
|
||||
((CIndicatorBuffer*)At(1)).Offset(teeth_shift);
|
||||
((CIndicatorBuffer*)At(2)).Name("LIPS_LINE");
|
||||
((CIndicatorBuffer*)At(2)).Offset(lips_shift);
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Jaw buffer of "Alligator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiAlligator::Jaw(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Teeth buffer of "Alligator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiAlligator::Teeth(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(1);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Lips buffer of "Alligator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiAlligator::Lips(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(2);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiAO. |
|
||||
//| Purpose: Class of the "Awesome Oscillator" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiAO : public CIndicator
|
||||
{
|
||||
public:
|
||||
CiAO(void);
|
||||
~CiAO(void);
|
||||
//--- method of creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
//--- methods of access to data of indicator
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_AO); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAO::CiAO(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAO::~CiAO(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Awesome Oscillator" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAO::Create(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iAO(symbol,period);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- indicator successfullly created
|
||||
if(!Initialize(symbol,period))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAO::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Awesome Oscillator" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAO::Initialize(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_status="AO("+symbol+","+PeriodDescription()+") H="+IntegerToString(m_handle);
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to buffer of "Awesome Oscillator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiAO::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiFractals. |
|
||||
//| Purpose: Class of the "Fractals" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiFractals : public CIndicator
|
||||
{
|
||||
public:
|
||||
CiFractals(void);
|
||||
~CiFractals(void);
|
||||
//--- method of creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
//--- methods of access to indicator data
|
||||
double Upper(const int index) const;
|
||||
double Lower(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_FRACTALS); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiFractals::CiFractals(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiFractals::~CiFractals(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Fractals" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiFractals::Create(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iFractals(symbol,period);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- idicator successfully created
|
||||
if(!Initialize(symbol,period))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiFractals::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiFractals::Initialize(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,2))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="Fractals";
|
||||
m_status="("+symbol+","+PeriodDescription()+") H="+IntegerToString(m_handle);
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("UPPER_LINE");
|
||||
((CIndicatorBuffer*)At(1)).Name("LOWER_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Upper buffer of "Fractals" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiFractals::Upper(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Lower buffer of "Fractals" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiFractals::Lower(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(1);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiGator. |
|
||||
//| Purpose: Class of the "Gator oscillator" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiGator : public CIndicator
|
||||
{
|
||||
protected:
|
||||
int m_jaw_period;
|
||||
int m_jaw_shift;
|
||||
int m_teeth_period;
|
||||
int m_teeth_shift;
|
||||
int m_lips_period;
|
||||
int m_lips_shift;
|
||||
ENUM_MA_METHOD m_ma_method;
|
||||
int m_applied;
|
||||
|
||||
public:
|
||||
CiGator(void);
|
||||
~CiGator(void);
|
||||
//--- methods of access to protected data
|
||||
int JawPeriod(void) const { return(m_jaw_period); }
|
||||
int JawShift(void) const { return(m_jaw_shift); }
|
||||
int TeethPeriod(void) const { return(m_teeth_period); }
|
||||
int TeethShift(void) const { return(m_teeth_shift); }
|
||||
int LipsPeriod(void) const { return(m_lips_period); }
|
||||
int LipsShift(void) const { return(m_lips_shift); }
|
||||
ENUM_MA_METHOD MaMethod(void) const { return(m_ma_method); }
|
||||
int Applied(void) const { return(m_applied); }
|
||||
//--- method of creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied);
|
||||
//--- methods of access to data of indicator
|
||||
double Upper(const int index) const;
|
||||
double Lower(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_GATOR); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiGator::CiGator(void) : m_jaw_period(-1),
|
||||
m_jaw_shift(-1),
|
||||
m_teeth_period(-1),
|
||||
m_teeth_shift(-1),
|
||||
m_lips_period(-1),
|
||||
m_lips_shift(-1),
|
||||
m_ma_method(WRONG_VALUE),
|
||||
m_applied(-1)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiGator::~CiGator(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create indicator "Gator oscillator" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiGator::Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iGator(symbol,period,jaw_period,jaw_shift,teeth_period,teeth_shift,lips_period,lips_shift,ma_method,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- idicator successfully created
|
||||
if(!Initialize(symbol,period,jaw_period,jaw_shift,teeth_period,teeth_shift,lips_period,lips_shift,ma_method,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiGator::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,
|
||||
(int)params[2].integer_value,(int)params[3].integer_value,
|
||||
(int)params[4].integer_value,(int)params[5].integer_value,
|
||||
(ENUM_MA_METHOD)params[6].integer_value,(int)params[7].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiGator::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int jaw_period,const int jaw_shift,
|
||||
const int teeth_period,const int teeth_shift,
|
||||
const int lips_period,const int lips_shift,
|
||||
const ENUM_MA_METHOD ma_method,const int applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,2))
|
||||
{
|
||||
//--- string of status drawing
|
||||
m_name ="Gator";
|
||||
m_status="("+symbol+","+PeriodDescription()+","+
|
||||
IntegerToString(jaw_period)+","+IntegerToString(jaw_shift)+","+
|
||||
IntegerToString(teeth_period)+","+IntegerToString(teeth_shift)+","+
|
||||
IntegerToString(lips_period)+","+IntegerToString(lips_shift)+","+
|
||||
MethodDescription(ma_method)+","+PriceDescription(applied)+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_jaw_period =jaw_period;
|
||||
m_jaw_shift =jaw_shift;
|
||||
m_teeth_period=teeth_period;
|
||||
m_teeth_shift =teeth_shift;
|
||||
m_lips_period =lips_period;
|
||||
m_lips_shift =lips_shift;
|
||||
m_ma_method =ma_method;
|
||||
m_applied =applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("UPPER_LINE");
|
||||
((CIndicatorBuffer*)At(0)).Offset(teeth_shift);
|
||||
((CIndicatorBuffer*)At(1)).Name("LOWER_LINE");
|
||||
((CIndicatorBuffer*)At(1)).Offset(lips_shift);
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Upper buffer of "Gator oscillator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiGator::Upper(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to Lower buffer of "Gator oscillator" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiGator::Lower(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(1);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiBWMFI. |
|
||||
//| Purpose: Class of the "Market Facilitation Index" indicator |
|
||||
//| by Bill Williams". |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiBWMFI : public CIndicator
|
||||
{
|
||||
protected:
|
||||
ENUM_APPLIED_VOLUME m_applied;
|
||||
|
||||
public:
|
||||
CiBWMFI(void);
|
||||
~CiBWMFI(void);
|
||||
//--- methods of access to protected data
|
||||
ENUM_APPLIED_VOLUME Applied(void) const { return(m_applied); }
|
||||
//--- method of creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
//--- methods of access to data of indicator
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_BWMFI); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiBWMFI::CiBWMFI(void) : m_applied(WRONG_VALUE)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiBWMFI::~CiBWMFI(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create "Market Facilitation Index by Bill Williams" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiBWMFI::Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iBWMFI(symbol,period,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- idicator successfully created
|
||||
if(!Initialize(symbol,period,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiBWMFI::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(ENUM_APPLIED_VOLUME)params[0].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize indicator with the special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiBWMFI::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="BWMFI";
|
||||
m_status="BWMFI("+symbol+","+PeriodDescription()+","+VolumeDescription(applied)+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_applied=applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to buffer of "Market Facilitation Index by Bill Williams".|
|
||||
//+------------------------------------------------------------------+
|
||||
double CiBWMFI::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,194 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Indicator.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiCustom. |
|
||||
//| Purpose: Class of custom indicators. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiCustom : public CIndicator
|
||||
{
|
||||
protected:
|
||||
int m_num_params; // number of creation parameters
|
||||
MqlParam m_params[]; // creation parameters
|
||||
|
||||
public:
|
||||
CiCustom(void);
|
||||
~CiCustom(void);
|
||||
//--- methods of access to protected data
|
||||
bool NumBuffers(const int buffers);
|
||||
int NumParams(void) const { return(m_num_params); }
|
||||
ENUM_DATATYPE ParamType(const int ind) const;
|
||||
long ParamLong(const int ind) const;
|
||||
double ParamDouble(const int ind) const;
|
||||
string ParamString(const int ind) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_CUSTOM); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiCustom::CiCustom(void) : m_num_params(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiCustom::~CiCustom(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set number of buffers of indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiCustom::NumBuffers(const int buffers)
|
||||
{
|
||||
bool result=true;
|
||||
//---
|
||||
if(m_buffers_total==0)
|
||||
{
|
||||
m_buffers_total=buffers;
|
||||
return(true);
|
||||
}
|
||||
if(m_buffers_total!=buffers)
|
||||
{
|
||||
Shutdown();
|
||||
result=CreateBuffers(m_symbol,m_period,buffers);
|
||||
if(result)
|
||||
{
|
||||
//--- create buffers
|
||||
for(int i=0;i<m_buffers_total;i++)
|
||||
((CIndicatorBuffer*)At(i)).Name("LINE "+IntegerToString(i));
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get type of specified parameter of creation |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_DATATYPE CiCustom::ParamType(const int ind) const
|
||||
{
|
||||
if(ind>=m_num_params)
|
||||
return(WRONG_VALUE);
|
||||
//---
|
||||
return(m_params[ind].type);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get specified parameter of creatiob as a long value |
|
||||
//+------------------------------------------------------------------+
|
||||
long CiCustom::ParamLong(const int ind) const
|
||||
{
|
||||
if(ind>=m_num_params)
|
||||
return(0);
|
||||
switch(m_params[ind].type)
|
||||
{
|
||||
case TYPE_DOUBLE:
|
||||
case TYPE_FLOAT:
|
||||
case TYPE_STRING:
|
||||
return(0);
|
||||
}
|
||||
//---
|
||||
return(m_params[ind].integer_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get specified parameter of creation as a double value |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiCustom::ParamDouble(const int ind) const
|
||||
{
|
||||
if(ind>=m_num_params)
|
||||
return(EMPTY_VALUE);
|
||||
switch(m_params[ind].type)
|
||||
{
|
||||
case TYPE_DOUBLE:
|
||||
case TYPE_FLOAT:
|
||||
break;
|
||||
default:
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
//---
|
||||
return(m_params[ind].double_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get specified parameter of creation as a string value |
|
||||
//+------------------------------------------------------------------+
|
||||
string CiCustom::ParamString(const int ind) const
|
||||
{
|
||||
if(ind>=m_num_params || m_params[ind].type!=TYPE_STRING)
|
||||
return("");
|
||||
//---
|
||||
return(m_params[ind].string_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiCustom::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
int i;
|
||||
//--- tune
|
||||
if(m_buffers_total==0)
|
||||
m_buffers_total=256;
|
||||
if(CreateBuffers(symbol,period,m_buffers_total))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="Custom "+params[0].string_value;
|
||||
m_status="("+symbol+","+PeriodDescription();
|
||||
for(i=1;i<num_params;i++)
|
||||
{
|
||||
switch(params[i].type)
|
||||
{
|
||||
case TYPE_BOOL:
|
||||
m_status=m_status+","+((params[i].integer_value)?"true":"false");
|
||||
break;
|
||||
case TYPE_CHAR:
|
||||
case TYPE_UCHAR:
|
||||
case TYPE_SHORT:
|
||||
case TYPE_USHORT:
|
||||
case TYPE_INT:
|
||||
case TYPE_UINT:
|
||||
case TYPE_LONG:
|
||||
case TYPE_ULONG:
|
||||
m_status=m_status+","+IntegerToString(params[i].integer_value);
|
||||
break;
|
||||
case TYPE_COLOR:
|
||||
m_status=m_status+","+ColorToString((color)params[i].integer_value);
|
||||
break;
|
||||
case TYPE_DATETIME:
|
||||
m_status=m_status+","+TimeToString(params[i].integer_value);
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
case TYPE_DOUBLE:
|
||||
m_status=m_status+","+DoubleToString(params[i].double_value);
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
m_status=m_status+",'"+params[i].string_value+"'";
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_status=m_status+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
ArrayResize(m_params,num_params);
|
||||
for(i=0;i<num_params;i++)
|
||||
{
|
||||
m_params[i].type =params[i].type;
|
||||
m_params[i].integer_value=params[i].integer_value;
|
||||
m_params[i].double_value =params[i].double_value;
|
||||
m_params[i].string_value =params[i].string_value;
|
||||
}
|
||||
m_num_params=num_params;
|
||||
//--- create buffers
|
||||
for(i=0;i<m_buffers_total;i++)
|
||||
((CIndicatorBuffer*)At(i)).Name("LINE "+IntegerToString(i));
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,516 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Indicator.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Series.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CIndicatorBuffer. |
|
||||
//| Purpose: Class for access to data of buffers of |
|
||||
//| technical indicators. |
|
||||
//| Derives from class CDoubleBuffer. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CIndicatorBuffer : public CDoubleBuffer
|
||||
{
|
||||
protected:
|
||||
int m_offset; // shift along the time axis (in bars)
|
||||
string m_name; // name of buffer
|
||||
|
||||
public:
|
||||
CIndicatorBuffer(void);
|
||||
~CIndicatorBuffer(void);
|
||||
//--- methods of access to protected data
|
||||
int Offset(void) const { return(m_offset); }
|
||||
void Offset(const int offset) { m_offset=offset; }
|
||||
string Name(void) const { return(m_name); }
|
||||
void Name(const string name) { m_name=name; }
|
||||
//--- methods of access to data
|
||||
double At(const int index) const;
|
||||
//--- method of refreshing of data in buffer
|
||||
bool Refresh(const int handle,const int num);
|
||||
bool RefreshCurrent(const int handle,const int num);
|
||||
|
||||
private:
|
||||
virtual bool Refresh(void) { return(CDoubleBuffer::Refresh()); }
|
||||
virtual bool RefreshCurrent(void) { return(CDoubleBuffer::RefreshCurrent()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CIndicatorBuffer::CIndicatorBuffer(void) : m_offset(0),
|
||||
m_name("")
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CIndicatorBuffer::~CIndicatorBuffer(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in a specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
double CIndicatorBuffer::At(const int index) const
|
||||
{
|
||||
return(CDoubleBuffer::At(index+m_offset));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Refreshing of data in buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicatorBuffer::Refresh(const int handle,const int num)
|
||||
{
|
||||
//--- check
|
||||
if(handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
m_data_total=CopyBuffer(handle,num,-m_offset,m_size,m_data);
|
||||
//---
|
||||
return(m_data_total>0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Refreshing of the data in buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicatorBuffer::RefreshCurrent(const int handle,const int num)
|
||||
{
|
||||
double array[1];
|
||||
//--- check
|
||||
if(handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
if(CopyBuffer(handle,num,-m_offset,1,array)>0 && m_data_total>0)
|
||||
{
|
||||
m_data[0]=array[0];
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CIndicator. |
|
||||
//| Purpose: Base class of technical indicators. |
|
||||
//| Derives from class CSeries. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CIndicator : public CSeries
|
||||
{
|
||||
protected:
|
||||
int m_handle; // indicator handle
|
||||
string m_status; // status of creation
|
||||
bool m_full_release; // flag
|
||||
bool m_redrawer; // flag
|
||||
|
||||
public:
|
||||
CIndicator(void);
|
||||
~CIndicator(void);
|
||||
//--- methods of access to protected data
|
||||
int Handle(void) const { return(m_handle); }
|
||||
string Status(void) const { return(m_status); }
|
||||
void FullRelease(const bool flag=true) { m_full_release=flag; }
|
||||
void Redrawer(const bool flag=true) { m_redrawer=flag; }
|
||||
//--- method for creating
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const ENUM_INDICATOR type,const int num_params,const MqlParam ¶ms[]);
|
||||
virtual bool BufferResize(const int size);
|
||||
//--- methods of access to data
|
||||
int BarsCalculated(void) const;
|
||||
double GetData(const int buffer_num,const int index) const;
|
||||
int GetData(const int start_pos,const int count,const int buffer_num,double &buffer[]) const;
|
||||
int GetData(const datetime start_time,const int count,const int buffer_num,double &buffer[]) const;
|
||||
int GetData(const datetime start_time,const datetime stop_time,const int buffer_num,double &buffer[]) const;
|
||||
//--- methods for find extremum
|
||||
int Minimum(const int buffer_num,const int start,const int count) const;
|
||||
double MinValue(const int buffer_num,const int start,const int count,int &index) const;
|
||||
int Maximum(const int buffer_num,const int start,const int count) const;
|
||||
double MaxValue(const int buffer_num,const int start,const int count,int &index) const;
|
||||
//--- method of "freshening" of the data
|
||||
virtual void Refresh(const int flags=OBJ_ALL_PERIODS);
|
||||
//--- methods for working with chart
|
||||
bool AddToChart(const long chart,const int subwin);
|
||||
bool DeleteFromChart(const long chart,const int subwin);
|
||||
//--- methods of conversion of constants to strings
|
||||
static string MethodDescription(const int val);
|
||||
static string PriceDescription(const int val);
|
||||
static string VolumeDescription(const int val);
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
bool CreateBuffers(const string symbol,const ENUM_TIMEFRAMES period,const int buffers);
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int num_params,const MqlParam ¶ms[]) {return(false);}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CIndicator::CIndicator(void) : m_handle(INVALID_HANDLE),
|
||||
m_status(""),
|
||||
m_full_release(false),
|
||||
m_redrawer(false)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CIndicator::~CIndicator(void)
|
||||
{
|
||||
//--- indicator handle release
|
||||
if(m_full_release && m_handle!=INVALID_HANDLE)
|
||||
{
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Creation of the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicator::Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const ENUM_INDICATOR type,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=IndicatorCreate(symbol,period,type,num_params,params);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- idicator successfully created
|
||||
if(!Initialize(symbol,period,num_params,params))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the amount of calculated indicator data |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicator::BarsCalculated(void) const
|
||||
{
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(-1);
|
||||
//---
|
||||
return(::BarsCalculated(m_handle));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| API access method "Copying an element of indicator buffer |
|
||||
//| by specifying number of buffer and position of element" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CIndicator::GetData(const int buffer_num,const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(buffer_num);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
{
|
||||
Print(__FUNCTION__,": invalid buffer");
|
||||
return(EMPTY_VALUE);
|
||||
}
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| API access method "Copying the buffer of indicator by specifying |
|
||||
//| a start position and number of elements" |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicator::GetData(const int start_pos,const int count,const int buffer_num,double &buffer[]) const
|
||||
{
|
||||
//--- check
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(-1);
|
||||
}
|
||||
if(buffer_num>=m_buffers_total)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_BUFF_NUM);
|
||||
return(-1);
|
||||
}
|
||||
//---
|
||||
return(CopyBuffer(m_handle,buffer_num,start_pos,count,buffer));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| API access method "Copying the buffer of indicator by specifying |
|
||||
//| start time and number of elements" |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicator::GetData(const datetime start_time,const int count,const int buffer_num,double &buffer[]) const
|
||||
{
|
||||
//--- check
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(-1);
|
||||
}
|
||||
if(buffer_num>=m_buffers_total)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_BUFF_NUM);
|
||||
return(-1);
|
||||
}
|
||||
//---
|
||||
return(CopyBuffer(m_handle,buffer_num,start_time,count,buffer));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| API access method "Copying the buffer of indicator by specifying |
|
||||
//| start and final time |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicator::GetData(const datetime start_time,const datetime stop_time,const int buffer_num,double &buffer[]) const
|
||||
{
|
||||
//--- check
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(-1);
|
||||
}
|
||||
if(buffer_num>=m_buffers_total)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_BUFF_NUM);
|
||||
return(-1);
|
||||
}
|
||||
//---
|
||||
return(CopyBuffer(m_handle,buffer_num,start_time,stop_time,buffer));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find minimum of a specified buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicator::Minimum(const int buffer_num,const int start,const int count) const
|
||||
{
|
||||
//--- check
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(-1);
|
||||
}
|
||||
if(buffer_num>=m_buffers_total)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_BUFF_NUM);
|
||||
return(-1);
|
||||
}
|
||||
//---
|
||||
CIndicatorBuffer *buffer=At(buffer_num);
|
||||
if(buffer==NULL)
|
||||
return(-1);
|
||||
//---
|
||||
return(buffer.Minimum(start,count));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find minimum of a specified buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
double CIndicator::MinValue(const int buffer_num,const int start,const int count,int &index) const
|
||||
{
|
||||
int idx=Minimum(buffer_num,start,count);
|
||||
double res=EMPTY_VALUE;
|
||||
//--- check
|
||||
if(idx!=-1)
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(buffer_num);
|
||||
res=buffer.At(idx);
|
||||
index=idx;
|
||||
}
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find maximum of a specified buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicator::Maximum(const int buffer_num,const int start,const int count) const
|
||||
{
|
||||
//--- check
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(-1);
|
||||
}
|
||||
if(buffer_num>=m_buffers_total)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_BUFF_NUM);
|
||||
return(-1);
|
||||
}
|
||||
//---
|
||||
CIndicatorBuffer *buffer=At(buffer_num);
|
||||
if(buffer==NULL)
|
||||
return(-1);
|
||||
//---
|
||||
return(buffer.Maximum(start,count));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find maximum of specified buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
double CIndicator::MaxValue(const int buffer_num,const int start,const int count,int &index) const
|
||||
{
|
||||
int idx=Maximum(buffer_num,start,count);
|
||||
double res=EMPTY_VALUE;
|
||||
//--- check
|
||||
if(idx!=-1)
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(buffer_num);
|
||||
res=buffer.At(idx);
|
||||
index=idx;
|
||||
}
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Creating data buffers of indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicator::CreateBuffers(const string symbol,const ENUM_TIMEFRAMES period,const int buffers)
|
||||
{
|
||||
bool result=true;
|
||||
//--- check
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
{
|
||||
SetUserError(ERR_USER_INVALID_HANDLE);
|
||||
return(false);
|
||||
}
|
||||
if(buffers==0)
|
||||
return(false);
|
||||
if(!Reserve(buffers))
|
||||
return(false);
|
||||
//---
|
||||
for(int i=0;i<buffers;i++)
|
||||
result&=Add(new CIndicatorBuffer);
|
||||
//---
|
||||
if(result)
|
||||
m_buffers_total=buffers;
|
||||
//---
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set size of buffers of indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicator::BufferResize(const int size)
|
||||
{
|
||||
if(size>m_buffer_size && !CSeries::BufferResize(size))
|
||||
return(false);
|
||||
//-- history is avalible
|
||||
int total=Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CIndicatorBuffer *buff=At(i);
|
||||
//--- check pointer
|
||||
if(buff==NULL)
|
||||
return(false);
|
||||
buff.Size(size);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Refreshing data of indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
void CIndicator::Refresh(const int flags)
|
||||
{
|
||||
int i;
|
||||
CIndicatorBuffer *buff;
|
||||
//--- refreshing buffers
|
||||
for(i=0;i<Total();i++)
|
||||
{
|
||||
buff=At(i);
|
||||
if(m_redrawer)
|
||||
{
|
||||
buff.Refresh(m_handle,i);
|
||||
continue;
|
||||
}
|
||||
if(!(flags&m_timeframe_flags))
|
||||
{
|
||||
if(m_refresh_current)
|
||||
buff.RefreshCurrent(m_handle,i);
|
||||
}
|
||||
else
|
||||
buff.Refresh(m_handle,i);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adds indicator to chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicator::AddToChart(const long chart,const int subwin)
|
||||
{
|
||||
if(ChartIndicatorAdd(chart,subwin,m_handle))
|
||||
{
|
||||
m_name=ChartIndicatorName(chart,subwin,ChartIndicatorsTotal(chart,subwin)-1);
|
||||
return(true);
|
||||
}
|
||||
//--- failed
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deletes indicator from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicator::DeleteFromChart(const long chart,const int subwin)
|
||||
{
|
||||
return(ChartIndicatorDelete(chart,subwin,m_name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting value of ENUM_MA_METHOD into string |
|
||||
//+------------------------------------------------------------------+
|
||||
string CIndicator::MethodDescription(const int val)
|
||||
{
|
||||
//--- select by value
|
||||
switch(val)
|
||||
{
|
||||
case ENUM_MA_METHOD::MODE_SMA:
|
||||
return("SMA");
|
||||
case ENUM_MA_METHOD::MODE_EMA:
|
||||
return("EMA");
|
||||
case ENUM_MA_METHOD::MODE_SMMA:
|
||||
return("SMMA");
|
||||
case ENUM_MA_METHOD::MODE_LWMA:
|
||||
return("LWMA");
|
||||
}
|
||||
//--- wrong value
|
||||
return("MethodUnknown="+IntegerToString(val));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting value of ENUM_APPLIED_PRICE into string |
|
||||
//+------------------------------------------------------------------+
|
||||
string CIndicator::PriceDescription(const int val)
|
||||
{
|
||||
//--- select by value
|
||||
switch(val)
|
||||
{
|
||||
case ENUM_APPLIED_PRICE::PRICE_CLOSE:
|
||||
return("Close");
|
||||
case ENUM_APPLIED_PRICE::PRICE_OPEN:
|
||||
return("Open");
|
||||
case ENUM_APPLIED_PRICE::PRICE_HIGH:
|
||||
return("High");
|
||||
case ENUM_APPLIED_PRICE::PRICE_LOW:
|
||||
return("Low");
|
||||
case ENUM_APPLIED_PRICE::PRICE_MEDIAN:
|
||||
return("Median");
|
||||
case ENUM_APPLIED_PRICE::PRICE_TYPICAL:
|
||||
return("Typical");
|
||||
case ENUM_APPLIED_PRICE::PRICE_WEIGHTED:
|
||||
return("Weighted");
|
||||
default:
|
||||
//--- is an indicator handle
|
||||
if(val>=10)
|
||||
return("AppliedHandle="+IntegerToString(val));
|
||||
//---
|
||||
break;
|
||||
}
|
||||
//--- wrong value
|
||||
return("PriceUnknown="+IntegerToString(val));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting value of ENUM_APPLIED_VOLUME into string |
|
||||
//+------------------------------------------------------------------+
|
||||
string CIndicator::VolumeDescription(const int val)
|
||||
{
|
||||
//--- select by value
|
||||
switch(val)
|
||||
{
|
||||
case ENUM_APPLIED_VOLUME::VOLUME_TICK:
|
||||
return("Tick");
|
||||
case ENUM_APPLIED_VOLUME::VOLUME_REAL:
|
||||
return("Real");
|
||||
}
|
||||
//--- wrong value
|
||||
return("VolumeUnknown="+IntegerToString(val));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,385 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Indicators.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Trend.mqh"
|
||||
#include "Oscilators.mqh"
|
||||
#include "Volumes.mqh"
|
||||
#include "BillWilliams.mqh"
|
||||
#include "Custom.mqh"
|
||||
#include "TimeSeries.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CIndicators. |
|
||||
//| Purpose: Class for creation of collection of instances of |
|
||||
//| technical indicators. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CIndicators : public CArrayObj
|
||||
{
|
||||
protected:
|
||||
MqlDateTime m_prev_time;
|
||||
|
||||
public:
|
||||
CIndicators(void);
|
||||
~CIndicators(void);
|
||||
//--- method for creation
|
||||
CIndicator *Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const ENUM_INDICATOR type,const int count,const MqlParam ¶ms[]);
|
||||
bool BufferResize(const int size);
|
||||
//--- method of refreshing of the data of all indicators in the collection
|
||||
int Refresh(void);
|
||||
protected:
|
||||
//--- method of formation of flags timeframes
|
||||
int TimeframesFlags(const MqlDateTime &time);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CIndicators::CIndicators(void)
|
||||
{
|
||||
m_prev_time.min=-1;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CIndicators::~CIndicators(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Indicator creation |
|
||||
//+------------------------------------------------------------------+
|
||||
CIndicator *CIndicators::Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const ENUM_INDICATOR type,const int count,const MqlParam ¶ms[])
|
||||
{
|
||||
CIndicator *result=NULL;
|
||||
//---
|
||||
switch(type)
|
||||
{
|
||||
case IND_AC:
|
||||
//--- Identifier of "Accelerator Oscillator"
|
||||
if(count==0)
|
||||
result=new CiAC;
|
||||
break;
|
||||
case IND_AD:
|
||||
//--- Identifier of "Accumulation/Distribution"
|
||||
if(count==1)
|
||||
result=new CiAD;
|
||||
break;
|
||||
case IND_ALLIGATOR:
|
||||
//--- Identifier of "Alligator"
|
||||
if(count==8)
|
||||
result=new CiAlligator;
|
||||
break;
|
||||
case IND_ADX:
|
||||
//--- Identifier of "Average Directional Index"
|
||||
if(count==1)
|
||||
result=new CiADX;
|
||||
break;
|
||||
case IND_ADXW:
|
||||
//--- Identifier of "Average Directional Index by Welles Wilder"
|
||||
if(count==1)
|
||||
result=new CiADXWilder;
|
||||
break;
|
||||
case IND_ATR:
|
||||
//--- Identifier of "Average True Range"
|
||||
if(count==1)
|
||||
result=new CiATR;
|
||||
break;
|
||||
case IND_AO:
|
||||
//--- Identifier of "Awesome Oscillator"
|
||||
if(count==0)
|
||||
result=new CiAO;
|
||||
break;
|
||||
case IND_BEARS:
|
||||
//--- Identifier of "Bears Power"
|
||||
if(count==1)
|
||||
result=new CiBearsPower;
|
||||
break;
|
||||
case IND_BANDS:
|
||||
//--- Identifier of "Bollinger Bands"
|
||||
if(count==4)
|
||||
result=new CiBands;
|
||||
break;
|
||||
case IND_BULLS:
|
||||
//--- Identifier of "Bulls Power"
|
||||
if(count==1)
|
||||
result=new CiBullsPower;
|
||||
break;
|
||||
case IND_CCI:
|
||||
//--- Identifier of "Commodity Channel Index"
|
||||
if(count==2)
|
||||
result=new CiCCI;
|
||||
break;
|
||||
case IND_CHAIKIN:
|
||||
//--- Identifier of "Chaikin Oscillator"
|
||||
if(count==4)
|
||||
result=new CiChaikin;
|
||||
break;
|
||||
case IND_DEMARKER:
|
||||
//--- Identifier of "DeMarker"
|
||||
if(count==1)
|
||||
result=new CiDeMarker;
|
||||
break;
|
||||
case IND_ENVELOPES:
|
||||
//--- Identifier of "Envelopes"
|
||||
if(count==5)
|
||||
result=new CiEnvelopes;
|
||||
break;
|
||||
case IND_FORCE:
|
||||
//--- Identifier of "Force Index"
|
||||
if(count==3)
|
||||
result=new CiForce;
|
||||
break;
|
||||
case IND_FRACTALS:
|
||||
//--- Identifier of "Fractals"
|
||||
if(count==0)
|
||||
result=new CiFractals;
|
||||
break;
|
||||
case IND_GATOR:
|
||||
//--- Identifier of "Gator oscillator"
|
||||
if(count==8)
|
||||
result=new CiGator;
|
||||
break;
|
||||
case IND_ICHIMOKU:
|
||||
//--- Identifier of "Ichimoku Kinko Hyo"
|
||||
if(count==3)
|
||||
result=new CiIchimoku;
|
||||
break;
|
||||
case IND_MACD:
|
||||
//--- Identifier of "Moving Averages Convergence-Divergence"
|
||||
if(count==4)
|
||||
result=new CiMACD;
|
||||
break;
|
||||
case IND_BWMFI:
|
||||
//--- Identifier of "Market Facilitation Index by Bill Williams"
|
||||
if(count==1)
|
||||
result=new CiBWMFI;
|
||||
break;
|
||||
case IND_MOMENTUM:
|
||||
//--- Identifier of "Momentum"
|
||||
if(count==2)
|
||||
result=new CiMomentum;
|
||||
break;
|
||||
case IND_MFI:
|
||||
//--- Identifier of "Money Flow Index"
|
||||
if(count==2)
|
||||
result=new CiMFI;
|
||||
break;
|
||||
case IND_MA:
|
||||
//--- Identifier of "Moving Average"
|
||||
if(count==4)
|
||||
result=new CiMA;
|
||||
break;
|
||||
case IND_OSMA:
|
||||
//--- Identifier of "Moving Average of Oscillator (MACD histogram)"
|
||||
if(count==4)
|
||||
result=new CiOsMA;
|
||||
break;
|
||||
case IND_OBV:
|
||||
//--- Identifier of "On Balance Volume"
|
||||
if(count==1)
|
||||
result=new CiOBV;
|
||||
break;
|
||||
case IND_SAR:
|
||||
//--- Identifier of "Parabolic Stop And Reverse System"
|
||||
if(count==2)
|
||||
result=new CiSAR;
|
||||
break;
|
||||
case IND_RSI:
|
||||
//--- Identifier of "Relative Strength Index"
|
||||
if(count==2)
|
||||
result=new CiRSI;
|
||||
break;
|
||||
case IND_RVI:
|
||||
//--- Identifier of "Relative Vigor Index"
|
||||
if(count==1)
|
||||
result=new CiRVI;
|
||||
break;
|
||||
case IND_STDDEV:
|
||||
//--- Identifier of "Standard Deviation"
|
||||
if(count==4)
|
||||
result=new CiStdDev;
|
||||
break;
|
||||
case IND_STOCHASTIC:
|
||||
//--- Identifier of "Stochastic Oscillator"
|
||||
if(count==5)
|
||||
result=new CiStochastic;
|
||||
break;
|
||||
case IND_WPR:
|
||||
//--- Identifier of "Williams' Percent Range"
|
||||
if(count==1)
|
||||
result=new CiWPR;
|
||||
break;
|
||||
case IND_DEMA:
|
||||
//--- Identifier of "Double Exponential Moving Average"
|
||||
if(count==3)
|
||||
result=new CiDEMA;
|
||||
break;
|
||||
case IND_TEMA:
|
||||
//--- Identifier of "Triple Exponential Moving Average"
|
||||
if(count==3)
|
||||
result=new CiTEMA;
|
||||
break;
|
||||
case IND_TRIX:
|
||||
//--- Identifier of "Triple Exponential Moving Averages Oscillator"
|
||||
if(count==2)
|
||||
result=new CiTriX;
|
||||
break;
|
||||
case IND_FRAMA:
|
||||
//--- Identifier of "Fractal Adaptive Moving Average"
|
||||
if(count==3)
|
||||
result=new CiFrAMA;
|
||||
break;
|
||||
case IND_AMA:
|
||||
//--- Identifier of "Adaptive Moving Average"
|
||||
if(count==5)
|
||||
result=new CiAMA;
|
||||
break;
|
||||
case IND_VIDYA:
|
||||
//--- Identifier of "Variable Index DYnamic Average"
|
||||
if(count==4)
|
||||
result=new CiVIDyA;
|
||||
break;
|
||||
case IND_VOLUMES:
|
||||
//--- Identifier of "Volumes"
|
||||
if(count==1)
|
||||
result=new CiVolumes;
|
||||
break;
|
||||
//--- Identifier of "Custom"
|
||||
case IND_CUSTOM:
|
||||
if(count>0)
|
||||
result=new CiCustom;
|
||||
break;
|
||||
}
|
||||
if(result!=NULL)
|
||||
{
|
||||
if(result.Create(symbol,period,type,count,params))
|
||||
Add(result);
|
||||
else
|
||||
{
|
||||
delete result;
|
||||
result=NULL;
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set size of buffers of all indicators in the collection |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CIndicators::BufferResize(const int size)
|
||||
{
|
||||
int total=Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CSeries *series=At(i);
|
||||
//--- check pointer
|
||||
if(series==NULL)
|
||||
return(false);
|
||||
if(!series.BufferResize(size))
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Refreshing of the data of all indicators in the collection |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicators::Refresh(void)
|
||||
{
|
||||
MqlDateTime time;
|
||||
TimeCurrent(time);
|
||||
//---
|
||||
int flags=TimeframesFlags(time);
|
||||
int total=Total();
|
||||
//---
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CSeries *indicator=At(i);
|
||||
if(indicator!=NULL)
|
||||
indicator.Refresh(flags);
|
||||
}
|
||||
//---
|
||||
m_prev_time=time;
|
||||
//---
|
||||
return(flags);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Formation of timeframe flags |
|
||||
//+------------------------------------------------------------------+
|
||||
int CIndicators::TimeframesFlags(const MqlDateTime &time)
|
||||
{
|
||||
//--- set flags for all timeframes
|
||||
int result=OBJ_ALL_PERIODS;
|
||||
//--- if first check, then setting flags all timeframes
|
||||
if(m_prev_time.min==-1)
|
||||
return(result);
|
||||
//--- check change time
|
||||
if(time.min==m_prev_time.min &&
|
||||
time.hour==m_prev_time.hour &&
|
||||
time.day==m_prev_time.day &&
|
||||
time.mon==m_prev_time.mon)
|
||||
return(OBJ_NO_PERIODS);
|
||||
//--- new month?
|
||||
if(time.mon!=m_prev_time.mon)
|
||||
return(result);
|
||||
//--- reset the "new month" flag
|
||||
result^=OBJ_PERIOD_MN1;
|
||||
//--- new day?
|
||||
if(time.day!=m_prev_time.day)
|
||||
return(result);
|
||||
//--- reset the "new day" and "new week" flags
|
||||
result^=OBJ_PERIOD_D1+OBJ_PERIOD_W1;
|
||||
//--- temporary variables to speed up working with structures
|
||||
int curr,delta;
|
||||
//--- new hour?
|
||||
curr=time.hour;
|
||||
delta=curr-m_prev_time.hour;
|
||||
if(delta!=0)
|
||||
{
|
||||
if(curr%2>=delta)
|
||||
result^=OBJ_PERIOD_H2;
|
||||
if(curr%3>=delta)
|
||||
result^=OBJ_PERIOD_H3;
|
||||
if(curr%4>=delta)
|
||||
result^=OBJ_PERIOD_H4;
|
||||
if(curr%6>=delta)
|
||||
result^=OBJ_PERIOD_H6;
|
||||
if(curr%8>=delta)
|
||||
result^=OBJ_PERIOD_H8;
|
||||
if(curr%12>=delta)
|
||||
result^=OBJ_PERIOD_H12;
|
||||
return(result);
|
||||
}
|
||||
//--- reset all flags for hour timeframes
|
||||
result^=OBJ_PERIOD_H1+OBJ_PERIOD_H2+OBJ_PERIOD_H3+OBJ_PERIOD_H4+OBJ_PERIOD_H6+OBJ_PERIOD_H8+OBJ_PERIOD_H12;
|
||||
//--- new minute?
|
||||
curr=time.min;
|
||||
delta=curr-m_prev_time.min;
|
||||
if(delta!=0)
|
||||
{
|
||||
if(curr%2>=delta)
|
||||
result^=OBJ_PERIOD_M2;
|
||||
if(curr%3>=delta)
|
||||
result^=OBJ_PERIOD_M3;
|
||||
if(curr%4>=delta)
|
||||
result^=OBJ_PERIOD_M4;
|
||||
if(curr%5>=delta)
|
||||
result^=OBJ_PERIOD_M5;
|
||||
if(curr%6>=delta)
|
||||
result^=OBJ_PERIOD_M6;
|
||||
if(curr%10>=delta)
|
||||
result^=OBJ_PERIOD_M10;
|
||||
if(curr%12>=delta)
|
||||
result^=OBJ_PERIOD_M12;
|
||||
if(curr%15>=delta)
|
||||
result^=OBJ_PERIOD_M15;
|
||||
if(curr%20>=delta)
|
||||
result^=OBJ_PERIOD_M20;
|
||||
if(curr%30>=delta)
|
||||
result^=OBJ_PERIOD_M30;
|
||||
}
|
||||
//---
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,299 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Series.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\ArrayObj.mqh>
|
||||
#include <Arrays\ArrayDouble.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| defines |
|
||||
//+------------------------------------------------------------------+
|
||||
#define DEFAULT_BUFFER_SIZE 1024
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CSeries. |
|
||||
//| Purpose: Base class for access to timeseries. |
|
||||
//| Derives from class CArrayObj. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSeries : public CArrayObj
|
||||
{
|
||||
protected:
|
||||
string m_name; // name of series
|
||||
int m_buffers_total; // number of buffers
|
||||
int m_buffer_size; // buffer size
|
||||
int m_timeframe_flags; // flags of timeframes (similar to "flags of visibility of objects")
|
||||
string m_symbol; // symbol
|
||||
ENUM_TIMEFRAMES m_period; // period
|
||||
bool m_refresh_current; // flag
|
||||
//---
|
||||
datetime m_first_date;
|
||||
|
||||
public:
|
||||
CSeries(void);
|
||||
~CSeries(void);
|
||||
//--- methods of access to protected data
|
||||
string Name(void) const { return(m_name); }
|
||||
int BuffersTotal(void) const { return(m_buffers_total); }
|
||||
int BufferSize(void) const { return(m_buffer_size); }
|
||||
int Timeframe(void) const { return(m_timeframe_flags); }
|
||||
string Symbol(void) const { return(m_symbol); }
|
||||
ENUM_TIMEFRAMES Period(void) const { return(m_period); }
|
||||
string PeriodDescription(const int val=0);
|
||||
void RefreshCurrent(const bool flag) { m_refresh_current=flag; }
|
||||
//--- method of tuning
|
||||
virtual bool BufferResize(const int size);
|
||||
//--- method of refreshing" of the data
|
||||
virtual void Refresh(const int flags) { }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
bool SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
void PeriodToTimeframeFlag(const ENUM_TIMEFRAMES period);
|
||||
//---
|
||||
bool CheckLoadHistory(const int size);
|
||||
bool CheckTerminalHistory(const int size);
|
||||
bool CheckServerHistory(const int size);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CSeries::CSeries(void) : m_name(""),
|
||||
m_timeframe_flags(0),
|
||||
m_buffers_total(0),
|
||||
m_buffer_size(0),
|
||||
m_symbol(""),
|
||||
m_period(WRONG_VALUE),
|
||||
m_refresh_current(true)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSeries::~CSeries(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set buffer size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSeries::BufferResize(const int size)
|
||||
{
|
||||
//--- check history
|
||||
if(!CheckLoadHistory(size))
|
||||
{
|
||||
printf("failed to get %d bars for %s,%s",size,m_symbol,EnumToString(m_period));
|
||||
return(false);
|
||||
}
|
||||
//--- history is available
|
||||
m_buffer_size=size;
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set symbol and period |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSeries::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
m_symbol=(symbol==NULL) ? ChartSymbol() : symbol;
|
||||
m_period=(period==0) ? ChartPeriod() : period;
|
||||
PeriodToTimeframeFlag(m_period);
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Convert period to timeframe flag (similar to visibility flags) |
|
||||
//+------------------------------------------------------------------+
|
||||
void CSeries::PeriodToTimeframeFlag(const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
static ENUM_TIMEFRAMES _p_int[]=
|
||||
{
|
||||
PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,
|
||||
PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,
|
||||
PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,
|
||||
PERIOD_D1,PERIOD_W1,PERIOD_MN1
|
||||
};
|
||||
//--- cycle for all timeframes
|
||||
for(int i=0;i<ArraySize(_p_int);i++)
|
||||
if(period==_p_int[i])
|
||||
{
|
||||
//--- at the same time generate the flag of the working timeframe
|
||||
m_timeframe_flags=((int)1)<<i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting value of ENUM_TIMEFRAMES to string |
|
||||
//+------------------------------------------------------------------+
|
||||
string CSeries::PeriodDescription(const int val)
|
||||
{
|
||||
int i,frame;
|
||||
//--- arrays for conversion of ENUM_TIMEFRAMES to string
|
||||
static string _p_str[]=
|
||||
{
|
||||
"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30",
|
||||
"H1","H2","H3","H4","H6","H8","H12","D1","W1","MN","UNKNOWN"
|
||||
};
|
||||
static ENUM_TIMEFRAMES _p_int[]=
|
||||
{
|
||||
PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,
|
||||
PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,
|
||||
PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,
|
||||
PERIOD_D1,PERIOD_W1,PERIOD_MN1
|
||||
};
|
||||
//--- check
|
||||
frame=(val==0)?m_period:val;
|
||||
if(frame==WRONG_VALUE)
|
||||
return("WRONG_VALUE");
|
||||
//--- cycle for all timeframes
|
||||
for(i=0;i<ArraySize(_p_int);i++)
|
||||
if(frame==_p_int[i])
|
||||
break;
|
||||
//---
|
||||
return(_p_str[i]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Checks data by specified symbol's timeframe and |
|
||||
//| downloads it from server, if necessary |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSeries::CheckLoadHistory(const int size)
|
||||
{
|
||||
//--- don't ask for load of its own data if it is an indicator
|
||||
if(MQL5InfoInteger(MQL5_PROGRAM_TYPE)==PROGRAM_INDICATOR && Period()==m_period && Symbol()==m_symbol)
|
||||
return(true);
|
||||
if(size>TerminalInfoInteger(TERMINAL_MAXBARS))
|
||||
{
|
||||
//--- Definitely won't have such amount of data
|
||||
printf(__FUNCTION__+": requested too much data (%d)",size);
|
||||
return(false);
|
||||
}
|
||||
m_first_date=0;
|
||||
if(CheckTerminalHistory(size))
|
||||
return(true);
|
||||
if(CheckServerHistory(size))
|
||||
return(true);
|
||||
//--- failed
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Checks data in terminal |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSeries::CheckTerminalHistory(const int size)
|
||||
{
|
||||
datetime times[1];
|
||||
long bars=0;
|
||||
//--- Enough data in timeseries?
|
||||
if(Bars(m_symbol,m_period)>=size)
|
||||
return(true);
|
||||
//--- second attempt
|
||||
if(SeriesInfoInteger(m_symbol,PERIOD_M1,SERIES_BARS_COUNT,bars))
|
||||
{
|
||||
//--- there is loaded data to build timeseries
|
||||
if(bars>size*PeriodSeconds(m_period)/60)
|
||||
{
|
||||
//--- force timeseries build
|
||||
CopyTime(m_symbol,m_period,size-1,1,times);
|
||||
//--- check date
|
||||
if(SeriesInfoInteger(m_symbol,m_period,SERIES_BARS_COUNT,bars))
|
||||
//--- Timeseries generated using data from terminal
|
||||
if(bars>size)
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
//--- failed
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Downloads missing data from server |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSeries::CheckServerHistory(const int size)
|
||||
{
|
||||
//--- load symbol history info
|
||||
datetime first_server_date=0;
|
||||
while(!SeriesInfoInteger(m_symbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,first_server_date) && !IsStopped())
|
||||
Sleep(5);
|
||||
//--- Enough data on server?
|
||||
if(first_server_date>TimeCurrent()-size*PeriodSeconds(m_period))
|
||||
return(false);
|
||||
//--- load data step by step
|
||||
int fail_cnt=0;
|
||||
datetime times[1];
|
||||
while(!IsStopped())
|
||||
{
|
||||
//--- wait for timeseries build
|
||||
while(!SeriesInfoInteger(m_symbol,m_period,SERIES_SYNCHRONIZED) && !IsStopped())
|
||||
Sleep(5);
|
||||
//--- ask for built bars
|
||||
int bars=Bars(m_symbol,m_period);
|
||||
if(bars>size)
|
||||
return(true);
|
||||
//--- copying of next part forces data loading
|
||||
if(CopyTime(m_symbol,m_period,size-1,1,times)==1)
|
||||
return(true);
|
||||
//--- no more than 100 failed attempts
|
||||
if(++fail_cnt>=100)
|
||||
return(false);
|
||||
Sleep(10);
|
||||
}
|
||||
//--- failed
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDoubleBuffer. |
|
||||
//| Purpose: Base class of buffer of data of the double type. |
|
||||
//| Derives from class CArrayDouble. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDoubleBuffer : public CArrayDouble
|
||||
{
|
||||
protected:
|
||||
string m_symbol; // symbol
|
||||
ENUM_TIMEFRAMES m_period; // period
|
||||
int m_size; // size of used history
|
||||
|
||||
public:
|
||||
CDoubleBuffer(void);
|
||||
~CDoubleBuffer(void);
|
||||
//--- methods of access to protected data
|
||||
void Size(const int size) { m_size=size; }
|
||||
//--- methods of access to data
|
||||
double At(const int index) const;
|
||||
//--- method of refreshing of the data buffer
|
||||
virtual bool Refresh(void) { return(true); }
|
||||
virtual bool RefreshCurrent(void) { return(true); }
|
||||
//--- methods of tuning
|
||||
void SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDoubleBuffer::CDoubleBuffer(void) : m_symbol(""),
|
||||
m_period(WRONG_VALUE),
|
||||
m_size(DEFAULT_BUFFER_SIZE)
|
||||
{
|
||||
ArraySetAsSeries(m_data,true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDoubleBuffer::~CDoubleBuffer(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in a specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
double CDoubleBuffer::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index>=m_data_total)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
double d=CArrayDouble::At(index);
|
||||
//---
|
||||
return(d);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set symbol and period |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDoubleBuffer::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period)
|
||||
{
|
||||
m_symbol=(symbol==NULL) ? ChartSymbol() : symbol;
|
||||
m_period=(period==0) ? ChartPeriod() : period;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,424 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Volumes.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Indicator.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiAD. |
|
||||
//| Purpose: Class of the "Accumulation/Distribution" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiAD : public CIndicator
|
||||
{
|
||||
protected:
|
||||
ENUM_APPLIED_VOLUME m_applied; // applied volume
|
||||
|
||||
public:
|
||||
CiAD(void);
|
||||
~CiAD(void);
|
||||
//--- methods of access to protected data
|
||||
ENUM_APPLIED_VOLUME Applied(void) const { return(m_applied); }
|
||||
//--- method of creation
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
//--- methods of access to indicator data
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_AD); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAD::CiAD(void) : m_applied(WRONG_VALUE)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiAD::~CiAD(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Accumulation/Distribution" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAD::Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iAD(symbol,period,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- indicator successfully created
|
||||
if(!Initialize(symbol,period,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAD::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(ENUM_APPLIED_VOLUME)params[0].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiAD::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="AD";
|
||||
m_status="("+symbol+","+PeriodDescription()+","+VolumeDescription(applied)+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_applied=applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to buffer of "Accumulation/Distribution" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiAD::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiMFI. |
|
||||
//| Purpose: Class of the "Money Flow Index" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiMFI : public CIndicator
|
||||
{
|
||||
protected:
|
||||
int m_ma_period;
|
||||
ENUM_APPLIED_VOLUME m_applied;
|
||||
|
||||
public:
|
||||
CiMFI(void);
|
||||
~CiMFI(void);
|
||||
//--- methods of access to protected data
|
||||
int MaPeriod(void) const { return(m_ma_period); }
|
||||
ENUM_APPLIED_VOLUME Applied(void) const { return(m_applied); }
|
||||
//--- method of creation
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int ma_period,const ENUM_APPLIED_VOLUME applied);
|
||||
//--- methods of access to indicator data
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_MFI); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int ma_period,const ENUM_APPLIED_VOLUME applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiMFI::CiMFI(void) : m_ma_period(-1),
|
||||
m_applied(WRONG_VALUE)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiMFI::~CiMFI(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Money Flow Index" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiMFI::Create(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int ma_period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iMFI(symbol,period,ma_period,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- indicator successfully created
|
||||
if(!Initialize(symbol,period,ma_period,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiMFI::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(int)params[0].integer_value,(ENUM_APPLIED_VOLUME)params[1].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiMFI::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
|
||||
const int ma_period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="MFI";
|
||||
m_status="("+symbol+","+PeriodDescription()+","+
|
||||
IntegerToString(ma_period)+","+VolumeDescription(applied)+","+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_ma_period=ma_period;
|
||||
m_applied =applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to buffer of "Money Flow Index" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiMFI::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiOBV. |
|
||||
//| Purpose: Class of the "On Balance Volume" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiOBV : public CIndicator
|
||||
{
|
||||
protected:
|
||||
ENUM_APPLIED_VOLUME m_applied;
|
||||
|
||||
public:
|
||||
CiOBV(void);
|
||||
~CiOBV(void);
|
||||
//--- methods of access to protected data
|
||||
ENUM_APPLIED_VOLUME Applied(void) const { return(m_applied); }
|
||||
//--- method create
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
//--- methods of access to indicator data
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_OBV); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiOBV::CiOBV(void) : m_applied(WRONG_VALUE)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiOBV::~CiOBV(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "On Balance Volume" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiOBV::Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iOBV(symbol,period,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- indicator successfully created
|
||||
if(!Initialize(symbol,period,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiOBV::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(ENUM_APPLIED_VOLUME)params[0].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiOBV::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="OBV";
|
||||
m_status="("+symbol+","+PeriodDescription()+","+VolumeDescription(applied)+","+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_applied=applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to buffer of "On Balance Volume" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiOBV::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CiVolumes. |
|
||||
//| Purpose: Class of the "Volumes" indicator. |
|
||||
//| Derives from class CIndicator. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CiVolumes : public CIndicator
|
||||
{
|
||||
protected:
|
||||
ENUM_APPLIED_VOLUME m_applied;
|
||||
|
||||
public:
|
||||
CiVolumes(void);
|
||||
~CiVolumes(void);
|
||||
//--- methods of access to protected data
|
||||
ENUM_APPLIED_VOLUME Applied(void) const { return(m_applied); }
|
||||
//--- method create
|
||||
bool Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
//--- methods of access to indicator data
|
||||
double Main(const int index) const;
|
||||
//--- method of identifying
|
||||
virtual int Type(void) const { return(IND_VOLUMES); }
|
||||
|
||||
protected:
|
||||
//--- methods of tuning
|
||||
virtual bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[]);
|
||||
bool Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiVolumes::CiVolumes(void) : m_applied(WRONG_VALUE)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CiVolumes::~CiVolumes(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Volumes" indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiVolumes::Create(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
//--- check history
|
||||
if(!SetSymbolPeriod(symbol,period))
|
||||
return(false);
|
||||
//--- create
|
||||
m_handle=iVolumes(symbol,period,applied);
|
||||
//--- check result
|
||||
if(m_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- indicator successfully created
|
||||
if(!Initialize(symbol,period,applied))
|
||||
{
|
||||
//--- initialization failed
|
||||
IndicatorRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
return(false);
|
||||
}
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with universal parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiVolumes::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam ¶ms[])
|
||||
{
|
||||
return(Initialize(symbol,period,(ENUM_APPLIED_VOLUME)params[0].integer_value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize the indicator with special parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CiVolumes::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const ENUM_APPLIED_VOLUME applied)
|
||||
{
|
||||
if(CreateBuffers(symbol,period,1))
|
||||
{
|
||||
//--- string of status of drawing
|
||||
m_name ="Volumes";
|
||||
m_status="("+symbol+","+PeriodDescription()+","+VolumeDescription(applied)+","+") H="+IntegerToString(m_handle);
|
||||
//--- save settings
|
||||
m_applied=applied;
|
||||
//--- create buffers
|
||||
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
|
||||
//--- ok
|
||||
return(true);
|
||||
}
|
||||
//--- error
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to buffer of "Volumes" |
|
||||
//+------------------------------------------------------------------+
|
||||
double CiVolumes::Main(const int index) const
|
||||
{
|
||||
CIndicatorBuffer *buffer=At(0);
|
||||
//--- check
|
||||
if(buffer==NULL)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(buffer.At(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Box.mqh |
|
||||
//| Enrico Lambino |
|
||||
//| www.mql5.com/en/users/iceron|
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Enrico Lambino"
|
||||
#property link "www.mql5.com/en/users/iceron"
|
||||
#include <Controls\WndClient.mqh>
|
||||
#define CLASS_LAYOUT 999
|
||||
|
||||
#ifdef LAYOUT_BOX_DEBUG
|
||||
#define COLOR_BOX_BORDER clrRed
|
||||
#else
|
||||
#define COLOR_BOX_BORDER clrNONE
|
||||
#endif
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
enum LAYOUT_STYLE
|
||||
{
|
||||
LAYOUT_STYLE_VERTICAL,
|
||||
LAYOUT_STYLE_HORIZONTAL
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
enum VERTICAL_ALIGN
|
||||
{
|
||||
VERTICAL_ALIGN_CENTER,
|
||||
VERTICAL_ALIGN_CENTER_NOSIDES,
|
||||
VERTICAL_ALIGN_TOP,
|
||||
VERTICAL_ALIGN_BOTTOM
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
enum HORIZONTAL_ALIGN
|
||||
{
|
||||
HORIZONTAL_ALIGN_CENTER,
|
||||
HORIZONTAL_ALIGN_CENTER_NOSIDES,
|
||||
HORIZONTAL_ALIGN_LEFT,
|
||||
HORIZONTAL_ALIGN_RIGHT
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class CBox: public CWndClient
|
||||
{
|
||||
protected:
|
||||
LAYOUT_STYLE m_layout_style;
|
||||
VERTICAL_ALIGN m_vertical_align;
|
||||
HORIZONTAL_ALIGN m_horizontal_align;
|
||||
CSize m_min_size;
|
||||
int m_controls_total;
|
||||
int m_padding_top;
|
||||
int m_padding_bottom;
|
||||
int m_padding_left;
|
||||
int m_padding_right;
|
||||
int m_total_x;
|
||||
int m_total_y;
|
||||
|
||||
public:
|
||||
CBox();
|
||||
~CBox();
|
||||
virtual int Type() const
|
||||
{
|
||||
return CLASS_LAYOUT;
|
||||
}
|
||||
virtual bool Create(const long chart, const string name, const int subwin,
|
||||
const int x1, const int y1, const int x2, const int y2);
|
||||
virtual bool Pack();
|
||||
void LayoutStyle(LAYOUT_STYLE style)
|
||||
{
|
||||
m_layout_style = style;
|
||||
}
|
||||
LAYOUT_STYLE LayoutStyle() const
|
||||
{
|
||||
return (m_layout_style);
|
||||
}
|
||||
void HorizontalAlign(const HORIZONTAL_ALIGN align)
|
||||
{
|
||||
m_horizontal_align = align;
|
||||
}
|
||||
HORIZONTAL_ALIGN HorizontalAlign() const
|
||||
{
|
||||
return (m_horizontal_align);
|
||||
}
|
||||
void VerticalAlign(const VERTICAL_ALIGN align)
|
||||
{
|
||||
m_vertical_align = align;
|
||||
}
|
||||
VERTICAL_ALIGN VerticalAlign() const
|
||||
{
|
||||
return (m_vertical_align);
|
||||
}
|
||||
void Padding(const int top, const int bottom, const int left, const int right,const int padding);
|
||||
//void Padding(const int padding);
|
||||
void PaddingTop(const int padding)
|
||||
{
|
||||
m_padding_top = padding;
|
||||
}
|
||||
int PaddingTop() const
|
||||
{
|
||||
return (m_padding_top);
|
||||
}
|
||||
void PaddingRight(const int padding)
|
||||
{
|
||||
m_padding_right = padding;
|
||||
}
|
||||
int PaddingRight() const
|
||||
{
|
||||
return (m_padding_right);
|
||||
}
|
||||
void PaddingBottom(const int padding)
|
||||
{
|
||||
m_padding_bottom = padding;
|
||||
}
|
||||
int PaddingBottom() const
|
||||
{
|
||||
return (m_padding_bottom);
|
||||
}
|
||||
void PaddingLeft(const int padding)
|
||||
{
|
||||
m_padding_left = padding;
|
||||
}
|
||||
int PaddingLeft() const
|
||||
{
|
||||
return (m_padding_left);
|
||||
}
|
||||
CSize GetMinSize() const
|
||||
{
|
||||
CSize sz;
|
||||
sz.cx = m_min_size.cx + m_padding_left + m_padding_right;
|
||||
sz.cy = m_min_size.cy + m_padding_top + m_padding_bottom;
|
||||
return sz;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void CheckControlSize(CWnd *control);
|
||||
virtual void GetTotalControlsSize(void);
|
||||
virtual bool GetSpace(int &x_space, int &y_space);
|
||||
virtual bool Render(void);
|
||||
virtual void Shift(CWnd *control, int &x, int &y, const int x_space, const int y_space);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CBox::CBox():
|
||||
m_layout_style(LAYOUT_STYLE_HORIZONTAL),
|
||||
m_vertical_align(VERTICAL_ALIGN_CENTER),
|
||||
m_horizontal_align(HORIZONTAL_ALIGN_CENTER),
|
||||
m_controls_total(0),
|
||||
m_padding_top(2),
|
||||
m_padding_bottom(2),
|
||||
m_padding_left(2),
|
||||
m_padding_right(2),
|
||||
m_total_x(0),
|
||||
m_total_y(0)
|
||||
|
||||
{
|
||||
m_min_size.cx = 0;
|
||||
m_min_size.cy = 0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CBox::~CBox()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBox::Create(const long chart, const string name, const int subwin,
|
||||
const int x1, const int y1, const int x2, const int y2)
|
||||
{
|
||||
if(!CWndContainer::Create(chart, name, subwin, x1, y1, x2, y2))
|
||||
return (false);
|
||||
if(!CreateBack())
|
||||
return (false);
|
||||
if(!ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG))
|
||||
return (false);
|
||||
if(!ColorBorder(COLOR_BOX_BORDER))
|
||||
return (false);
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBox::Pack(void)
|
||||
{
|
||||
GetTotalControlsSize();
|
||||
return (Render());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CBox::CheckControlSize(CWnd *control)
|
||||
{
|
||||
bool adjust = false;
|
||||
CSize size = Size();
|
||||
CSize control_size = control.Size();
|
||||
if(control_size.cx > size.cx - (m_padding_left + m_padding_right))
|
||||
{
|
||||
control_size.cx = size.cx - (m_padding_left + m_padding_right);
|
||||
adjust = true;
|
||||
}
|
||||
if(control_size.cy > size.cy - (m_padding_top + m_padding_bottom))
|
||||
{
|
||||
control_size.cy = size.cy - (m_padding_top + m_padding_bottom);
|
||||
adjust = true;
|
||||
}
|
||||
if(adjust)
|
||||
control.Size(control_size.cx, control_size.cy);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CBox::GetTotalControlsSize(void)
|
||||
{
|
||||
m_total_x = 0;
|
||||
m_total_y = 0;
|
||||
m_controls_total = 0;
|
||||
m_min_size.cx = 0;
|
||||
m_min_size.cy = 0;
|
||||
int total = ControlsTotal();
|
||||
|
||||
|
||||
for(int i = 0; i < total; i++)
|
||||
{
|
||||
CWnd *control = Control(i);
|
||||
if(control == NULL) continue;
|
||||
if(control == &m_background) continue;
|
||||
CheckControlSize(control);
|
||||
if(control.Type() == CLASS_LAYOUT)
|
||||
{
|
||||
((CBox *)control).GetTotalControlsSize();
|
||||
}
|
||||
|
||||
CSize control_size = control.Size();
|
||||
if(m_min_size.cx < control_size.cx)
|
||||
m_min_size.cx = control_size.cx;
|
||||
if(m_min_size.cy < control_size.cy)
|
||||
m_min_size.cy = control_size.cy;
|
||||
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL) m_total_x += control_size.cx;
|
||||
else m_total_x = MathMax(m_min_size.cx, m_total_x);
|
||||
if(m_layout_style == LAYOUT_STYLE_VERTICAL) m_total_y += control_size.cy;
|
||||
else m_total_y = MathMax(m_min_size.cy, m_total_y);
|
||||
m_controls_total++;
|
||||
}
|
||||
|
||||
CSize size = Size();
|
||||
|
||||
if(m_total_x > size.cx && m_layout_style == LAYOUT_STYLE_HORIZONTAL)
|
||||
{
|
||||
size.cx = m_total_x;
|
||||
}
|
||||
if(m_total_y > size.cy && m_layout_style == LAYOUT_STYLE_VERTICAL) // shrink
|
||||
{
|
||||
size.cy = m_total_y;
|
||||
}
|
||||
|
||||
Size(size);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBox::GetSpace(int &x_space, int &y_space)
|
||||
{
|
||||
if(m_controls_total == 0)
|
||||
return (true);
|
||||
if(m_controls_total == 1)
|
||||
{
|
||||
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
|
||||
m_horizontal_align = HORIZONTAL_ALIGN_CENTER;
|
||||
if(m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
|
||||
m_vertical_align = VERTICAL_ALIGN_CENTER;
|
||||
}
|
||||
CSize size = Size();
|
||||
|
||||
int x_space_total = 0;
|
||||
int y_space_total = 0;
|
||||
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL)
|
||||
{
|
||||
x_space_total = size.cx - (m_total_x + m_padding_left + m_padding_right);
|
||||
y_space_total = size.cy - (m_min_size.cy + m_padding_top + m_padding_bottom);
|
||||
|
||||
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
|
||||
x_space = x_space_total / (m_controls_total - 1);
|
||||
else if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER)
|
||||
x_space = x_space_total / (m_controls_total + 1);
|
||||
else
|
||||
x_space = x_space_total / m_controls_total;
|
||||
|
||||
if(m_vertical_align == VERTICAL_ALIGN_CENTER || m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
|
||||
y_space = y_space_total / 2;
|
||||
else
|
||||
y_space = y_space_total;
|
||||
}
|
||||
else if(m_layout_style == LAYOUT_STYLE_VERTICAL)
|
||||
{
|
||||
x_space_total = size.cx - (m_min_size.cx + m_padding_left + m_padding_right);
|
||||
y_space_total = size.cy - (m_total_y + m_padding_top + m_padding_bottom);
|
||||
|
||||
if(m_horizontal_align == HORIZONTAL_ALIGN_CENTER || m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES)
|
||||
x_space = x_space_total / 2;
|
||||
else
|
||||
x_space = x_space_total;
|
||||
|
||||
if(m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES)
|
||||
y_space = y_space_total / (m_controls_total - 1);
|
||||
else if(m_vertical_align == VERTICAL_ALIGN_CENTER)
|
||||
y_space = y_space_total / (m_controls_total + 1);
|
||||
else
|
||||
y_space = y_space_total / m_controls_total;
|
||||
}
|
||||
else
|
||||
return (false);
|
||||
|
||||
if(x_space < 0) x_space = 0;
|
||||
if(y_space < 0) y_space = 0;
|
||||
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CBox::Shift(CWnd *control, int &x, int &y, const int x_space, const int y_space)
|
||||
{
|
||||
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL)
|
||||
x += x_space + control.Width();
|
||||
else if(m_layout_style == LAYOUT_STYLE_VERTICAL)
|
||||
y += y_space + control.Height();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBox::Render(void)
|
||||
{
|
||||
int x_space = 0, y_space = 0;
|
||||
if(!GetSpace(x_space, y_space))
|
||||
return (false);
|
||||
int x = Left() + m_padding_left +
|
||||
((m_horizontal_align == HORIZONTAL_ALIGN_LEFT || m_horizontal_align == HORIZONTAL_ALIGN_CENTER_NOSIDES) ? 0 : x_space);
|
||||
int y = Top() + m_padding_top +
|
||||
((m_vertical_align == VERTICAL_ALIGN_TOP || m_vertical_align == VERTICAL_ALIGN_CENTER_NOSIDES) ? 0 : y_space);
|
||||
for(int j = 0; j < ControlsTotal(); j++)
|
||||
{
|
||||
CWnd *control = Control(j);
|
||||
if(control == NULL)
|
||||
continue;
|
||||
if(control == GetPointer(m_background))
|
||||
continue;
|
||||
control.Move(x, y);
|
||||
if(control.Type() == CLASS_LAYOUT)
|
||||
{
|
||||
CBox *container = control;
|
||||
container.Pack();
|
||||
}
|
||||
if(j < ControlsTotal() - 1)
|
||||
Shift(GetPointer(control), x, y, x_space, y_space);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CBox::Padding(const int top, const int right, const int bottom, const int left,const int padding)
|
||||
{
|
||||
m_padding_top = top;
|
||||
m_padding_right = right;
|
||||
m_padding_bottom = bottom;
|
||||
m_padding_left = left;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
// CBox::Padding(const int padding)
|
||||
// {
|
||||
// m_padding_top = padding;
|
||||
// m_padding_right = padding;
|
||||
// m_padding_bottom = padding;
|
||||
// m_padding_left = padding;
|
||||
// }
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,66 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ComboBoxResizable.mqh |
|
||||
//| Copyright (c) 2019, Marketeer |
|
||||
//| https://www.mql5.com/en/users/marketeer |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#include <Controls/ComboBox.mqh>
|
||||
|
||||
class ComboBoxResizable: public CComboBox
|
||||
{
|
||||
public:
|
||||
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
|
||||
|
||||
virtual bool OnResize(void) override
|
||||
{
|
||||
m_edit.Width(Width());
|
||||
|
||||
int x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_COMBO_BUTTON_X_OFF);
|
||||
int y1 = (Height() - CONTROLS_BUTTON_SIZE) / 2;
|
||||
m_drop.Move(Left() + x1, Top() + y1);
|
||||
|
||||
m_list.Width(Width());
|
||||
|
||||
return CWndContainer::OnResize();
|
||||
}
|
||||
|
||||
virtual bool OnClickButton(void) override
|
||||
{
|
||||
// this is a hack to trigger resizing of elements in the list
|
||||
// we need it because standard ListView is incorrectly coded in such a way
|
||||
// that elements are resized only if vscroll is present
|
||||
bool vs = m_list.VScrolled();
|
||||
if(m_drop.Pressed())
|
||||
{
|
||||
m_list.VScrolled(true);
|
||||
}
|
||||
bool b = CComboBox::OnClickButton();
|
||||
m_list.VScrolled(vs);
|
||||
return b;
|
||||
}
|
||||
|
||||
virtual bool Enable(void) override
|
||||
{
|
||||
m_edit.Show();
|
||||
m_drop.Show();
|
||||
return CComboBox::Enable();
|
||||
}
|
||||
|
||||
virtual bool Disable(void) override
|
||||
{
|
||||
m_edit.Hide();
|
||||
m_drop.Hide();
|
||||
return CComboBox::Disable();
|
||||
}
|
||||
};
|
||||
|
||||
#define EXIT_ON_DISABLED \
|
||||
if(!IsEnabled()) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
EVENT_MAP_BEGIN(ComboBoxResizable)
|
||||
EXIT_ON_DISABLED
|
||||
ON_EVENT(ON_CLICK, m_drop, OnClickButton)
|
||||
EVENT_MAP_END(CComboBox)
|
||||
@@ -0,0 +1,153 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Grid.mqh |
|
||||
//| Enrico Lambino |
|
||||
//| www.mql5.com/en/users/iceron|
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Enrico Lambino"
|
||||
#property link "http://www.mql5.com"
|
||||
#property strict
|
||||
#include "Box.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class CGrid: public CBox
|
||||
{
|
||||
protected:
|
||||
int m_cols;
|
||||
int m_rows;
|
||||
int m_hgap;
|
||||
int m_vgap;
|
||||
CSize m_cell_size;
|
||||
|
||||
public:
|
||||
CGrid();
|
||||
CGrid(int rows, int cols, int hgap = 0, int vgap = 0);
|
||||
~CGrid();
|
||||
virtual int Type() const
|
||||
{
|
||||
return CLASS_LAYOUT;
|
||||
}
|
||||
virtual bool Init(int rows, int cols, int hgap = 0, int vgap = 0);
|
||||
virtual bool Create(const long chart, const string name, const int subwin,
|
||||
const int x1, const int y1, const int x2, const int y2);
|
||||
virtual int Columns()
|
||||
{
|
||||
return (m_cols);
|
||||
}
|
||||
virtual void Columns(int cols)
|
||||
{
|
||||
m_cols = cols;
|
||||
}
|
||||
virtual int Rows()
|
||||
{
|
||||
return (m_rows);
|
||||
}
|
||||
virtual void Rows(int rows)
|
||||
{
|
||||
m_rows = rows;
|
||||
}
|
||||
virtual int HGap()
|
||||
{
|
||||
return (m_hgap);
|
||||
}
|
||||
virtual void HGap(int gap)
|
||||
{
|
||||
m_hgap = gap;
|
||||
}
|
||||
virtual int VGap()
|
||||
{
|
||||
return (m_vgap);
|
||||
}
|
||||
virtual void VGap(int gap)
|
||||
{
|
||||
m_vgap = gap;
|
||||
}
|
||||
virtual bool Pack();
|
||||
|
||||
protected:
|
||||
virtual void CheckControlSize(CWnd *control);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGrid::CGrid()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGrid::CGrid(int rows, int cols, int hgap = 0, int vgap = 0)
|
||||
{
|
||||
Init(rows, cols, hgap, vgap);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGrid::~CGrid()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CGrid::Init(int rows, int cols, int hgap = 0, int vgap = 0)
|
||||
{
|
||||
Columns(cols);
|
||||
Rows(rows);
|
||||
HGap(hgap);
|
||||
VGap(vgap);
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CGrid::Create(const long chart, const string name, const int subwin,
|
||||
const int x1, const int y1, const int x2, const int y2)
|
||||
{
|
||||
return (CBox::Create(chart, name, subwin, x1, y1, x2, y2));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CGrid::Pack()
|
||||
{
|
||||
CSize size = Size();
|
||||
m_cell_size.cx = (size.cx - ((m_cols + 1) * m_hgap)) / m_cols;
|
||||
m_cell_size.cy = (size.cy - ((m_rows + 1) * m_vgap)) / m_rows;
|
||||
int x = Left(), y = Top();
|
||||
int cnt = 0;
|
||||
for(int i = 0; i < ControlsTotal(); i++)
|
||||
{
|
||||
CWnd *control = Control(i);
|
||||
if(control == NULL)
|
||||
continue;
|
||||
if(control == GetPointer(m_background))
|
||||
continue;
|
||||
if(cnt == 0 || Right() - (x + m_cell_size.cx) < m_cell_size.cx + m_hgap)
|
||||
{
|
||||
if(cnt == 0)
|
||||
y += m_vgap;
|
||||
else
|
||||
y += m_vgap + m_cell_size.cy;
|
||||
x = Left() + m_hgap;
|
||||
}
|
||||
else
|
||||
x += m_cell_size.cx + m_hgap;
|
||||
CheckControlSize(control);
|
||||
control.Move(x, y);
|
||||
if(control.Type() == CLASS_LAYOUT)
|
||||
{
|
||||
CBox *container = control;
|
||||
container.Pack();
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGrid::CheckControlSize(CWnd *control)
|
||||
{
|
||||
control.Size(m_cell_size.cx, m_cell_size.cy);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,154 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| GridTk.mqh |
|
||||
//| Enrico Lambino |
|
||||
//| www.mql5.com/en/users/iceron|
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Enrico Lambino"
|
||||
#property link "http://www.mql5.com"
|
||||
#property strict
|
||||
#include "Grid.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class CGridConstraints: public CObject
|
||||
{
|
||||
protected:
|
||||
CWnd *m_control;
|
||||
int m_row;
|
||||
int m_col;
|
||||
int m_rowspan;
|
||||
int m_colspan;
|
||||
|
||||
public:
|
||||
CGridConstraints(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1);
|
||||
~CGridConstraints();
|
||||
CWnd *Control()
|
||||
{
|
||||
return (m_control);
|
||||
}
|
||||
int Row()
|
||||
{
|
||||
return (m_row);
|
||||
}
|
||||
int Column()
|
||||
{
|
||||
return (m_col);
|
||||
}
|
||||
int RowSpan()
|
||||
{
|
||||
return (m_rowspan);
|
||||
}
|
||||
int ColSpan()
|
||||
{
|
||||
return (m_colspan);
|
||||
}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGridConstraints::CGridConstraints(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1)
|
||||
{
|
||||
m_control = control;
|
||||
m_row = MathMax(0, row);
|
||||
m_col = MathMax(0, column);
|
||||
m_rowspan = MathMax(1, rowspan);
|
||||
m_colspan = MathMax(1, colspan);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGridConstraints::~CGridConstraints()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
class CGridTk: public CGrid
|
||||
{
|
||||
protected:
|
||||
CArrayObj m_constraints;
|
||||
|
||||
public:
|
||||
CGridTk();
|
||||
~CGridTk();
|
||||
bool Grid(CWnd *control, int row, int column, int rowspan, int colspan);
|
||||
bool Pack();
|
||||
CGridConstraints *GetGridConstraints(CWnd *control);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGridTk::CGridTk(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGridTk::~CGridTk(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CGridTk::Grid(CWnd *control, int row, int column, int rowspan = 1, int colspan = 1)
|
||||
{
|
||||
CGridConstraints *constraints = new CGridConstraints(control, row, column, rowspan, colspan);
|
||||
if(!CheckPointer(constraints))
|
||||
return (false);
|
||||
if(!m_constraints.Add(constraints))
|
||||
return (false);
|
||||
return (Add(control));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CGridTk::Pack()
|
||||
{
|
||||
CGrid::Pack();
|
||||
CSize size = Size();
|
||||
m_cell_size.cx = (size.cx - (m_cols + 1) * m_hgap) / m_cols;
|
||||
m_cell_size.cy = (size.cy - (m_rows + 1) * m_vgap) / m_rows;
|
||||
for(int i = 0; i < ControlsTotal(); i++)
|
||||
{
|
||||
int x = Left(), y = Top();
|
||||
CWnd *control = Control(i);
|
||||
if(control == NULL)
|
||||
continue;
|
||||
if(control == GetPointer(m_background))
|
||||
continue;
|
||||
CGridConstraints *constraints = GetGridConstraints(control);
|
||||
if(constraints == NULL)
|
||||
continue;
|
||||
int column = constraints.Column();
|
||||
int row = constraints.Row();
|
||||
x += (column * m_cell_size.cx) + ((column + 1) * m_hgap);
|
||||
y += (row * m_cell_size.cy) + ((row + 1) * m_vgap);
|
||||
int colspan = constraints.ColSpan();
|
||||
int rowspan = constraints.RowSpan();
|
||||
control.Size(colspan * m_cell_size.cx + ((colspan - 1) * m_hgap), rowspan * m_cell_size.cy + ((rowspan - 1) * m_vgap));
|
||||
control.Move(x, y);
|
||||
if(control.Type() == CLASS_LAYOUT)
|
||||
{
|
||||
CBox *container = control;
|
||||
container.Pack();
|
||||
}
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
CGridConstraints *CGridTk::GetGridConstraints(CWnd *control)
|
||||
{
|
||||
for(int i = 0; i < m_constraints.Total(); i++)
|
||||
{
|
||||
CGridConstraints *constraints = m_constraints.At(i);
|
||||
CWnd *ctrl = constraints.Control();
|
||||
if(ctrl == NULL)
|
||||
continue;
|
||||
if(ctrl == control)
|
||||
return (constraints);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,337 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MaximizableAppDialog.mqh |
|
||||
//| Copyright (c) 2019, Marketeer |
|
||||
//| https://www.mql5.com/en/users/marketeer |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#include <Controls\Dialog.mqh>
|
||||
#include <Controls\Button.mqh>
|
||||
|
||||
#resource "res\\Expand2.bmp"
|
||||
#resource "res\\size6.bmp"
|
||||
#resource "res\\size10.bmp"
|
||||
|
||||
class MaximizableAppDialog: public CAppDialog
|
||||
{
|
||||
protected:
|
||||
CBmpButton m_button_truemax;
|
||||
CBmpButton m_button_size;
|
||||
bool m_maximized;
|
||||
CRect m_max_rect;
|
||||
CSize m_size_limit;
|
||||
bool m_sizing;
|
||||
|
||||
// window maximization
|
||||
virtual bool CreateButtonMinMax(void) override;
|
||||
virtual void OnClickButtonMinMax(void) override;
|
||||
virtual void OnClickButtonTrueMax(void);
|
||||
virtual void OnClickButtonSizeFixMe(void);
|
||||
virtual void Expand(void);
|
||||
virtual void Restore(void);
|
||||
|
||||
virtual void Minimize(void) override;
|
||||
|
||||
// window resizing
|
||||
bool CreateButtonSize(void);
|
||||
bool OnDialogSizeStart(void);
|
||||
virtual bool OnDialogDragStart(void) override;
|
||||
virtual bool OnDialogDragProcess(void) override;
|
||||
virtual bool OnDialogDragEnd(void) override;
|
||||
|
||||
virtual void SelfAdjustment(const bool minimized = false) = 0;
|
||||
|
||||
public:
|
||||
MaximizableAppDialog(): m_maximized(false), m_sizing(false) {}
|
||||
virtual bool Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2) override;
|
||||
virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override;
|
||||
|
||||
virtual bool OnChartChange(const long &lparam, const double &dparam, const string &sparam);
|
||||
|
||||
void ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
|
||||
|
||||
void SetSizeLimit(const CSize &limit) { m_size_limit = limit; }
|
||||
CSize GetSizeLimit() { return m_size_limit; }
|
||||
};
|
||||
|
||||
void MaximizableAppDialog::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
|
||||
{
|
||||
if(id == CHARTEVENT_CHART_CHANGE)
|
||||
{
|
||||
if(OnChartChange(lparam, dparam, sparam)) return;
|
||||
}
|
||||
CAppDialog::ChartEvent(id, lparam, dparam, sparam);
|
||||
}
|
||||
|
||||
EVENT_MAP_BEGIN(MaximizableAppDialog)
|
||||
ON_EVENT(ON_CLICK, m_button_truemax, OnClickButtonTrueMax)
|
||||
ON_EVENT(ON_CLICK, m_button_size, OnClickButtonSizeFixMe)
|
||||
ON_EVENT(ON_DRAG_START, m_button_size, OnDialogSizeStart)
|
||||
ON_EVENT_PTR(ON_DRAG_PROCESS, m_drag_object, OnDialogDragProcess)
|
||||
ON_EVENT_PTR(ON_DRAG_END, m_drag_object, OnDialogDragEnd)
|
||||
EVENT_MAP_END(CAppDialog)
|
||||
|
||||
bool MaximizableAppDialog::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
|
||||
{
|
||||
// 1 * CONTROLS_BORDER_WIDTH - stays here, because the standard control library minimizes window
|
||||
// when it's height is 1 pixel smaller than the entire chart height
|
||||
m_max_rect.SetBound(0,
|
||||
0,
|
||||
(int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH,
|
||||
(int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH);
|
||||
if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
|
||||
if(!CreateButtonSize()) return false;
|
||||
m_size_limit.cx = x2 - x1;
|
||||
m_size_limit.cy = y2 - y1;
|
||||
if(m_size_limit.cx >= m_max_rect.Width() || m_size_limit.cy >= m_max_rect.Height())
|
||||
{
|
||||
m_size_limit.cx = m_min_rect.Width() * 3;
|
||||
m_size_limit.cy = m_min_rect.Height() * 7;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaximizableAppDialog::CreateButtonMinMax(void) override
|
||||
{
|
||||
if(!CAppDialog::CreateButtonMinMax()) return false;
|
||||
|
||||
// add maximization button
|
||||
int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH;
|
||||
|
||||
int x1 = Width() - off - 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF);
|
||||
int y1 = off + CONTROLS_DIALOG_BUTTON_OFF;
|
||||
int x2 = x1 + CONTROLS_BUTTON_SIZE;
|
||||
int y2 = y1 + CONTROLS_BUTTON_SIZE;
|
||||
|
||||
if(!m_button_truemax.Create(m_chart_id, m_name + "TrueMax", m_subwin, x1, y1, x2, y2)) return false;
|
||||
if(!m_button_truemax.BmpNames("::res\\Expand2.bmp", "::res\\Restore.bmp")) return false;
|
||||
if(!CWndContainer::Add(m_button_truemax)) return false;
|
||||
|
||||
m_button_truemax.Locking(true);
|
||||
m_button_truemax.Alignment(WND_ALIGN_RIGHT, 0, 0, off + 2 * CONTROLS_BUTTON_SIZE + 2 * CONTROLS_DIALOG_BUTTON_OFF, 0);
|
||||
|
||||
CaptionAlignment(WND_ALIGN_WIDTH, off, 0, off + 3 * (CONTROLS_BUTTON_SIZE + CONTROLS_DIALOG_BUTTON_OFF), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaximizableAppDialog::CreateButtonSize(void)
|
||||
{
|
||||
int off = (m_panel_flag) ? 0 : 2 * CONTROLS_BORDER_WIDTH;
|
||||
|
||||
int x1 = Width() - CONTROLS_BUTTON_SIZE + 1;
|
||||
int y1 = Height() - CONTROLS_BUTTON_SIZE + 1;
|
||||
int x2 = x1 + CONTROLS_BUTTON_SIZE - 1;
|
||||
int y2 = y1 + CONTROLS_BUTTON_SIZE - 1;
|
||||
|
||||
if(!m_button_size.Create(m_chart_id, m_name + "Size", m_subwin, x1, y1, x2, y2)) return false;
|
||||
if(!m_button_size.BmpNames("::res\\size6.bmp", "::res\\size10.bmp")) return false;
|
||||
if(!CWndContainer::Add(m_button_size)) return false;
|
||||
m_button_size.Alignment(WND_ALIGN_RIGHT|WND_ALIGN_BOTTOM, 0, 0, 0, 0);
|
||||
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MaximizableAppDialog::OnClickButtonTrueMax(void)
|
||||
{
|
||||
if(m_button_truemax.Pressed())
|
||||
Expand();
|
||||
else
|
||||
Restore();
|
||||
|
||||
SubwinOff();
|
||||
}
|
||||
|
||||
// This is a hack. It's required because in minimized state sizing button somehow "overlaps"
|
||||
// the close button and intercepts clicks on it (which prevents exit from minimized app).
|
||||
// This happens despite the fact that the sizing button is hidden, disabled and assigned
|
||||
// with minimal Z-order (checked out, then removed).
|
||||
// Looks like a bug in the standard control library, specifically:
|
||||
// In CWnd::OnMouseEvent there must be a line:
|
||||
//
|
||||
// if(!IS_ENABLED || !IS_VISIBLE) return false;
|
||||
//
|
||||
// but it's not there, so invisible, disabled and even background objects are processed
|
||||
// in the same manner as all other objects. Specifically in CWndContainer::OnMouseEvent
|
||||
// there is a reverse loop through all objects (it does _not_ respect Z-order anyhow).
|
||||
|
||||
void MaximizableAppDialog::OnClickButtonSizeFixMe(void)
|
||||
{
|
||||
if(m_minimized)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void MaximizableAppDialog::Expand(void)
|
||||
{
|
||||
m_maximized = true;
|
||||
m_minimized = false;
|
||||
m_button_minmax.Pressed(false);
|
||||
Rebound(m_max_rect);
|
||||
m_button_size.Hide();
|
||||
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
|
||||
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
|
||||
if(!m_panel_flag)
|
||||
{
|
||||
m_caption.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
|
||||
}
|
||||
|
||||
ClientAreaVisible(true);
|
||||
SelfAdjustment();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Restore dialog window |
|
||||
//+------------------------------------------------------------------+
|
||||
void MaximizableAppDialog::Restore(void)
|
||||
{
|
||||
m_maximized = false;
|
||||
m_minimized = false;
|
||||
m_button_minmax.Pressed(false);
|
||||
m_button_size.Show();
|
||||
m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE);
|
||||
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
|
||||
CAppDialog::Maximize();
|
||||
if(!m_panel_flag)
|
||||
{
|
||||
m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
|
||||
}
|
||||
SelfAdjustment();
|
||||
}
|
||||
|
||||
void MaximizableAppDialog::Minimize()
|
||||
{
|
||||
CAppDialog::Minimize();
|
||||
m_button_size.Hide();
|
||||
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
|
||||
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
|
||||
}
|
||||
|
||||
bool MaximizableAppDialog::OnChartChange(const long &lparam, const double &dparam, const string &sparam)
|
||||
{
|
||||
m_max_rect.SetBound(0, 0,
|
||||
(int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) - 0 * CONTROLS_BORDER_WIDTH,
|
||||
(int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS) - 1 * CONTROLS_BORDER_WIDTH);
|
||||
if(m_maximized)
|
||||
{
|
||||
if(m_rect.Width() != m_max_rect.Width() || m_rect.Height() != m_max_rect.Height())
|
||||
{
|
||||
Rebound(m_max_rect);
|
||||
SelfAdjustment();
|
||||
m_chart.Redraw();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaximizableAppDialog::OnClickButtonMinMax(void)
|
||||
{
|
||||
CAppDialog::OnClickButtonMinMax();
|
||||
m_button_truemax.Pressed(false);
|
||||
m_maximized = false;
|
||||
if(m_minimized)
|
||||
{
|
||||
m_button_size.Hide();
|
||||
m_button_size.StateFlagsReset(WND_STATE_FLAG_ENABLE);
|
||||
m_button_size.PropFlagsReset(WND_PROP_FLAG_CAN_DRAG);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_button_size.Show();
|
||||
m_button_size.StateFlagsSet(WND_STATE_FLAG_ENABLE);
|
||||
m_button_size.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
|
||||
}
|
||||
if(!m_panel_flag)
|
||||
{
|
||||
m_caption.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
|
||||
}
|
||||
SelfAdjustment(m_minimized);
|
||||
}
|
||||
|
||||
bool MaximizableAppDialog::OnDialogSizeStart(void)
|
||||
{
|
||||
if(m_drag_object == NULL)
|
||||
{
|
||||
m_drag_object = new CDragWnd;
|
||||
if(m_drag_object == NULL) return false;
|
||||
}
|
||||
int x1 = m_button_size.Left() - CONTROLS_DRAG_SPACING;
|
||||
int y1 = m_button_size.Top() - CONTROLS_DRAG_SPACING;
|
||||
int x2 = m_button_size.Right() + CONTROLS_DRAG_SPACING;
|
||||
int y2 = m_button_size.Bottom() + CONTROLS_DRAG_SPACING;
|
||||
|
||||
m_drag_object.Create(m_chart_id, "", m_subwin, x1, y1, x2, y2);
|
||||
m_drag_object.PropFlagsSet(WND_PROP_FLAG_CAN_DRAG);
|
||||
|
||||
CChart chart;
|
||||
chart.Attach(m_chart_id);
|
||||
m_drag_object.Limits(-CONTROLS_DRAG_SPACING, -CONTROLS_DRAG_SPACING,
|
||||
chart.WidthInPixels() + CONTROLS_DRAG_SPACING,
|
||||
chart.HeightInPixels(m_subwin) + CONTROLS_DRAG_SPACING);
|
||||
chart.Detach();
|
||||
|
||||
m_drag_object.MouseX(m_button_size.MouseX());
|
||||
m_drag_object.MouseY(m_button_size.MouseY());
|
||||
m_drag_object.MouseFlags(m_button_size.MouseFlags());
|
||||
|
||||
m_sizing = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaximizableAppDialog::OnDialogDragStart(void)
|
||||
{
|
||||
if(m_maximized) return false;
|
||||
|
||||
return CAppDialog::OnDialogDragStart();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Continue dragging the dialog box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MaximizableAppDialog::OnDialogDragProcess(void)
|
||||
{
|
||||
if(!m_sizing) return CDialog::OnDialogDragProcess();
|
||||
|
||||
if(m_drag_object == NULL) return false;
|
||||
|
||||
int x = m_drag_object.Right() - Right() - CONTROLS_DRAG_SPACING;
|
||||
int y = m_drag_object.Bottom() - Bottom() - CONTROLS_DRAG_SPACING;
|
||||
|
||||
// resize dialog
|
||||
CRect r = Rect();
|
||||
r.right += x;
|
||||
r.bottom += y;
|
||||
|
||||
if(r.Width() < m_size_limit.cx) r.right = r.left + m_size_limit.cx;
|
||||
if(r.Height() < m_size_limit.cy) r.bottom = r.top + m_size_limit.cy;
|
||||
|
||||
Rebound(r);
|
||||
|
||||
SelfAdjustment();
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| End dragging the dialog box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MaximizableAppDialog::OnDialogDragEnd(void)
|
||||
{
|
||||
if(!m_sizing) return CDialog::OnDialogDragEnd();
|
||||
|
||||
if(m_drag_object != NULL)
|
||||
{
|
||||
m_button_size.MouseFlags(m_drag_object.MouseFlags());
|
||||
delete m_drag_object;
|
||||
m_drag_object = NULL;
|
||||
}
|
||||
|
||||
m_norm_rect.SetBound(m_rect);
|
||||
m_sizing = false;
|
||||
|
||||
SelfAdjustment();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SpinEditResizable.mqh |
|
||||
//| Copyright (c) 2019, Marketeer |
|
||||
//| https://www.mql5.com/en/users/marketeer |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
#include <Controls/SpinEdit.mqh>
|
||||
|
||||
class SpinEditResizable: public CSpinEdit
|
||||
{
|
||||
public:
|
||||
virtual bool OnResize(void) override
|
||||
{
|
||||
m_edit.Width(Width());
|
||||
m_edit.Height(Height());
|
||||
|
||||
int x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_SPIN_BUTTON_X_OFF);
|
||||
int y1 = (Height() - 2 * CONTROLS_SPIN_BUTTON_SIZE) / 2;
|
||||
m_inc.Move(Left() + x1, Top() + y1);
|
||||
|
||||
x1 = Width() - (CONTROLS_BUTTON_SIZE + CONTROLS_SPIN_BUTTON_X_OFF);
|
||||
y1 = (Height() - 2 * CONTROLS_SPIN_BUTTON_SIZE) / 2 + CONTROLS_SPIN_BUTTON_SIZE;
|
||||
m_dec.Move(Left() + x1, Top() + y1);
|
||||
|
||||
return CWndContainer::OnResize();
|
||||
}
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
// header
|
||||
"isindex",
|
||||
"base",
|
||||
"meta",
|
||||
"link",
|
||||
"nextid",
|
||||
"range",
|
||||
// elsewhere
|
||||
"img",
|
||||
"br",
|
||||
"hr",
|
||||
"frame",
|
||||
"wbr",
|
||||
"basefont",
|
||||
"spacer",
|
||||
"area",
|
||||
"param",
|
||||
"keygen",
|
||||
"col",
|
||||
"limittext"
|
||||
+38345
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2549
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| arrayresize.mqh |
|
||||
//| Copyright 2003-2022 Sergey Bochkanov (ALGLIB project) |
|
||||
//| Copyright 2012-2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of ALGLIB library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Linear algebra (direct algorithms, EVD, SVD) |
|
||||
//| - Solving systems of linear and non-linear equations |
|
||||
//| - Interpolation |
|
||||
//| - Optimization |
|
||||
//| - FFT (Fast Fourier Transform) |
|
||||
//| - Numerical integration |
|
||||
//| - Linear and nonlinear least-squares fitting |
|
||||
//| - Ordinary differential equations |
|
||||
//| - Computation of special functions |
|
||||
//| - Descriptive statistics and hypothesis testing |
|
||||
//| - Data analysis - classification, regression |
|
||||
//| - Implementing linear algebra algorithms, interpolation, etc. |
|
||||
//| in high-precision arithmetic (using MPFR) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//--- forward declaration
|
||||
class CRowInt;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayResizeAL for Alglib library with MQL5 features |
|
||||
//+------------------------------------------------------------------+
|
||||
int ArrayResizeAL(int &arr[],const int size)
|
||||
{
|
||||
int old=ArraySize(arr);
|
||||
int res=ArrayResize(arr,size);
|
||||
//--- fill array if necessary
|
||||
if(res>0 && old<size)
|
||||
ArrayFill(arr,old,size-old,0);
|
||||
//--- return result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayResizeAL for Alglib library with MQL5 features |
|
||||
//+------------------------------------------------------------------+
|
||||
int ArrayResizeAL(short &arr[],const int size)
|
||||
{
|
||||
int old=ArraySize(arr);
|
||||
int res=ArrayResize(arr,size);
|
||||
//--- fill array if necessary
|
||||
if(res>0 && old<size)
|
||||
ArrayFill(arr,old,size-old,0);
|
||||
//--- return result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayResizeAL for Alglib library with MQL5 features |
|
||||
//+------------------------------------------------------------------+
|
||||
int ArrayResizeAL(char &arr[],const int size)
|
||||
{
|
||||
int old=ArraySize(arr);
|
||||
int res=ArrayResize(arr,size);
|
||||
//--- fill array if necessary
|
||||
if(res>0 && old<size)
|
||||
ArrayFill(arr,old,size-old,0);
|
||||
//--- return result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayResizeAL for Alglib library with MQL5 features |
|
||||
//+------------------------------------------------------------------+
|
||||
int ArrayResizeAL(bool &arr[],const int size)
|
||||
{
|
||||
int old=ArraySize(arr);
|
||||
int res=ArrayResize(arr,size);
|
||||
//--- fill array if necessary
|
||||
if(res>0 && old<size)
|
||||
ArrayFill(arr,old,size-old,false);
|
||||
//--- return result
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayResizeAL for Alglib library with MQL5 features |
|
||||
//+------------------------------------------------------------------+
|
||||
int ArrayResizeAL(string &arr[],const int size)
|
||||
{
|
||||
return(ArrayResize(arr,size));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayResizeAL for Alglib library with MQL4 and MQL5 features |
|
||||
//+------------------------------------------------------------------+
|
||||
int ArrayResizeAL(CRowInt &arr[],const int size)
|
||||
{
|
||||
return(ArrayResize(arr,size));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,411 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| bitconvert.mqh |
|
||||
//| Copyright 2003-2022 Sergey Bochkanov (ALGLIB project) |
|
||||
//| Copyright 2012-2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of ALGLIB library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Linear algebra (direct algorithms, EVD, SVD) |
|
||||
//| - Solving systems of linear and non-linear equations |
|
||||
//| - Interpolation |
|
||||
//| - Optimization |
|
||||
//| - FFT (Fast Fourier Transform) |
|
||||
//| - Numerical integration |
|
||||
//| - Linear and nonlinear least-squares fitting |
|
||||
//| - Ordinary differential equations |
|
||||
//| - Computation of special functions |
|
||||
//| - Descriptive statistics and hypothesis testing |
|
||||
//| - Data analysis - classification, regression |
|
||||
//| - Implementing linear algebra algorithms, interpolation, etc. |
|
||||
//| in high-precision arithmetic (using MPFR) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "arrayresize.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting numbers into an array of bits and vice versa |
|
||||
//+------------------------------------------------------------------+
|
||||
class BitConverter
|
||||
{
|
||||
public:
|
||||
static void GetBytes(const int d,uchar &bytes[]);
|
||||
static void GetBytes(const double d,uchar &bytes[]);
|
||||
static int ToInt32(uchar &bytes[]);
|
||||
static double ToDouble(uchar &bytes[]);
|
||||
static bool IsLittleEndian(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting integer to a byte array |
|
||||
//+------------------------------------------------------------------+
|
||||
void BitConverter::GetBytes(const int d,uchar &bytes[])
|
||||
{
|
||||
//--- create variables
|
||||
int x;
|
||||
int q;
|
||||
int r;
|
||||
int i;
|
||||
int div;
|
||||
//--- allocation
|
||||
ArrayResize(bytes,4);
|
||||
for(i=0; i<4; i++)
|
||||
{
|
||||
//--- check
|
||||
if(d>=0)
|
||||
bytes[i]=0;
|
||||
else
|
||||
bytes[i]=255;
|
||||
}
|
||||
//--- initialization
|
||||
q=-1;
|
||||
r=-1;
|
||||
i=3;
|
||||
div=256*256*256;
|
||||
//--- check
|
||||
if(d<0)
|
||||
x=~d;
|
||||
else
|
||||
x=d;
|
||||
//--- converting number
|
||||
while(i!=-1)
|
||||
{
|
||||
//--- quotient
|
||||
q=x/div;
|
||||
//--- remainder of division
|
||||
r=x%div;
|
||||
//--- get byte
|
||||
if(d>=0)
|
||||
bytes[i]+=(uchar)q;
|
||||
else
|
||||
bytes[i]-=(uchar)q;
|
||||
//--- the next iteration is reduced divisor
|
||||
x=r;
|
||||
div=div/256;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting double to a byte array |
|
||||
//+------------------------------------------------------------------+
|
||||
void BitConverter::GetBytes(const double d,uchar &bytes[])
|
||||
{
|
||||
//--- module
|
||||
double abs_d=MathAbs(d);
|
||||
//--- number without its fractional
|
||||
double floor_d=MathFloor(abs_d);
|
||||
//--- fractional part
|
||||
double fractional_d=abs_d-floor_d;
|
||||
//--- variable will store the degree
|
||||
int power;
|
||||
//--- exponent shift
|
||||
double exp_shift;
|
||||
//--- create variables
|
||||
int k;
|
||||
int j;
|
||||
uchar u;
|
||||
double step;
|
||||
double f;
|
||||
//--- abs_d as bits
|
||||
bool abs_d_to_bitArray[];
|
||||
//--- d as bits in format IEEE 754
|
||||
bool d_to_bitArray[];
|
||||
//--- allocation
|
||||
ArrayResizeAL(d_to_bitArray,64);
|
||||
ArrayResizeAL(bytes,8);
|
||||
//--- initialization
|
||||
power=0;
|
||||
//--- for integer part
|
||||
while(1)
|
||||
{
|
||||
//--- if the number is less than or equal floor_d, we increase the degree
|
||||
//--- if 2^power > floor_d, then maximal number < floor_d - it 2^(power-1)
|
||||
if(floor_d>=MathPow(2,power))
|
||||
power++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
//--- get power-1
|
||||
power--;
|
||||
//--- if power=-1, then floor_d=0
|
||||
//--- find a negative power for the fractional part
|
||||
if(power==-1)
|
||||
{
|
||||
power=0;
|
||||
while(1)
|
||||
{
|
||||
//--- the same principle as above
|
||||
if(fractional_d<MathPow(2,power))
|
||||
power--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
//--- convert decimal to binary
|
||||
j=0;
|
||||
step=power;
|
||||
while(abs_d!=0.0)
|
||||
{
|
||||
f=MathPow(2,step);
|
||||
//--- check
|
||||
if(f>abs_d)
|
||||
{
|
||||
//--- if abs_d < f - this bit is zero
|
||||
ArrayResize(abs_d_to_bitArray,j+1);
|
||||
abs_d_to_bitArray[j]=0;
|
||||
j++;
|
||||
step-=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- if abs_d >= f, then this bit is equal one
|
||||
//--- reduction abs_d
|
||||
abs_d-=f;
|
||||
ArrayResize(abs_d_to_bitArray,j+1);
|
||||
abs_d_to_bitArray[j]=1;
|
||||
j++;
|
||||
step-=1;
|
||||
}
|
||||
}
|
||||
//--- according to IEEE 754,
|
||||
//--- zero bit determines sign of the number, 0 -> '+', 1 -> '-'.
|
||||
if(d>=0)
|
||||
d_to_bitArray[0]=0;
|
||||
else
|
||||
d_to_bitArray[0]=1;
|
||||
//--- offset input
|
||||
exp_shift=1023+power;
|
||||
//--- bits from the first and 11 are reserved for the shifted exponential
|
||||
j=1;
|
||||
for(int i=10; i>=0; i--)
|
||||
{
|
||||
if(MathPow(2,i)>exp_shift)
|
||||
d_to_bitArray[j]=0;
|
||||
else
|
||||
{
|
||||
d_to_bitArray[j]=1;
|
||||
//--- reduction
|
||||
exp_shift-=MathPow(2,i);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
//--- Get the length of the array of the binary representation of abs_d
|
||||
k=ArraySize(abs_d_to_bitArray);
|
||||
j=1;
|
||||
//--- Bits from 12 to 63 are filled with binary representation of abs_b
|
||||
//--- the first element abs_d_to_bitArray is always 1
|
||||
for(int i=12; i<64; i++)
|
||||
{
|
||||
if(j<k)
|
||||
{
|
||||
d_to_bitArray[i]=abs_d_to_bitArray[i-11];
|
||||
j++;
|
||||
}
|
||||
else
|
||||
d_to_bitArray[i]=0;
|
||||
}
|
||||
//--- reverse
|
||||
ArrayReverse(d_to_bitArray);
|
||||
//--- converting bit array to byte array
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
u=0;
|
||||
//--- get byte
|
||||
for(int t=0; t<8; t++)
|
||||
u+=(uchar)(d_to_bitArray[i*8+t]*MathPow(2,t));
|
||||
//--- save byte
|
||||
bytes[i]=u;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting byte array to a integer |
|
||||
//+------------------------------------------------------------------+
|
||||
int BitConverter::ToInt32(uchar &bytes[])
|
||||
{
|
||||
//--- get size
|
||||
int size=ArraySize(bytes);
|
||||
//--- create variables
|
||||
int d=0;
|
||||
int mul=256*256*256;
|
||||
//--- get number
|
||||
for(int i=size-1; i>=0; i--)
|
||||
{
|
||||
d+=bytes[i]*mul;
|
||||
mul=mul/256;
|
||||
}
|
||||
//--- return result
|
||||
return(d);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Converting byte array to a double |
|
||||
//+------------------------------------------------------------------+
|
||||
double BitConverter::ToDouble(uchar &bytes[])
|
||||
{
|
||||
//--- create variables
|
||||
int s;
|
||||
//--- exponent shift
|
||||
int e=0;
|
||||
//--- mantissa
|
||||
double m=0;
|
||||
//--- array of bits in IEEE 754
|
||||
bool bits[];
|
||||
ArrayResize(bits,64);
|
||||
//--- get array of bits from array of bytes
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
for(int j=7; j>=0; j--)
|
||||
{
|
||||
//--- if 2 in power >, bits[i*8+j]=0, else bits[i*8+j]=0
|
||||
if(MathPow(2,j)>bytes[i])
|
||||
bits[i*8+j]=0;
|
||||
else
|
||||
{
|
||||
bits[i*8+j]=1;
|
||||
//--- reduction
|
||||
bytes[i]-=(uchar)MathPow(2,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- search bits with 1
|
||||
bool allzero=true;
|
||||
for(int i=0; i<64; i++)
|
||||
if(bits[i]==1)
|
||||
allzero=false;
|
||||
//--- if all bits are 0, then number is 0
|
||||
if(allzero==true)
|
||||
return(0.0);
|
||||
//--- reverse array
|
||||
ArrayReverse(bits);
|
||||
//--- s-the first bit, determines sign of the number
|
||||
s=bits[0];
|
||||
//--- calculation exponent shift
|
||||
for(int i=10; i>=0; i--)
|
||||
e+=(int)(bits[11-i]*MathPow(2,i));
|
||||
//--- get mantissa
|
||||
for(int i=0; i<52; i++)
|
||||
m+=bits[12+i]*MathPow(2,-1-i);
|
||||
//--- return result
|
||||
return(MathPow(-1,s)*MathPow(2,e-1023)*(1+m));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Byte ordering (forward, backward) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool BitConverter::IsLittleEndian(void)
|
||||
{
|
||||
//--- forward
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get string from char array |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetSelectionString(char &buf[],int startIndex,int lenght)
|
||||
{
|
||||
return(CharArrayToString(buf,startIndex,lenght));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get sign of number |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathSign(const double x)
|
||||
{
|
||||
//--- if x>0
|
||||
if(x>0)
|
||||
return(1);
|
||||
//--- if ?==0
|
||||
if(x==0)
|
||||
return(0);
|
||||
//--- ?<0
|
||||
return(-1);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Structure stores a variable of type double |
|
||||
//+------------------------------------------------------------------+
|
||||
union UDoubleValue
|
||||
{
|
||||
double value;
|
||||
long bits;
|
||||
|
||||
UDoubleValue(double dbl): value(dbl) { }
|
||||
UDoubleValue(long bit_value): bits(bit_value) { }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Work with infinity and NaN |
|
||||
//+------------------------------------------------------------------+
|
||||
class CInfOrNaN
|
||||
{
|
||||
public:
|
||||
//--- checks
|
||||
static bool IsPositiveInfinity(const double x);
|
||||
static bool IsNegativeInfinity(const double x);
|
||||
static bool IsInfinity(const double x);
|
||||
static bool IsNaN(const double x);
|
||||
//--- generation values
|
||||
static double PositiveInfinity(void);
|
||||
static double NegativeInfinity(void);
|
||||
static double NaN(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for +inf |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CInfOrNaN::IsPositiveInfinity(const double x)
|
||||
{
|
||||
UDoubleValue val=x;
|
||||
//--- check
|
||||
return(val.bits==0x7FF0000000000000);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for -inf |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CInfOrNaN::IsNegativeInfinity(const double x)
|
||||
{
|
||||
UDoubleValue val=x;
|
||||
//--- check
|
||||
return(val.bits==0xFFF0000000000000);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for +-inf |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CInfOrNaN::IsInfinity(const double x)
|
||||
{
|
||||
return(MathClassify(x)==FP_INFINITE);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for NaN |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CInfOrNaN::IsNaN(const double x)
|
||||
{
|
||||
return(MathClassify(x)==FP_NAN);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return +inf |
|
||||
//+------------------------------------------------------------------+
|
||||
double CInfOrNaN::PositiveInfinity(void)
|
||||
{
|
||||
UDoubleValue val(0x7FF0000000000000);
|
||||
return(val.value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return -inf |
|
||||
//+------------------------------------------------------------------+
|
||||
double CInfOrNaN::NegativeInfinity(void)
|
||||
{
|
||||
UDoubleValue val(0xFFF0000000000000);
|
||||
return(val.value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return NaN |
|
||||
//+------------------------------------------------------------------+
|
||||
double CInfOrNaN::NaN(void)
|
||||
{
|
||||
UDoubleValue val(0x7FFFFFFFFFFFFFFF);
|
||||
return(val.value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,444 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| delegatefunctions.mqh |
|
||||
//| Copyright 2003-2022 Sergey Bochkanov (ALGLIB project) |
|
||||
//| Copyright 2012-2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of ALGLIB library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Linear algebra (direct algorithms, EVD, SVD) |
|
||||
//| - Solving systems of linear and non-linear equations |
|
||||
//| - Interpolation |
|
||||
//| - Optimization |
|
||||
//| - FFT (Fast Fourier Transform) |
|
||||
//| - Numerical integration |
|
||||
//| - Linear and nonlinear least-squares fitting |
|
||||
//| - Ordinary differential equations |
|
||||
//| - Computation of special functions |
|
||||
//| - Descriptive statistics and hypothesis testing |
|
||||
//| - Data analysis - classification, regression |
|
||||
//| - Implementing linear algebra algorithms, interpolation, etc. |
|
||||
//| in high-precision arithmetic (using MPFR) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Object.mqh>
|
||||
#include "matrix.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates f(arg), stores result to func |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_Func
|
||||
{
|
||||
public:
|
||||
CNDimensional_Func(void);
|
||||
~CNDimensional_Func(void);
|
||||
|
||||
virtual void Func(double &x[],double &func,CObject &obj);
|
||||
virtual void Func(CRowDouble &x,double &func,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Func::CNDimensional_Func(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Func::~CNDimensional_Func(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Func::Func(double &x[],double &func,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Func::Func(CRowDouble &x,double &func,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| calculates func = f(arg), grad[i] = df(arg)/d(arg[i]) |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_Grad
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_Grad(void);
|
||||
~CNDimensional_Grad(void);
|
||||
//--- virtual method
|
||||
virtual void Grad(double &x[],double &func,double &grad[],CObject &obj);
|
||||
virtual void Grad(CRowDouble &x,double &func,CRowDouble &grad,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Grad::CNDimensional_Grad(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Grad::~CNDimensional_Grad(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Grad::Grad(double &x[],double &func,double &grad[],
|
||||
CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Grad::Grad(CRowDouble &x,double &func,CRowDouble &grad,
|
||||
CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates func = f(arg), grad[i] = df(arg)/d(arg[i]), |
|
||||
//| hess[i,j] = d2f(arg)/(d(arg[i])*d(arg[j])) |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_Hess
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_Hess(void);
|
||||
~CNDimensional_Hess(void);
|
||||
//--- virtual method
|
||||
virtual void Hess(double &x[],double &func,double &grad[],CMatrixDouble &hess,CObject &obj);
|
||||
virtual void Hess(CRowDouble &x,double &func,CRowDouble &grad,CMatrixDouble &hess,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Hess::CNDimensional_Hess(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Hess::~CNDimensional_Hess(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Hess::Hess(double &x[],double &func,double &grad[],
|
||||
CMatrixDouble &hess,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Hess::Hess(CRowDouble &x,double &func,CRowDouble &grad,
|
||||
CMatrixDouble &hess,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates vector function f(arg), stores result to fi |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_FVec
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_FVec(void);
|
||||
~CNDimensional_FVec(void);
|
||||
//--- virtual method
|
||||
virtual void FVec(double &x[],double &fi[],CObject &obj);
|
||||
virtual void FVec(CRowDouble &x,CRowDouble &fi,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_FVec::CNDimensional_FVec(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_FVec::~CNDimensional_FVec(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_FVec::FVec(double &x[],double &fi[],CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_FVec::FVec(CRowDouble &x,CRowDouble &fi,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates f[i] = fi(arg), jac[i,j] = df[i](arg)/d(arg[j]) |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_Jac
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_Jac(void);
|
||||
~CNDimensional_Jac(void);
|
||||
//--- virtual method
|
||||
virtual void Jac(double &x[],double &fi[],CMatrixDouble &jac,CObject &obj);
|
||||
virtual void Jac(CRowDouble &x,CRowDouble &fi,CMatrixDouble &jac,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Jac::CNDimensional_Jac(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Jac::~CNDimensional_Jac(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Jac::Jac(double &x[],double &fi[],CMatrixDouble &jac,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Jac::Jac(CRowDouble &x,CRowDouble &fi,CMatrixDouble &jac,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates f(p,q), stores result to func |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_PFunc
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_PFunc(void);
|
||||
~CNDimensional_PFunc(void);
|
||||
//--- virtual method
|
||||
virtual void PFunc(double &c[],double &x[],double &func,CObject &obj);
|
||||
virtual void PFunc(CRowDouble &c,CRowDouble &x,double &func,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_PFunc::CNDimensional_PFunc(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_PFunc::~CNDimensional_PFunc(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_PFunc::PFunc(double &c[],double &x[],double &func,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_PFunc::PFunc(CRowDouble &c,CRowDouble &x,double &func,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates func = f(p,q), grad[i] = df(p,q)/d(p[i]) |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_PGrad
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_PGrad(void);
|
||||
~CNDimensional_PGrad(void);
|
||||
//--- virtual method
|
||||
virtual void PGrad(double &c[],double &x[],double &func,double &grad[],CObject &obj);
|
||||
virtual void PGrad(CRowDouble &c,CRowDouble &x,double &func,CRowDouble &grad,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_PGrad::CNDimensional_PGrad(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_PGrad::~CNDimensional_PGrad(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_PGrad::PGrad(double &c[],double &x[],double &func,
|
||||
double &grad[],CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_PGrad::PGrad(CRowDouble &c,CRowDouble &x,double &func,
|
||||
CRowDouble &grad,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates func = f(p,q), grad[i] = df(p,q)/d(p[i]), |
|
||||
//| hess[i,j] = d2f(p,q)/(d(p[i])*d(p[j])) |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_PHess
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_PHess(void);
|
||||
~CNDimensional_PHess(void);
|
||||
//--- virtual method
|
||||
virtual void PHess(double &c[],double &x[],double &func,double &grad[],CMatrixDouble &hess,CObject &obj);
|
||||
virtual void PHess(CRowDouble &c,CRowDouble &x,double &func,CRowDouble &grad,CMatrixDouble &hess,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_PHess::CNDimensional_PHess(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_PHess::~CNDimensional_PHess(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_PHess::PHess(double &c[],double &x[],double &func,
|
||||
double &grad[],CMatrixDouble &hess,
|
||||
CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_PHess::PHess(CRowDouble &c,CRowDouble &x,double &func,
|
||||
CRowDouble &grad,CMatrixDouble &hess,
|
||||
CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Callbacks for ODE solvers: calculates dy/dx for given y[] and x |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_ODE_RP
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_ODE_RP(void);
|
||||
~CNDimensional_ODE_RP(void);
|
||||
//--- virtual method
|
||||
virtual void ODE_RP(double &y[],double x,double &dy[],CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_ODE_RP::CNDimensional_ODE_RP(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_ODE_RP::~CNDimensional_ODE_RP(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_ODE_RP::ODE_RP(double &y[],double x,double &dy[],
|
||||
CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Callbacks for integrators: calculates f(x) for given x |
|
||||
//| (additional parameters xminusa and bminusx contain x-a and b-x) |
|
||||
//+------------------------------------------------------------------+
|
||||
class CIntegrator1_Func
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CIntegrator1_Func(void);
|
||||
~CIntegrator1_Func(void);
|
||||
//--- virtual method
|
||||
virtual void Int_Func(double x,double xminusa,double bminusx,double &y,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CIntegrator1_Func::CIntegrator1_Func(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CIntegrator1_Func::~CIntegrator1_Func(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CIntegrator1_Func::Int_Func(double x,double xminusa,double bminusx,
|
||||
double &y,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Callbacks for progress reports: reports current position of |
|
||||
//| optimization algo |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNDimensional_Rep
|
||||
{
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CNDimensional_Rep(void);
|
||||
~CNDimensional_Rep(void);
|
||||
//--- virtual method
|
||||
virtual void Rep(double &arg[],double func,CObject &obj);
|
||||
virtual void Rep(CRowDouble &arg,double func,CObject &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Rep::CNDimensional_Rep(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CNDimensional_Rep::~CNDimensional_Rep(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Empty function body |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Rep::Rep(double &arg[],double func,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNDimensional_Rep::Rep(CRowDouble &arg,double func,CObject &obj)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,849 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| diffequations.mqh |
|
||||
//| Copyright 2003-2022 Sergey Bochkanov (ALGLIB project) |
|
||||
//| Copyright 2012-2023, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of ALGLIB library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Linear algebra (direct algorithms, EVD, SVD) |
|
||||
//| - Solving systems of linear and non-linear equations |
|
||||
//| - Interpolation |
|
||||
//| - Optimization |
|
||||
//| - FFT (Fast Fourier Transform) |
|
||||
//| - Numerical integration |
|
||||
//| - Linear and nonlinear least-squares fitting |
|
||||
//| - Ordinary differential equations |
|
||||
//| - Computation of special functions |
|
||||
//| - Descriptive statistics and hypothesis testing |
|
||||
//| - Data analysis - classification, regression |
|
||||
//| - Implementing linear algebra algorithms, interpolation, etc. |
|
||||
//| in high-precision arithmetic (using MPFR) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "matrix.mqh"
|
||||
#include "alglibinternal.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Auxiliary class for CODESolver |
|
||||
//+------------------------------------------------------------------+
|
||||
class CODESolverState
|
||||
{
|
||||
public:
|
||||
int m_n;
|
||||
int m_m;
|
||||
double m_xscale;
|
||||
double m_h;
|
||||
double m_eps;
|
||||
bool m_fraceps;
|
||||
int m_repterminationtype;
|
||||
int m_repnfev;
|
||||
int m_solvertype;
|
||||
bool m_needdy;
|
||||
double m_x;
|
||||
RCommState m_rstate;
|
||||
//--- arrays
|
||||
double m_yc[];
|
||||
double m_escale[];
|
||||
double m_xg[];
|
||||
double m_y[];
|
||||
double m_dy[];
|
||||
double m_yn[];
|
||||
double m_yns[];
|
||||
double m_rka[];
|
||||
double m_rkc[];
|
||||
double m_rkcs[];
|
||||
//--- matrices
|
||||
CMatrixDouble m_ytbl;
|
||||
CMatrixDouble m_rkb;
|
||||
CMatrixDouble m_rkk;
|
||||
|
||||
public:
|
||||
CODESolverState(void);
|
||||
~CODESolverState(void) {}
|
||||
|
||||
void Copy(CODESolverState &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CODESolverState::CODESolverState(void)
|
||||
{
|
||||
m_n=0;
|
||||
m_m=0;
|
||||
m_xscale=0;
|
||||
m_h=0;
|
||||
m_eps=0;
|
||||
m_fraceps=false;
|
||||
m_repterminationtype=0;
|
||||
m_repnfev=0;
|
||||
m_solvertype=0;
|
||||
m_needdy=false;
|
||||
m_x=0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolverState::Copy(CODESolverState &obj)
|
||||
{
|
||||
//--- copy variables
|
||||
m_n=obj.m_n;
|
||||
m_m=obj.m_m;
|
||||
m_xscale=obj.m_xscale;
|
||||
m_h=obj.m_h;
|
||||
m_eps=obj.m_eps;
|
||||
m_fraceps=obj.m_fraceps;
|
||||
m_repterminationtype=obj.m_repterminationtype;
|
||||
m_repnfev=obj.m_repnfev;
|
||||
m_solvertype=obj.m_solvertype;
|
||||
m_needdy=obj.m_needdy;
|
||||
m_x=obj.m_x;
|
||||
m_rstate.Copy(obj.m_rstate);
|
||||
//--- copy arrays
|
||||
ArrayCopy(m_yc,obj.m_yc);
|
||||
ArrayCopy(m_escale,obj.m_escale);
|
||||
ArrayCopy(m_xg,obj.m_xg);
|
||||
ArrayCopy(m_y,obj.m_y);
|
||||
ArrayCopy(m_dy,obj.m_dy);
|
||||
ArrayCopy(m_yn,obj.m_yn);
|
||||
ArrayCopy(m_yns,obj.m_yns);
|
||||
ArrayCopy(m_rka,obj.m_rka);
|
||||
ArrayCopy(m_rkc,obj.m_rkc);
|
||||
ArrayCopy(m_rkcs,obj.m_rkcs);
|
||||
//--- copy matrices
|
||||
m_ytbl=obj.m_ytbl;
|
||||
m_rkb=obj.m_rkb;
|
||||
m_rkk=obj.m_rkk;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| This class is a shell for class CODESolverState |
|
||||
//+------------------------------------------------------------------+
|
||||
class CODESolverStateShell
|
||||
{
|
||||
private:
|
||||
CODESolverState m_innerobj;
|
||||
|
||||
public:
|
||||
//--- constructors, destructor
|
||||
CODESolverStateShell(void) {}
|
||||
CODESolverStateShell(CODESolverState &obj) { m_innerobj.Copy(obj); }
|
||||
~CODESolverStateShell(void) {}
|
||||
//--- methods
|
||||
bool GetNeedDY(void);
|
||||
void SetNeedDY(const bool b);
|
||||
double GetX(void);
|
||||
void SetX(const double d);
|
||||
CODESolverState *GetInnerObj(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the value of the variable needdy |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CODESolverStateShell::GetNeedDY(void)
|
||||
{
|
||||
return(m_innerobj.m_needdy);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Changing the value of the variable needdy |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolverStateShell::SetNeedDY(const bool b)
|
||||
{
|
||||
m_innerobj.m_needdy=b;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the value of the variable x |
|
||||
//+------------------------------------------------------------------+
|
||||
double CODESolverStateShell::GetX(void)
|
||||
{
|
||||
return(m_innerobj.m_x);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Changing the value of the variable x |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolverStateShell::SetX(const double d)
|
||||
{
|
||||
m_innerobj.m_x=d;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return object of class |
|
||||
//+------------------------------------------------------------------+
|
||||
CODESolverState *CODESolverStateShell::GetInnerObj(void)
|
||||
{
|
||||
return(GetPointer(m_innerobj));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Auxiliary class for CODESolver |
|
||||
//+------------------------------------------------------------------+
|
||||
class CODESolverReport
|
||||
{
|
||||
public:
|
||||
//--- class variables
|
||||
int m_nfev;
|
||||
int m_terminationtype;
|
||||
//--- constructor, destructor
|
||||
CODESolverReport(void) { ZeroMemory(this); }
|
||||
~CODESolverReport(void) {}
|
||||
//--- copy
|
||||
void Copy(CODESolverReport &obj);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolverReport::Copy(CODESolverReport &obj)
|
||||
{
|
||||
//--- copy variables
|
||||
m_nfev=obj.m_nfev;
|
||||
m_terminationtype=obj.m_terminationtype;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| This class is a shell for class CODESolverReport |
|
||||
//+------------------------------------------------------------------+
|
||||
class CODESolverReportShell
|
||||
{
|
||||
private:
|
||||
CODESolverReport m_innerobj;
|
||||
|
||||
public:
|
||||
//--- constructor, destructor
|
||||
CODESolverReportShell(void) {}
|
||||
CODESolverReportShell(CODESolverReport &obj) { m_innerobj.Copy(obj); }
|
||||
~CODESolverReportShell(void) {}
|
||||
//--- methods
|
||||
int GetNFev(void);
|
||||
void SetNFev(const int i);
|
||||
int GetTerminationType(void);
|
||||
void SetTerminationType(const int i);
|
||||
CODESolverReport *GetInnerObj(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the value of the variable nfev |
|
||||
//+------------------------------------------------------------------+
|
||||
int CODESolverReportShell::GetNFev(void)
|
||||
{
|
||||
return(m_innerobj.m_nfev);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Changing the value of the variable nfev |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolverReportShell::SetNFev(const int i)
|
||||
{
|
||||
m_innerobj.m_nfev=i;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Returns the value of the variable terminationtype |
|
||||
//+------------------------------------------------------------------+
|
||||
int CODESolverReportShell::GetTerminationType(void)
|
||||
{
|
||||
return(m_innerobj.m_terminationtype);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Changing the value of the variable terminationtype |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolverReportShell::SetTerminationType(const int i)
|
||||
{
|
||||
m_innerobj.m_terminationtype=i;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Return object of class |
|
||||
//+------------------------------------------------------------------+
|
||||
CODESolverReport *CODESolverReportShell::GetInnerObj(void)
|
||||
{
|
||||
return(GetPointer(m_innerobj));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Solution of ordinary differential equations |
|
||||
//+------------------------------------------------------------------+
|
||||
class CODESolver
|
||||
{
|
||||
public:
|
||||
//--- class constants
|
||||
static const double m_odesolvermaxgrow;
|
||||
static const double m_odesolvermaxshrink;
|
||||
//--- public methods
|
||||
static void ODESolverRKCK(double &y[],const int n,double &x[],const int m,const double eps,const double h,CODESolverState &state);
|
||||
static void ODESolverResults(CODESolverState &state,int &m,double &xtbl[],CMatrixDouble &ytbl,CODESolverReport &rep);
|
||||
static bool ODESolverIteration(CODESolverState &state);
|
||||
|
||||
private:
|
||||
//--- private method
|
||||
static void ODESolverInit(int solvertype,double &y[],const int n,double &x[],const int m,const double eps,double h,CODESolverState &state);
|
||||
//--- auxiliary functions for ODESolverIteration
|
||||
static void Func_lbl_rcomm(CODESolverState &state,int n,int m,int i,int j,int k,int klimit,bool gridpoint,double xc,double v,double h,double h2,double err,double maxgrowpow);
|
||||
static bool Func_lbl_6(CODESolverState &state,int &n,int &m,int &i,int &j,int &k,int &klimit,bool &gridpoint,double &xc,double &v,double &h,double &h2,double &err,double &maxgrowpow);
|
||||
static bool Func_lbl_8(CODESolverState &state,int &n,int &m,int &i,int &j,int &k,int &klimit,bool &gridpoint,double &xc,double &v,double &h,double &h2,double &err,double &maxgrowpow);
|
||||
static bool Func_lbl_10(CODESolverState &state,int &n,int &m,int &i,int &j,int &k,int &klimit,bool &gridpoint,double &xc,double &v,double &h,double &h2,double &err,double &maxgrowpow);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize constants |
|
||||
//+------------------------------------------------------------------+
|
||||
const double CODESolver::m_odesolvermaxgrow=3.0;
|
||||
const double CODESolver::m_odesolvermaxshrink=10.0;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cash-Karp adaptive ODE solver. |
|
||||
//| This subroutine solves ODE Y'=f(Y,x) with initial conditions |
|
||||
//| Y(xs)=Ys (here Y may be single variable or vector of N variables)|
|
||||
//| INPUT PARAMETERS: |
|
||||
//| Y - initial conditions, array[0..N-1]. |
|
||||
//| contains values of Y[] at X[0] |
|
||||
//| N - system size |
|
||||
//| X - points at which Y should be tabulated, |
|
||||
//| array[0..M-1] integrations starts at X[0], ends |
|
||||
//| at X[M-1], intermediate values at X[i] are |
|
||||
//| returned too. |
|
||||
//| SHOULD BE ORDERED BY ASCENDING OR BY DESCENDING!!|
|
||||
//| M - number of intermediate points + first point + |
|
||||
//| last point: |
|
||||
//| * M>2 means that you need both Y(X[M-1]) and M-2 |
|
||||
//| values at intermediate points |
|
||||
//| * M=2 means that you want just to integrate from |
|
||||
//| X[0] to X[1] and don't interested in |
|
||||
//| intermediate values. |
|
||||
//| * M=1 means that you don't want to integrate :) |
|
||||
//| it is degenerate case, but it will be handled |
|
||||
//| correctly. |
|
||||
//| * M<1 means error |
|
||||
//| Eps - tolerance (absolute/relative error on each step |
|
||||
//| will be less than Eps). When passing: |
|
||||
//| * Eps>0, it means desired ABSOLUTE error |
|
||||
//| * Eps<0, it means desired RELATIVE error. |
|
||||
//| Relative errors are calculated with respect to |
|
||||
//| maximum values of Y seen so far. Be careful to |
|
||||
//| use this criterion when starting from Y[] that |
|
||||
//| are close to zero. |
|
||||
//| H - initial step lenth, it will be adjusted |
|
||||
//| automatically after the first step. If H=0, step |
|
||||
//| will be selected automatically (usualy it will |
|
||||
//| be equal to 0.001 of min(x[i]-x[j])). |
|
||||
//| OUTPUT PARAMETERS |
|
||||
//| State - structure which stores algorithm state between |
|
||||
//| subsequent calls of OdeSolverIteration. Used |
|
||||
//| for reverse communication. This structure should |
|
||||
//| be passed to the OdeSolverIteration subroutine. |
|
||||
//| SEE ALSO |
|
||||
//| AutoGKSmoothW, AutoGKSingular, AutoGKIteration, AutoGKResults|
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolver::ODESolverRKCK(double &y[],const int n,double &x[],
|
||||
const int m,const double eps,
|
||||
const double h,CODESolverState &state)
|
||||
{
|
||||
//--- check
|
||||
if(!CAp::Assert(n>=1,"ODESolverRKCK: N<1!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(m>=1,"ODESolverRKCK: M<1!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(CAp::Len(y)>=n,"ODESolverRKCK: Length(Y)<N!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(CAp::Len(x)>=m,"ODESolverRKCK: Length(X)<M!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(CApServ::IsFiniteVector(y,n),"ODESolverRKCK: Y contains infinite or NaN values!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(CApServ::IsFiniteVector(x,m),"ODESolverRKCK: Y contains infinite or NaN values!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(CMath::IsFinite(eps),"ODESolverRKCK: Eps is not finite!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(eps!=0.0,"ODESolverRKCK: Eps is zero!"))
|
||||
return;
|
||||
//--- check
|
||||
if(!CAp::Assert(CMath::IsFinite(h),"ODESolverRKCK: H is not finite!"))
|
||||
return;
|
||||
//--- function call
|
||||
ODESolverInit(0,y,n,x,m,eps,h,state);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| ODE solver results |
|
||||
//| Called after OdeSolverIteration returned False. |
|
||||
//| INPUT PARAMETERS: |
|
||||
//| State - algorithm state (used by OdeSolverIteration). |
|
||||
//| OUTPUT PARAMETERS: |
|
||||
//| M - number of tabulated values, M>=1 |
|
||||
//| XTbl - array[0..M-1], values of X |
|
||||
//| YTbl - array[0..M-1,0..N-1], values of Y in X[i] |
|
||||
//| Rep - solver report: |
|
||||
//| * Rep.TerminationType completetion code: |
|
||||
//| * -2 X is not ordered by |
|
||||
//| ascending/descending or there are |
|
||||
//| non-distinct X[], i.e. X[i]=X[i+1] |
|
||||
//| * -1 incorrect parameters were specified |
|
||||
//| * 1 task has been solved |
|
||||
//| * Rep.NFEV contains number of function |
|
||||
//| calculations |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolver::ODESolverResults(CODESolverState &state,int &m,
|
||||
double &xtbl[],CMatrixDouble &ytbl,
|
||||
CODESolverReport &rep)
|
||||
{
|
||||
//--- create variables
|
||||
double v=0;
|
||||
int i=0;
|
||||
int i_=0;
|
||||
//--- initialization
|
||||
m=0;
|
||||
rep.m_terminationtype=state.m_repterminationtype;
|
||||
//--- check
|
||||
if(rep.m_terminationtype>0)
|
||||
{
|
||||
//--- change values
|
||||
m=state.m_m;
|
||||
rep.m_nfev=state.m_repnfev;
|
||||
//--- allocation
|
||||
ArrayResize(xtbl,state.m_m);
|
||||
v=state.m_xscale;
|
||||
//--- calculation
|
||||
for(i_=0; i_<=state.m_m-1; i_++)
|
||||
xtbl[i_]=v*state.m_xg[i_];
|
||||
//--- allocation
|
||||
ytbl.Resize(state.m_m,state.m_n);
|
||||
for(i=0; i<=state.m_m-1; i++)
|
||||
{
|
||||
for(i_=0; i_<=state.m_n-1; i_++)
|
||||
ytbl.Set(i,i_,state.m_ytbl[i][i_]);
|
||||
}
|
||||
}
|
||||
else
|
||||
rep.m_nfev=0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Internal initialization subroutine |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolver::ODESolverInit(int solvertype,double &y[],const int n,
|
||||
double &x[],const int m,const double eps,
|
||||
double h,CODESolverState &state)
|
||||
{
|
||||
//--- create variables
|
||||
int i=0;
|
||||
double v=0;
|
||||
int i_=0;
|
||||
//--- Prepare RComm
|
||||
state.m_rstate.ia.Resize(6);
|
||||
ArrayResizeAL(state.m_rstate.ba,1);
|
||||
state.m_rstate.ra.Resize(6);
|
||||
state.m_rstate.stage=-1;
|
||||
state.m_needdy=false;
|
||||
//--- check parameters.
|
||||
if((n<=0 || m<1) || eps==0.0)
|
||||
{
|
||||
state.m_repterminationtype=-1;
|
||||
return;
|
||||
}
|
||||
//--- check
|
||||
if(h<0.0)
|
||||
h=-h;
|
||||
//--- quick exit if necessary.
|
||||
//--- after this block we assume that M>1
|
||||
if(m==1)
|
||||
{
|
||||
//--- change values
|
||||
state.m_repnfev=0;
|
||||
state.m_repterminationtype=1;
|
||||
state.m_ytbl.Resize(1,n);
|
||||
for(i_=0; i_<=n-1; i_++)
|
||||
state.m_ytbl.Set(0,i_,y[i_]);
|
||||
//--- allocation
|
||||
ArrayResize(state.m_xg,m);
|
||||
for(i_=0; i_<=m-1; i_++)
|
||||
state.m_xg[i_]=x[i_];
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- check again: correct order of X[]
|
||||
if(x[1]==x[0])
|
||||
{
|
||||
state.m_repterminationtype=-2;
|
||||
return;
|
||||
}
|
||||
for(i=1; i<=m-1; i++)
|
||||
{
|
||||
//--- check
|
||||
if((x[1]>x[0] && x[i]<=x[i-1]) || (x[1]<x[0] && x[i]>=x[i-1]))
|
||||
{
|
||||
state.m_repterminationtype=-2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//--- auto-select H if necessary
|
||||
if(h==0.0)
|
||||
{
|
||||
v=MathAbs(x[1]-x[0]);
|
||||
for(i=2; i<=m-1; i++)
|
||||
v=MathMin(v,MathAbs(x[i]-x[i-1]));
|
||||
h=0.001*v;
|
||||
}
|
||||
//--- store parameters
|
||||
state.m_n=n;
|
||||
state.m_m=m;
|
||||
state.m_h=h;
|
||||
state.m_eps=MathAbs(eps);
|
||||
state.m_fraceps=eps<0.0;
|
||||
//--- allocation
|
||||
ArrayResize(state.m_xg,m);
|
||||
for(i_=0; i_<=m-1; i_++)
|
||||
state.m_xg[i_]=x[i_];
|
||||
//--- check
|
||||
if(x[1]>x[0])
|
||||
state.m_xscale=1;
|
||||
else
|
||||
{
|
||||
state.m_xscale=-1;
|
||||
for(i_=0; i_<=m-1; i_++)
|
||||
state.m_xg[i_]=-1*state.m_xg[i_];
|
||||
}
|
||||
//--- allocation
|
||||
ArrayResize(state.m_yc,n);
|
||||
for(i_=0; i_<=n-1; i_++)
|
||||
state.m_yc[i_]=y[i_];
|
||||
//--- change values
|
||||
state.m_solvertype=solvertype;
|
||||
state.m_repterminationtype=0;
|
||||
//--- Allocate arrays
|
||||
ArrayResize(state.m_y,n);
|
||||
ArrayResize(state.m_dy,n);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Iterative method |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CODESolver::ODESolverIteration(CODESolverState &state)
|
||||
{
|
||||
//--- create variables
|
||||
int n=0;
|
||||
int m=0;
|
||||
int i=0;
|
||||
int j=0;
|
||||
int k=0;
|
||||
double xc=0;
|
||||
double v=0;
|
||||
double h=0;
|
||||
double h2=0;
|
||||
bool gridpoint;
|
||||
double err=0;
|
||||
double maxgrowpow=0;
|
||||
int klimit=0;
|
||||
int i_=0;
|
||||
//--- This code initializes locals by:
|
||||
//--- * random values determined during code
|
||||
//--- generation - on first subroutine call
|
||||
//--- * values from previous call - on subsequent calls
|
||||
if(state.m_rstate.stage>=0)
|
||||
{
|
||||
//--- initialization
|
||||
n=state.m_rstate.ia[0];
|
||||
m=state.m_rstate.ia[1];
|
||||
i=state.m_rstate.ia[2];
|
||||
j=state.m_rstate.ia[3];
|
||||
k=state.m_rstate.ia[4];
|
||||
klimit=state.m_rstate.ia[5];
|
||||
gridpoint=state.m_rstate.ba[0];
|
||||
xc=state.m_rstate.ra[0];
|
||||
v=state.m_rstate.ra[1];
|
||||
h=state.m_rstate.ra[2];
|
||||
h2=state.m_rstate.ra[3];
|
||||
err=state.m_rstate.ra[4];
|
||||
maxgrowpow=state.m_rstate.ra[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- initialization
|
||||
n=-983;
|
||||
m=-989;
|
||||
i=-834;
|
||||
j=900;
|
||||
k=-287;
|
||||
klimit=364;
|
||||
gridpoint=false;
|
||||
xc=-338;
|
||||
v=-686;
|
||||
h=912;
|
||||
h2=585;
|
||||
err=497;
|
||||
maxgrowpow=-271;
|
||||
}
|
||||
//--- check
|
||||
if(state.m_rstate.stage==0)
|
||||
{
|
||||
//--- change values
|
||||
state.m_needdy=false;
|
||||
state.m_repnfev=state.m_repnfev+1;
|
||||
v=h*state.m_xscale;
|
||||
for(i_=0; i_<=n-1; i_++)
|
||||
state.m_rkk.Set(k,i_,v*state.m_dy[i_]);
|
||||
//--- update YN/YNS
|
||||
v=state.m_rkc[k];
|
||||
for(i_=0; i_<=n-1; i_++)
|
||||
state.m_yn[i_]=state.m_yn[i_]+v*state.m_rkk[k][i_];
|
||||
v=state.m_rkcs[k];
|
||||
for(i_=0; i_<=n-1; i_++)
|
||||
state.m_yns[i_]=state.m_yns[i_]+v*state.m_rkk[k][i_];
|
||||
k=k+1;
|
||||
return(Func_lbl_8(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
}
|
||||
//--- Routine body
|
||||
//--- prepare
|
||||
if(state.m_repterminationtype!=0)
|
||||
return(false);
|
||||
//--- change values
|
||||
n=state.m_n;
|
||||
m=state.m_m;
|
||||
h=state.m_h;
|
||||
maxgrowpow=MathPow(m_odesolvermaxgrow,5);
|
||||
state.m_repnfev=0;
|
||||
//--- some preliminary checks for internal errors
|
||||
//--- after this we assume that H>0 and M>1
|
||||
if(!CAp::Assert(state.m_h>0.0,"ODESolver: internal error"))
|
||||
return(false);
|
||||
//--- check
|
||||
if(!CAp::Assert(m>1,"ODESolverIteration: internal error"))
|
||||
return(false);
|
||||
//--- choose solver
|
||||
if(state.m_solvertype!=0)
|
||||
return(false);
|
||||
//--- Cask-Karp solver
|
||||
//--- Prepare coefficients table.
|
||||
//--- Check it for errors
|
||||
ArrayResize(state.m_rka,6);
|
||||
//--- calculation
|
||||
state.m_rka[0]=0;
|
||||
state.m_rka[1]=1.0/5.0;
|
||||
state.m_rka[2]=3.0/10.0;
|
||||
state.m_rka[3]=3.0/5.0;
|
||||
state.m_rka[4]=1;
|
||||
state.m_rka[5]=7.0/8.0;
|
||||
state.m_rkb.Resize(6,5);
|
||||
state.m_rkb.Set(1,0,1.0/5.0);
|
||||
state.m_rkb.Set(2,0,3.0/40.0);
|
||||
state.m_rkb.Set(2,1,9.0/40.0);
|
||||
state.m_rkb.Set(3,0,3.0/10.0);
|
||||
state.m_rkb.Set(3,1,-(9.0/10.0));
|
||||
state.m_rkb.Set(3,2,6.0/5.0);
|
||||
state.m_rkb.Set(4,0,-(11.0/54.0));
|
||||
state.m_rkb.Set(4,1,5.0/2.0);
|
||||
state.m_rkb.Set(4,2,-(70.0/27.0));
|
||||
state.m_rkb.Set(4,3,35.0/27.0);
|
||||
state.m_rkb.Set(5,0,1631.0/55296.0);
|
||||
state.m_rkb.Set(5,1,175.0/512.0);
|
||||
state.m_rkb.Set(5,2,575.0/13824.0);
|
||||
state.m_rkb.Set(5,3,44275.0/110592.0);
|
||||
state.m_rkb.Set(5,4,253.0/4096.0);
|
||||
//--- allocation
|
||||
ArrayResize(state.m_rkc,6);
|
||||
//--- calculation
|
||||
state.m_rkc[0]=37.0/378.0;
|
||||
state.m_rkc[1]=0;
|
||||
state.m_rkc[2]=250.0/621.0;
|
||||
state.m_rkc[3]=125.0/594.0;
|
||||
state.m_rkc[4]=0;
|
||||
state.m_rkc[5]=512.0/1771.0;
|
||||
//--- allocation
|
||||
ArrayResize(state.m_rkcs,6);
|
||||
//--- calculation
|
||||
state.m_rkcs[0]=2825.0/27648.0;
|
||||
state.m_rkcs[1]=0;
|
||||
state.m_rkcs[2]=18575.0/48384.0;
|
||||
state.m_rkcs[3]=13525.0/55296.0;
|
||||
state.m_rkcs[4]=277.0/14336.0;
|
||||
state.m_rkcs[5]=1.0/4.0;
|
||||
state.m_rkk.Resize(6,n);
|
||||
//--- Main cycle consists of two iterations:
|
||||
//--- * outer where we travel from X[i-1] to X[i]
|
||||
//--- * inner where we travel inside [X[i-1],X[i]]
|
||||
state.m_ytbl.Resize(m,n);
|
||||
ArrayResize(state.m_escale,n);
|
||||
ArrayResize(state.m_yn,n);
|
||||
ArrayResize(state.m_yns,n);
|
||||
//--- change value
|
||||
xc=state.m_xg[0];
|
||||
for(i_=0; i_<=n-1; i_++)
|
||||
state.m_ytbl.Set(0,i_,state.m_yc[i_]);
|
||||
for(j=0; j<=n-1; j++)
|
||||
state.m_escale[j]=0;
|
||||
i=1;
|
||||
//--- check
|
||||
if(i>m-1)
|
||||
{
|
||||
state.m_repterminationtype=1;
|
||||
//--- return result
|
||||
return(false);
|
||||
}
|
||||
//--- begin inner iteration
|
||||
return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Auxiliary function for ODESolverIteration. Is a product to get |
|
||||
//| rid of the operator unconditional jump goto |
|
||||
//+------------------------------------------------------------------+
|
||||
void CODESolver::Func_lbl_rcomm(CODESolverState &state,int n,int m,
|
||||
int i,int j,int k,int klimit,
|
||||
bool gridpoint,double xc,double v,
|
||||
double h,double h2,double err,
|
||||
double maxgrowpow)
|
||||
{
|
||||
//--- save
|
||||
state.m_rstate.ia.Set(0,n);
|
||||
state.m_rstate.ia.Set(1,m);
|
||||
state.m_rstate.ia.Set(2,i);
|
||||
state.m_rstate.ia.Set(3,j);
|
||||
state.m_rstate.ia.Set(4,k);
|
||||
state.m_rstate.ia.Set(5,klimit);
|
||||
state.m_rstate.ba[0]= gridpoint;
|
||||
state.m_rstate.ra.Set(0,xc);
|
||||
state.m_rstate.ra.Set(1,v);
|
||||
state.m_rstate.ra.Set(2,h);
|
||||
state.m_rstate.ra.Set(3,h2);
|
||||
state.m_rstate.ra.Set(4,err);
|
||||
state.m_rstate.ra.Set(5,maxgrowpow);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Auxiliary function for ODESolverIteration. Is a product to get |
|
||||
//| rid of the operator unconditional jump goto |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CODESolver::Func_lbl_6(CODESolverState &state,int &n,int &m,
|
||||
int &i,int &j,int &k,int &klimit,
|
||||
bool &gridpoint,double &xc,double &v,
|
||||
double &h,double &h2,double &err,
|
||||
double &maxgrowpow)
|
||||
{
|
||||
//--- truncate step if needed (beyond right boundary).
|
||||
//--- determine should we store X or not
|
||||
if(xc+h>=state.m_xg[i])
|
||||
{
|
||||
h=state.m_xg[i]-xc;
|
||||
gridpoint=true;
|
||||
}
|
||||
else
|
||||
gridpoint=false;
|
||||
//--- Update error scale maximums
|
||||
//--- These maximums are initialized by zeros,
|
||||
//--- then updated every iterations.
|
||||
for(j=0; j<=n-1; j++)
|
||||
state.m_escale[j]=MathMax(state.m_escale[j],MathAbs(state.m_yc[j]));
|
||||
//--- make one step:
|
||||
//--- 1. calculate all info needed to do step
|
||||
//--- 2. update errors scale maximums using values/derivatives
|
||||
//--- obtained during (1)
|
||||
//--- Take into account that we use scaling of X to reduce task
|
||||
//--- to the form where x[0] < x[1] < ... < x[n-1]. So X is
|
||||
//--- replaced by x=xscale*t,and dy/dx=f(y,x) is replaced
|
||||
//--- by dy/dt=xscale*f(y,xscale*t).
|
||||
for(int i_=0; i_<=n-1; i_++)
|
||||
state.m_yn[i_]=state.m_yc[i_];
|
||||
for(int i_=0; i_<=n-1; i_++)
|
||||
state.m_yns[i_]=state.m_yc[i_];
|
||||
k=0;
|
||||
//--- function call, return result
|
||||
return(Func_lbl_8(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Auxiliary function for ODESolverIteration. Is a product to get |
|
||||
//| rid of the operator unconditional jump goto |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CODESolver::Func_lbl_8(CODESolverState &state,int &n,int &m,
|
||||
int &i,int &j,int &k,int &klimit,
|
||||
bool &gridpoint,double &xc,double &v,
|
||||
double &h,double &h2,double &err,
|
||||
double &maxgrowpow)
|
||||
{
|
||||
//--- check
|
||||
if(k>5)
|
||||
return(Func_lbl_10(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
//--- prepare data for the next update of YN/YNS
|
||||
state.m_x=state.m_xscale*(xc+state.m_rka[k]*h);
|
||||
for(int i_=0; i_<=n-1; i_++)
|
||||
state.m_y[i_]=state.m_yc[i_];
|
||||
//--- calculation
|
||||
for(j=0; j<=k-1; j++)
|
||||
{
|
||||
v=state.m_rkb[k][j];
|
||||
for(int i_=0; i_<=n-1; i_++)
|
||||
state.m_y[i_]=state.m_y[i_]+v*state.m_rkk[j][i_];
|
||||
}
|
||||
state.m_needdy=true;
|
||||
state.m_rstate.stage=0;
|
||||
//--- Saving state
|
||||
Func_lbl_rcomm(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow);
|
||||
//--- return result
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Auxiliary function for ODESolverIteration. Is a product to get |
|
||||
//| rid of the operator unconditional jump goto |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CODESolver::Func_lbl_10(CODESolverState &state,int &n,int &m,
|
||||
int &i,int &j,int &k,int &klimit,
|
||||
bool &gridpoint,double &xc,double &v,
|
||||
double &h,double &h2,double &err,
|
||||
double &maxgrowpow)
|
||||
{
|
||||
//--- estimate error
|
||||
err=0;
|
||||
for(j=0; j<=n-1; j++)
|
||||
{
|
||||
//--- check
|
||||
if(!state.m_fraceps)
|
||||
{
|
||||
//--- absolute error is estimated
|
||||
err=MathMax(err,MathAbs(state.m_yn[j]-state.m_yns[j]));
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- Relative error is estimated
|
||||
v=state.m_escale[j];
|
||||
//--- check
|
||||
if(v==0.0)
|
||||
v=1;
|
||||
err=MathMax(err,MathAbs(state.m_yn[j]-state.m_yns[j])/v);
|
||||
}
|
||||
}
|
||||
//--- calculate new step,restart if necessary
|
||||
if(maxgrowpow*err<=state.m_eps)
|
||||
h2=m_odesolvermaxgrow*h;
|
||||
else
|
||||
h2=h*MathPow(state.m_eps/err,0.2);
|
||||
//--- check
|
||||
if(h2<h/m_odesolvermaxshrink)
|
||||
h2=h/m_odesolvermaxshrink;
|
||||
//--- check
|
||||
if(err>state.m_eps)
|
||||
{
|
||||
h=h2;
|
||||
//--- begin inner iteration
|
||||
return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
}
|
||||
//--- advance position
|
||||
xc=xc+h;
|
||||
for(int i_=0; i_<=n-1; i_++)
|
||||
state.m_yc[i_]=state.m_yn[i_];
|
||||
//--- update H
|
||||
h=h2;
|
||||
//--- break on grid point
|
||||
if(gridpoint)
|
||||
{
|
||||
//--- save result
|
||||
for(int i_=0; i_<=n-1; i_++)
|
||||
state.m_ytbl.Set(i,i_,state.m_yc[i_]);
|
||||
i=i+1;
|
||||
//--- check
|
||||
if(i>m-1)
|
||||
{
|
||||
state.m_repterminationtype=1;
|
||||
return(false);
|
||||
}
|
||||
//--- begin inner iteration
|
||||
return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
}
|
||||
//--- begin inner iteration
|
||||
return(Func_lbl_6(state,n,m,i,j,k,klimit,gridpoint,xc,v,h,h2,err,maxgrowpow));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+37629
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,197 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| dictionary.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Object.mqh>
|
||||
#include <Arrays\List.mqh>
|
||||
#include "RuleParser.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gets the value associated with the specified key in the CList |
|
||||
//| Where key - string, value - CObject |
|
||||
//+------------------------------------------------------------------+
|
||||
bool TryGetValue(CList *list,string key,CObject *&value)
|
||||
{
|
||||
for(int i=0; i<list.Total(); i++)
|
||||
{
|
||||
CDictionary_String_Obj *pair=list.GetNodeAtIndex(i);
|
||||
if(pair.Key()==key)
|
||||
{
|
||||
value=pair.Value();
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Removes a range of elements from a list of CList |
|
||||
//+------------------------------------------------------------------+
|
||||
void RemoveRange(CArrayObj &list,const int index,const int count)
|
||||
{
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
list.Delete(index);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| It creates a shallow copy of a range of elements |
|
||||
//| from the original list of CList |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayObj *GetRange(CArrayObj *list,const int index,const int count)
|
||||
{
|
||||
CArrayObj *new_list=new CArrayObj;
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
new_list.Add(list.At(i+index));
|
||||
}
|
||||
return (new_list);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dictionary: Object - Object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDictionary_Obj_Obj : public CObject
|
||||
{
|
||||
private:
|
||||
CObject *m_key;
|
||||
CObject *m_value;
|
||||
|
||||
public:
|
||||
CDictionary_Obj_Obj(void);
|
||||
~CDictionary_Obj_Obj(void);
|
||||
//--- methods gets or sets the value
|
||||
CObject *Key() { return(m_key); }
|
||||
void Key(CObject *key) { m_key=key; }
|
||||
//--- methods gets or sets the key
|
||||
CObject *Value() { return(m_value); }
|
||||
void Value(CObject *value) { m_value=value; }
|
||||
//--- method sets the value and key
|
||||
void SetAll(CObject *key,CObject *value);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CDictionary_Obj_Obj::CDictionary_Obj_Obj(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDictionary_Obj_Obj::~CDictionary_Obj_Obj()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets the value and key |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDictionary_Obj_Obj::SetAll(CObject *key,CObject *value)
|
||||
{
|
||||
m_key=key;
|
||||
m_value=value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dictionary: String - Object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDictionary_String_Obj : public CObject
|
||||
{
|
||||
private:
|
||||
string m_key;
|
||||
CObject *m_value;
|
||||
|
||||
public:
|
||||
CDictionary_String_Obj(void);
|
||||
~CDictionary_String_Obj(void);
|
||||
//--- methods gets or sets the value
|
||||
string Key() { return(m_key); }
|
||||
void Key(const string key) { m_key=key; }
|
||||
//--- methods gets or sets the key
|
||||
CObject *Value() { return(m_value); }
|
||||
void Value(CObject *value) { m_value=value; }
|
||||
//--- method sets the value and key
|
||||
void SetAll(const string key,CObject *value);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CDictionary_String_Obj::CDictionary_String_Obj(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDictionary_String_Obj::~CDictionary_String_Obj()
|
||||
{
|
||||
if(CheckPointer(m_value)==POINTER_DYNAMIC)
|
||||
delete m_value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets the value and key |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDictionary_String_Obj::SetAll(const string key,CObject *value)
|
||||
{
|
||||
m_key=key;
|
||||
m_value=value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dictionary: Object - Double |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDictionary_Obj_Double : public CObject
|
||||
{
|
||||
private:
|
||||
CObject *m_key;
|
||||
double m_value;
|
||||
|
||||
public:
|
||||
CDictionary_Obj_Double(void);
|
||||
~CDictionary_Obj_Double(void);
|
||||
//--- methods gets or sets the value
|
||||
CObject *Key() { return(m_key); }
|
||||
void Key(CObject *key) { m_key=key; }
|
||||
//--- methods gets or sets the key
|
||||
double Value() { return(m_value); }
|
||||
void Value(const double value) { m_value=value; }
|
||||
//--- method sets the value and key
|
||||
void SetAll(CObject *key,const double value);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CDictionary_Obj_Double::CDictionary_Obj_Double(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDictionary_Obj_Double::~CDictionary_Obj_Double()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets the value and key |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDictionary_Obj_Double::SetAll(CObject *key,const double value)
|
||||
{
|
||||
m_key=key;
|
||||
m_value=value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,371 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| fuzzyrule.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include "FuzzyVariable.mqh"
|
||||
#include "InferenceMethod.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Creating fuzzy rules |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| And/Or operator type |
|
||||
//+------------------------------------------------------------------+
|
||||
enum OperatorType
|
||||
{
|
||||
And, // And operator
|
||||
Or // Or operator
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hedge modifiers |
|
||||
//+------------------------------------------------------------------+
|
||||
enum HedgeType
|
||||
{
|
||||
None, // None
|
||||
Slightly, // Cube root
|
||||
Somewhat, // Square root
|
||||
Very, // Square
|
||||
Extremely // Cube
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class of CConditions used in the 'if' expression |
|
||||
//+------------------------------------------------------------------+
|
||||
class ICondition : public CObject
|
||||
{
|
||||
public:
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_ICondition); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Single condition |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSingleCondition : public ICondition
|
||||
{
|
||||
private:
|
||||
INamedVariable *m_var; // Type of variable
|
||||
INamedValue *m_term; // Type of value
|
||||
bool m_not; // Is MF inverted
|
||||
|
||||
public:
|
||||
CSingleCondition(void);
|
||||
CSingleCondition(INamedVariable *var,INamedValue *term);
|
||||
CSingleCondition(INamedVariable *var,INamedValue *term,bool not);
|
||||
~CSingleCondition(void);
|
||||
//--- methods gets or sets the varriable
|
||||
INamedVariable *Var(void) { return(m_var); }
|
||||
void Var(INamedVariable *value) { m_var=value; }
|
||||
//--- methods gets or sets mark "Is MF inverted"
|
||||
bool Not(void) { return(m_not); }
|
||||
void Not(bool not) { m_not=not; }
|
||||
//--- methods gets or sets term in expression
|
||||
INamedValue *Term(void) { return(m_term); }
|
||||
void Term(INamedValue *value) { m_term=value; }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_SingleCondition); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CSingleCondition::CSingleCondition(void)
|
||||
{
|
||||
m_var = NULL;
|
||||
m_not = false;
|
||||
m_term=NULL;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| First constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CSingleCondition::CSingleCondition(INamedVariable *var,INamedValue *term)
|
||||
{
|
||||
m_var=var;
|
||||
m_term=term;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Second constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CSingleCondition::CSingleCondition(INamedVariable *var,INamedValue *term,bool not)
|
||||
{
|
||||
m_var=var;
|
||||
m_term=term;
|
||||
m_not=not;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSingleCondition::~CSingleCondition(void)
|
||||
{
|
||||
if(CheckPointer(m_var)==POINTER_DYNAMIC)
|
||||
delete m_var;
|
||||
if(CheckPointer(m_term)==POINTER_DYNAMIC)
|
||||
delete m_term;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Condition of fuzzy rule for the both Mamdani and Sugeno systems |
|
||||
//+------------------------------------------------------------------+
|
||||
class CFuzzyCondition : public CSingleCondition
|
||||
{
|
||||
private:
|
||||
HedgeType m_hedge; // hedge type
|
||||
|
||||
public:
|
||||
CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not);
|
||||
CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge);
|
||||
CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term);
|
||||
~CFuzzyCondition(void);
|
||||
//--- methods gets or sets the hedge type
|
||||
HedgeType Hedge(void) { return (m_hedge); }
|
||||
void Hedge(HedgeType value) { m_hedge=value; }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_FuzzyCondition); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| First constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not)
|
||||
{
|
||||
CSingleCondition::Var(var);
|
||||
CSingleCondition::Term(term);
|
||||
CSingleCondition::Not(not);
|
||||
m_hedge=None;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Second constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge)
|
||||
{
|
||||
CSingleCondition::Var(var);
|
||||
CSingleCondition::Term(term);
|
||||
CSingleCondition::Not(not);
|
||||
m_hedge=hedge;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Thrid constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition::CFuzzyCondition(CFuzzyVariable *var,CFuzzyTerm *term)
|
||||
|
||||
{
|
||||
CSingleCondition::Var(var);
|
||||
CSingleCondition::Term(term);
|
||||
CSingleCondition::Not(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition::~CFuzzyCondition(void)
|
||||
{
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Several CConditions linked by or/and operators |
|
||||
//+------------------------------------------------------------------+
|
||||
class CConditions : public ICondition
|
||||
{
|
||||
private:
|
||||
bool m_not; // Default : false
|
||||
OperatorType m_op; // Type of operator. Default : And
|
||||
CList *m_conditions; // List of CConditions
|
||||
|
||||
public:
|
||||
CConditions(void);
|
||||
~CConditions(void);
|
||||
//--- methods gets or sets the mark "Is MF inverted"
|
||||
bool Not(void) { return(m_not); }
|
||||
void Not(bool value) { m_not=value; }
|
||||
//--- methods gets or sets operator that links expressions (and/or)
|
||||
OperatorType Op(void) { return (m_op); }
|
||||
void Op(OperatorType value) { m_op=value; }
|
||||
//--- method gets the list of CConditions (single or multiples)
|
||||
CList *ConditionsList(void) { return(m_conditions); }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnCondition type) { return(type==TYPE_CLASS_Conditions); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CConditions::CConditions(void)
|
||||
{
|
||||
m_not=false;
|
||||
m_op = And;
|
||||
m_conditions=new CList;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CConditions::~CConditions(void)
|
||||
{
|
||||
delete m_conditions;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class used by rule parser |
|
||||
//+------------------------------------------------------------------+
|
||||
class IParsableRule : public CObject
|
||||
{
|
||||
public:
|
||||
//--- methods gets or sets the condition (IF) part of the rule
|
||||
virtual CConditions *Condition(void) { return(NULL); }
|
||||
virtual void Condition(CConditions *value) { }
|
||||
//--- methods gets or sets the conclusion (THEN) part of the rule
|
||||
virtual CSingleCondition *Conclusion(void) { return(NULL); }
|
||||
virtual void Conclusion(CSingleCondition *value) { }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_IParsableRule); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implements common functionality of fuzzy rules |
|
||||
//+------------------------------------------------------------------+
|
||||
class CGenericFuzzyRule : public IParsableRule
|
||||
{
|
||||
private:
|
||||
CConditions *m_generic_condition; // Generic path of condition
|
||||
|
||||
public:
|
||||
CGenericFuzzyRule(void);
|
||||
~CGenericFuzzyRule(void);
|
||||
//--- methods gets or sets the condition (IF) part of the rule
|
||||
CConditions *Condition(void) { return(m_generic_condition); }
|
||||
void Condition(CConditions *value) { m_generic_condition=value; }
|
||||
//--- methods create a single condition
|
||||
CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term);
|
||||
CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not);
|
||||
CFuzzyCondition *CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge);
|
||||
//--- methods gets or sets the conclusion (THEN) part of the rule
|
||||
virtual CSingleCondition *Conclusion(void) { return(NULL); }
|
||||
virtual void Conclusion(CSingleCondition *value) { }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_GenericFuzzyRule); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CGenericFuzzyRule::CGenericFuzzyRule(void)
|
||||
{
|
||||
m_generic_condition=new CConditions();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CGenericFuzzyRule::~CGenericFuzzyRule(void)
|
||||
{
|
||||
delete m_generic_condition;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a single condition(1) |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term)
|
||||
{
|
||||
//--- return fuzzy condition
|
||||
return new CFuzzyCondition(var, term);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a single condition(2) |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not)
|
||||
{
|
||||
//--- return fuzzy condition
|
||||
return new CFuzzyCondition(var, term, not);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a single condition(3) |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyCondition *CGenericFuzzyRule::CreateCondition(CFuzzyVariable *var,CFuzzyTerm *term,bool not,HedgeType hedge)
|
||||
{
|
||||
//--- return fuzzy condition
|
||||
return new CFuzzyCondition(var, term, not, hedge);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fuzzy rule for Mamdani fuzzy system. |
|
||||
//| NOTE: a rule cannot be created directly, only via |
|
||||
//| MamdaniFuzzySystem::EmptyRule or MamdaniFuzzySystem::ParseRule |
|
||||
//+------------------------------------------------------------------+
|
||||
class CMamdaniFuzzyRule : public CGenericFuzzyRule
|
||||
{
|
||||
private:
|
||||
CSingleCondition *m_mamdani_conclusion; // Mamdani conclusion
|
||||
double m_weight; // Weight of Mamdani rule
|
||||
|
||||
public:
|
||||
CMamdaniFuzzyRule(void);
|
||||
~CMamdaniFuzzyRule(void);
|
||||
//--- methods gets or sets the conclusion (THEN) part of the rule
|
||||
CSingleCondition *Conclusion(void) { return(m_mamdani_conclusion); }
|
||||
void Conclusion(CSingleCondition *value) { m_mamdani_conclusion=value; }
|
||||
//--- methods gets or sets the rule weight
|
||||
double Weight(void) { return(m_weight); }
|
||||
void Weight(const double value) { m_weight=value; }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_MamdaniFuzzyRule); }
|
||||
};
|
||||
//+---------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+---------------------------------------------------------------+
|
||||
CMamdaniFuzzyRule::CMamdaniFuzzyRule(void)
|
||||
{
|
||||
m_weight=1.0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzyRule::~CMamdaniFuzzyRule(void)
|
||||
{
|
||||
if(CheckPointer(m_mamdani_conclusion)==POINTER_DYNAMIC)
|
||||
delete m_mamdani_conclusion;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fuzzy rule for Sugeno fuzzy system |
|
||||
//| NOTE: a rule cannot be created directly, only via |
|
||||
//| SugenoFuzzySystem::EmptyRule or SugenoFuzzySystem::ParseRule |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSugenoFuzzyRule : public CGenericFuzzyRule
|
||||
{
|
||||
private:
|
||||
CSingleCondition *m_sugeno_conclusion; // Sugeno conclusion
|
||||
|
||||
public:
|
||||
CSugenoFuzzyRule(void);
|
||||
~CSugenoFuzzyRule(void);
|
||||
//--- methods gets or sets the conclusion (THEN) part of the rule
|
||||
CSingleCondition *Conclusion(void) { return(m_sugeno_conclusion); }
|
||||
void Conclusion(CSingleCondition *value) { m_sugeno_conclusion=value; }
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnRule type) { return(type==TYPE_CLASS_SugenoFuzzyRule); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+-------------------------- ---------------------------------------+
|
||||
CSugenoFuzzyRule::CSugenoFuzzyRule(void)
|
||||
{
|
||||
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoFuzzyRule::~CSugenoFuzzyRule(void)
|
||||
{
|
||||
if(CheckPointer(m_sugeno_conclusion)==POINTER_DYNAMIC)
|
||||
delete m_sugeno_conclusion;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,69 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| fuzzyterm.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include "MembershipFunction.mqh"
|
||||
#include "Helper.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: creating fuzzy term. |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fuzzy or linguistic term. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CFuzzyTerm : public CNamedValueImpl
|
||||
{
|
||||
private:
|
||||
IMembershipFunction *m_mf; // The membership function of the term
|
||||
|
||||
public:
|
||||
CFuzzyTerm(const string name,IMembershipFunction *mf);
|
||||
~CFuzzyTerm(void);
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_FuzzyTerm); }
|
||||
//--- method gets the membership function initially associated with the term
|
||||
IMembershipFunction *MembershipFunction() { return(m_mf); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyTerm::CFuzzyTerm(const string name,IMembershipFunction *mf)
|
||||
{
|
||||
CNamedValueImpl::Name(name);
|
||||
m_mf=mf;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyTerm::~CFuzzyTerm(void)
|
||||
{
|
||||
if(CheckPointer(m_mf)==POINTER_DYNAMIC)
|
||||
{
|
||||
delete m_mf;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,113 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| fuzzyvariable.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include "FuzzyTerm.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: creating fuzzy variable |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fuzzy or linguistic variable. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CFuzzyVariable : public CNamedVariableImpl
|
||||
{
|
||||
private:
|
||||
double m_min; // Minimum value of the variable
|
||||
double m_max; // Maximum value of the variable
|
||||
CList *m_terms; // List of terms in a variable
|
||||
|
||||
public :
|
||||
CFuzzyVariable(const string name,const double min,const double max);
|
||||
~CFuzzyVariable(void);
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_FuzzyVariable); }
|
||||
//--- methods gets or sets parameters of varriable
|
||||
void Max(const double max) { m_max=max; }
|
||||
double Max(void) { return (m_max); }
|
||||
void Min(const double min) { m_min=min; }
|
||||
double Min(void) { return (m_min); }
|
||||
//--- methods gets or sets the terms
|
||||
CList *Terms() { return(m_terms); }
|
||||
void Terms(CList *terms) { m_terms=terms; }
|
||||
//--- add fuzzy term
|
||||
void AddTerm(CFuzzyTerm *term);
|
||||
//--- get membership function by name
|
||||
CFuzzyTerm *GetTermByName(const string name);
|
||||
//--- overload
|
||||
CList *Values() { return(m_terms); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyVariable::CFuzzyVariable(const string name,const double min,const double max)
|
||||
{
|
||||
CNamedVariableImpl::Name(name);
|
||||
m_terms=new CList();
|
||||
if(min>max)
|
||||
{
|
||||
Print("Incorrect parameters! Maximum value must be greater than minimum one.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_min = min;
|
||||
m_max = max;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyVariable::~CFuzzyVariable(void)
|
||||
{
|
||||
delete m_terms;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add fuzzy term to list terms in a variable |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFuzzyVariable::AddTerm(CFuzzyTerm *term)
|
||||
{
|
||||
m_terms.Add(term);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get membership function (term) by name |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyTerm *CFuzzyVariable::GetTermByName(const string name)
|
||||
{
|
||||
for(int i=0; i<m_terms.Total(); i++)
|
||||
{
|
||||
CFuzzyTerm *term=m_terms.GetNodeAtIndex(i);
|
||||
if(term.Name()==name)
|
||||
{
|
||||
//--- return fuzzy term
|
||||
return (term);
|
||||
}
|
||||
}
|
||||
Print("Term with the same name can not be found!");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,333 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| genericfuzzysystem.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include <Arrays\ArrayObj.mqh>
|
||||
#include "FuzzyRule.mqh"
|
||||
#include "InferenceMethod.mqh"
|
||||
#include "Dictionary.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Creating generic fuzzy system |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common functionality of Mamdani and Sugeno fuzzy systems |
|
||||
//+------------------------------------------------------------------+
|
||||
class CGenericFuzzySystem
|
||||
{
|
||||
private:
|
||||
CList *m_input; // List of input fuzzy variables
|
||||
EnAndMethod m_and_method; // And method from InferenceMethod
|
||||
EnOrMethod m_or_method; // Or method from InferenceMethod
|
||||
|
||||
protected:
|
||||
CGenericFuzzySystem(void);
|
||||
~CGenericFuzzySystem(void);
|
||||
public:
|
||||
//--- method gets the input linguistic variables
|
||||
CList *Input(void) { return(m_input); }
|
||||
//--- method gets or sets the type of "And method"
|
||||
void AndMethod(EnAndMethod value) { m_and_method=value; }
|
||||
EnAndMethod AndMethod(void) const { return (m_and_method); }
|
||||
//--- method gets or sets the type of "Or method"
|
||||
void OrMethod(EnOrMethod value) { m_or_method=value; }
|
||||
EnOrMethod OrMethod(void) const { return (m_or_method); }
|
||||
//--- method gets the varriable by name
|
||||
CFuzzyVariable *InputByName(const string name);
|
||||
//--- common steps of calculating
|
||||
CList *Fuzzify(CList *inputValues);
|
||||
protected:
|
||||
double EvaluateCondition(ICondition *condition,CList *fuzzifiedInput);
|
||||
double EvaluateConditionPair(const double cond1,const double cond2,OperatorType op);
|
||||
private:
|
||||
bool ValidateInputValues(CList *inputValues,string &msg);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CGenericFuzzySystem::CGenericFuzzySystem(void)
|
||||
{
|
||||
m_input=new CList;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CGenericFuzzySystem::~CGenericFuzzySystem(void)
|
||||
{
|
||||
if(CheckPointer(m_input)==POINTER_DYNAMIC)
|
||||
{
|
||||
delete m_input;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get input linguistic variable by its name |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyVariable *CGenericFuzzySystem::InputByName(const string name)
|
||||
{
|
||||
CList *result=CGenericFuzzySystem::Input();
|
||||
for(int i=0; i<result.Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=result.GetNodeAtIndex(i);
|
||||
if(var.Name()==name)
|
||||
{
|
||||
//--- return fuzzy variable
|
||||
return (var);
|
||||
}
|
||||
}
|
||||
Print("The variable with that name is not found");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fuzzify input |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CGenericFuzzySystem::Fuzzify(CList *inputValues)
|
||||
{
|
||||
//--- Validate input
|
||||
string msg;
|
||||
if(!ValidateInputValues(inputValues,msg))
|
||||
{
|
||||
Print(msg);
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//--- Fill results list
|
||||
CList *result=new CList;
|
||||
for(int i=0; i<Input().Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=Input().GetNodeAtIndex(i);
|
||||
double value=NULL;
|
||||
for(int k=0; k<inputValues.Total(); k++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=inputValues.GetNodeAtIndex(i);
|
||||
CFuzzyVariable *v=p_vd.Key();
|
||||
if(p_vd.Key()==var)
|
||||
{
|
||||
value=p_vd.Value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
CList *resultForVar=new CList;
|
||||
for(int j=0; j<var.Terms().Total(); j++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=new CDictionary_Obj_Double;
|
||||
CFuzzyTerm *term=var.Terms().GetNodeAtIndex(j);
|
||||
p_vd.SetAll(term,term.MembershipFunction().GetValue(value));
|
||||
resultForVar.Add(p_vd);
|
||||
}
|
||||
CDictionary_Obj_Obj *p_vl=new CDictionary_Obj_Obj;
|
||||
p_vl.SetAll(var,resultForVar);
|
||||
result.Add(p_vl);
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Evaluate fuzzy condition (or conditions) |
|
||||
//+------------------------------------------------------------------+
|
||||
double CGenericFuzzySystem::EvaluateCondition(ICondition *condition,CList *fuzzifiedInput)
|
||||
{
|
||||
double result=0.0;
|
||||
ICondition *IC;
|
||||
if(condition.IsTypeOf(TYPE_CLASS_Conditions))
|
||||
{
|
||||
CConditions *conds=condition;
|
||||
if(conds.ConditionsList().Total()==0)
|
||||
{
|
||||
Print("Inner exception.");
|
||||
}
|
||||
else if(conds.ConditionsList().Total()==1)
|
||||
{
|
||||
IC=conds.ConditionsList().GetNodeAtIndex(0);
|
||||
result=EvaluateCondition(IC,fuzzifiedInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
IC=conds.ConditionsList().GetNodeAtIndex(0);
|
||||
result=EvaluateCondition(IC,fuzzifiedInput);
|
||||
for(int i=1; i<conds.ConditionsList().Total(); i++)
|
||||
{
|
||||
IC=conds.ConditionsList().GetNodeAtIndex(i);
|
||||
double cond2=EvaluateCondition(IC,fuzzifiedInput);;
|
||||
result=EvaluateConditionPair(result,cond2,conds.Op());
|
||||
}
|
||||
}
|
||||
if(conds.Not())
|
||||
{
|
||||
result=1.0-result;
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
else if(condition.IsTypeOf(TYPE_CLASS_FuzzyCondition))
|
||||
{
|
||||
CFuzzyCondition *cond=condition;
|
||||
CDictionary_Obj_Obj *p_vl;
|
||||
CDictionary_Obj_Double *p_td;
|
||||
for(int i=0; i<fuzzifiedInput.Total(); i++)
|
||||
{
|
||||
p_vl=fuzzifiedInput.GetNodeAtIndex(i);
|
||||
if(p_vl.Key()==cond.Var())
|
||||
{
|
||||
CList *list=p_vl.Value();
|
||||
for(int j=0; j<list.Total(); j++)
|
||||
{
|
||||
p_td=list.GetNodeAtIndex(j);
|
||||
if(p_td.Key()==cond.Term())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
result=p_td.Value();
|
||||
switch(cond.Hedge())
|
||||
{
|
||||
case Slightly:
|
||||
//--- Cube root
|
||||
result=pow(result,1.0/3.0);
|
||||
break;
|
||||
case Somewhat:
|
||||
result=sqrt(result);
|
||||
break;
|
||||
case Very:
|
||||
result=result*result;
|
||||
break;
|
||||
case Extremely:
|
||||
result=result*result*result;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(cond.Not())
|
||||
{
|
||||
result=1.0-result;
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Internal error.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Evaluate fuzzy condition (or conditions) |
|
||||
//+------------------------------------------------------------------+
|
||||
double CGenericFuzzySystem::EvaluateConditionPair(const double cond1,const double cond2,OperatorType op)
|
||||
{
|
||||
if(op==And)
|
||||
{
|
||||
if(CGenericFuzzySystem::AndMethod()==MinAnd)
|
||||
{
|
||||
//--- return evaluate condition
|
||||
return fmin(cond1, cond2);
|
||||
}
|
||||
else if(CGenericFuzzySystem::AndMethod()==ProductionAnd)
|
||||
{
|
||||
//--- return evaluate condition
|
||||
return (cond1 * cond2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Internal error.");
|
||||
//--- return
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
else if(op==Or)
|
||||
{
|
||||
if(CGenericFuzzySystem::OrMethod()==MaxOr)
|
||||
{
|
||||
//--- return evaluate condition
|
||||
return fmax(cond1, cond2);
|
||||
}
|
||||
else if(CGenericFuzzySystem::OrMethod()==ProbabilisticOr)
|
||||
{
|
||||
//--- return evaluate condition
|
||||
return (cond1 + cond2 - cond1 * cond2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Internal error.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Internal error.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Validate input values |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CGenericFuzzySystem::ValidateInputValues(CList *inputValues,string &msg)
|
||||
{
|
||||
msg=NULL;
|
||||
if(inputValues.Total()!=Input().Total())
|
||||
{
|
||||
msg="Input values count is incorrect.";
|
||||
//--- return false
|
||||
return (false);
|
||||
}
|
||||
bool contain;
|
||||
for(int i=0; i<Input().Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=Input().GetNodeAtIndex(i);
|
||||
contain=false;
|
||||
for(int j=0; j<inputValues.Total();j++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=inputValues.GetNodeAtIndex(j);
|
||||
if(p_vd.Key()==var)
|
||||
{
|
||||
contain=true;
|
||||
double val=p_vd.Value();
|
||||
if(val<var.Min() || val>var.Max())
|
||||
{
|
||||
msg=StringFormat("Value for the %s variable is out of range.",var.Name());
|
||||
//--- return false
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(contain==false)
|
||||
{
|
||||
msg=StringFormat("Value for the %s variable does not present.",var.Name());
|
||||
//--- return false
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
//--- return true
|
||||
return (true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,158 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| helper.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include "InferenceMethod.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Analysis of the fuzzy rules |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| This class must be implemented by values in parsable rules |
|
||||
//+------------------------------------------------------------------+
|
||||
class INamedValue : public CObject
|
||||
{
|
||||
public:
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_INamedValue); }
|
||||
//--- methods gets or sets the name
|
||||
virtual string Name(void) { return(""); }
|
||||
virtual void Name(const string name) { }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| This class must be implemented by values in parsable rules |
|
||||
//+------------------------------------------------------------------+
|
||||
class INamedVariable : public INamedValue
|
||||
{
|
||||
public:
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_INamedValue); }
|
||||
//--- get list of values that belongs to the variable
|
||||
virtual CList *Values(void) { return(NULL); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Named variable |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNamedVariableImpl : public INamedVariable
|
||||
{
|
||||
private:
|
||||
string m_name; // Name of the variable
|
||||
|
||||
public:
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_NamedVariableImpl); }
|
||||
//--- methods gets or sets varriable name
|
||||
virtual void Name(const string name);
|
||||
virtual string Name(void) { return(m_name); }
|
||||
//--- get list of values that belongs to the variable
|
||||
virtual CList *Values(void) { return(NULL); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set variable name |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNamedVariableImpl::Name(const string name)
|
||||
{
|
||||
if(!CNameHelper::IsValidName(name))
|
||||
{
|
||||
Print("Invalid variable name.");
|
||||
}
|
||||
m_name=name;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Named value of variable |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNamedValueImpl : public INamedValue
|
||||
{
|
||||
private:
|
||||
string m_name; // Name of the value
|
||||
|
||||
public:
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_NamedVariableImpl); }
|
||||
//--- methods gets or sets varriable name
|
||||
virtual void Name(const string name);
|
||||
virtual string Name(void) { return(m_name); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set variable name |
|
||||
//+------------------------------------------------------------------+
|
||||
void CNamedValueImpl::Name(const string name)
|
||||
{
|
||||
if(!CNameHelper::IsValidName(name))
|
||||
{
|
||||
Print("Invalid term name.");
|
||||
}
|
||||
m_name=name;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Keywords: |
|
||||
//+------------------------------------------------------------------+
|
||||
static string KEYWORDS[]={ "if","then","is","and","or","not","(",")","slightly","somewhat","very","extremely" }; // Keywords in rules
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class NameHelper checks the availability of names |
|
||||
//+------------------------------------------------------------------+
|
||||
class CNameHelper
|
||||
{
|
||||
public:
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check the name of variable/term |
|
||||
//+------------------------------------------------------------------+
|
||||
static bool IsValidName(const string name)
|
||||
{
|
||||
//--- Empty names are not allowed
|
||||
if(StringLen(name)==0)
|
||||
{
|
||||
//--- return false
|
||||
return (false);
|
||||
}
|
||||
|
||||
for(int i=0; i<StringLen(name); i++)
|
||||
{
|
||||
//--- Only letters, numbers or '_' are allowed
|
||||
char s=(char) StringGetCharacter(name,i);
|
||||
if(s!='_' && !(s>=48 && s<=57) // Not numbers and symbol '_'
|
||||
&& !( s >= 65 && s <= 90 ) // Not capital letters
|
||||
&& !( s >= 97 && s <= 122 )) // Not letters
|
||||
{
|
||||
//--- return false
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
//--- Identifier cannot be a keword
|
||||
for(int i=0; i<ArraySize(KEYWORDS); i++)
|
||||
{
|
||||
if(name==KEYWORDS[i])
|
||||
{
|
||||
//--- return false
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
//--- return true
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,125 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| inferencemethod.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Contains a number of enumerations, |
|
||||
//| for the convenience of working with other files |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| And evaluating method |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnAndMethod
|
||||
{
|
||||
MinAnd, // Minimum: min(a, b)
|
||||
ProductionAnd // Production: a * b
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Or evaluating method |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnOrMethod
|
||||
{
|
||||
MaxOr, // Maximum: max(a, b)
|
||||
ProbabilisticOr // Probabilistic OR: a + b - a * b
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fuzzy implication method |
|
||||
//+------------------------------------------------------------------+
|
||||
enum ImplicationMethod
|
||||
{
|
||||
MinIpm, // Truncation of output fuzzy set
|
||||
ProductionImp // Scaling of output fuzzy set
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Aggregation method for membership functions |
|
||||
//+------------------------------------------------------------------+
|
||||
enum AggregationMethod
|
||||
{
|
||||
MaxAgg, // Maximum of rule outpus
|
||||
SumAgg // Sum of rule output
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Defuzzification method |
|
||||
//+------------------------------------------------------------------+
|
||||
enum DefuzzificationMethod
|
||||
{
|
||||
CentroidDef, // Center of area of fuzzy result MF
|
||||
BisectorDef, // The point divides the area under the MF into two equal
|
||||
AverageMaximumDef, // Arithmetic mean of all the maxima of the MF
|
||||
LargestMaximumDef, // The largest of the maxima of the membership function
|
||||
SmallestMaximumDef // The smallest of the maxima of the membership function
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Type of varriable and term |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnType
|
||||
{
|
||||
TYPE_CLASS_INamedValue, // Base class
|
||||
TYPE_CLASS_INamedVariable, // INamedVariable : INamedValue
|
||||
TYPE_CLASS_NamedVariableImpl, // NamedVariableImpl : INamedVariable
|
||||
TYPE_CLASS_NamedValueImpl, // NamedValueImpl : INamedValue
|
||||
TYPE_CLASS_FuzzyTerm, // FuzzyTerm : NamedValueImpl
|
||||
TYPE_CLASS_FuzzyVariable, // FuzzyVariable : NamedVariableImpl
|
||||
TYPE_CLASS_SugenoVariable, // SugenoVariable : NamedVariableImpl
|
||||
TYPE_CLASS_ISugenoFunction, // ISugenoFunction : NamedValueImpl
|
||||
TYPE_CLASS_LinearSugenoFunction // LinearSugenoFunction : ISugenoFunction
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Type of expression |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnLexem
|
||||
{
|
||||
TYPE_CLASS_IExpression, // Base class
|
||||
TYPE_CLASS_Lexem, // Lexem : IExpression
|
||||
TYPE_CLASS_ConditionExpression, // ConditionExpression : IExpression
|
||||
TYPE_CLASS_VarLexem, // VarLexem : Lexem
|
||||
TYPE_CLASS_KeywordLexem, // KeywordLexem : Lexem
|
||||
TYPE_CLASS_AltLexem, // AltLexem : Lexem
|
||||
TYPE_CLASS_TermLexem // TermLexem : AltLexem
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Type of condition |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnCondition
|
||||
{
|
||||
TYPE_CLASS_ICondition, // Base class
|
||||
TYPE_CLASS_Conditions, // Conditions : ICondition
|
||||
TYPE_CLASS_SingleCondition, // SingleCondition : ICondition
|
||||
TYPE_CLASS_FuzzyCondition // FuzzyCondition : SingleCondition
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Type of rule |
|
||||
//+------------------------------------------------------------------+
|
||||
enum EnRule
|
||||
{
|
||||
TYPE_CLASS_IParsableRule, // Base class
|
||||
TYPE_CLASS_GenericFuzzyRule, // GenericFuzzyRule : IParsableRule
|
||||
TYPE_CLASS_MamdaniFuzzyRule, // MamdaniFuzzyRule : GenericFuzzyRule
|
||||
TYPE_CLASS_SugenoFuzzyRule // SugenoFuzzyRule : GenericFuzzyRule
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,556 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| mandanifuzzysystem.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include <Arrays\ArrayDouble.mqh>
|
||||
#include "GenericFuzzySystem.mqh"
|
||||
#include "InferenceMethod.mqh"
|
||||
#include "RuleParser.mqh"
|
||||
#include "FuzzyRule.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Creating Mamdani fuzzy system |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Mamdani fuzzy inference system |
|
||||
//+------------------------------------------------------------------+
|
||||
class CMamdaniFuzzySystem : public CGenericFuzzySystem
|
||||
{
|
||||
private:
|
||||
CList* m_output; // List of fuzzy variable
|
||||
CList* m_rules; // List of Mamdani fuzzy rule
|
||||
ImplicationMethod m_impl_method; // Implication method
|
||||
AggregationMethod m_aggr_method; // Aggregation method
|
||||
DefuzzificationMethod m_defuzz_method; // Defuzzification method
|
||||
|
||||
public:
|
||||
CMamdaniFuzzySystem(void);
|
||||
~CMamdaniFuzzySystem(void);
|
||||
//--- method gets the output linguistic variables
|
||||
CList* Output(void) { return(m_output); }
|
||||
//--- method gets the fuzzy rule
|
||||
CList* Rules(void) { return(m_rules); }
|
||||
//--- methods gets or sets the implication method
|
||||
ImplicationMethod GetImplicationMethod(void) const { return (m_impl_method); }
|
||||
void SetImplicationMethod(ImplicationMethod value) { m_impl_method=value; }
|
||||
//--- methods gets or sets the aggregation method
|
||||
AggregationMethod GetAggregationMethod(void) const { return (m_aggr_method); }
|
||||
void SetAggregationMethod(AggregationMethod value) { m_aggr_method=value; }
|
||||
//--- methods gets or sets the defuzzification method
|
||||
DefuzzificationMethod GetDefuzzificationMethod(void) const { return (m_defuzz_method); }
|
||||
void SetDefuzzificationMethod(DefuzzificationMethod value) { m_defuzz_method=value; }
|
||||
//--- maethod gets the variable by name
|
||||
CFuzzyVariable* OutputByName(const string name);
|
||||
//--- create a new rule
|
||||
CMamdaniFuzzyRule* EmptyRule(void);
|
||||
//--- parse rule
|
||||
CMamdaniFuzzyRule* ParseRule(const string rule);
|
||||
//--- method for calculate result
|
||||
CList* Calculate(CList *inputValues);
|
||||
CList* EvaluateConditions(CList *fuzzifiedInput);
|
||||
CList* Implicate(CList *conditions);
|
||||
CList* Aggregate(CList *conclusions);
|
||||
CList* Defuzzify(CList *fuzzyResult);
|
||||
double Defuzzify(IMembershipFunction *mf,const double min,const double max);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzySystem::CMamdaniFuzzySystem(void)
|
||||
{
|
||||
m_output = new CList;
|
||||
m_rules = new CList;
|
||||
m_impl_method = MinIpm; // Implication method default is Min
|
||||
m_aggr_method = MaxAgg; // Aggregation method default is Max
|
||||
m_defuzz_method = CentroidDef; // Defuzzification method default is Centroid
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzySystem::~CMamdaniFuzzySystem(void)
|
||||
{
|
||||
delete m_output;
|
||||
delete m_rules;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get output linguistic variable by its name |
|
||||
//+------------------------------------------------------------------+
|
||||
CFuzzyVariable *CMamdaniFuzzySystem::OutputByName(const string name)
|
||||
{
|
||||
for(int i=0; i<m_output.Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=m_output.GetNodeAtIndex(i);
|
||||
if(var.Name()==name)
|
||||
{
|
||||
//--- return varriable
|
||||
return (var);
|
||||
}
|
||||
}
|
||||
Print("Variable with that name is not found");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create new empty rule |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzyRule *CMamdaniFuzzySystem::EmptyRule()
|
||||
{
|
||||
//--- return empty rule
|
||||
return new CMamdaniFuzzyRule();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Parse rule from the string |
|
||||
//+------------------------------------------------------------------+
|
||||
CMamdaniFuzzyRule *CMamdaniFuzzySystem::ParseRule(const string rule)
|
||||
{
|
||||
//--- return Mamdani fuzzy rule
|
||||
return CRuleParser::Parse(rule, EmptyRule(), Input(), Output());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate output values |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Calculate(CList *inputValues)
|
||||
{
|
||||
//--- There should be one rule as minimum
|
||||
if(m_rules.Total()==0)
|
||||
{
|
||||
Print("There should be one rule as minimum.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//--- Fuzzification step
|
||||
CList *fuzzifiedInput=Fuzzify(inputValues);
|
||||
//--- Evaluate the conditions
|
||||
CList *evaluatedConditions=EvaluateConditions(fuzzifiedInput);
|
||||
//--- Do implication for each rule
|
||||
CList *implicatedConclusions=Implicate(evaluatedConditions);
|
||||
//--- Aggrerate the results
|
||||
CList *fuzzyResult=Aggregate(implicatedConclusions);
|
||||
//--- Defuzzify the result
|
||||
CList *result=Defuzzify(fuzzyResult);
|
||||
//---
|
||||
delete fuzzyResult;
|
||||
for(int i=0; i<implicatedConclusions.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Obj *pair=implicatedConclusions.GetNodeAtIndex(i);
|
||||
CCompositeMembershipFunction *composite=pair.Value();
|
||||
delete composite.MembershipFunctions().GetNodeAtIndex(0);
|
||||
delete composite;
|
||||
}
|
||||
delete implicatedConclusions;
|
||||
delete evaluatedConditions;
|
||||
for(int i=0; i<fuzzifiedInput.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Obj *pair=fuzzifiedInput.GetNodeAtIndex(i);
|
||||
delete pair.Value();
|
||||
}
|
||||
delete fuzzifiedInput;
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Evaluate conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::EvaluateConditions(CList *fuzzifiedInput)
|
||||
{
|
||||
CList *result=new CList;
|
||||
for(int i=0; i<Rules().Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_rd=new CDictionary_Obj_Double;
|
||||
CMamdaniFuzzyRule *rule=Rules().GetNodeAtIndex(i);
|
||||
p_rd.SetAll(rule,EvaluateCondition(rule.Condition(),fuzzifiedInput));
|
||||
result.Add(p_rd);
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implicate rule results |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Implicate(CList *conditions)
|
||||
{
|
||||
CList *conclusions=new CList;
|
||||
for(int i=0; i<conditions.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_rd=conditions.GetNodeAtIndex(i);
|
||||
CMamdaniFuzzyRule *rule=p_rd.Key();
|
||||
MfCompositionType compType;
|
||||
switch(m_impl_method)
|
||||
{
|
||||
case MinIpm :
|
||||
{
|
||||
compType=MinMF;
|
||||
break;
|
||||
}
|
||||
case ProductionImp :
|
||||
{
|
||||
compType=ProdMF;
|
||||
break;
|
||||
}
|
||||
default :
|
||||
{
|
||||
Print("Internal error.");
|
||||
//---
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
CFuzzyTerm *val=rule.Conclusion().Term();
|
||||
IMembershipFunction *first_fun=new CConstantMembershipFunction(p_rd.Value());
|
||||
IMembershipFunction *second_fun=val.MembershipFunction();
|
||||
CCompositeMembershipFunction *resultMF=new CCompositeMembershipFunction(compType,first_fun,second_fun);
|
||||
CDictionary_Obj_Obj *p_rf=new CDictionary_Obj_Obj;
|
||||
p_rf.SetAll(rule,resultMF);
|
||||
conclusions.Add(p_rf);
|
||||
}
|
||||
//--- return conclusions
|
||||
return (conclusions);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Aggregate results |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Aggregate(CList *conclusions)
|
||||
{
|
||||
CList *fuzzyResult=new CList;
|
||||
for(int i=0; i<Output().Total(); i++)
|
||||
{
|
||||
CFuzzyVariable *var=Output().GetNodeAtIndex(i);
|
||||
CList *mfList=new CList;
|
||||
for(int j=0; j<conclusions.Total(); j++)
|
||||
{
|
||||
CDictionary_Obj_Obj *p_rf=conclusions.GetNodeAtIndex(j);
|
||||
CMamdaniFuzzyRule *rule=p_rf.Key();
|
||||
if(rule.Conclusion().Var()==var)
|
||||
{
|
||||
mfList.Add(p_rf.Value());
|
||||
}
|
||||
}
|
||||
MfCompositionType composType;
|
||||
switch(m_aggr_method)
|
||||
{
|
||||
case MaxAgg:
|
||||
composType=MaxMF;
|
||||
break;
|
||||
case SumAgg:
|
||||
composType=SumMF;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Print("Internal exception.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
CDictionary_Obj_Obj *p_vf=new CDictionary_Obj_Obj;
|
||||
CCompositeMembershipFunction *func=new CCompositeMembershipFunction(composType,mfList);
|
||||
p_vf.SetAll(var,func);
|
||||
fuzzyResult.Add(p_vf);
|
||||
}
|
||||
//--- return result
|
||||
return (fuzzyResult);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate crisp result for each rule |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CMamdaniFuzzySystem::Defuzzify(CList *fuzzyResult)
|
||||
{
|
||||
CList *crispResult=new CList;
|
||||
for(int i=0; i<fuzzyResult.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=new CDictionary_Obj_Double;
|
||||
CDictionary_Obj_Obj *p_vf=fuzzyResult.GetNodeAtIndex(i);
|
||||
CFuzzyVariable *var=p_vf.Key();
|
||||
p_vd.SetAll(var,Defuzzify(p_vf.Value(),var.Min(),var.Max()));
|
||||
crispResult.Add(p_vd);
|
||||
}
|
||||
//--- return result
|
||||
return (crispResult);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Helpers |
|
||||
//+------------------------------------------------------------------+
|
||||
double CMamdaniFuzzySystem::Defuzzify(IMembershipFunction *mf,const double min,const double max)
|
||||
{
|
||||
if(m_defuzz_method==CentroidDef)
|
||||
{
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate a center of gravity as integral |
|
||||
//+------------------------------------------------------------------+
|
||||
double ptLeft=0.0;
|
||||
double ptCenter= 0.0;
|
||||
double ptRight = 0.0;
|
||||
double valLeft=0.0;
|
||||
double valCenter= 0.0;
|
||||
double valRight = 0.0;
|
||||
double val2Left=0.0;
|
||||
double val2Center= 0.0;
|
||||
double val2Right = 0.0;
|
||||
double numerator=0.0;
|
||||
double denominator=0.0;
|
||||
for(int i=0; i<k; i++)
|
||||
{
|
||||
if(i==0)
|
||||
{
|
||||
ptRight=min;
|
||||
valRight=mf.GetValue(ptRight);
|
||||
val2Right=ptRight*valRight;
|
||||
}
|
||||
ptLeft=ptRight;
|
||||
ptCenter= min+step *((double)i+0.5);
|
||||
ptRight = min+step *(i+1);
|
||||
valLeft=valRight;
|
||||
valCenter= mf.GetValue(ptCenter);
|
||||
valRight = mf.GetValue(ptRight);
|
||||
val2Left=val2Right;
|
||||
val2Center= ptCenter * valCenter;
|
||||
val2Right = ptRight * valRight;
|
||||
numerator+=step *(val2Left+4*val2Center+val2Right)/3.0;
|
||||
denominator+=step *(valLeft+4*valCenter+valRight)/3.0;
|
||||
}
|
||||
delete mf;
|
||||
if(denominator!=0)
|
||||
{
|
||||
//--- return result
|
||||
return (numerator / denominator);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- return NAN
|
||||
return (MathLog(-1));
|
||||
}
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==BisectorDef)
|
||||
{
|
||||
//+-------------------------------------------------------------------------------------+
|
||||
//| The method Bisector consists in finding the point on the abscissa, |
|
||||
//| which divides the area under the curve of the membership function in two equal parts|
|
||||
//+-------------------------------------------------------------------------------------+
|
||||
double Area=0.0; // The area under the function
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
for(int i=0; i<k; i++)
|
||||
{
|
||||
Area+=mf.GetValue(now);
|
||||
now=now+(max-min)/k;
|
||||
}
|
||||
now=min;
|
||||
double halfArea=fabs(Area/2-mf.GetValue(min));
|
||||
Area=0.0;
|
||||
while(true)
|
||||
{
|
||||
Area+=mf.GetValue(now);
|
||||
if(Area>=halfArea)
|
||||
{
|
||||
break;
|
||||
}
|
||||
now=now+(max-min)/k;
|
||||
}
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (now);
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==AverageMaximumDef)
|
||||
{
|
||||
//+------------------------------------------------------------------------------------------+
|
||||
//| AverageMaximum method is the arithmetic mean of all the maxima of the membership function|
|
||||
//+------------------------------------------------------------------------------------------+
|
||||
double sum_max=0; // Sum of local maxima
|
||||
double count_max=0; // Count of local maxima
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
for(int i=1; i<k; i++)
|
||||
{
|
||||
double point_1 = mf.GetValue(now);
|
||||
double point_0 = mf.GetValue(now - step);
|
||||
double point_2 = mf.GetValue(now + step);
|
||||
//--- check the first element
|
||||
if(i==1)
|
||||
{
|
||||
if(mf.GetValue(min)>mf.GetValue(min+step))
|
||||
{
|
||||
sum_max+=mf.GetValue(min);
|
||||
count_max++;
|
||||
}
|
||||
}
|
||||
//--- check the second element
|
||||
if(i==k-1)
|
||||
{
|
||||
if(mf.GetValue(max)>mf.GetValue(max-step))
|
||||
{
|
||||
sum_max+=mf.GetValue(max);
|
||||
count_max++;
|
||||
}
|
||||
}
|
||||
//--- check all the other elements
|
||||
if((point_1>point_0) && (point_1>point_2))
|
||||
{
|
||||
sum_max+=point_1;
|
||||
count_max++;
|
||||
}
|
||||
}
|
||||
if(count_max==0)
|
||||
{
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (sum_max/count_max);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==LargestMaximumDef)
|
||||
{
|
||||
CArrayDouble *local_max=new CArrayDouble; // Array of all local maximum
|
||||
double result; // Result of defuzzification method
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
for(int i=1; i<k; i++)
|
||||
{
|
||||
double point_1 = mf.GetValue(now);
|
||||
double point_0 = mf.GetValue(now - step);
|
||||
double point_2 = mf.GetValue(now + step);
|
||||
//--- check the first element
|
||||
if(i==1)
|
||||
{
|
||||
if(mf.GetValue(min)>mf.GetValue(min+step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(min));
|
||||
}
|
||||
}
|
||||
//--- check the second element
|
||||
if(i==k-1)
|
||||
{
|
||||
if(mf.GetValue(max)>mf.GetValue(max-step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(max));
|
||||
}
|
||||
}
|
||||
//--- check all the other elements
|
||||
if((point_1>point_0) && (point_1>point_2))
|
||||
{
|
||||
local_max.Add(point_1);
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
result=local_max.At(0);
|
||||
for(int i=0; i<local_max.Total(); i++)
|
||||
{
|
||||
if(result<=local_max.At(i))
|
||||
{
|
||||
result=local_max.At(i);
|
||||
}
|
||||
}
|
||||
now=min;
|
||||
while(true)
|
||||
{
|
||||
if(mf.GetValue(now)==result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
delete local_max;
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (now);
|
||||
}
|
||||
else
|
||||
if(m_defuzz_method==SmallestMaximumDef)
|
||||
{
|
||||
CArrayDouble *local_max=new CArrayDouble; // Array of all local maximum
|
||||
double result; // Result of defuzzification method
|
||||
int k=50; // The function is divided into "k" steps
|
||||
double now=min; // The current position
|
||||
double step=(max-min)/k; // Calculate the step function
|
||||
for(int i=1; i<k; i++)
|
||||
{
|
||||
double point_1 = mf.GetValue(now);
|
||||
double point_0 = mf.GetValue(now - step);
|
||||
double point_2 = mf.GetValue(now + step);
|
||||
//--- check the first element
|
||||
if(i==1)
|
||||
{
|
||||
if(mf.GetValue(min)>mf.GetValue(min+step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(min));
|
||||
}
|
||||
}
|
||||
//--- check the second element
|
||||
if(i==k-1)
|
||||
{
|
||||
if(mf.GetValue(max)>mf.GetValue(max-step))
|
||||
{
|
||||
local_max.Add(mf.GetValue(max));
|
||||
}
|
||||
}
|
||||
//--- check all the other elements
|
||||
if((point_1>point_0) && (point_1>point_2))
|
||||
{
|
||||
local_max.Add(point_1);
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
result=local_max.At(0);
|
||||
for(int i=0; i<local_max.Total(); i++)
|
||||
{
|
||||
if(result>=local_max.At(i))
|
||||
{
|
||||
result=local_max.At(i);
|
||||
}
|
||||
}
|
||||
now=min;
|
||||
while(true)
|
||||
{
|
||||
if(mf.GetValue(now)==result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
now+=step;
|
||||
}
|
||||
delete local_max;
|
||||
delete mf;
|
||||
//--- return result
|
||||
return (now);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Internal exception.");
|
||||
delete mf;
|
||||
//--- return
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,327 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| sugenofuzzysystem.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include "GenericFuzzySystem.mqh"
|
||||
#include "InferenceMethod.mqh"
|
||||
#include "RuleParser.mqh"
|
||||
#include "FuzzyRule.mqh"
|
||||
#include "SugenoVariable.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: Creating Sugeno fuzzy system |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sugeno fuzzy inference system |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSugenoFuzzySystem : public CGenericFuzzySystem
|
||||
{
|
||||
private:
|
||||
CList *m_output; // List of Sugeno variable
|
||||
CList *m_rules; // List of Sugeno fuzzy rule
|
||||
|
||||
public:
|
||||
CSugenoFuzzySystem(void);
|
||||
~CSugenoFuzzySystem(void);
|
||||
//--- method gets the output linguistic variables
|
||||
CList* Output(void) { return(m_output); }
|
||||
//--- method gets the fuzzy rule
|
||||
CList* Rules(void) { return(m_rules); }
|
||||
//--- maethod gets the variable by name
|
||||
CSugenoVariable* OutputByName(const string name);
|
||||
//--- method create new linear function
|
||||
CLinearSugenoFunction* CreateSugenoFunction(const string name,CList *coeffs,const double constValue);
|
||||
CLinearSugenoFunction* CreateSugenoFunction(const string name,const double &coeffs[]);
|
||||
//--- method create a new rule
|
||||
CSugenoFuzzyRule* EmptyRule(void);
|
||||
//--- method for calculate result
|
||||
CSugenoFuzzyRule* ParseRule(const string rule);
|
||||
CList* EvaluateConditions(CList *fuzzifiedInput);
|
||||
CList* EvaluateFunctions(CList *inputValues);
|
||||
CList* CombineResult(CList *ruleWeights,CList *functionResults);
|
||||
CList* Calculate(CList *inputValues);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor without parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoFuzzySystem::CSugenoFuzzySystem(void)
|
||||
{
|
||||
m_output=new CList;
|
||||
m_rules=new CList;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoFuzzySystem::~CSugenoFuzzySystem(void)
|
||||
{
|
||||
delete m_output;
|
||||
delete m_rules;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the output variable of the system by name |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoVariable *CSugenoFuzzySystem::OutputByName(const string name)
|
||||
{
|
||||
for(int i=0; i<m_output.Total(); i++)
|
||||
{
|
||||
CSugenoVariable *var=m_output.GetNodeAtIndex(i);
|
||||
if(var.Name()==name)
|
||||
{
|
||||
//--- return Sugeno variable
|
||||
return (var);
|
||||
}
|
||||
}
|
||||
Print("Variable with that name is not found");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------------+
|
||||
//| Use this method to create a linear function for the Sugeno fuzzy system|
|
||||
//+------------------------------------------------------------------------+
|
||||
CLinearSugenoFunction *CSugenoFuzzySystem::CreateSugenoFunction(const string name,CList *coeffs,const double constValue)
|
||||
{
|
||||
//--- return linear Sugeno function
|
||||
return new CLinearSugenoFunction(name, CGenericFuzzySystem::Input(), coeffs, constValue);
|
||||
}
|
||||
//+------------------------------------------------------------------------+
|
||||
//| Use this method to create a linear function for the Sugeno fuzzy system|
|
||||
//+------------------------------------------------------------------------+
|
||||
CLinearSugenoFunction *CSugenoFuzzySystem::CreateSugenoFunction(const string name,const double &coeffs[])
|
||||
{
|
||||
//--- return linear Sugeno function
|
||||
return new CLinearSugenoFunction(name, Input(), coeffs);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Use this method to create an empty rule for the system |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoFuzzyRule *CSugenoFuzzySystem::EmptyRule()
|
||||
{
|
||||
//--- return Sugeno fuzzy rule
|
||||
return new CSugenoFuzzyRule();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Use this method to create rule by its textual representation |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoFuzzyRule *CSugenoFuzzySystem::ParseRule(const string rule)
|
||||
{
|
||||
//--- return Sugeno fuzzy rule
|
||||
return CRuleParser::Parse(rule, EmptyRule(), Input(), Output());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Evaluate conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CSugenoFuzzySystem::EvaluateConditions(CList *fuzzifiedInput)
|
||||
{
|
||||
CList *result=new CList;
|
||||
for(int i=0; i<Rules().Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_rd=new CDictionary_Obj_Double;
|
||||
CSugenoFuzzyRule *rule=Rules().GetNodeAtIndex(i);
|
||||
p_rd.SetAll(rule,EvaluateCondition(rule.Condition(),fuzzifiedInput));
|
||||
result.Add(p_rd);
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate functions results |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CSugenoFuzzySystem::EvaluateFunctions(CList *inputValues)
|
||||
{
|
||||
CList *result=new CList;
|
||||
for(int i=0; i<Output().Total(); i++)
|
||||
{
|
||||
CSugenoVariable *var=Output().GetNodeAtIndex(i);
|
||||
CList *varResult=new CList;
|
||||
for(int j=0; j<var.Functions().Total(); j++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_fd=new CDictionary_Obj_Double;
|
||||
CLinearSugenoFunction *func=var.Functions().GetNodeAtIndex(j);
|
||||
p_fd.SetAll(func,func.Evaluate(inputValues));
|
||||
varResult.Add(p_fd);
|
||||
}
|
||||
CDictionary_Obj_Obj *p_vl=new CDictionary_Obj_Obj;
|
||||
p_vl.SetAll(var,varResult);
|
||||
result.Add(p_vl);
|
||||
}
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Combine results of functions and rule evaluation |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CSugenoFuzzySystem::CombineResult(CList *ruleWeights,CList *functionResults)
|
||||
{
|
||||
CList *results=new CList;
|
||||
CList *numerators=new CList;
|
||||
CDictionary_Obj_Double *p_vd1;
|
||||
CList *denominators=new CList;
|
||||
CDictionary_Obj_Double *p_vd2;
|
||||
//--- Calculate numerator and denominator separately for each output
|
||||
for(int i=0; i<Output().Total(); i++)
|
||||
{
|
||||
p_vd1=new CDictionary_Obj_Double;
|
||||
p_vd1.SetAll(Output().GetNodeAtIndex(i),0.0);
|
||||
numerators.Add(p_vd1);
|
||||
p_vd2=new CDictionary_Obj_Double;
|
||||
p_vd2.SetAll(Output().GetNodeAtIndex(i),0.0);
|
||||
denominators.Add(p_vd2);
|
||||
}
|
||||
for(int i=0; i<ruleWeights.Total(); i++)
|
||||
{
|
||||
double z=NULL;
|
||||
double w=NULL;
|
||||
CDictionary_Obj_Double *p_rd=ruleWeights.GetNodeAtIndex(i);
|
||||
CSugenoFuzzyRule *rule=p_rd.Key();
|
||||
CSugenoVariable *var=rule.Conclusion().Var();
|
||||
for(int j=0; j<functionResults.Total(); j++)
|
||||
{
|
||||
CDictionary_Obj_Obj *p_vl=functionResults.GetNodeAtIndex(j);
|
||||
if(p_vl.Key()==var)
|
||||
{
|
||||
CList *list=p_vl.Value();
|
||||
for(int k=0; k<list.Total(); k++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_fd=list.GetNodeAtIndex(k);
|
||||
if(p_fd.Key()==rule.Conclusion().Term())
|
||||
{
|
||||
z=p_fd.Value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int j=0; j<ruleWeights.Total(); j++)
|
||||
{
|
||||
p_rd=ruleWeights.GetNodeAtIndex(j);
|
||||
if(p_rd.Key()==rule)
|
||||
{
|
||||
w=p_rd.Value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int j=0; j<numerators.Total(); j++)
|
||||
{
|
||||
p_vd1=numerators.GetNodeAtIndex(j);
|
||||
double num=p_vd1.Value();
|
||||
if(p_vd1.Key()==rule.Conclusion().Var())
|
||||
{
|
||||
num=num+(z*w);
|
||||
p_vd1.Value(num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int j=0; j<denominators.Total(); j++)
|
||||
{
|
||||
p_vd2=denominators.GetNodeAtIndex(j);
|
||||
double den=p_vd2.Value();
|
||||
if(p_vd2.Key()==rule.Conclusion().Var())
|
||||
{
|
||||
den=den+w;
|
||||
p_vd2.Value(den);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- Calculate the fractions
|
||||
for(int i=0; i<Output().Total(); i++)
|
||||
{
|
||||
CSugenoVariable *var=Output().GetNodeAtIndex(i);
|
||||
CDictionary_Obj_Double *p_vd_res=new CDictionary_Obj_Double;
|
||||
CDictionary_Obj_Double *p_vd_num;
|
||||
CDictionary_Obj_Double *p_vd_den;
|
||||
for(int j=0; j<numerators.Total(); j++)
|
||||
{
|
||||
p_vd_num=numerators.GetNodeAtIndex(j);
|
||||
if(p_vd_num.Key()==var)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int j=0; j<denominators.Total(); j++)
|
||||
{
|
||||
p_vd_den=denominators.GetNodeAtIndex(j);
|
||||
if(p_vd_den.Key()==var)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(p_vd_den.Value()==0.0)
|
||||
{
|
||||
p_vd_res.Value(0.0);
|
||||
results.Add(p_vd_res);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_vd_res.Value(p_vd_num.Value()/p_vd_den.Value());
|
||||
results.Add(p_vd_res);
|
||||
}
|
||||
}
|
||||
//--- return result
|
||||
delete numerators;
|
||||
delete denominators;
|
||||
return (results);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate output of fuzzy system |
|
||||
//+------------------------------------------------------------------+
|
||||
CList *CSugenoFuzzySystem::Calculate(CList *inputValues)
|
||||
{
|
||||
//--- There should be one rule as minimum
|
||||
if(m_rules.Total()==0)
|
||||
{
|
||||
Print("There should be one rule as minimum.");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//--- Fuzzification step
|
||||
CList *fuzzifiedInput=Fuzzify(inputValues);
|
||||
//--- Evaluate the conditions
|
||||
CList *ruleWeights=EvaluateConditions(fuzzifiedInput);
|
||||
//--- Functions evaluation
|
||||
CList *functionsResult=EvaluateFunctions(inputValues);
|
||||
//--- Combine output
|
||||
CList *result=CombineResult(ruleWeights,functionsResult);
|
||||
//---
|
||||
for(int i=0; i<functionsResult.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Obj *pair=functionsResult.GetNodeAtIndex(i);
|
||||
delete pair.Value();
|
||||
}
|
||||
delete functionsResult;
|
||||
delete ruleWeights;
|
||||
for(int i=0; i<fuzzifiedInput.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Obj *pair=fuzzifiedInput.GetNodeAtIndex(i);
|
||||
delete pair.Value();
|
||||
}
|
||||
delete fuzzifiedInput;
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,254 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| sugenovariable.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Implementation of Fuzzy library in MetaQuotes Language 5 |
|
||||
//| |
|
||||
//| The features of the library include: |
|
||||
//| - Create Mamdani fuzzy model |
|
||||
//| - Create Sugeno fuzzy model |
|
||||
//| - Normal membership function |
|
||||
//| - Triangular membership function |
|
||||
//| - Trapezoidal membership function |
|
||||
//| - Constant membership function |
|
||||
//| - Defuzzification method of center of gravity (COG) |
|
||||
//| - Defuzzification method of bisector of area (BOA) |
|
||||
//| - Defuzzification method of mean of maxima (MeOM) |
|
||||
//| |
|
||||
//| This file is free software; you can redistribute it and/or |
|
||||
//| modify it under the terms of the GNU General Public License as |
|
||||
//| published by the Free Software Foundation (www.fsf.org); either |
|
||||
//| version 2 of the License, or (at your option) any later version. |
|
||||
//| |
|
||||
//| This program is distributed in the hope that it will be useful, |
|
||||
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
//| GNU General Public License for more details. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Arrays\List.mqh>
|
||||
#include "FuzzyVariable.mqh"
|
||||
#include "Dictionary.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Purpose: creating Sugeno variable. |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| The base class for Linear Sugeno Function |
|
||||
//+------------------------------------------------------------------+
|
||||
class ISugenoFunction : public CNamedValueImpl
|
||||
{
|
||||
public:
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_ISugenoFunction); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lenear function for Sugeno Fuzzy System |
|
||||
//+------------------------------------------------------------------+
|
||||
class CLinearSugenoFunction : public ISugenoFunction
|
||||
{
|
||||
private:
|
||||
CList *m_input; // List of input variables
|
||||
CList *m_coeffs; // The dictionary which stores variables and their coefficients
|
||||
double m_const_value; // The constant term of the linear equation
|
||||
|
||||
public:
|
||||
CLinearSugenoFunction(const string name,CList *in);
|
||||
CLinearSugenoFunction(const string name,CList *in,CList *coeffs,const double constValue);
|
||||
CLinearSugenoFunction(const string name,CList *in,const double &coeffs[]);
|
||||
~CLinearSugenoFunction(void);
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_LinearSugenoFunction); }
|
||||
//--- methods gets or sets constant coefficient
|
||||
double ConstValue() { return(m_const_value); }
|
||||
void ConstValue(const double value) { m_const_value=value; }
|
||||
//--- methods gets or sets coefficient by fuzzy variable
|
||||
double GetCoefficient(CFuzzyVariable *var);
|
||||
void SetCoefficient(CFuzzyVariable *var,const double coeff);
|
||||
//--- calculate
|
||||
double Evaluate(CList *inputValues);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| First constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CLinearSugenoFunction::CLinearSugenoFunction(const string name,CList *in)
|
||||
{
|
||||
m_coeffs=new CList;
|
||||
CNamedValueImpl::Name(name);
|
||||
m_input=in;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Second constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CLinearSugenoFunction::CLinearSugenoFunction(const string name,CList *in,CList *coeffs,const double constValue)
|
||||
{
|
||||
CNamedValueImpl::Name(name);
|
||||
m_input=in;
|
||||
//--- Check that all coeffecients are related to the variable from input
|
||||
for(int i=0; i<coeffs.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=coeffs.GetNodeAtIndex(i);
|
||||
if((m_input.IndexOf(p_vd.Key())==-1) && (in.Total()==coeffs.Total()))
|
||||
{
|
||||
Print("Input of the fuzzy system does not contain all variable.");
|
||||
}
|
||||
}
|
||||
m_coeffs=coeffs;
|
||||
m_const_value=constValue;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Third constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CLinearSugenoFunction::CLinearSugenoFunction(const string name,CList *in,const double &coeffs[])
|
||||
{
|
||||
m_coeffs=new CList;
|
||||
m_input=in;
|
||||
CNamedValueImpl::Name(name);
|
||||
//--- Check input values
|
||||
if(ArraySize(coeffs)!=in.Total() && ArraySize(coeffs)!=(in.Total()+1))
|
||||
{
|
||||
Print("Wrong lenght of coefficients array");
|
||||
}
|
||||
//--- Fill list of coefficients
|
||||
for(int i=0; i<in.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=new CDictionary_Obj_Double;
|
||||
CFuzzyVariable *var=in.GetNodeAtIndex(i);
|
||||
p_vd.SetAll(var,coeffs[i]);
|
||||
m_coeffs.Add(p_vd);
|
||||
}
|
||||
if(ArraySize(coeffs)==(in.Total()+1))
|
||||
{
|
||||
m_const_value=coeffs[ArraySize(coeffs)-1];
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CLinearSugenoFunction::~CLinearSugenoFunction(void)
|
||||
{
|
||||
if(CheckPointer(m_input)==POINTER_DYNAMIC)
|
||||
delete m_input;
|
||||
if(CheckPointer(m_coeffs)==POINTER_DYNAMIC)
|
||||
delete m_coeffs;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get coefficient by fuzzy variable |
|
||||
//+------------------------------------------------------------------+
|
||||
double CLinearSugenoFunction::GetCoefficient(CFuzzyVariable *var)
|
||||
{
|
||||
if(var==NULL)
|
||||
{
|
||||
//--- return const coefficient
|
||||
return (m_const_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0; i<m_coeffs.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=m_coeffs.GetNodeAtIndex(i);
|
||||
if(p_vd.Key()==var)
|
||||
{
|
||||
//--- return coefficient
|
||||
return (p_vd.Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- return NULL
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set coefficient by fuzzy variable |
|
||||
//+------------------------------------------------------------------+
|
||||
void CLinearSugenoFunction::SetCoefficient(CFuzzyVariable *var,const double coeff)
|
||||
{
|
||||
if(var==NULL)
|
||||
{
|
||||
m_const_value=coeff;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i=0; i<m_coeffs.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd=m_coeffs.GetNodeAtIndex(i);
|
||||
if(p_vd.Key()==var)
|
||||
{
|
||||
p_vd.Value(coeff);
|
||||
}
|
||||
m_coeffs.Delete(i);
|
||||
m_coeffs.Insert(p_vd,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate result of linear function |
|
||||
//+------------------------------------------------------------------+
|
||||
double CLinearSugenoFunction::Evaluate(CList *inputValues)
|
||||
{
|
||||
double result=0.0;
|
||||
for(int i=0; i<m_coeffs.Total(); i++)
|
||||
{
|
||||
CDictionary_Obj_Double *p_vd1=m_coeffs.GetNodeAtIndex(i);
|
||||
CDictionary_Obj_Double *p_vd2=inputValues.GetNodeAtIndex(i);
|
||||
result+=(p_vd1.Value())*(p_vd2.Value());
|
||||
}
|
||||
result+=m_const_value;
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Used as an output variable in Sugeno fuzzy inference system |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSugenoVariable : public CNamedVariableImpl
|
||||
{
|
||||
private:
|
||||
CList *m_functions; // List of Sugeno functions
|
||||
|
||||
public:
|
||||
CSugenoVariable(const string name);
|
||||
~CSugenoVariable(void);
|
||||
//--- method to check type
|
||||
virtual bool IsTypeOf(EnType type) { return(type==TYPE_CLASS_SugenoVariable); }
|
||||
//--- method gets the list of functions that belongs to the variable
|
||||
CList *Functions() { return(m_functions); }
|
||||
//--- overload gets the list of functions that belongs to the variable
|
||||
CList *Values() { return(m_functions); }
|
||||
//--- find function by name
|
||||
ISugenoFunction *GetFuncByName(const string name);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor with parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoVariable::CSugenoVariable(const string name)
|
||||
{
|
||||
m_functions=new CList;
|
||||
CNamedVariableImpl::Name(name);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSugenoVariable::~CSugenoVariable(void)
|
||||
{
|
||||
delete m_functions;
|
||||
}
|
||||
//+--------------------------------------------------------------------------------------+
|
||||
//| Find function by its name |
|
||||
//+--------------------------------------------------------------------------------------+
|
||||
ISugenoFunction *CSugenoVariable::GetFuncByName(const string name)
|
||||
{
|
||||
CList *values=CSugenoVariable::Values();
|
||||
values.Total();
|
||||
for(int i=0; i<values.Total(); i++)
|
||||
{
|
||||
CNamedValueImpl *func=values.GetNodeAtIndex(i);
|
||||
if(func.Name()==name)
|
||||
{
|
||||
ISugenoFunction *result=m_functions.GetNodeAtIndex(i);
|
||||
//--- return result
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
Print("The function of the same name is not found");
|
||||
//--- return
|
||||
return (NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,772 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| the Beta distribution with shape parameters a and b. |
|
||||
//| |
|
||||
//| f(x,a,b)= (1/Beta(a,b))*x^(a-1)*(1-x)^(b-1) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityBeta(const double x,const double a,const double b,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x range
|
||||
if(x<=0.0 || x>=1.0)
|
||||
return TailLog0(true,log_mode);
|
||||
|
||||
double log_result=(a-1.0)*MathLog(x)+(b-1.0)*MathLog(1.0-x)-MathBetaLog(a,b);
|
||||
//--- return log beta density
|
||||
if(log_mode==true)
|
||||
return log_result;
|
||||
//--- return beta density
|
||||
return MathExp(log_result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| the Beta distribution with shape parameters a and b. |
|
||||
//| |
|
||||
//| f(x,a,b)= (1/Beta(a,b))*x^(a-1)*(1-x)^(b-1) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityBeta(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityBeta(x,a,b,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| Beta distribution with shape parameters a and b for values in |
|
||||
//| x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityBeta(const double &x[],const double a,const double b,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<=0.0 || x_arg>=1.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
double log_result=(a-1.0)*MathLog(x_arg)+(b-1.0)*MathLog(1.0-x_arg)-MathBetaLog(a,b);
|
||||
if(log_mode==true)
|
||||
result[i]=log_result;
|
||||
else
|
||||
result[i]=MathExp(log_result);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| Beta distribution with shape parameters a and b for values in |
|
||||
//| x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityBeta(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityBeta(x,a,b,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Beta distribution with shape parameters a and b, evaluated |
|
||||
//| at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Beta cumulative distribution function with |
|
||||
//| shape parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionBeta(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x range
|
||||
if(x<=0.0)
|
||||
return TailLog0(tail,log_mode);
|
||||
if(x>=1.0)
|
||||
return TailLog1(tail,log_mode);
|
||||
//--- calculate probability and take into account round-off errors
|
||||
double cdf=MathMin(MathBetaIncomplete(x,a,b),1.0);
|
||||
//--- return result depending on arguments
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Beta distribution with shape parameters a and b, evaluated |
|
||||
//| at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Beta cumulative distribution function with |
|
||||
//| shape parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionBeta(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionBeta(x,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| The Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Beta distribution with shape parameters a and b for values |
|
||||
//| in x[] array |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionBeta(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
if(MathIsValidNumber(x_arg))
|
||||
{
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
if(x_arg>=1.0)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate probability and take into account round-off errors
|
||||
double cdf=MathMin(MathBetaIncomplete(x_arg,a,b),1.0);
|
||||
//--- return result depending on arguments
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Beta distribution with shape parameters a and b for values |
|
||||
//| in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionBeta(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionBeta(x,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Beta distribution with shape parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function of |
|
||||
//| the Beta distribution with shape parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileBeta(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check probabilty
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
if(prob==1.0)
|
||||
return 1.0;
|
||||
|
||||
const double eps=10e-16;
|
||||
//--- set h and h_min
|
||||
double h=1.0;
|
||||
double h_min=MathSqrt(eps);
|
||||
|
||||
//--- initial x value
|
||||
double x=a/(a+b);
|
||||
if(x==0.0)
|
||||
x=h_min;
|
||||
else
|
||||
if(x==1.0)
|
||||
x=1.0-h_min;
|
||||
|
||||
int err_code=0;
|
||||
const int max_iterations=100;
|
||||
int iterations=0;
|
||||
//--- Newton iterations
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convergence
|
||||
if(((MathAbs(h)>h_min*MathAbs(x)) && (MathAbs(h)>h_min))==false)
|
||||
break;
|
||||
//--- calculate pdf and cdf
|
||||
double pdf=MathProbabilityDensityBeta(x,a,b,false,err_code);
|
||||
double cdf=MathCumulativeDistributionBeta(x,a,b,true,false,err_code);
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
|
||||
double x_new=x-h;
|
||||
//--- check x
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1.0-x)*0.1;
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
return x;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Beta distribution with shape parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Beta distribution with shape parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileBeta(const double probability,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathQuantileBeta(probability,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the the inverse cumulative distribution |
|
||||
//| function of the Beta distribution with shape parameters a and b |
|
||||
//| for the probability values from probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probability values |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| tail : Lower tail flag (lower tail of probability used) |
|
||||
//| log_mode : Logarithm mode flag (log probability used) |
|
||||
//| result : Output array with quantile values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileBeta(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
const double eps=10e-16;
|
||||
double h_min=MathSqrt(eps);
|
||||
|
||||
int err_code=0;
|
||||
const int max_iterations=1000;
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
if(MathIsValidNumber(prob))
|
||||
{
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
//--- check probabilty
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=1.0;
|
||||
else
|
||||
{
|
||||
//--- initial x value
|
||||
double x=a/(a+b);
|
||||
if(x==0.0)
|
||||
x=h_min;
|
||||
else
|
||||
if(x==1.0)
|
||||
x=1.0-h_min;
|
||||
|
||||
double h=1.0;
|
||||
int iterations=0;
|
||||
//--- Newton iterations
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convergence
|
||||
if(((MathAbs(h)>h_min*MathAbs(x)) && (MathAbs(h)>h_min))==false)
|
||||
break;
|
||||
//--- calculate pdf and cdf
|
||||
double pdf=MathProbabilityDensityBeta(x,a,b,false,err_code);
|
||||
double cdf=MathCumulativeDistributionBeta(x,a,b,true,false,err_code);
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
|
||||
double x_new=x-h;
|
||||
//--- check x
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1.0-x)*0.1;
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
result[i]=x;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the the inverse cumulative distribution |
|
||||
//| function of the Beta distribution with shape parameters a and b |
|
||||
//| for the probability values from probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probability values |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| result : Output array with quantile values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileBeta(const double &probability[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathQuantileBeta(probability,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Beta distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns a single random deviate from the Beta |
|
||||
//| distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Beta distribution. |
|
||||
//| |
|
||||
//| Reference: |
|
||||
//| Russell Cheng, |
|
||||
//| "Generating Beta Variates with Nonintegral Shape Parameters", |
|
||||
//| Communications of the ACM, |
|
||||
//| Volume 21, Number 4, April 1978, pages 317-322. |
|
||||
//| |
|
||||
//| Original FORTRAN77 version by Barry Brown, James Lovato. |
|
||||
//| C version by John Burkardt. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomBeta(const double a,const double b)
|
||||
{
|
||||
const double log4 = MathLog(4);
|
||||
const double log5 = MathLog(5);
|
||||
double a1,b1,alpha,beta,gamma,delta,r,s,u1,u2,v,y,z;
|
||||
double w=0.0;
|
||||
double value=0;
|
||||
//---
|
||||
if(1.0<a && 1.0<b)
|
||||
{
|
||||
//--- algorithm BB
|
||||
a1 = MathMin(a,b);
|
||||
b1 = MathMax(a,b);
|
||||
alpha= a1+b1;
|
||||
beta = MathSqrt((alpha-2.0)/(2.0*a1*b1-alpha));
|
||||
gamma= a1+1.0/beta;
|
||||
//---
|
||||
for(;;)
|
||||
{
|
||||
u1 = MathRandomNonZero();
|
||||
u2 = MathRandomNonZero();
|
||||
|
||||
if(u1!=1.0)
|
||||
v=beta*MathLog(u1/(1.0-u1));
|
||||
else
|
||||
v=0.0;
|
||||
|
||||
w=a1*MathExp(v);
|
||||
|
||||
z = u1*u1*u2;
|
||||
r = gamma*v - log4;
|
||||
s = a1+r-w;
|
||||
|
||||
if(5.0*z<=s+1.0+log5)
|
||||
break;
|
||||
|
||||
double t=MathLog(z);
|
||||
if(t<=s)
|
||||
break;
|
||||
|
||||
if(t<=(r+alpha*MathLog(alpha/(b1+w))))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- algorithm BC
|
||||
a1 = MathMax(a,b);
|
||||
b1 = MathMin(a,b);
|
||||
alpha=a1+b1;
|
||||
beta =1.0/b1;
|
||||
delta=1.0+a1-b1;
|
||||
double k1=delta*(1.0/72.0+b1/24.0)/(a1/b1-7.0/9.0);
|
||||
double k2=0.25+(0.5+0.25/delta)*b1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
u1 = MathRandomNonZero();
|
||||
u2 = MathRandomNonZero();
|
||||
|
||||
if(u1<0.5)
|
||||
{
|
||||
y = u1*u2;
|
||||
z = u1*y;
|
||||
|
||||
if(k1<=0.25*u2+z-y)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
z=u1*u1*u2;
|
||||
|
||||
if(z<=0.25)
|
||||
{
|
||||
if(u1!=1.0)
|
||||
v=beta*MathLog(u1/(1.0-u1));
|
||||
else
|
||||
v=0.0;
|
||||
|
||||
w=a1*MathExp(v);
|
||||
|
||||
if(a==a1)
|
||||
value=w/(b1+w);
|
||||
else
|
||||
value=b1/(b1+w);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
if(k2<z)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(u1!=1.0)
|
||||
v=beta*MathLog(u1/(1.0-u1));
|
||||
else
|
||||
v=0.0;
|
||||
w=a1*MathExp(v);
|
||||
|
||||
if(MathLog(z)<=alpha*(MathLog(alpha/(b1+w))+v)-log4)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(a==a1)
|
||||
value=w/(b1+w);
|
||||
else
|
||||
value=b1/(b1+w);
|
||||
//---
|
||||
return value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Beta distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns a single random deviate from the Beta |
|
||||
//| distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Beta distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomBeta(const double a,const double b,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- return beta random value
|
||||
return MathRandomBeta(a,b);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from Beta distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function generates random variables from Beta distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomBeta(const double a,const double b,const int data_count,double &result[])
|
||||
{
|
||||
if(data_count<=0)
|
||||
return false;
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
return false;
|
||||
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=MathRandomBeta(a,b);
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta distriburion moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Beta distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsBeta(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- initial values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =a/(a+b);
|
||||
variance=(a*b)/((a+b)*(a+b)*(a+b+1));
|
||||
skewness=2*(b-a)*MathSqrt(a+b+1)/(MathSqrt(a*b)*(a+b+2));
|
||||
kurtosis=6*(a*a*a+a*a*(1-2*b)+b*b*(1+b)-2*a*b*(2+b))/(a*b*(a+b+2)*(a+b+3));
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,874 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Beta.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the Binomial probability mass function |
|
||||
//| with parameters n and p at x. |
|
||||
//| |
|
||||
//| f(x,n,p)= C(n,x)*(p^x)*(1-p)^(n-x) |
|
||||
//| |
|
||||
//| where binomial coefficient C(n,k)=n!/(k!*(n-k)!) |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Integer random variable |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass function evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityBinomial(const double x,const double n,const double p,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check p range
|
||||
if(p<0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- case p=0
|
||||
if(p==0.0 || p==1.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- check x range
|
||||
if(x<0 || x>n)
|
||||
return TailLog0(true,log_mode);
|
||||
|
||||
double log_result=MathGammaLog(n+1.0)-MathGammaLog(x+1.0)-MathGammaLog(n-x+1.0)+x*MathLog(p)+(n-x)*MathLog(1.0-p);
|
||||
if(log_mode==true)
|
||||
return log_result;
|
||||
//--- return probability mass
|
||||
return MathExp(log_result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the Binomial probability mass function |
|
||||
//| with parameters n and p at x. |
|
||||
//| |
|
||||
//| f(x,n,p)= C(n,x)*(p^x)*(1-p)^(n-x) |
|
||||
//| |
|
||||
//| where binomial coefficient C(n,k)=n!/(k!*(n-k)!) |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Integer random variable |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass function evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityBinomial(const double x,const double n,const double p,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityBinomial(x,n,p,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the Binomial probability mass function |
|
||||
//| with parameters n and p for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with integer random variables |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityBinomial(const double &x[],const double n,const double p,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
return false;
|
||||
//--- check p range
|
||||
if(p<0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
//--- case p=0 or p=1
|
||||
if(p==0.0 || p==1.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
return true;
|
||||
}
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
if(MathIsValidNumber(x_arg) && x_arg==MathRound(x_arg))
|
||||
{
|
||||
//--- check x range
|
||||
if(x_arg<0 || x_arg>n)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
double log_result=MathGammaLog(n+1.0)-MathGammaLog(x_arg+1.0)-MathGammaLog(n-x_arg+1.0)+x_arg*MathLog(p)+(n-x_arg)*MathLog(1.0-p);
|
||||
if(log_mode==true)
|
||||
result[i]=log_result;
|
||||
else
|
||||
result[i]=MathExp(log_result);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the Binomial probability mass function |
|
||||
//| with parameters n and p for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with integer random variables |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityBinomial(const double &x[],const double n,const double p,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityBinomial(x,n,p,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the Binomial cumulative |
|
||||
//| distribution function with given n and p at the desired x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Integer random variable |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The cumulative distribution function evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionBinomial(const double x,const double n,double p,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check probability
|
||||
if(p<0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- case p==0
|
||||
if(p==0.0)
|
||||
{
|
||||
if(x>=0)
|
||||
return TailLog1(tail,log_mode);
|
||||
else
|
||||
return TailLog0(tail,log_mode);
|
||||
}
|
||||
//--- case p==1
|
||||
if(p==1.0)
|
||||
{
|
||||
if(x>n)
|
||||
return TailLog1(tail,log_mode);
|
||||
else
|
||||
return TailLog0(tail,log_mode);
|
||||
}
|
||||
//--- x must be>=0
|
||||
if(x<0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- check x
|
||||
if(x>n)
|
||||
return TailLog1(tail,log_mode);
|
||||
int err_code=0;
|
||||
//--- calculate using Beta distribution and correct round-off errors
|
||||
double result=MathMin(1.0-MathCumulativeDistributionBeta(p,x+1.0,n-x,err_code),1.0);
|
||||
//--- return result depending on arguments
|
||||
return TailLogValue(result,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the Binomial cumulative |
|
||||
//| distribution function with given n and p at the desired x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Integer random variable |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The cumulative distribution function evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionBinomial(const double x,const double n,double p,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionBinomial(x,n,p,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the Binomial cumulative |
|
||||
//| distribution function with given n and p at the desired x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with integer random variables |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionBinomial(const double &x[],const double n,double p,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
return false;
|
||||
//--- check probability
|
||||
if(p<0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
//--- case p=0 and p==1
|
||||
if(p==0.0 || p==1.0)
|
||||
{
|
||||
if(p==0.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(x[i]>=0)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
}
|
||||
}
|
||||
else
|
||||
//--- p==1.0
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(x[i]>n)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int err_code=0;
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
if(MathIsValidNumber(x_arg))
|
||||
{
|
||||
if(x_arg<0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
if(x_arg>n)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
{
|
||||
double value=MathMin(1.0-MathCumulativeDistributionBeta(p,x_arg+1.0,n-x_arg,err_code),1.0);
|
||||
//--- calculate result depending on arguments
|
||||
result[i]=TailLogValue(value,tail,log_mode);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the Binomial cumulative |
|
||||
//| distribution function with given n and p for values |
|
||||
//| from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with integer random variables |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionBinomial(const double &x[],const double n,double p,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionBinomial(x,n,p,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the inverse Binomial cumulative|
|
||||
//| distribution function with parameters n and p for the desired |
|
||||
//| probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| tail : Lower tail flag (lower tail of probability used) |
|
||||
//| log_mode : Logarithm mode flag (log probability used) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Binomial distribution with parameters n and p. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileBinomial(const double probability,const double n,const double p,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check p range
|
||||
if(p<0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
int iterations=0;
|
||||
const int max_iterations=1000;
|
||||
//--- direct cdf calculation
|
||||
double sum=MathProbabilityDensityBinomial(0,n,p,false,error_code);
|
||||
while(sum<prob && iterations<max_iterations)
|
||||
{
|
||||
sum+=MathProbabilityDensityBinomial(iterations,n,p,false,error_code);
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
{
|
||||
if(iterations==0)
|
||||
return 0.0;
|
||||
else
|
||||
return iterations-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the inverse Binomial cumulative|
|
||||
//| distribution function with parameters n and p for the desired |
|
||||
//| probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Binomial distribution with parameters n and p. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileBinomial(const double probability,const double n,const double p,int &error_code)
|
||||
{
|
||||
return MathQuantileBinomial(probability,n,p,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the value of the inverse Binomial |
|
||||
//| cumulative distribution function with parameters n and p for |
|
||||
//| the probability values from probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probability values |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| tail : Lower tail flag (lower tail of probability used) |
|
||||
//| log_mode : Logarithm mode flag (log probability used) |
|
||||
//| result : Output array with quantile values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileBinomial(const double &probability[],const double n,const double p,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
return false;
|
||||
//--- check p range
|
||||
if(p<0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
const int max_iterations=1000;
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
if(MathIsValidNumber(prob))
|
||||
{
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
int iterations=0;
|
||||
//--- direct cdf calculation
|
||||
double sum=MathProbabilityDensityBinomial(0,n,p,false,error_code);
|
||||
while(sum<prob && iterations<max_iterations)
|
||||
{
|
||||
sum+=MathProbabilityDensityBinomial(iterations,n,p,false,error_code);
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
{
|
||||
if(iterations==0)
|
||||
result[i]=0;
|
||||
else
|
||||
result[i]=iterations-1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the value of the inverse Binomial cumulative|
|
||||
//| distribution function with parameters n and p for the desired |
|
||||
//| probability values from probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probability values |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| result : Output array with quantile values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileBinomial(const double &probability[],const double n,const double p,double &result[])
|
||||
{
|
||||
return MathQuantileBinomial(probability,n,p,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from Binomial distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| This procedure generates a single random deviate from Binomial |
|
||||
//| distribution whose number of trials is N and whose probability |
|
||||
//| of an event in each trial is p. |
|
||||
//| |
|
||||
//| Input parameters: |
|
||||
//| n : Number of binomial trials from which a random deviate |
|
||||
//| will be generated. |
|
||||
//| p : The probability of an event in each trial of the binomial |
|
||||
//| distribution from which a random deviate is to be generated. |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Binomial distribution. |
|
||||
//| |
|
||||
//| Reference: |
|
||||
//| Voratas Kachitvichyanukul, Bruce Schmeiser, |
|
||||
//| "Binomial Random Variate Generation", Communications of the ACM, |
|
||||
//| Volume 31, Number 2, February 1988, pages 216-222. |
|
||||
//| |
|
||||
//| Original FORTRAN77 version by Barry Brown, James Lovato. |
|
||||
//| C version by John Burkardt. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomBinomial(const double n,const double p)
|
||||
{
|
||||
int ix,ix1,mp;
|
||||
double f,g,qn,r,t,u,v,w,w2,x,z;
|
||||
int value=0;
|
||||
int n1=(int)n;
|
||||
|
||||
double pp= MathMin(p,1.0-p);
|
||||
double q = 1.0-pp;
|
||||
double xnp=(double)(n1)*pp;
|
||||
|
||||
if(xnp<30.0)
|
||||
{
|
||||
qn= MathPow(q,n1);
|
||||
r = pp/q;
|
||||
g = r*(double)(n1+1);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
ix= 0;
|
||||
f = qn;
|
||||
u = MathRandomNonZero();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(u<f)
|
||||
{
|
||||
if(0.5<p)
|
||||
{
|
||||
ix=n1-ix;
|
||||
}
|
||||
value=ix;
|
||||
return value;
|
||||
}
|
||||
if(110<ix)
|
||||
break;
|
||||
u=u-f;
|
||||
ix=ix+1;
|
||||
f=f*(g/(double)(ix)-r);
|
||||
}
|
||||
}
|
||||
}
|
||||
double ffm=xnp+pp;
|
||||
int m=int(ffm);
|
||||
double fm=m;
|
||||
double xnpq=xnp*q;
|
||||
double p1 = (int)(2.195*MathSqrt(xnpq)-4.6*q)+0.5;
|
||||
double xm = fm + 0.5;
|
||||
double xl = xm - p1;
|
||||
double xr = xm + p1;
|
||||
double c=0.134+20.5/(15.3+fm);
|
||||
double al=(ffm-xl)/(ffm-xl*pp);
|
||||
double xll=al*(1.0+0.5*al);
|
||||
al=(xr-ffm)/(xr*q);
|
||||
double xlr= al*(1.0 + 0.5*al);
|
||||
double p2 = p1*(1.0 + c + c);
|
||||
double p3 = p2 + c/xll;
|
||||
double p4 = p3 + c/xlr;
|
||||
//--- generate a variate
|
||||
for(;;)
|
||||
{
|
||||
u = MathRandomNonZero()*p4;
|
||||
v = MathRandomNonZero();
|
||||
//--- triangle
|
||||
if(u<p1)
|
||||
{
|
||||
ix=int(xm-p1*v+u);
|
||||
if(0.5<p)
|
||||
ix=n1-ix;
|
||||
|
||||
value=ix;
|
||||
return value;
|
||||
}
|
||||
//--- parallelogram
|
||||
if(u<=p2)
|
||||
{
|
||||
x = xl+(u - p1)/c;
|
||||
v = v*c + 1.0 - MathAbs(xm-x)/p1;
|
||||
|
||||
if(v<=0.0 || 1.0<v)
|
||||
continue;
|
||||
ix=int(x);
|
||||
}
|
||||
else
|
||||
if(u<=p3)
|
||||
{
|
||||
ix=int(xl+MathLog(v)/xll);
|
||||
if(ix<0)
|
||||
continue;
|
||||
v=v*(u-p2)*xll;
|
||||
}
|
||||
else
|
||||
{
|
||||
ix=int(xr-MathLog(v)/xlr);
|
||||
if(n1<ix)
|
||||
continue;
|
||||
v=v*(u-p3)*xlr;
|
||||
}
|
||||
int k=MathAbs(ix-m);
|
||||
|
||||
if(k<=20 || xnpq/2.0-1.0<=k)
|
||||
{
|
||||
f = 1.0;
|
||||
r = pp/q;
|
||||
g = (n1+1)*r;
|
||||
|
||||
if(m<ix)
|
||||
{
|
||||
mp=m+1;
|
||||
for(int i=mp; i<=ix; i++)
|
||||
f=f*(g/i-r);
|
||||
}
|
||||
else
|
||||
if(ix<m)
|
||||
{
|
||||
ix1=ix+1;
|
||||
for(int i=ix1; i<=m; i++)
|
||||
f=f/(g/i-r);
|
||||
}
|
||||
|
||||
if(v<=f)
|
||||
{
|
||||
if(0.5<p)
|
||||
ix=n1-ix;
|
||||
|
||||
value=ix;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double amaxp=(k/xnpq)*((k*(k/3.0+0.625)+0.1666666666666)/xnpq+0.5);
|
||||
double ynorm=-double((k*k)/(2.0*xnpq));
|
||||
double alv=MathLog(v);
|
||||
|
||||
if(alv<ynorm-amaxp)
|
||||
{
|
||||
if(0.5<p)
|
||||
ix=n1-ix;
|
||||
|
||||
value=ix;
|
||||
return value;
|
||||
}
|
||||
|
||||
if(ynorm+amaxp<alv)
|
||||
continue;
|
||||
|
||||
double x1 = double(ix+1);
|
||||
double f1 = fm + 1.0;
|
||||
z = (double)(n1+1) - fm;
|
||||
w = (double)(n1-ix+1);
|
||||
double z2 = z * z;
|
||||
double x2 = x1 * x1;
|
||||
double f2 = f1 * f1;
|
||||
w2=w*w;
|
||||
|
||||
t=xm*MathLog(f1/x1)+(n1-m+0.5)*MathLog(z/w)+(double)(ix-m)*MathLog(w*pp/(x1*q))
|
||||
+(13860.0 -(462.0 -(132.0 -(99.0-140.0/f2)/f2)/f2)/f2)/f1/166320.0
|
||||
+(13860.0 -(462.0 -(132.0 -(99.0-140.0/z2)/z2)/z2)/z2)/z/166320.0
|
||||
+(13860.0 -(462.0 -(132.0 -(99.0-140.0/x2)/x2)/x2)/x2)/x1/166320.0
|
||||
+(13860.0 -(462.0 -(132.0 -(99.0-140.0/w2)/w2)/w2)/w2)/w/166320.0;
|
||||
|
||||
if(alv<=t)
|
||||
{
|
||||
if(0.5<p)
|
||||
ix=n1-ix;
|
||||
|
||||
value=ix;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from Binomial distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns random deviate from Binomial distribution |
|
||||
//| with parameters n and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Binomial distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomBinomial(const double n,const double p,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check n
|
||||
if(n<=0 || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check probability
|
||||
if(p<=0 || p>=1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- return binomial random value
|
||||
return MathRandomBinomial(n,p);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from Binomial distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function generates random variables from Binomial |
|
||||
//| distribution with parameters n and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomBinomial(const double n,const double p,const int data_count,double &result[])
|
||||
{
|
||||
if(data_count<=0)
|
||||
return false;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check n
|
||||
if(n<=0 || n!=MathRound(n))
|
||||
return false;
|
||||
//--- check probability
|
||||
if(p<=0 || p>=1.0)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=MathRandomBinomial(n,p);
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Binomial distriburion moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Binomial |
|
||||
//| distribution with parameters n and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| n : Number of trials |
|
||||
//| p : Probability of success for each trial |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsBinomial(const double n,const double p,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(n) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check n
|
||||
if(n<0 || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
//--- check p range
|
||||
if(p<=0.0 || p>=1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- prepare factors
|
||||
double np=n*p;
|
||||
double one_mp=(1.0-p);
|
||||
//--- calculate moments
|
||||
mean =np;
|
||||
variance=np*one_mp;
|
||||
skewness=(1-2*p)/MathSqrt(variance);
|
||||
kurtosis=(1-6*p*one_mp)/variance;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,539 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the value of the Cauchy probability density function |
|
||||
//| with parameters a and b at the desired quantile x. |
|
||||
//| |
|
||||
//| f(x,a,b)= 1/(pi*b*(1.0+((x-a)/b)^2) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityCauchy(const double x,const double a,const double b,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check scale
|
||||
if(b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- prepare argument
|
||||
double y=(x-a)/b;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(log_mode==true)
|
||||
return -MathLog(M_PI*b*(1.0+y*y));
|
||||
//--- return Cauchy density
|
||||
return 1.0/(M_PI*b*(1.0+y*y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the value of the Cauchy probability density function |
|
||||
//| with parameters a and b at the desired quantile x. |
|
||||
//| |
|
||||
//| f(x,a,b)= 1/(pi*b*(1.0+((x-a)/b)^2) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityCauchy(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityCauchy(x,a,b,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| Cauchy distribution with parameters a and b for values |
|
||||
//| from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityCauchy(const double &x[],const double a,const double b,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check scale
|
||||
if(b<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
//--- prepare argument
|
||||
double y=(x_arg-a)/b;
|
||||
if(log_mode==true)
|
||||
result[i]=-MathLog(M_PI*b*(1.0+y*y));
|
||||
else
|
||||
result[i]=(1.0/(M_PI*b*(1.0+y*y)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| Cauchy distribution with parameters a and b for values |
|
||||
//| in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityCauchy(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityCauchy(x,a,b,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Cauchy distribution with parameters a and b |
|
||||
//| is less than or equal to x. |
|
||||
//| F(x,a,b)=(1/2)+(1/pi)*arctan((x-a)/b) |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| The value of the Cauchy cumulative distribution function with |
|
||||
//| parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionCauchy(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check scale
|
||||
if(b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate argument
|
||||
double y=(x-a)/b;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- calculate probability and take into account round-off errors
|
||||
double cdf=0;
|
||||
if(y>-1.0)
|
||||
cdf=MathMin(0.5+M_1_PI*MathArctan(y),1.0);
|
||||
else
|
||||
cdf=MathMin(M_1_PI*MathArctan(-1/y),1.0);
|
||||
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Cauchy distribution with parameters a and b, evaluated at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| The value of the Cauchy cumulative distribution function with |
|
||||
//| parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionCauchy(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionCauchy(x,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Cauchy distribution with parameters a and b for values from |
|
||||
//| x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionCauchy(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check scale
|
||||
if(b<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- calculate argument
|
||||
double y=(x_arg-a)/b;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
return false;
|
||||
//--- calculate probability and take into account round-off errors
|
||||
double cdf=0;
|
||||
if(y>-1.0)
|
||||
cdf=MathMin(0.5+M_1_PI*MathArctan(y),1.0);
|
||||
else
|
||||
cdf=MathMin(M_1_PI*MathArctan(-1/y),1.0);
|
||||
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function |
|
||||
//| of the Cauchy distribution with parameters a and b for values |
|
||||
//| from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionCauchy(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionCauchy(x,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Cauchy distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| Q(p,a,b)=a+b*tan*(pi*(p-1/2)) |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Cauchy distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileCauchy(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check scale
|
||||
if(b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- f(1)= + infinity
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
//--- f(0)= - infinity
|
||||
if(prob==0.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QNEGINF;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- return quantile
|
||||
return a+b*MathTan(M_PI*(prob-0.5));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Cauchy distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Cauchy distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileCauchy(const double probability,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathQuantileCauchy(probability,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Cauchy distribution with parameters a and b |
|
||||
//| for the probability values from array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileCauchy(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check scale
|
||||
if(b<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(!MathIsValidNumber(probability[i]))
|
||||
return false;
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- f(1)= + infinity
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
//--- f(0)= - infinity
|
||||
if(prob==0.0)
|
||||
result[i]=QNEGINF;
|
||||
else
|
||||
result[i]=a+b*MathTan(M_PI*(prob-0.5));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileCauchy(const double &probability[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathQuantileCauchy(probability,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Cauchy distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Cauchy distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Cauchy distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomCauchy(const double a,const double b,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check scale
|
||||
if(b<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check scale=0
|
||||
if(b==0.0)
|
||||
return a;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
//--- return result
|
||||
return a+b*MathTan(M_PI*(rnd-0.5));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Cauchy distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Cauchy distribution with |
|
||||
//| parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomCauchy(const double a,const double b,const int data_count,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check scale
|
||||
if(b<0)
|
||||
return false;
|
||||
|
||||
//--- prepare output array
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
//--- check scale=0
|
||||
if(b==0.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=a;
|
||||
}
|
||||
else
|
||||
//--- calculate random values
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
result[i]=a+b*MathTan(M_PI*(rnd-0.5));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cauchy distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of Cauchy distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsCauchy(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
//--- set theoretical values for moments (undefined)
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,531 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChiSquare.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Gamma.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Chi-Square distribution with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu : Degrees of freedom |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityChiSquare(const double x,const double nu,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check arguments
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- nu must be positive integer
|
||||
if(nu<=0 || nu!=MathRound(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
|
||||
//--- calculate using Gamma density
|
||||
double pdf=MathProbabilityDensityGamma(x,nu*0.5,2.0,error_code);
|
||||
if(log_mode==true)
|
||||
return MathLog(pdf);
|
||||
return pdf;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Chi-Square distribution with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityChiSquare(const double x,const double nu,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityChiSquare(x,nu,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| ChiSquare distribution with parameter nu for values in x[] array.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityChiSquare(const double &x[],const double nu,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check arguments
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- nu must be positive integer
|
||||
if(nu<=0 || nu!=MathRound(nu))
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate using Gamma density
|
||||
double pdf=MathProbabilityDensityGamma(x_arg,nu*0.5,2.0,error_code);
|
||||
if(log_mode==true)
|
||||
result[i]=MathLog(pdf);
|
||||
else
|
||||
result[i]=pdf;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| ChiSquare distribution with parameter nu for values in x[] array.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityChiSquare(const double &x[],const double nu,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityChiSquare(x,nu,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| Chi-Square distribution with given nu, evaluated at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of Chi-Square cumulative distribution function with |
|
||||
//| parameter nu, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionChiSquare(const double x,const double nu,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check x
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- nu must be positive integer
|
||||
if(nu<=0 || nu!=MathRound(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//---- calculate using Gamma distribution
|
||||
return MathCumulativeDistributionGamma(x,nu*0.5,2.0,tail,log_mode,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| Chi-Square distribution with given nu, evaluated at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of Chi-Square cumulative distribution function with |
|
||||
//| parameter nu, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionChiSquare(const double x,const double nu,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionChiSquare(x,nu,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Chi-Square distribution with parameter nu for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionChiSquare(const double &x[],const double nu,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- nu must be positive integer
|
||||
if(nu<=0 || nu!=MathRound(nu))
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
double cdf=MathCumulativeDistributionGamma(x_arg,nu*0.5,2.0,true,false,error_code);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Chi-Square distribution with parameter nu for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionChiSquare(const double &x[],const double nu,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionChiSquare(x,nu,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Chi-Square distribution with parameter nu |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Chi-Square distribution with parameter nu. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileChiSquare(const double probability,const double nu,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- nu must be positive
|
||||
if(nu<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- nu must be integer
|
||||
if(nu!=MathRound(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
|
||||
if(prob==1.0)
|
||||
return QPOSINF;
|
||||
|
||||
//---- calculate quantile using Gamma distribution
|
||||
return MathQuantileGamma(prob,nu*0.5,2.0,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Chi-Square distribution with parameter nu |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Chi-Square distribution with parameter nu. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileChiSquare(const double probability,const double nu,int &error_code)
|
||||
{
|
||||
return MathQuantileChiSquare(probability,nu,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Chi-Square distribution with parameter nu |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileChiSquare(const double &probability[],const double nu,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- nu must be positive
|
||||
if(nu<=0)
|
||||
return false;
|
||||
//--- nu must be integer
|
||||
if(nu!=MathRound(nu))
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
//--- calculate using Gamma distribution
|
||||
result[i]=MathQuantileGamma(prob,nu*0.5,2.0,error_code);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Chi-Square distribution with parameter nu |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu : Degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileChiSquare(const double &probability[],const double nu,double &result[])
|
||||
{
|
||||
return MathQuantileChiSquare(probability,nu,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Chi-Square distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the Chi-Square distribution |
|
||||
//| with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Chi-Square distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomChiSquare(const double nu,int &error_code)
|
||||
{
|
||||
//--- NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- nu must be integer
|
||||
if(nu!=MathRound(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- nu must be positive
|
||||
if(nu<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- return gamma(nu/2,2)
|
||||
return MathRandomGamma(nu*0.5,2.0,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from Chi-Square distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Chi-Square distribution |
|
||||
//| with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomChiSquare(const double nu,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- nu must be integer
|
||||
if(nu!=MathRound(nu))
|
||||
return false;
|
||||
//--- nu must be positive
|
||||
if(nu<=0)
|
||||
return false;
|
||||
int error_code=0;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate Gamma random number
|
||||
result[i]=MathRandomGamma(nu*0.5,2.0,error_code);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chi-Square distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of Chi-Square |
|
||||
//| distribution with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsChiSquare(const double nu,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- nu must be positive integer
|
||||
if(nu<=0 || nu!=MathRound(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =nu;
|
||||
variance=2*nu;
|
||||
skewness=MathSqrt(8/nu);
|
||||
kurtosis=12/nu;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,520 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| the Exponential distribution with parameter mu. |
|
||||
//| f(x,mu)=(1/mu)*exp(-x/mu) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Mean |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityExponential(const double x,const double mu,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- calculate lambda;
|
||||
double lambda=1.0/mu;
|
||||
if(log_mode==true)
|
||||
return MathLog(lambda*MathExp(-x*lambda));
|
||||
//--- return density
|
||||
return lambda*MathExp(-x*lambda);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| the Exponential distribution with parameter mu. |
|
||||
//| f(x,mu)=(1/mu)*exp(-x/mu) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityExponential(const double x,const double mu,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityExponential(x,mu,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Exponential distribution with parameter mu for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityExponential(const double &x[],const double mu,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu))
|
||||
return false;
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate lambda;
|
||||
double lambda=1.0/mu;
|
||||
if(log_mode==true)
|
||||
result[i]=MathLog(lambda*MathExp(-x_arg*lambda));
|
||||
else
|
||||
result[i]=lambda*MathExp(-x_arg*lambda);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Exponential distribution with parameter mu for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityExponential(const double &x[],const double mu,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityExponential(x,mu,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution functin of the |
|
||||
//| Exponential distribution with parameter mu, evaluated at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Exponential cumulative distribution function |
|
||||
//| with parameter mu, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionExponential(const double x,const double mu,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check mu
|
||||
if(mu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<0.0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- calculate cdf and take into account round-off errors for probability
|
||||
double result=MathMin(1.0-MathExp(-x/mu),1.0);
|
||||
return TailLogValue(result,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| Exponential distribution with parameter mu, evaluated at x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Exponential cumulative distribution function |
|
||||
//| with parameter mu, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionExponential(const double x,const double mu,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionExponential(x,mu,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Exponential distribution with parameter mu for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionExponential(const double &x[],const double mu,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu))
|
||||
return false;
|
||||
//--- check mu
|
||||
if(mu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate cdf and take into account round-off errors for probability
|
||||
double cdf=MathMin(1.0-MathExp(-x_arg/mu),1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distirbution function of |
|
||||
//| the Exponential distribution with parameter mu for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionExponential(const double &x[],const double mu,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionExponential(x,mu,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Exponential distribution with parameter mu |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Exponential distribution with parameter mu. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileExponential(const double probability,const double mu,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check zero probability case
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
return QPOSINF;
|
||||
//--- return quantile
|
||||
return -mu*MathLog(1.0-prob);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Exponential distribution with parameter mu |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Exponential distribution with parameter mu. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileExponential(const double probability,const double mu,int &error_code)
|
||||
{
|
||||
return MathQuantileExponential(probability,mu,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Exponential distribution with parameter mu |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileExponential(const double &probability[],const double mu,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu))
|
||||
return false;
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- check zero probability case
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
result[i]=-mu*MathLog(1.0-prob);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Exponential distribution with parameter mu |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Mean |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileExponential(const double &probability[],const double mu,double &result[])
|
||||
{
|
||||
return MathQuantileExponential(probability,mu,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Exponential distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Exponential distribution |
|
||||
//| with parameter mu using simple inversion method. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Exponential distribution. |
|
||||
//| |
|
||||
//| Reference: |
|
||||
//| Devroye L. "Non-uniform random variate generation",Springer,1986.|
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomExponential(const double mu,int &error_code)
|
||||
{
|
||||
//--- check mu
|
||||
if(!MathIsValidNumber(mu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
//--- return variate using quantile
|
||||
return -mu*MathLog(1.0-rnd);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Exponential distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Exponential distribution |
|
||||
//| with parameter mu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomExponential(const double mu,const int data_count,double &result[])
|
||||
{
|
||||
//--- check mu
|
||||
if(!MathIsValidNumber(mu))
|
||||
return false;
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
result[i]=-mu*MathLog(1.0-rnd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Exponential distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Exponential |
|
||||
//| distribution with parameter mu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsExponential(const double mu,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- mu must be positive
|
||||
if(mu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =mu;
|
||||
variance=mu*mu;
|
||||
skewness=2;
|
||||
kurtosis=6;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
+563
@@ -0,0 +1,563 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| F.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Beta.mqh"
|
||||
#include "ChiSquare.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of the |
|
||||
//| F-distribution with parameters nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityF(const double x,const double nu1,const double nu2,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu1!=MathRound(nu1) || nu1<1 || nu2<1)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- calculate F density
|
||||
double value=MathPow((nu1/nu2),nu1*0.5)*MathPow(x,(nu1-2)*0.5)/MathBeta(nu1*0.5,nu2*0.5);
|
||||
value=value*MathPow(1.0+(nu1/nu2)*x,-(nu1+nu2)*0.5);
|
||||
if(log_mode==true)
|
||||
return MathLog(value);
|
||||
//--- return F density
|
||||
return value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of the |
|
||||
//| F-distribution with parameters nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityF(const double x,const double nu1,const double nu2,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityF(x,nu1,nu2,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| F distribution with parameters nu1 and nu2 for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityF(const double &x[],const double nu1,const double nu2,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu1!=MathRound(nu1) || nu1<1 || nu2<1)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate F density
|
||||
double value=MathPow((nu1/nu2),nu1*0.5)*MathPow(x_arg,(nu1-2)*0.5)/MathBeta(nu1*0.5,nu2*0.5);
|
||||
value=value*MathPow(1.0+(nu1/nu2)*x_arg,-(nu1+nu2)*0.5);
|
||||
if(log_mode==true)
|
||||
result[i]=MathLog(value);
|
||||
else
|
||||
result[i]=value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| F distribution with parameters nu1 and nu2 for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityF(const double &x[],const double nu1,const double nu2,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityF(x,nu1,nu2,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| F-distribution with given nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the F cumulative distribution function with |
|
||||
//| parameters nu1 and nu2, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionF(const double x,const double nu1,const double nu2,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- calculate cdf using incomplete Beta and take into account round-off errors for probability
|
||||
double cdf=MathMin(1.0-MathBetaIncomplete(nu2/(nu2+nu1*x),nu2*0.5,nu1*0.5),1.0);
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| F-distribution with given nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the F cumulative distribution function with |
|
||||
//| parameters nu1 and nu2, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionF(const double x,const double nu1,const double nu2,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionF(x,nu1,nu2,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the F distribution with parameters nu1 and nu2 for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionF(const double &x[],const double nu1,const double nu2,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
//--- check x
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate cdf using incomplete Beta and take into account round-off errors for probability
|
||||
double cdf=MathMin(1.0-MathBetaIncomplete(nu2/(nu2+nu1*x_arg),nu2*0.5,nu1*0.5),1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the F distribution with parameters nu1 and nu2 for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionF(const double &x[],const double nu1,const double nu2,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionF(x,nu1,nu2,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of F-distribution with parameters nu1 and nu2 |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of F-distribution with parameters nu1 and nu2. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileF(const double probability,const double nu1,const double nu2,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check case probability==1
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
//--- calculate quantile using Beta distribution
|
||||
double qBeta=MathQuantileBeta(1.0-prob,nu2*0.5,nu1*0.5,error_code);
|
||||
//--- return quantile;
|
||||
return (nu2/qBeta-nu2)/nu1;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of F-distribution with parameters nu1 and nu2 |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of F-distribution with parameters nu1 and nu2. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileF(const double probability,const double nu1,const double nu2,int &error_code)
|
||||
{
|
||||
return MathQuantileF(probability,nu1,nu2,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the F distribution with parameters nu1 and nu2 |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileF(const double &probability[],const double nu1,const double nu2,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- check case probability==1,0
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
//--- calculate quantile using Beta distribution
|
||||
double qBeta=MathQuantileBeta(1.0-prob,nu2*0.5,nu1*0.5,error_code);
|
||||
result[i]=(nu2/qBeta-nu2)/nu1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the F distribution with parameters nu1 and nu2 |
|
||||
//| for values from probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileF(const double &probability[],const double nu1,const double nu2,double &result[])
|
||||
{
|
||||
return MathQuantileF(probability,nu1,nu2,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the F-distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from F-distribution |
|
||||
//| with parameters nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with F-distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomF(const double nu1,const double nu2,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- random F=ChiSquare(nu1)*nu2/ChiSquare(nu2)*nu1;
|
||||
double xnum = MathRandomGamma(nu1*0.5,1.0,error_code)*nu2;
|
||||
double xden = MathRandomGamma(nu2*0.5,1.0,error_code)*nu1;
|
||||
//---
|
||||
double value=0.0;
|
||||
if(xden!=0)
|
||||
value= xnum/xden;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
value=QNaN;
|
||||
}
|
||||
//--- return random F
|
||||
return value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the F distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the F distribution with |
|
||||
//| parameters nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomF(const double nu1,const double nu2,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
int error_code=0;
|
||||
//--- random F=ChiSquare(nu1)*nu2/ChiSquare(nu2)*nu1;
|
||||
double xnum = MathRandomGamma(nu1*0.5,1.0,error_code)*nu2;
|
||||
double xden = MathRandomGamma(nu2*0.5,1.0,error_code)*nu1;
|
||||
//---
|
||||
double value=0.0;
|
||||
if(xden!=0)
|
||||
value= xnum/xden;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
value=QNaN;
|
||||
}
|
||||
//--- random F
|
||||
result[i]=value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| F-distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of F-distribution |
|
||||
//| with parameters nu1 and nu2. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsF(const double nu1,const double nu2,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu1!=MathRound(nu1) || nu1<1 || nu2<1)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
if(nu2>2)
|
||||
mean=nu2/(nu2-2);
|
||||
if(nu2>4)
|
||||
variance=2*nu2*nu2*(nu1+nu2-2)/(nu1*(nu2-2)*(nu2-2)*(nu2-4));
|
||||
if(nu2>6)
|
||||
skewness=2*MathSqrt(2)*MathSqrt(nu2-4)*(2*nu1+nu2-2)/(MathSqrt(nu1*(nu1+nu2-2))*(nu2-6));
|
||||
if(nu2>8)
|
||||
kurtosis=12*(nu1*(5*nu2-22)*(nu1+nu2-2)+(nu2-4)*(nu2-2)*(nu2-2))/(nu1*(nu2-8)*(nu2-6)*(nu1+nu2-2));
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,764 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Normal.mqh"
|
||||
|
||||
const double DoubleEpsilon=1.11022302462515654042E-16;
|
||||
const double LogMax=7.09782712893383996732E2;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inverse of the incomplete Gamma integral |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathInverseGammaIncomplete(const double a,const double y)
|
||||
{
|
||||
//--- bound the solution
|
||||
double x0 = DBL_MAX;
|
||||
double yl = 0;
|
||||
double x1 = 0;
|
||||
double yh = 1.0;
|
||||
double dithresh=5.0*DoubleEpsilon;
|
||||
//--- approximation to inverse function
|
||||
double d=1.0/(9.0*a);
|
||||
int err_code=0;
|
||||
double q_normal=MathQuantileNormal(y,0,1,true,false,err_code);
|
||||
double yy=(1.0-d-q_normal*MathSqrt(d));
|
||||
double x=a*yy*yy*yy;
|
||||
double lgm=MathGammaLog(a);
|
||||
for(int i=0; i<10; i++)
|
||||
{
|
||||
if(x>x0 || x<x1)
|
||||
break;
|
||||
yy=1.0-MathGammaIncomplete(x,a);
|
||||
if(yy<yl || yy>yh)
|
||||
break;
|
||||
if(yy<y)
|
||||
{
|
||||
x0 = x;
|
||||
yl = yy;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = x;
|
||||
yh = yy;
|
||||
}
|
||||
//--- compute the derivative of the function at this point
|
||||
d=(a-1.0)*MathLog(x)-x-lgm;
|
||||
if(d<-LogMax)
|
||||
break;
|
||||
d=-MathExp(d);
|
||||
//--- compute the step to the next approximation of x
|
||||
d=(yy-y)/d;
|
||||
if(MathAbs(d/x)<DoubleEpsilon)
|
||||
return (x);
|
||||
x=x-d;
|
||||
}
|
||||
//--- resort to interval halving if Newton iteration did not converge.
|
||||
d=0.0625;
|
||||
if(x0==DBL_MAX)
|
||||
{
|
||||
if(x<=0.0)
|
||||
x=1.0;
|
||||
while(x0==DBL_MAX && MathIsValidNumber(x))
|
||||
{
|
||||
x=(1.0+d)*x;
|
||||
yy=1.0-MathGammaIncomplete(x,a);
|
||||
if(yy<y)
|
||||
{
|
||||
x0 = x;
|
||||
yl = yy;
|
||||
break;
|
||||
}
|
||||
d=d+d;
|
||||
}
|
||||
}
|
||||
d=0.5;
|
||||
double dir=0;
|
||||
for(int i=0; i<400; i++)
|
||||
{
|
||||
double t=x1+d *(x0-x1);
|
||||
if(!MathIsValidNumber(t))
|
||||
break;
|
||||
x=t;
|
||||
yy=1.0-MathGammaIncomplete(x,a);
|
||||
lgm=(x0-x1)/(x1+x0);
|
||||
if(MathAbs(lgm)<dithresh)
|
||||
break;
|
||||
lgm=(yy-y)/y;
|
||||
if(MathAbs(lgm)<dithresh)
|
||||
break;
|
||||
if(x<=0.0)
|
||||
break;
|
||||
if(yy>=y)
|
||||
{
|
||||
x1 = x;
|
||||
yh = yy;
|
||||
if(dir<0)
|
||||
{
|
||||
dir=0;
|
||||
d=0.5;
|
||||
}
|
||||
else
|
||||
if(dir>1)
|
||||
d=0.5*d+0.5;
|
||||
else
|
||||
d=(y-yl)/(yh-yl);
|
||||
dir+=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = x;
|
||||
yl = yy;
|
||||
if(dir>0)
|
||||
{
|
||||
dir=0;
|
||||
d=0.5;
|
||||
}
|
||||
else
|
||||
if(dir<-1)
|
||||
d=0.5*d;
|
||||
else
|
||||
d=(y-yl)/(yh-yl);
|
||||
dir-=1;
|
||||
}
|
||||
}
|
||||
if(x==0.0 || !MathIsValidNumber(x))
|
||||
{
|
||||
Print("Errors in an arithmetic, casting, or conversion operation.");
|
||||
return(QNaN);
|
||||
}
|
||||
//---
|
||||
return(x);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| of the Gamma distribution with shape parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityGamma(const double x,const double a,const double b,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- check negative x
|
||||
if(x<=0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- calculate log Gamma density
|
||||
double log_result=(a-1.0)*MathLog(x)-(x/b)-MathGammaLog(a)-a*MathLog(b);
|
||||
if(log_mode==true)
|
||||
return(log_result);
|
||||
//--- return Gamma density
|
||||
return MathExp(log_result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| of the Gamma distribution with shape parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityGamma(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityGamma(x,a,b,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the Gamma probability density function |
|
||||
//| with parameters a and b for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| result : Output array for calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityGamma(const double &x[],const double a,const double b,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg>0)
|
||||
{
|
||||
//--- calculate log Gamma density
|
||||
double log_result=(a-1.0)*MathLog(x_arg)-(x_arg/b)-MathGammaLog(a)-a*MathLog(b);
|
||||
if(log_mode==true)
|
||||
result[i]=log_result;
|
||||
else
|
||||
result[i]=MathExp(log_result);
|
||||
}
|
||||
else
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the Gamma probability density function |
|
||||
//| with parameters a and b for values from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityGamma(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityGamma(x,a,b,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| Gamma distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Gamma cumulative distribution function |
|
||||
//| with parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionGamma(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- calculate probability using Incomplete Gamma function and take into account round-off errors
|
||||
double cdf=MathMin(MathGammaIncomplete(x/b,a),1.0);
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of the |
|
||||
//| Gamma distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Gamma cumulative distribution function |
|
||||
//| with parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionGamma(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionGamma(x,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the values of the Gamma cumulative |
|
||||
//| distribution function with given a and b for values in x[] array.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| resut : Output array for calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successul, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionGamma(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate probability using Incomplete Gamma function and take into account round-off errors
|
||||
double cdf=MathMin(MathGammaIncomplete(x_arg/b,a),1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the values of the Gamma cumulative |
|
||||
//| distribution function with given a and b for values in x[] array.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| result : Output array for calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successul, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionGamma(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionGamma(x,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Gamma distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Gamma distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileGamma(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- case log probability==-inf
|
||||
if(log_mode==true && probability==QNEGINF)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return 0.0;
|
||||
}
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- case probability==0
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
//--- case probability==1
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
//--- calculate quantile
|
||||
double quantile=MathInverseGammaIncomplete(a,1.0-prob)*b;
|
||||
if(!MathIsValidNumber(quantile))
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
//---
|
||||
return(quantile);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Gamma distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Gamma distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileGamma(const double probability,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathQuantileGamma(probability,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Gamma distribution with parameters a and b |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| result : Output array for calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileGamma(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
const double eps=10E-18;
|
||||
double max_h=MathSqrt(eps);
|
||||
const int max_iterations=1000;
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
if(!MathIsValidNumber(prob))
|
||||
return false;
|
||||
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- case probability==0
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
//--- case probability==1
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
double quantile=MathInverseGammaIncomplete(a,1.0-prob)*b;
|
||||
if(MathIsValidNumber(quantile))
|
||||
result[i]=quantile;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Gamma distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileGamma(const double &probability[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathQuantileGamma(probability,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Gamma distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Gamma distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Gamma distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Author: Robert Kern |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomGamma(const double a,const double b)
|
||||
{
|
||||
double bb,c,U,V,X=0,Y;
|
||||
//--- check shape
|
||||
if(a==1.0)
|
||||
{
|
||||
//--- exponential
|
||||
return -MathLog(1.0-MathRandomNonZero());
|
||||
}
|
||||
else
|
||||
if(a<1.0)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
U=MathRandomNonZero();
|
||||
//--- exponential
|
||||
V=-MathLog(1.0-MathRandomNonZero());
|
||||
|
||||
if(U<=1.0-a)
|
||||
{
|
||||
X=MathPow(U,1.0/a);
|
||||
if(X<=V)
|
||||
return b*X;
|
||||
}
|
||||
else
|
||||
{
|
||||
Y = -MathLog((1-U)/a);
|
||||
X = MathPow(1.0 - a + a*Y, 1.0/a);
|
||||
if(X<=(V+Y))
|
||||
return(b*X);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bb= a-1.0/3.0;
|
||||
c = 1.0/MathSqrt(9*bb);
|
||||
for(;;)
|
||||
{
|
||||
do
|
||||
{
|
||||
//--- generate normal random variate
|
||||
double f,x1,x2,r2;
|
||||
do
|
||||
{
|
||||
x1=2.0*MathRandomNonZero()-1.0;
|
||||
x2=2.0*MathRandomNonZero()-1.0;
|
||||
r2=x1*x1+x2*x2;
|
||||
}
|
||||
while(r2>=1.0 || r2==0.0);
|
||||
//--- Box-Muller transform
|
||||
f=MathSqrt(-2.0*MathLog(r2)/r2);
|
||||
X=f*x2;
|
||||
|
||||
V=1.0+c*X;
|
||||
}
|
||||
while(V<=0.0);
|
||||
|
||||
V = V*V*V;
|
||||
U = MathRandomNonZero();
|
||||
|
||||
if(U<1.0-0.0331*(X*X)*(X*X))
|
||||
return(bb*V*b);
|
||||
|
||||
if(MathLog(U)<0.5*X*X+bb*(1.0-V+MathLog(V)))
|
||||
return(bb*V*b);
|
||||
}
|
||||
}
|
||||
return(X*b);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Gamma distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Gamma distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Gamma distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomGamma(const double a,const double b,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
return MathRandomGamma(a,b);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Gamma distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function generates random variables from the Gamma |
|
||||
//| distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter (a>0) |
|
||||
//| b : Second shape parameter (b>0) |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array for random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomGamma(const double a,const double b,const int data_count,double &result[])
|
||||
{
|
||||
if(data_count<=0)
|
||||
return false;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
//--- prepare output array and calculate values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=MathRandomGamma(a,b);
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gamma distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of Gamma distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Shape |
|
||||
//| b : Scale |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsGamma(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =a*b;
|
||||
variance=a*b*b;
|
||||
skewness=2/MathSqrt(a);
|
||||
kurtosis=6/a;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,567 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function of the |
|
||||
//| Geometric distribution with parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| p : Probability parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityGeometric(const double x,const double p,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check probability
|
||||
if(p<=0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check x
|
||||
if(x!=MathRound(x))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<0)
|
||||
return TailLog0(true,log_mode);
|
||||
|
||||
if(p==1.0)
|
||||
{
|
||||
if(x==0.0)
|
||||
return TailLog1(true,log_mode);
|
||||
else
|
||||
return TailLog0(true,log_mode);
|
||||
}
|
||||
//--- return geometric density
|
||||
return TailLogValue(p*MathPow(1.0-p,x),true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function of |
|
||||
//| the Geometric distribution with parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| p : Probability parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityGeometric(const double x,const double p,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityGeometric(x,p,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability mass function of |
|
||||
//| the Geometric distribution with parameter p for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| p : Probability parameter |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityGeometric(const double &x[],const double p,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check probability
|
||||
if(p<=0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
//--- special case p==1.0
|
||||
if(p==1.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(x[i]==0.0)
|
||||
result[i]=TailLog1(true,log_mode);
|
||||
else
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg!=MathRound(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
double pdf=p*MathPow(1.0-p,x_arg);
|
||||
result[i]=TailLogValue(pdf,true,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability mass function of |
|
||||
//| the Geometric distribution with parameter p for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| p : Probability parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityGeometric(const double &x[],const double p,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityGeometric(x,p,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Geometric distribution with parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| p : Probability parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Geometric cumulative distribution function |
|
||||
//| with parameter p, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionGeometric(const double x,const double p,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check probability range
|
||||
if(p<=0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- check p
|
||||
if(p==1.0)
|
||||
{
|
||||
if(x==0.0)
|
||||
return TailLog1(true,log_mode);
|
||||
else
|
||||
return TailLog0(true,log_mode);
|
||||
}
|
||||
//--- calculate cdf and take into account round-off errors for probability
|
||||
double cdf=1.0-MathPow(1.0-p,x+1.0);
|
||||
return TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Geometric distribution with parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| p : Probability parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Geometric cumulative distribution function |
|
||||
//| with parameter p, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionGeometric(const double x,const double p,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionGeometric(x,p,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Geometric distribution with parameter p for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| p : Probability parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionGeometric(const double &x[],const double p,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check probability range
|
||||
if(p<=0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
//--- special case p==1.0
|
||||
if(p==1.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(x[i]==0.0)
|
||||
result[i]=TailLog1(true,log_mode);
|
||||
else
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
result[i]=TailLogValue(MathMin(1.0-MathPow(1.0-p,x_arg+1.0),1.0),tail,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Geometric distribution with parameter p for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| p : Probability parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionGeometric(const double &x[],const double p,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionGeometric(x,p,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Geometric distribution with parameter p for the |
|
||||
//| desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| p : Probability parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Geometric inverse cumulative distribution |
|
||||
//| function with parameter p, evaluated at probability. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileGeometric(const double probability,const double p,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check p range
|
||||
if(p<=0.0 || p>=1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- +infinity
|
||||
if(prob==1.0)
|
||||
return QPOSINF;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
|
||||
double res=MathCeil(-1.0+MathLog(1.0-prob)/MathLog(1.0-p)-1e-12);
|
||||
if(res<0)
|
||||
res=0;
|
||||
//--- return quantile
|
||||
return res;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Geometric distribution with parameter p |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| p : Probability parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Geometric quantile function for probability. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileGeometric(const double probability,const double p,int &error_code)
|
||||
{
|
||||
return MathQuantileGeometric(probability,p,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Geometric distribution with parameter p |
|
||||
//| for values form the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| p : Probability parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileGeometric(const double &probability[],const double p,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check p range
|
||||
if(p<=0.0 || p>=1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- +infinity
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
{
|
||||
double res=MathCeil(-1.0+MathLog(1.0-prob)/MathLog(1.0-p)-1e-12);
|
||||
if(res<0)
|
||||
res=0;
|
||||
result[i]=res;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Geometric distribution with parameter p |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| p : Probability parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileGeometric(const double &probability[],const double p,double &result[])
|
||||
{
|
||||
return MathQuantileGeometric(probability,p,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Geometric distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the Geometric distribution |
|
||||
//| with parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| p : Probability parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Geometric distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomGeometric(const double p,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check probability range
|
||||
if(p<0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
double res=MathCeil(-1.0+MathLog(rnd)/MathLog(1.0-p)-1e-12);
|
||||
if(res<0)
|
||||
res=0;
|
||||
return res;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Geometric distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Geometric distribution with |
|
||||
//| parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| p : Probability parameter |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomGeometric(const double p,const int data_count,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check probability range
|
||||
if(p<0.0 || p>1.0)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
double res=MathCeil(-1.0+MathLog(rnd)/MathLog(1.0-p)-1e-12);
|
||||
if(res<0)
|
||||
res=0;
|
||||
result[i]=res;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Geometric distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of Geometric |
|
||||
//| distribution with parameter p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| p : Probability parameter |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsGeometric(const double p,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check probability range
|
||||
if(p<=0.0 || p>=1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return(false);
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =(1.0/p)-1;
|
||||
variance=(1.0-p)/(p*p);
|
||||
skewness=(2.0-p)/MathSqrt(1.0-p);
|
||||
kurtosis=(p*p-6*p+6)/(1-p);
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,754 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function |
|
||||
//| of the Hypergeometric distribution with parameters m,n,k. |
|
||||
//| f(x,m,k,n)=C(k,x)*C(m-k,n-x)/C(m,n) |
|
||||
//| where binomial coefficient C(n,k)=n!/(k!*(n-k)! |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired number of objects |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass function, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityHypergeometric(const double x,const double m,const double k,const double n,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return(QNaN);
|
||||
}
|
||||
//--- m,k,n must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return(QNaN);
|
||||
}
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return(QNaN);
|
||||
}
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return(QNaN);
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check ranges
|
||||
if(x>n)
|
||||
return TailLog0(true,log_mode);
|
||||
if(x>k || m-k-n+x+1<=0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- calculate log binomial coefficients
|
||||
double log_pdf=MathBinomialCoefficientLog(k,x)+MathBinomialCoefficientLog(m-k,n-x)-MathBinomialCoefficientLog(m,n);
|
||||
if(log_mode==true)
|
||||
return log_pdf;
|
||||
//--- return hypergeometric density
|
||||
return MathExp(log_pdf);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function |
|
||||
//| of the Hypergeometric distribution with parameters m,n,k. |
|
||||
//| f(x,m,k,n)=C(k,x)*C(m-k,n-x)/C(m,n) |
|
||||
//| where binomial coefficient C(n,k)=n!/(k!*(n-k)! |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired number of objects |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass function, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityHypergeometric(const double x,const double m,const double k,const double n,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityHypergeometric(x,m,k,n,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability mass function of the |
|
||||
//| Hypergeometric distribution with parameter m,k,n for values in x.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| x : The desired number of objects |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityHypergeometric(const double &x[],const double m,const double k,const double n,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
return false;
|
||||
//--- m,k,n must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
return false;
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
return false;
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
double m_k=m-k;
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0 || x_arg!=MathRound(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg>n)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
//--- check ranges
|
||||
if(x_arg>k || m_k-n+x_arg+1<=0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate log binomial coefficients
|
||||
double log_pdf=MathBinomialCoefficientLog(k,x_arg)+MathBinomialCoefficientLog(m_k,n-x_arg)-MathBinomialCoefficientLog(m,n);
|
||||
if(log_mode==true)
|
||||
result[i]=log_pdf;
|
||||
else
|
||||
result[i]=MathExp(log_pdf);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability mass function of the |
|
||||
//| Hypergeometric distribution with parameter m,k,n for values in x.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| x : The desired number of objects |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityHypergeometric(const double &x[],const double m,const double k,const double n,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityHypergeometric(x,m,k,n,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Hypergeometric distribution with parameters m,n,k |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired number of objects |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Hypergeometric cumulative distribution function |
|
||||
//| with parameters m,n,k, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Based on algorithm by John Burkardt |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionHypergeometric(const double x,const double m,const double k,const double n,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- m,k,n,x must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n) || x!=MathRound(x))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- m,k,n,x must be positive
|
||||
if(m<0 || k<0 || n<0 || x<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x>=n || x>=k)
|
||||
return TailLog1(tail,log_mode);
|
||||
//--- calculate cdf
|
||||
double pdf = MathExp(MathBinomialCoefficientLog(m-k,n)-MathBinomialCoefficientLog(m,n));
|
||||
double cdf = pdf;
|
||||
double coef=m-k-n+1;
|
||||
for(int j=0; j<=x-1; j++)
|
||||
{
|
||||
pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j));
|
||||
cdf = cdf + pdf;
|
||||
}
|
||||
return TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Hypergeometric distribution with parameters m,n,k |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired number of objects |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Hypergeometric cumulative distribution function |
|
||||
//| with parameters m,n,k, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionHypergeometric(const double x,const double m,const double k,const double n,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionHypergeometric(x,m,k,n,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Hypergeometric distribution with parameters m,k,n for |
|
||||
//| the values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Based on algorithm by John Burkardt |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionHypergeometric(const double &x[],const double m,const double k,const double n,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
return false;
|
||||
//--- m,k,n,x must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
return false;
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
return false;
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
double coef=m-k-n+1;
|
||||
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- x must be positive and integer
|
||||
if(x_arg<0 || x_arg!=MathRound(x_arg))
|
||||
return false;
|
||||
|
||||
//--- check ranges
|
||||
if(x_arg>=n || x_arg>=k)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate cdf
|
||||
double pdf = MathExp(MathBinomialCoefficientLog(m-k,n)-MathBinomialCoefficientLog(m,n));
|
||||
double cdf = pdf;
|
||||
for(int j=0; j<=x_arg-1; j++)
|
||||
{
|
||||
pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j));
|
||||
cdf = cdf + pdf;
|
||||
}
|
||||
result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Hypergeometric distribution with parameters m,k,n for |
|
||||
//| the values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionHypergeometric(const double &x[],const double m,const double k,const double n,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionHypergeometric(x,m,k,n,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the inverse cumulative distribution function of the |
|
||||
//| Hypergeometric distribution with parameters m,n,k for the |
|
||||
//| desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The probability |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The smallest value x, such that the hypergeometric CDF(x) |
|
||||
//| equals or exceeds the desired probability. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Based on algorithm by John Burkardt |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileHypergeometric(const double probability,const double m,const double k,const double n,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- m,k,n,x must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check probability
|
||||
if(prob==0)
|
||||
return 0.0;
|
||||
if(prob==1.0)
|
||||
return QPOSINF;
|
||||
|
||||
int max_terms=1000;
|
||||
prob*=1-1000*DBL_EPSILON;
|
||||
double m_k=m-k;
|
||||
double pdf = MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n));
|
||||
double cdf = pdf;
|
||||
double coef=m_k-n+1;
|
||||
int j=0;
|
||||
while(cdf<prob && j<max_terms)
|
||||
{
|
||||
pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j));
|
||||
cdf = cdf + pdf;
|
||||
j++;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the inverse cumulative distribution function of the |
|
||||
//| Hypergeometric distribution with parameters m,n,k for the |
|
||||
//| desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The probability |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The smallest value x, such that the hypergeometric CDF(x) |
|
||||
//| equals or exceeds the desired probability. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileHypergeometric(const double probability,const double m,const double k,const double n,int &error_code)
|
||||
{
|
||||
return MathQuantileHypergeometric(probability,m,k,n,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Hypergeometric distribution with parameters |
|
||||
//| m,k,n for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Based on algorithm by John Burkardt |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileHypergeometric(const double &probability[],const double m,const double k,const double n,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
return false;
|
||||
//--- m,k,n,x must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
return false;
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
return false;
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int max_terms=1000;
|
||||
double m_k=m-k;
|
||||
double pdf0= MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n));
|
||||
double coef=m_k-n+1;
|
||||
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- check probability
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
prob*=1-1000*DBL_EPSILON;
|
||||
double pdf = pdf0;
|
||||
double cdf = pdf;
|
||||
int j=0;
|
||||
while(cdf<prob && j<max_terms)
|
||||
{
|
||||
pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j));
|
||||
cdf = cdf + pdf;
|
||||
j++;
|
||||
}
|
||||
result[i]=j;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Hypergeometric distribution with parameters |
|
||||
//| m,k,n for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileHypergeometric(const double &probability[],const double m,const double k,const double n,double &result[])
|
||||
{
|
||||
return MathQuantileHypergeometric(probability,m,k,n,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Hypergeometric distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Hypergeometric distribution |
|
||||
//| with parameters m,n,k. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Hypergeometric distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Author: John Burkardt |
|
||||
//| |
|
||||
//| Reference: |
|
||||
//| Jerry Banks, editor, Handbook of Simulation, |
|
||||
//| Engineering and Management Press Books, 1998, page 165. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomHypergeometric(const double m,const double k,const double n,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- m,k,n,x must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- generate random number
|
||||
double prob=MathRandomNonZero();
|
||||
prob*=1-1000*DBL_EPSILON;
|
||||
int max_terms=1000;
|
||||
double m_k=m-k;
|
||||
double coef=m_k-n+1;
|
||||
double pdf= MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n));
|
||||
double cdf= pdf;
|
||||
int j=0;
|
||||
while(cdf<prob && j<max_terms)
|
||||
{
|
||||
pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j));
|
||||
cdf = cdf + pdf;
|
||||
j++;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Hypergeometric distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Hypergeometric distribution |
|
||||
//| with parameters m,k,n. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomHypergeometric(const double m,const double k,const double n,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
return false;
|
||||
//--- m,k,n,x must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
return false;
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
return false;
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
return false;
|
||||
//--- prepare coefficients
|
||||
int max_terms=1000;
|
||||
double m_k=m-k;
|
||||
double coef=m_k-n+1;
|
||||
double pdf0= MathExp(MathBinomialCoefficientLog(m_k,n)-MathBinomialCoefficientLog(m,n));
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double prob=MathRandomNonZero();
|
||||
prob*=1-1000*DBL_EPSILON;
|
||||
//--- calculate using quantile
|
||||
double pdf = pdf0;
|
||||
double cdf = pdf;
|
||||
int j=0;
|
||||
while(cdf<prob && j<max_terms)
|
||||
{
|
||||
pdf = pdf*(k-j)*(n-j)/((j+1)*(coef+j));
|
||||
cdf = cdf + pdf;
|
||||
j++;
|
||||
}
|
||||
result[i]=j;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hypergeometric distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Hypergeometric |
|
||||
//| distribution with parameters m,n,k. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| m : Size of the population |
|
||||
//| k : Number of items with the desired characteristic |
|
||||
//| in the population |
|
||||
//| n : Number of samples drawn |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsHypergeometric(const double m,const double k,const double n,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(m) || !MathIsValidNumber(k) || !MathIsValidNumber(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- m,k,n must be integer
|
||||
if(m!=MathRound(m) || k!=MathRound(k) || n!=MathRound(n))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
//--- m,k,n must be positive
|
||||
if(m<0 || k<0 || n<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
//--- check ranges
|
||||
if(n>m || k>m)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =n*k/m;
|
||||
variance=k*n*(1-k/m)*(m-n)/(m*(m-1));
|
||||
skewness=MathSqrt(m-1)*(m-2*k)*(m-2*n)/((m-2)*MathSqrt(k*n*(m-k)*(m-n)));
|
||||
kurtosis=(m-1)*m*m/(k*n*(m-3)*(m-2)*(m-k)*(m-n));
|
||||
kurtosis*=3*k*(m-k)*(m*m*(n-2)-m*n*n+6*n*(m-n))/(m*m)-6*n*(m-n)+m*(m+1);
|
||||
kurtosis-=3;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,592 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| the Logistic distribution with parameters mu and sigma. |
|
||||
//| f(x,mu,sigma)=exp[-(x-mu)/sigma]/(sigma*(exp[-(x-mu)/sigma])^2) |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityLogistic(const double x,const double mu,const double sigma,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- prepare argument
|
||||
double y=(x-mu)/sigma;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
|
||||
//--- calculate exponents
|
||||
double e=MathExp(-y);
|
||||
double e1=(1+e);
|
||||
double pdf=e/(sigma*(e1*e1));
|
||||
if(log_mode==true)
|
||||
return MathLog(pdf);
|
||||
//--- return logistic density
|
||||
return pdf;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of |
|
||||
//| the Logistic distribution with parameters mu and sigma. |
|
||||
//| f(x,mu,sigma)=exp[-(x-mu)/sigma]/(sigma*(exp[-(x-mu)/sigma])^2) |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityLogistic(const double x,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityLogistic(x,mu,sigma,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Logistic distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityLogistic(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- prepare argument
|
||||
double y=(x_arg-mu)/sigma;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
return false;
|
||||
|
||||
//--- calculate exponents
|
||||
double e=MathExp(-y);
|
||||
double e1=(1+e);
|
||||
double pdf=e/(sigma*(e1*e1));
|
||||
if(log_mode==true)
|
||||
result[i]=MathLog(pdf);
|
||||
else
|
||||
result[i]=pdf;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Logistic distribution with parameters mu and sigma for |
|
||||
//| values from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityLogistic(const double &x[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityLogistic(x,mu,sigma,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Logistic distribution with parameters mu and sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Logistic cumulative distribution function |
|
||||
//| F(x,mu,sigma)=1/(1+exp[-(x-mu)/sigma]) |
|
||||
//| with parameters mu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionLogistic(const double x,const double mu,double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- prepare argument
|
||||
double y=(x-mu)/sigma;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate cdf and take into account round-off errors for probability
|
||||
double result=1.0/(1.0+MathExp(-y));
|
||||
return TailLogValue(MathMin(result,1.0),tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Logistic distribution with parameters mu and sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Logistic cumulative distribution function |
|
||||
//| F(x,mu,sigma)=1/(1+exp[-(x-mu)/sigma]) |
|
||||
//| with parameters mu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionLogistic(const double x,const double mu,double sigma,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionLogistic(x,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Logistic distribution with parameters mu and sigma for |
|
||||
//| values from the x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionLogistic(const double &x[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- prepare argument
|
||||
double y=(x_arg-mu)/sigma;
|
||||
//--- check result
|
||||
if(!MathIsValidNumber(y))
|
||||
return false;
|
||||
//--- calculate cdf and take into account round-off errors for probability
|
||||
double cdf=MathMin(1.0/(1.0+MathExp(-y)),1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Logistic distribution with parameters mu and sigma for |
|
||||
//| values from the x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionLogistic(const double &x[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionLogistic(x,mu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Logistic distribution with parameters mu |
|
||||
//| and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| Q(p,mu,sigma)= mu+sigma*log(p/(1-p)) |
|
||||
//| of the Logistic distribution with parameters mu and sigma. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileLogistic(const double probability,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
if(prob==0.0 || prob==1.0)
|
||||
{
|
||||
if(sigma==0.0)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return mu;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
if(prob==0.0)
|
||||
return QNEGINF;
|
||||
else
|
||||
return QPOSINF;
|
||||
}
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate quantile
|
||||
double q=MathLog(prob/(1.0-prob));
|
||||
//--- return rescaled/shifted quantile
|
||||
return mu+sigma*q;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Logistic distribution with parameters mu |
|
||||
//| and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Logistic distribution with parameters mu and sigma. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileLogistic(const double probability,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathQuantileLogistic(probability,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Logistic distribution with parameters mu and |
|
||||
//| sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileLogistic(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
if(prob==0.0 || prob==1.0)
|
||||
{
|
||||
if(sigma==0.0)
|
||||
result[i]=mu;
|
||||
else
|
||||
{
|
||||
if(prob==0.0)
|
||||
result[i]=QNEGINF;
|
||||
else
|
||||
result[i]=QPOSINF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- calculate quantile
|
||||
double q=MathLog(prob/(1.0-prob));
|
||||
//--- rescaled/shifted quantile
|
||||
result[i]=mu+sigma*q;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Logistic distribution with parameters mu and |
|
||||
//| sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileLogistic(const double &probability[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathQuantileLogistic(probability,mu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Logistic distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Logistic distribution |
|
||||
//| with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Logistic distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomLogistic(const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check sigma
|
||||
if(sigma==0.0)
|
||||
return mu;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
//--- return value
|
||||
return mu+sigma*MathLog(rnd/(1.0-rnd));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Logistic distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Logistic distribution |
|
||||
//| with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| sigma : Scale parameter |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomLogistic(const double mu,const double sigma,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
return false;
|
||||
|
||||
//--- prepare output array
|
||||
ArrayResize(result,data_count);
|
||||
//--- check sigma
|
||||
if(sigma==0.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=mu;
|
||||
return true;
|
||||
}
|
||||
//--- calculate random variables
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
//--- calculate logistic random number
|
||||
result[i]=mu+sigma*MathLog(rnd/(1.0-rnd));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Logistic distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Logistic |
|
||||
//| distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean parameter |
|
||||
//| sigma : Scale parameter |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsLogistic(const double mu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =mu;
|
||||
variance=MathPow(M_PI*sigma,2)/3.0;
|
||||
skewness=0;
|
||||
kurtosis=(21.0/5.0)-3;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,635 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Normal.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Lognormal distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| f(x,mu,sigma)=[1/(x*sigma*sqrt(2pi)]*exp(-(ln(x)-mu)/(2*sigma^2))|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityLognormal(const double x,const double mu,const double sigma,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- check case sigma==0
|
||||
if(sigma==0)
|
||||
{
|
||||
if(MathLog(MathAbs(x))==mu)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
else
|
||||
return TailLog0(true,log_mode);
|
||||
}
|
||||
//--- prepare argument
|
||||
double y=(MathLog(x)-mu)/sigma;
|
||||
//--- check argument
|
||||
if(!MathIsValidNumber(y))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check overflow
|
||||
y=MathAbs(y);
|
||||
if(y>=2*MathSqrt(DBL_MAX))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- return lognormal density
|
||||
return TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/(x*sigma),true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Lognormal distribution with parameters mu and sigma |
|
||||
//| for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityLognormal(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
//--- check case sigma==0
|
||||
if(sigma==0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(MathLog(MathAbs(x[i]))==mu)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- check x
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- prepare argument
|
||||
double y=(MathLog(x_arg)-mu)/sigma;
|
||||
//--- check argument
|
||||
if(!MathIsValidNumber(y))
|
||||
return false;
|
||||
//--- check overflow
|
||||
y=MathAbs(y);
|
||||
if(y>=2*MathSqrt(DBL_MAX))
|
||||
return false;
|
||||
//--- return lognormal density
|
||||
result[i]=TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/(x_arg*sigma),true,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Lognormal distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityLognormal(const double &x[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityLognormal(x,mu,sigma,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Lognormal distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| f(x,mu,sigma)=[1/(x*sigma*sqrt(2pi)]*exp(-(ln(x)-mu)/(2*sigma^2))|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityLognormal(const double x,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityLognormal(x,mu,sigma,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Lognormal distribution with parameters mu and sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Lognormal cumulative distribution function |
|
||||
//| with parameters mu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionLognormal(const double x,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0.0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- return lognormal cdf using Normal cdf
|
||||
return MathCumulativeDistributionNormal(MathLog(x),mu,sigma,tail,log_mode,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Lognormal distribution with parameters mu and sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Lognormal cumulative distribution function |
|
||||
//| with parameters mu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionLognormal(const double x,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionLognormal(x,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Lognormal distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionLognormal(const double &x[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- check x
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
//--- return lognormal cdf using Normal cdf
|
||||
result[i]=MathCumulativeDistributionNormal(MathLog(x_arg),mu,sigma,tail,log_mode,error_code);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Lognormal distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionLognormal(const double &x[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionLognormal(x,mu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Lognormal distribution with parameters mu |
|
||||
//| and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The quantile value of the Lognormal distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileLognormal(const double probability,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
if(log_mode==true && probability==QNEGINF)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return 0.0;
|
||||
}
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- special cases exp(a+b-+infinity)
|
||||
if(prob==0.0 || prob==1.0)
|
||||
{
|
||||
if(sigma==0.0)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return MathExp(mu);
|
||||
}
|
||||
else
|
||||
if(prob==0.0)
|
||||
{
|
||||
if(sigma>0)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
if(sigma>0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- return lognormal quantile using Normal distribution
|
||||
return MathExp(MathQuantileNormal(prob,mu,sigma,error_code));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Lognormal distribution with parameters mu and sigma |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The quantile value of the Lognormal distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileLognormal(const double probability,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathQuantileLognormal(probability,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Lognormal distribution with parameters mu and |
|
||||
//| sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileLognormal(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- special cases exp(a+b-+infinity)
|
||||
if(prob==0.0 || prob==1.0)
|
||||
{
|
||||
if(sigma==0.0)
|
||||
result[i]=MathExp(mu);
|
||||
else
|
||||
if(prob==0.0)
|
||||
{
|
||||
if(sigma>0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(sigma<0)
|
||||
result[i]=QPOSINF;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sigma<0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(sigma>0)
|
||||
result[i]=QPOSINF;
|
||||
}
|
||||
}
|
||||
else
|
||||
//--- calculate lognormal quantile using Normal distribution
|
||||
result[i]=MathExp(MathQuantileNormal(prob,mu,sigma,error_code));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Lognormal distribution with parameters mu and |
|
||||
//| sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileLognormal(const double &probability[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathQuantileLognormal(probability,mu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Lognormal distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the Lognormal distribution |
|
||||
//| with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Lognormal distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomLognormal(const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
//---
|
||||
rnd=MathQuantileNormal(rnd,mu,sigma,true,false,error_code);
|
||||
return MathExp(rnd);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Lognormal distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Lognormal distribution |
|
||||
//| with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomLognormal(const double mu,const double sigma,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
int err_code=0;
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=MathRandomNonZero();
|
||||
//--- return normal random array using quantile
|
||||
MathQuantileNormal(result,mu,sigma,result);
|
||||
return MathExp(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lognormal distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Lognormal |
|
||||
//| distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Log mean |
|
||||
//| sigma : Log standard deviation |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsLognormal(const double mu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- sigma squared
|
||||
double sigma_sqr=sigma*sigma;
|
||||
double exp_sigma_sqr=MathExp(sigma_sqr);
|
||||
//--- calculate moments
|
||||
mean =MathExp(mu+sigma_sqr*0.5);
|
||||
variance=(exp_sigma_sqr-1.0)*MathExp(2*mu+sigma_sqr);
|
||||
skewness=MathSqrt(exp_sigma_sqr-1.0)*(exp_sigma_sqr+2.0);
|
||||
kurtosis=3*MathPowInt(exp_sigma_sqr,2)+2*MathPowInt(exp_sigma_sqr,3)+MathPowInt(exp_sigma_sqr,4)-3-3;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
@@ -0,0 +1,643 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| NegativeBinomial.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Gamma.mqh"
|
||||
#include "Poisson.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function |
|
||||
//| of the Negative Binomial distribution with parameters r and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNegativeBinomial(const double x,const double r,const double p,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- calculate gamma factor for the density
|
||||
double coef=MathRound(MathExp(MathGammaLog(r+x)-MathGammaLog(x+1.0)-MathGammaLog(r)));
|
||||
//--- return density
|
||||
return TailLogValue(coef*MathPow(p,r)*MathPow(1.0-p,x),true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function |
|
||||
//| of the Negative Binomial distribution with parameters r and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNegativeBinomial(const double x,const double r,const double p,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityNegativeBinomial(x,r,p,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability mass function |
|
||||
//| of the Negative Binomial distribution with parameters r and p |
|
||||
//| for values from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNegativeBinomial(const double &x[],const double r,const double p,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
double power_p_r=MathPow(p,r);
|
||||
double log_gamma_r=MathGammaLog(r);
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate pdf
|
||||
double pdf=power_p_r*MathPow(1.0-p,x_arg)*MathRound(MathExp(MathGammaLog(r+x_arg)-MathGammaLog(x_arg+1.0)-log_gamma_r));
|
||||
result[i]=TailLogValue(pdf,true,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability mass function |
|
||||
//| of the Negative Binomial distribution with parameters r and p |
|
||||
//| for values from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNegativeBinomial(const double &x[],const double r,const double p,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityNegativeBinomial(x,r,p,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Negative Binomial distribution with parameters r and p |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Negative Binomial cumulative distribution |
|
||||
//| function with parameters r and p, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNegativeBinomial(const double x,const double r,double p,const bool tail,const bool log_mode,int error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0 || x<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<0.0)
|
||||
return TailLog0(tail,log_mode);
|
||||
int err_code=0;
|
||||
//--- calculate max term of the sum
|
||||
int max_j=(int)MathFloor(x);
|
||||
double p1=1.0-p;
|
||||
//--- initial factors
|
||||
double factor1=MathFactorial((int)r-1);
|
||||
double factor2=1.0;
|
||||
double factor_p=1.0;
|
||||
double factor_r=1.0/factor1;
|
||||
double power_p_r=MathPowInt(p,int(r))*factor_r;
|
||||
double cdf=0.0;
|
||||
for(int j=0; j<=max_j; j++)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
factor1*=(j+1);
|
||||
factor2*=j;
|
||||
factor_p*=p1;
|
||||
}
|
||||
double pdf=power_p_r*factor1*factor_p/factor2;
|
||||
cdf+=pdf;
|
||||
}
|
||||
//--- take into account round-off errors for probability
|
||||
return TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Negative Binomial distribution with parameters r and p |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Negative Binomial cumulative distribution |
|
||||
//| function with parameters r and p, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNegativeBinomial(const double x,const double r,double p,int error_code)
|
||||
{
|
||||
return MathCumulativeDistributionNegativeBinomial(x,r,p,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function |
|
||||
//| of the Negative Binomial distribution with parameters r and p |
|
||||
//| for values from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNegativeBinomial(const double &x[],const double r,double p,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
//--- common factors
|
||||
double fact1=MathFactorial((int)r-1);
|
||||
double factor_r=1.0/fact1;
|
||||
double power_p_r=MathPowInt(p,int(r))*factor_r;
|
||||
double p1=1.0-p;
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
int err_code=0;
|
||||
//--- calculate max term of the sum
|
||||
int max_j=(int)MathFloor(x_arg);
|
||||
//--- initial factors
|
||||
double factor1=fact1;
|
||||
double factor2=1.0;
|
||||
double factor_p=1.0;
|
||||
double cdf=0.0;
|
||||
for(int j=0; j<=max_j; j++)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
factor1*=(j+1);
|
||||
factor2*=j;
|
||||
factor_p*=p1;
|
||||
}
|
||||
double pdf=power_p_r*factor1*factor_p/factor2;
|
||||
cdf+=pdf;
|
||||
}
|
||||
//--- take into account round-off errors for probability
|
||||
result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function |
|
||||
//| of the Negative Binomial distribution with parameters r and p |
|
||||
//| for values from x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNegativeBinomial(const double &x[],const double r,double p,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionNegativeBinomial(x,r,p,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Negative Binomial distribution with parameters |
|
||||
//| r and p for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Negative Binomial distribution with parameters r and p. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNegativeBinomial(const double probability,const double r,const double p,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check cases p=0 and p=1
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
|
||||
int max_terms=1000;
|
||||
int err_code=0;
|
||||
//--- factors
|
||||
double fact1=MathFactorial((int)r-1);
|
||||
double factor_r=1.0/fact1;
|
||||
double power_p_r=MathPowInt(p,int(r))*factor_r;
|
||||
double p1=1.0-p;
|
||||
//--- initial factors
|
||||
double factor1=fact1;
|
||||
double factor2=1.0;
|
||||
double factor_p=1.0;
|
||||
double cdf=0.0;
|
||||
int j=0;
|
||||
while(cdf<prob && j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
factor1*=(j+1);
|
||||
factor2*=j;
|
||||
factor_p*=p1;
|
||||
}
|
||||
double pdf=power_p_r*factor1*factor_p/factor2;
|
||||
cdf+=pdf;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
{
|
||||
if(j==0)
|
||||
return 0;
|
||||
else
|
||||
return j-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Negative Binomial distribution with parameters |
|
||||
//| r and p for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Negative Binomial distribution with parameters r and p. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNegativeBinomial(const double probability,const double r,const double p,int &error_code)
|
||||
{
|
||||
return MathQuantileNegativeBinomial(probability,r,p,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Negative Binomial distribution with parameters |
|
||||
//| r and p for values form the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNegativeBinomial(const double &probability[],const double r,const double p,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<0.0 || p>1.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
//--- common factors
|
||||
double fact1=MathFactorial((int)r-1);
|
||||
double factor_r=1.0/fact1;
|
||||
double power_p_r=MathPowInt(p,int(r))*factor_r;
|
||||
double p1=1.0-p;
|
||||
int max_terms=500;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
double factor1=fact1;
|
||||
double factor2=1.0;
|
||||
double factor_p=1.0;
|
||||
double cdf=0.0;
|
||||
int j=0;
|
||||
while(cdf<prob && j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
factor1*=(j+1);
|
||||
factor2*=j;
|
||||
factor_p*=p1;
|
||||
}
|
||||
double pdf=power_p_r*factor1*factor_p/factor2;
|
||||
cdf+=pdf;
|
||||
j++;
|
||||
}
|
||||
if(j<max_terms)
|
||||
{
|
||||
if(j==0)
|
||||
result[i]=0;
|
||||
else
|
||||
result[i]=j-1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Negative Binomial distribution with parameters |
|
||||
//| r and p for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNegativeBinomial(const double &probability[],const double r,const double p,double &result[])
|
||||
{
|
||||
return MathQuantileNegativeBinomial(probability,r,p,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Negative Binomial distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the Negative Binomial |
|
||||
//| distribution with parameters r and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Negative Binomial distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomNegativeBinomial(const double r,const double p,int error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(r<=0.0 || p<=0.0 || p>=1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
double r_gamma=MathRandomGamma(r,(1-p)/p);
|
||||
return MathRandomPoisson(r_gamma,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Negative Binomial distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Negative Binomial |
|
||||
//| distribution with parameters r and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomNegativeBinomial(const double r,const double p,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(r<=0.0 || p<=0.0 || p>=1.0)
|
||||
return false;
|
||||
|
||||
double p_coef=(1-p)/p;
|
||||
int error_code=0;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double r_gamma=MathRandomGamma(r,p_coef);
|
||||
result[i]=MathRandomPoisson(r_gamma,error_code);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Negative Binomial distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of Negative Binomial |
|
||||
//| distribution with parameters r and p. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| r : Number of successes |
|
||||
//| p : Probability of success |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsNegativeBinomial(const double r,double p,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(r) || !MathIsValidNumber(p))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check arguments
|
||||
if(r!=MathRound(r) || r<1.0 || p<=0.0 || p>=1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =r*(1.0-p)/p;
|
||||
variance=mean/p;
|
||||
skewness=(2.0-p)/MathSqrt((r*(1.0-p)));
|
||||
kurtosis=(p*p-6*p+6)/(r*(1.0-p));
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,954 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| NoncentralBeta.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Beta.mqh"
|
||||
#include "NoncentralChiSquare.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Noncental Beta distribution with parameters a,b,lambda |
|
||||
//| Infinity |
|
||||
//| f(x,a,b,lambda)=Sum [p(k)*x^(a+k-1)*(1-x)^(b-1)]/Beta(a+k,b) |
|
||||
//| k=0 |
|
||||
//| |
|
||||
//| where p(k)=(1/k!)*exp(-lambda/2)*(lambda/2)^k, |
|
||||
//| Beta(a,b)=Gamma(a)*Gamma(b)/Gamma(a+b) |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNoncentralBeta(const double x,const double a,const double b,const double lambda,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- if lambda==0, return Beta density
|
||||
if(lambda==0.0)
|
||||
return MathProbabilityDensityBeta(x,a,b,error_code);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0 || x>=1.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- factors
|
||||
double lambda_half=lambda*0.5;
|
||||
double fact_mult=1.0;
|
||||
double pwr_lambda_half=1.0;
|
||||
double pwr_x=MathExp((a-1.0)*MathLog(x));
|
||||
double r_beta=MathBeta(a,b);
|
||||
double pdf=0;
|
||||
//--- direct sum calculation
|
||||
for(int j=0;; j++)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_x*=x;
|
||||
pwr_lambda_half*=lambda_half;
|
||||
fact_mult/=j;
|
||||
double jm1=j-1;
|
||||
r_beta*=((a+jm1)/(a+b+jm1));
|
||||
}
|
||||
double term=pwr_x*fact_mult*pwr_lambda_half/r_beta;
|
||||
//---
|
||||
if(term<10E-18)
|
||||
break;
|
||||
pdf+=term;
|
||||
}
|
||||
//--- calculate density coef
|
||||
pdf*=MathExp((b-1.0)*MathLog(1.0-x))*MathExp(-lambda_half);
|
||||
//--- return density
|
||||
return TailLogValue(pdf,true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Noncental Beta distribution with parameters a,b,lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNoncentralBeta(const double x,const double a,const double b,const double lambda,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityNoncentralBeta(x,a,b,lambda,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Noncentral Beta distribution with parameters a,b,lambda |
|
||||
//| for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNoncentralBeta(const double &x[],const double a,const double b,const double lambda,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- if lambda==0, return Beta density
|
||||
if(lambda==0.0)
|
||||
return MathProbabilityDensityBeta(x,a,b,log_mode,result);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
//--- common factors
|
||||
double lambda_half=lambda*0.5;
|
||||
double exp_lambda_half=MathExp(-lambda_half);
|
||||
double r_beta0=MathBeta(a,b);
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0.0 || x_arg>=1.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
double fact_mult=1.0;
|
||||
double pwr_lambda_half=1.0;
|
||||
double pwr_x=MathExp((a-1.0)*MathLog(x_arg));
|
||||
double r_beta=r_beta0;
|
||||
double pdf=0;
|
||||
for(int j=0;; j++)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_x*=x_arg;
|
||||
pwr_lambda_half*=lambda_half;
|
||||
fact_mult/=j;
|
||||
double jm1=j-1;
|
||||
r_beta*=((a+jm1)/(a+b+jm1));
|
||||
}
|
||||
double term=pwr_x*fact_mult*pwr_lambda_half/r_beta;
|
||||
//---
|
||||
if(term<10E-18)
|
||||
break;
|
||||
pdf+=term;
|
||||
}
|
||||
//--- calculate density coef
|
||||
pdf*=MathExp((b-1.0)*MathLog(1.0-x_arg))*exp_lambda_half;
|
||||
result[i]=TailLogValue(pdf,true,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Noncentral Beta distribution with parameters a,b,lambda |
|
||||
//| for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNoncentralBeta(const double &x[],const double a,const double b,const double lambda,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityNoncentralBeta(x,a,b,lambda,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Noncental Beta distribution with parameters a,b,lambda |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Input parameters: |
|
||||
//| x : The desired quantile |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Noncental Beta cumulative distribution function |
|
||||
//| with parameters a,b,lambda, evaluated at x. |
|
||||
//| |
|
||||
//| Infinity |
|
||||
//| F(x,a,b,lambda)=Sum p(k)*Ix(a+k,b) |
|
||||
//| k=0 |
|
||||
//| |
|
||||
//| where p(k)=(1/k!)*exp(-lambda/2)*(lambda/2)^k, |
|
||||
//| Ix(a,b) - incomplete Beta function |
|
||||
//| |
|
||||
//| Author: John Burkardt |
|
||||
//| |
|
||||
//| Reference: |
|
||||
//| Harry Posten,"An Effective Algorithm for the Noncentral Beta |
|
||||
//| Distribution Function", The American Statistician, |
|
||||
//| Volume 47, Number 2, May 1993, pages 129-131. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNoncentralBeta(const double x,const double a,const double b,const double lambda,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- if lambda==0, return Beta CDF
|
||||
if(lambda==0.0)
|
||||
return MathCumulativeDistributionBeta(x,a,b,error_code);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0)
|
||||
return TailLog0(tail,log_mode);
|
||||
if(x>=1.0)
|
||||
return TailLog1(tail,log_mode);
|
||||
|
||||
const int max_terms=100;
|
||||
double c=lambda*0.5;
|
||||
double x0 = int(MathMax(c - 5*MathSqrt(c), 0));
|
||||
double a0 = a + x0;
|
||||
double beta = MathGammaLog(a0) + MathGammaLog(b) - MathGammaLog(a0+b);
|
||||
double temp = MathBetaIncomplete(x, a0, b);
|
||||
double gx=MathExp(a0*MathLog(x)+b*MathLog(1-x)-beta-MathLog(a0));
|
||||
|
||||
double q=0;
|
||||
if(a0>a)
|
||||
q=MathExp(-c+x0*MathLog(c)-MathGammaLog(x0+1));
|
||||
else
|
||||
q=MathExp(-c);
|
||||
|
||||
double sumq=1-q;
|
||||
double betanc=q*temp;
|
||||
double ab=a+b;
|
||||
int j=0;
|
||||
for(;;)
|
||||
{
|
||||
j++;
|
||||
temp-=gx;
|
||||
gx*=x*(ab+j-1)/(a+j);
|
||||
q*=c/j;
|
||||
sumq-=q;
|
||||
betanc+=temp*q;
|
||||
double err=(temp-gx)*sumq;
|
||||
if(j>max_terms || err<1E-18)
|
||||
break;
|
||||
}
|
||||
double cdf=MathMin(betanc,1.0);
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Noncental Beta distribution with parameters a,b,lambda |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Input parameters: |
|
||||
//| x : The desired quantile |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Noncental Beta cumulative distribution function |
|
||||
//| with parameters a,b,lambda, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNoncentralBeta(const double x,const double a,const double b,const double lambda,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionNoncentralBeta(x,a,b,lambda,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Noncentral Beta distribution with parameters a,b,lambda |
|
||||
//| for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNoncentralBeta(const double &x[],const double a,const double b,const double lambda,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- if lambda==0, return Beta CDF
|
||||
if(lambda==0.0)
|
||||
return MathCumulativeDistributionBeta(x,a,b,tail,log_mode,result);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
const int max_terms=100;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
if(x_arg>=1.0)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
{
|
||||
double c=lambda*0.5;
|
||||
double x0 = int(MathMax(c - 5*MathSqrt(c), 0));
|
||||
double a0 = a + x0;
|
||||
double beta = MathGammaLog(a0) + MathGammaLog(b) - MathGammaLog(a0+b);
|
||||
double temp = MathBetaIncomplete(x_arg, a0, b);
|
||||
double gx=MathExp(a0*MathLog(x_arg)+b*MathLog(1-x_arg)-beta-MathLog(a0));
|
||||
|
||||
double q=0;
|
||||
if(a0>a)
|
||||
q=MathExp(-c+x0*MathLog(c)-MathGammaLog(x0+1));
|
||||
else
|
||||
q=MathExp(-c);
|
||||
|
||||
double sumq=1-q;
|
||||
double betanc=q*temp;
|
||||
int j=0;
|
||||
double ab=a+b;
|
||||
for(;;)
|
||||
{
|
||||
j++;
|
||||
temp-=gx;
|
||||
gx*=x_arg*(ab+j-1)/(a+j);
|
||||
q*=c/j;
|
||||
sumq-=q;
|
||||
betanc+=temp*q;
|
||||
double err=(temp-gx)*sumq;
|
||||
if(j>max_terms || err<1E-18)
|
||||
break;
|
||||
}
|
||||
double cdf=MathMin(betanc,1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Noncentral Beta distribution with parameters a,b,lambda |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNoncentralBeta(const double &x[],const double a,const double b,const double lambda,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionNoncentralBeta(x,a,b,lambda,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Noncental Beta distribution with parameters a,b |
|
||||
//| and lambda for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function of |
|
||||
//| of Noncental Beta distribution with parameters a,b and lambda. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNoncentralBeta(const double probability,const double a,const double b,const double lambda,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
if(log_mode==true && probability==QNEGINF)
|
||||
return 0.0;
|
||||
if(log_mode==false && probability==0)
|
||||
return 0.0;
|
||||
//--- if lambda==0, return beta quantile
|
||||
if(lambda==0.0)
|
||||
return MathQuantileBeta(probability,a,b,error_code);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check probabilty
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
if(prob==1.0)
|
||||
return 1.0;
|
||||
|
||||
double lambda_half=lambda*0.5;
|
||||
double lambda_half_log=MathLog(lambda_half);
|
||||
double lambda_half_sqrt=MathSqrt(lambda_half);
|
||||
double lambda_half_exp=MathExp(-lambda_half);
|
||||
|
||||
double x0=int(MathMax(lambda_half-5*lambda_half_sqrt,0));
|
||||
double b_gamma_log=MathGammaLog(b);
|
||||
double eps=10E-18;
|
||||
double h_min=MathSqrt(eps);
|
||||
|
||||
//double lambda_half=lambda*0.5;
|
||||
double r_beta0=MathBeta(a,b);
|
||||
|
||||
int err_code=0;
|
||||
double x=0.5;
|
||||
double h=1.0;
|
||||
const int max_terms=100;
|
||||
//--- Newton iterations
|
||||
const int max_iterations=50;
|
||||
int iterations=0;
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convergence
|
||||
if((MathAbs(h)>h_min*MathAbs(x) && MathAbs(h)>h_min)==false)
|
||||
break;
|
||||
|
||||
//--- calculate PDF
|
||||
double pdf=0;
|
||||
if(x<=0.0 || x>=1.0)
|
||||
pdf=0;
|
||||
else
|
||||
{
|
||||
double fact_mult=1.0;
|
||||
double pwr_lambda_half=1.0;
|
||||
double pwr_x=MathExp((a-1.0)*MathLog(x));
|
||||
double r_beta=r_beta0;
|
||||
//--- direct sum calculation
|
||||
for(int j=0;; j++)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_x*=x;
|
||||
pwr_lambda_half*=lambda_half;
|
||||
fact_mult/=j;
|
||||
double jm1=j-1;
|
||||
r_beta*=((a+jm1)/(a+b+jm1));
|
||||
}
|
||||
double term=pwr_x*fact_mult*pwr_lambda_half/r_beta;
|
||||
//---
|
||||
if(term<10E-18)
|
||||
break;
|
||||
pdf+=term;
|
||||
}
|
||||
//--- calculate density coef
|
||||
pdf*=MathExp((b-1.0)*MathLog(1.0-x))*lambda_half_exp;
|
||||
}
|
||||
|
||||
//--- calculate CDF
|
||||
double cdf=0;
|
||||
if(x<=0.0)
|
||||
cdf=0;
|
||||
if(x>=1.0)
|
||||
cdf=1;
|
||||
else
|
||||
{
|
||||
double a0=a+x0;
|
||||
double beta = MathGammaLog(a0) + b_gamma_log - MathGammaLog(a0+b);
|
||||
double temp = MathBetaIncomplete(x, a0, b);
|
||||
double gx=MathExp(a0*MathLog(x)+b*MathLog(1-x)-beta-MathLog(a0));
|
||||
|
||||
double q=0;
|
||||
if(a0>a)
|
||||
q=MathExp(-lambda_half+x0*lambda_half_log-MathGammaLog(x0+1));
|
||||
else
|
||||
q=lambda_half_exp;
|
||||
|
||||
double sumq=1-q;
|
||||
double betanc=q*temp;
|
||||
int j=0;
|
||||
double ab=a+b;
|
||||
for(;;)
|
||||
{
|
||||
j++;
|
||||
temp-=gx;
|
||||
gx*=x*(ab+j-1)/(a+j);
|
||||
q*=lambda_half/j;
|
||||
sumq-=q;
|
||||
betanc+=temp*q;
|
||||
double err=(temp-gx)*sumq;
|
||||
if(j>max_terms || err<1E-18)
|
||||
break;
|
||||
}
|
||||
cdf=MathMin(betanc,1.0);
|
||||
}
|
||||
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
|
||||
double x_new=x-h;
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1-x)*0.1;
|
||||
|
||||
if(MathAbs(x_new-x)<10E-16)
|
||||
break;
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
return x;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Noncental Beta distribution with parameters a, b |
|
||||
//| and lambda for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function of |
|
||||
//| of Noncental Beta distribution with parameters a,b and lambda. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNoncentralBeta(const double probability,const double a,const double b,const double lambda,int &error_code)
|
||||
{
|
||||
return MathQuantileNoncentralBeta(probability,a,b,lambda,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Noncentral Beta distribution with parameter a,b |
|
||||
//| lambda for the probability values from array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNoncentralBeta(const double &probability[],const double a,const double b,const double lambda,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- if lambda==0, return beta quantile
|
||||
if(lambda==0.0)
|
||||
return MathQuantileBeta(probability,a,b,tail,log_mode,result);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
|
||||
return false;
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int err_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
double lambda_half=lambda*0.5;
|
||||
double lambda_half_log=MathLog(lambda_half);
|
||||
double lambda_half_sqrt=MathSqrt(lambda_half);
|
||||
double lambda_half_exp=MathExp(-lambda_half);
|
||||
double r_beta0=MathBeta(a,b);
|
||||
|
||||
double x0=int(MathMax(lambda_half-5*lambda_half_sqrt,0));
|
||||
double b_gamma_log=MathGammaLog(b);
|
||||
const double eps=10E-18;
|
||||
double h_min=MathSqrt(eps);
|
||||
const int max_terms=100;
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
if(!MathIsValidNumber(prob))
|
||||
return false;
|
||||
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=1.0;
|
||||
else
|
||||
{
|
||||
double x=0.5;
|
||||
double h=1.0;
|
||||
//--- Newton iterations
|
||||
const int max_iterations=50;
|
||||
int iterations=0;
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convergence
|
||||
if((MathAbs(h)>h_min*MathAbs(x) && MathAbs(h)>h_min)==false)
|
||||
break;
|
||||
|
||||
//--- calculate PDF
|
||||
double pdf=0;
|
||||
if(x<=0.0 || x>=1.0)
|
||||
pdf=0;
|
||||
else
|
||||
{
|
||||
double fact_mult=1.0;
|
||||
double pwr_lambda_half=1.0;
|
||||
double pwr_x=MathExp((a-1.0)*MathLog(x));
|
||||
double r_beta=r_beta0;
|
||||
//--- direct sum calculation
|
||||
for(int j=0;; j++)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_x*=x;
|
||||
pwr_lambda_half*=lambda_half;
|
||||
fact_mult/=j;
|
||||
double jm1=j-1;
|
||||
r_beta*=((a+jm1)/(a+b+jm1));
|
||||
}
|
||||
double term=pwr_x*fact_mult*pwr_lambda_half/r_beta;
|
||||
//---
|
||||
if(term<10E-18)
|
||||
break;
|
||||
pdf+=term;
|
||||
}
|
||||
//--- calculate density coef
|
||||
pdf*=MathExp((b-1.0)*MathLog(1.0-x))*lambda_half_exp;
|
||||
}
|
||||
|
||||
//--- calculate CDF
|
||||
double cdf=0;
|
||||
if(x<=0.0)
|
||||
cdf=0;
|
||||
if(x>=1.0)
|
||||
cdf=1;
|
||||
else
|
||||
{
|
||||
double a0=a+x0;
|
||||
double beta = MathGammaLog(a0) + b_gamma_log - MathGammaLog(a0+b);
|
||||
double temp = MathBetaIncomplete(x, a0, b);
|
||||
double gx=MathExp(a0*MathLog(x)+b*MathLog(1-x)-beta-MathLog(a0));
|
||||
|
||||
double q=0;
|
||||
if(a0>a)
|
||||
q=MathExp(-lambda_half+x0*lambda_half_log-MathGammaLog(x0+1));
|
||||
else
|
||||
q=lambda_half_exp;
|
||||
|
||||
double sumq=1-q;
|
||||
double betanc=q*temp;
|
||||
int j=0;
|
||||
double ab=a+b;
|
||||
for(;;)
|
||||
{
|
||||
j++;
|
||||
temp-=gx;
|
||||
gx*=x*(ab+j-1)/(a+j);
|
||||
q*=lambda_half/j;
|
||||
sumq-=q;
|
||||
betanc+=temp*q;
|
||||
double err=(temp-gx)*sumq;
|
||||
if(j>max_terms || err<1E-18)
|
||||
break;
|
||||
}
|
||||
cdf=MathMin(betanc,1.0);
|
||||
}
|
||||
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
|
||||
double x_new=x-h;
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1-x)*0.1;
|
||||
|
||||
if(MathAbs(x_new-x)<10E-16)
|
||||
break;
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
result[i]=x;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Noncentral Beta distribution with parameter a,b |
|
||||
//| lambda for the probability values from array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNoncentralBeta(const double &probability[],const double a,const double b,const double lambda,double &result[])
|
||||
{
|
||||
return MathQuantileNoncentralBeta(probability,a,b,lambda,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Noncentral Beta distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Noncentral Beta |
|
||||
//| distribution with parameters a,b and lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Noncentral Beta distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomNoncentralBeta(const double a,const double b,const double lambda,int &error_code)
|
||||
{
|
||||
//--- if lambda==0, return beta random variate
|
||||
if(lambda==0.0)
|
||||
return MathRandomBeta(a,b,error_code);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- generate random number using Noncentral ChiSquare
|
||||
double chi1=MathRandomNoncentralChiSquare(2*a,lambda,error_code);
|
||||
double chi2=MathRandomChiSquare(2*b,error_code);
|
||||
return chi1/(chi1+chi2);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Noncentral Beta distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Noncentral Beta distribution |
|
||||
//| with parameters a,b, lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomNoncentralBeta(const double a,const double b,const double lambda,const int data_count,double &result[])
|
||||
{
|
||||
//--- if lambda==0, return beta random variate
|
||||
if(lambda==0.0)
|
||||
return MathRandomBeta(a,b,data_count,result);
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
|
||||
return false;
|
||||
//--- a,b,lambda must be positive
|
||||
if(a<=0.0 || b<=0.0 || lambda<0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
double a2=a*2;
|
||||
double b2=b*2;
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number using Noncentral ChiSquare
|
||||
double chi1=MathRandomNoncentralChiSquare(a2,lambda,error_code);
|
||||
double chi2=MathRandomChiSquare(b2,error_code);
|
||||
result[i]=chi1/(chi1+chi2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncental Beta distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Noncental Beta |
|
||||
//| distribution with parameters a,b and lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : First shape parameter |
|
||||
//| b : Second shape parameter |
|
||||
//| lambda : Noncentrality parameter |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathMomentsNoncentralBeta(const double a,const double b,const double lambda,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0.0 || b<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
//--- check lambda
|
||||
if(lambda<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- prepare coefficients
|
||||
double lambda_half=lambda*0.5;
|
||||
//--- hypergeometric function values
|
||||
double f1=MathHypergeometric2F2(a+1,a+b,a,a+b+1,lambda_half);
|
||||
double f2=MathHypergeometric2F2(a+2,a+b,a,a+b+2,lambda_half);
|
||||
double f3=MathHypergeometric2F2(a+3,a+b,a,a+b+3,lambda_half);
|
||||
double f4=MathHypergeometric2F2(a+4,a+b,a,a+b+4,lambda_half);
|
||||
//--- exponents
|
||||
double exp_lambda_half=MathExp(-lambda_half);
|
||||
double exp_lambda=MathPow(exp_lambda_half,2);
|
||||
//--- factors
|
||||
double aab=a/(a+b);
|
||||
double aab2=MathPow(aab,2);
|
||||
double ab1=(a+1)/(a+b+1);
|
||||
double ab2=(a+2)/(a+b+2);
|
||||
double ab3=(a+3)/(a+b+3);
|
||||
//--- calculate moments
|
||||
mean=aab*exp_lambda_half*f1;
|
||||
double mean2=MathPow(mean,2);
|
||||
variance=aab*ab1*exp_lambda_half*f2-mean2;
|
||||
skewness=(2*MathPow(mean,3)+exp_lambda_half*aab*ab1*(-3*mean*f2+ab2*f3))*MathPow(variance,-1.5);
|
||||
kurtosis=-3+(-3*MathPow(mean,4)+exp_lambda*f1*aab2*(6*mean*ab1*f2-4*ab1*ab2*f3)+aab*ab1*ab2*ab3*exp_lambda_half*f4)*MathPow(aab*ab1*exp_lambda_half*f2-mean2,-2);
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,912 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| NoncentralChiSquare.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Normal.mqh"
|
||||
#include "Poisson.mqh"
|
||||
#include "ChiSquare.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of the |
|
||||
//| Noncentral Chi-Square distribution with parameters nu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNoncentralChiSquare(const double x,const double nu,const double sigma,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- prepare parameters
|
||||
int err_code=0;
|
||||
int max_terms=1000;
|
||||
double lambda=sigma*0.5;
|
||||
double half_nu=nu*0.5;
|
||||
double pwr_lambda=1.0;
|
||||
double pwr_two=MathExp(-half_nu*MathLog(2));
|
||||
double pwr_x=MathExp((half_nu-1.0)*MathLog(x));
|
||||
double fact_mult=1.0;
|
||||
double coef_lambda_x=MathExp(-lambda-x*0.5);
|
||||
double coef_gamma=1.0/MathGamma(half_nu);
|
||||
double inv_factor=1.0;
|
||||
//--- calculate density using direct summation
|
||||
int j=0;
|
||||
double pdf=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
pwr_x*=x;
|
||||
pwr_two*=0.5;
|
||||
fact_mult*=1.0/j;
|
||||
inv_factor*=1.0/(j+half_nu-1);
|
||||
}
|
||||
double dp=coef_gamma*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x;
|
||||
pdf=pdf+dp;
|
||||
//--- check stop
|
||||
if(dp/(pdf+10E-10)<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
return TailLogValue(pdf,true,log_mode);
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of the |
|
||||
//| Noncentral Chi-Square distribution with parameters nu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNoncentralChiSquare(double x,const double nu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityNoncentralChiSquare(x,nu,sigma,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Chi Square distribution with parameter nu for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNoncentralChiSquare(const double &x[],const double nu,const double sigma,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
ArrayResize(result,data_count);
|
||||
//--- prepare parameters
|
||||
int max_terms=1000;
|
||||
double lambda=sigma*0.5;
|
||||
double half_nu=nu*0.5;
|
||||
double coef_gamma=1.0/MathGamma(half_nu);
|
||||
double pwr_two2=MathExp(-half_nu*MathLog(2));
|
||||
double pwr_half_num1=(half_nu-1.0);
|
||||
double coef_exp_lambda=MathExp(-lambda);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
int err_code=0;
|
||||
//result[i]=MathProbabilityDensityNoncentralChiSquare(x_arg,nu,sigma,false,err_code);
|
||||
double pwr_lambda=1.0;
|
||||
double pwr_two=pwr_two2;
|
||||
double pwr_x=MathPow(x_arg,pwr_half_num1);
|
||||
double fact_mult=1.0;
|
||||
double coef_lambda_x=coef_exp_lambda*MathExp(-x_arg*0.5);
|
||||
double inv_factor=1.0;
|
||||
//--- calculate density using direct summation
|
||||
int j=0;
|
||||
double pdf=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
pwr_x*=x_arg;
|
||||
pwr_two*=0.5;
|
||||
fact_mult*=1.0/j;
|
||||
inv_factor*=1.0/(j+half_nu-1);
|
||||
}
|
||||
double dp=coef_gamma*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x;
|
||||
pdf=pdf+dp;
|
||||
//--- check stop
|
||||
if(dp/(pdf+10E-10)<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
result[i]=TailLogValue(pdf,true,log_mode);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Chi-Square distribution with parameter nu for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNoncentralChiSquare(const double &x[],const double nu,const double sigma,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityNoncentralChiSquare(x,nu,sigma,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from a Noncentral Chi-Square distribution with parameters |
|
||||
//| nu and sigma is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of Noncentral Chi-Square cumulative distribution |
|
||||
//| function with parameters nu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNoncentralChiSquare(const double x,const double nu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
|
||||
//--- prepare parameters
|
||||
double cdf=0.0;
|
||||
int max_terms=100;
|
||||
double lambda=sigma*0.5;
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double pwr_lambda=1.0;
|
||||
double fact_mult=1.0;
|
||||
double half_x=x*0.5;
|
||||
double half_nu=nu*0.5;
|
||||
//--- direct summation
|
||||
int j=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
fact_mult/=j;
|
||||
}
|
||||
double coef1=coef_lambda*pwr_lambda*fact_mult;
|
||||
double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0);
|
||||
double dp=coef1*coef2;
|
||||
cdf=cdf+dp;
|
||||
if((dp/(cdf+10E-10))<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//---
|
||||
if(j<max_terms)
|
||||
{
|
||||
//--- take into account round-off errors for probability
|
||||
cdf=MathMin(cdf,1.0);
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from a Noncentral Chi-Square distribution with parameters |
|
||||
//| nu and sigma is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of Noncentral Chi-Square cumulative distribution |
|
||||
//| function with parameters nu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNoncentralChiSquare(const double x,const double nu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionNoncentralChiSquare(x,nu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Noncentral Chi-Square distribution with parameters nu and |
|
||||
//| sigma for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNoncentralChiSquare(const double &x[],const double nu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
//--- common factors
|
||||
double lambda=sigma*0.5;
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double half_nu=nu*0.5;
|
||||
const int max_terms=100;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
double pwr_lambda=1.0;
|
||||
double fact_mult=1.0;
|
||||
double half_x=x_arg*0.5;
|
||||
double cdf=0.0;
|
||||
int j=0;
|
||||
//--- direct summation
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
fact_mult/=j;
|
||||
}
|
||||
double coef1=coef_lambda*pwr_lambda*fact_mult;
|
||||
double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0);
|
||||
double dp=coef1*coef2;
|
||||
cdf=cdf+dp;
|
||||
if((dp/(cdf+10E-10))<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//---
|
||||
if(j<max_terms)
|
||||
{
|
||||
//--- take into account round-off errors for probability
|
||||
cdf=MathMin(cdf,1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Noncentral Chi-Square distribution with parameters nu and |
|
||||
//| sigma for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNoncentralChiSquare(const double &x[],const double nu,const double sigma,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionNoncentralChiSquare(x,nu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution quantile function(inverse CDF)|
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Noncentral Chi-Square distribution with parameters |
|
||||
//| nu and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function of |
|
||||
//| Noncentral Chi-Square distribution with parameters nu and sigma. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNoncentralChiSquare(const double probability,const double nu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
if(log_mode==true)
|
||||
{
|
||||
if(probability==QNEGINF)
|
||||
return 0.0;
|
||||
}
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
|
||||
if(prob==1.0)
|
||||
return QPOSINF;
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- common factors for pdf and cdf calculation
|
||||
const int max_terms=1000;
|
||||
double lambda=sigma*0.5;
|
||||
double half_nu=nu*0.5;
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double half_nu_m1=half_nu-1.0;
|
||||
double coef_gamma=1.0/MathGamma(half_nu);
|
||||
double pwr_two2=MathExp(-half_nu*MathLog(2));
|
||||
double pwr_half_num1=(half_nu-1.0);
|
||||
//--- prepare values for initial x estimation
|
||||
double x=0.5;
|
||||
double h=1.0;
|
||||
double h_min=10E-10;
|
||||
//--- Newton iterations
|
||||
const int max_iterations=50;
|
||||
int iterations=0;
|
||||
// int err_code=0;
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convergence
|
||||
if((MathAbs(h)>h_min && MathAbs(h)>MathAbs(h_min*x))==false)
|
||||
break;
|
||||
|
||||
//double pdf=MathProbabilityDensityNoncentralChiSquare(x,nu,sigma,false,err_code);
|
||||
double half_x=x*0.5;
|
||||
double pwr_lambda=1.0;
|
||||
double pwr_two=pwr_two2;
|
||||
double pwr_x=MathPow(x,pwr_half_num1);
|
||||
double fact_mult=1.0;
|
||||
double coef_lambda_x=coef_lambda*MathExp(-half_x);
|
||||
double inv_factor=1.0;
|
||||
//--- calculate density using direct summation
|
||||
int j=0;
|
||||
double pdf=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
pwr_x*=x;
|
||||
pwr_two*=0.5;
|
||||
fact_mult*=1.0/j;
|
||||
inv_factor*=1.0/(j+half_nu-1);
|
||||
}
|
||||
double dp=coef_gamma*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x;
|
||||
pdf=pdf+dp;
|
||||
//--- check stop
|
||||
if(dp/(pdf+10E-10)<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j>max_terms)
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate cdf
|
||||
pwr_lambda=1.0;
|
||||
fact_mult=1.0;
|
||||
double cdf=0.0;
|
||||
j=0;
|
||||
//--- direct summation
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
fact_mult/=j;
|
||||
}
|
||||
double coef1=coef_lambda*pwr_lambda*fact_mult;
|
||||
double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0);
|
||||
double dp=coef1*coef2;
|
||||
cdf=cdf+dp;
|
||||
if((dp/(cdf+10E-10))<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//---
|
||||
if(j>max_terms)
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
|
||||
double x_new=x-h;
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1-x)*0.1;
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
return x;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution quantile function(inverse CDF)|
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Noncentral Chi-Square distribution |
|
||||
//| with parameters mu and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function of |
|
||||
//| Noncentral Chi-Square distribution with parameters mu and sigma. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNoncentralChiSquare(const double probability,const double nu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathQuantileNoncentralChiSquare(probability,nu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution quantile function(inverse CDF)|
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Noncentral Chi-Square distribution with |
|
||||
//| parameters nu and sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNoncentralChiSquare(const double &probability[],const double nu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
//--- common factors for pdf and cdf calculation
|
||||
double lambda=sigma*0.5;
|
||||
double half_nu=nu*0.5;
|
||||
double pwr_two0=MathExp(-half_nu*MathLog(2));
|
||||
double pwr_gamma0=1.0/MathGamma(half_nu);
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double half_nu_m1=half_nu-1.0;
|
||||
const int max_terms=1000;
|
||||
const int max_iterations=50;
|
||||
double h_min=10E-10;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- prepare values for initial x estimation
|
||||
int err_code=0;
|
||||
double x=0.5;
|
||||
double h=1.0;
|
||||
//--- Newton iterations
|
||||
int iterations=0;
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convergence
|
||||
if((MathAbs(h)>h_min && MathAbs(h)>MathAbs(h_min*x))==false)
|
||||
break;
|
||||
|
||||
//double pdf=MathProbabilityDensityNoncentralChiSquare(x,nu,sigma,false,err_code);
|
||||
double half_x=x*0.5;
|
||||
double pwr_lambda=1.0;
|
||||
double pwr_two=pwr_two0;
|
||||
double pwr_x=MathPow(x,half_nu_m1);
|
||||
double fact_mult=1.0;
|
||||
double coef_lambda_x=coef_lambda*MathExp(-half_x);
|
||||
double inv_factor=1.0;
|
||||
//--- calculate density using direct summation
|
||||
int j=0;
|
||||
double pdf=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
pwr_x*=x;
|
||||
pwr_two*=0.5;
|
||||
fact_mult*=1.0/j;
|
||||
inv_factor*=1.0/(j+half_nu-1);
|
||||
}
|
||||
double dp=pwr_gamma0*inv_factor*pwr_lambda*pwr_two*pwr_x*fact_mult*coef_lambda_x;
|
||||
pdf=pdf+dp;
|
||||
//--- check stop
|
||||
if(dp/(pdf+10E-10)<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j>max_terms)
|
||||
return false;
|
||||
|
||||
//--- calculate cdf
|
||||
pwr_lambda=1.0;
|
||||
fact_mult=1.0;
|
||||
pwr_lambda=1.0;
|
||||
fact_mult=1.0;
|
||||
double cdf=0.0;
|
||||
j=0;
|
||||
//--- direct summation
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
fact_mult/=j;
|
||||
}
|
||||
double coef1=coef_lambda*pwr_lambda*fact_mult;
|
||||
double coef2=MathMin(MathGammaIncomplete(half_x,half_nu+j),1.0);
|
||||
double dp=coef1*coef2;
|
||||
cdf=cdf+dp;
|
||||
if((dp/(cdf+10E-10))<10E-16)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//---
|
||||
if(j>max_terms)
|
||||
return false;
|
||||
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
|
||||
double x_new=x-h;
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1-x)*0.1;
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
result[i]=x;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution quantile function(inverse CDF)|
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Noncentral Chi-Square distribution with |
|
||||
//| parameters nu and sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNoncentralChiSquare(const double &probability[],const double nu,const double sigma,double &result[])
|
||||
{
|
||||
return MathQuantileNoncentralChiSquare(probability,nu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Noncentral Chi-Square distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Noncentral Chi-Square |
|
||||
//| distribution with parameters nu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Noncentral Chi-Square distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Author: Robert Kern |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomNoncentralChiSquare(const double nu,const double sigma,int &error_code)
|
||||
{
|
||||
//--- return ChiSquare if sigma==0
|
||||
if(sigma==0.0)
|
||||
{
|
||||
return MathRandomChiSquare(nu,error_code);
|
||||
}
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
int err_code=0;
|
||||
if(nu>1.0)
|
||||
{
|
||||
double rnd_chisquare=MathRandomGamma((nu-1)*0.5,2.0,err_code);
|
||||
double rnd_normal=MathSqrt(sigma)+MathRandomNormal(0,1,err_code);
|
||||
return rnd_chisquare+rnd_normal*rnd_normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int rnd_poisson=(int)MathRandomPoisson(sigma*0.5);
|
||||
return MathRandomChiSquare(nu+2*rnd_poisson,err_code);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Noncentral Chi-Square distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Noncentral Chi-Square |
|
||||
//| distribution with parameters nu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Author: Robert Kern |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomNoncentralChiSquare(const double nu,const double sigma,const int data_count,double &result[])
|
||||
{
|
||||
//--- return ChiSquare if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathRandomChiSquare(nu,data_count,result);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<=0)
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
return false;
|
||||
|
||||
int err_code=0;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(nu>1.0)
|
||||
{
|
||||
double rnd_chisquare=MathRandomGamma((nu-1)*0.5,2.0,err_code);
|
||||
double rnd_normal=MathSqrt(sigma)+MathRandomNormal(0,1,err_code);
|
||||
result[i]=rnd_chisquare+rnd_normal*rnd_normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int rnd_poisson=(int)MathRandomPoisson(sigma*0.5);
|
||||
result[i]=MathRandomChiSquare(nu+2*rnd_poisson,err_code);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral Chi-Square distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of Noncental Chi-Square |
|
||||
//| distribution with parameters nu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsNoncentralChiSquare(const double nu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =nu+sigma;
|
||||
variance=2*nu+4*sigma;
|
||||
skewness=2*M_SQRT2*(nu+3*sigma)*MathPow(nu+2*sigma,-1.5);
|
||||
kurtosis=12*(nu+4*sigma)*MathPow(nu+2*sigma,-2);
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,790 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| NoncentralF.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "F.mqh"
|
||||
#include "Gamma.mqh"
|
||||
#include "NoncentralBeta.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral-F probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Noncentral-F distribution with parameters nu1,nu2,sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNoncentralF(const double x,const double nu1,const double nu2,const double sigma,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathProbabilityDensityF(x,nu1,nu2,error_code);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- factors
|
||||
double nu1_half=nu1*0.5;
|
||||
double nu2_half=nu2*0.5;
|
||||
double nu12_half=nu1_half+nu2_half;
|
||||
double lambda=sigma*0.5;
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double nu_coef=nu1/nu2;
|
||||
double g=x*nu_coef;
|
||||
double pwr_g=MathExp((nu1_half-1)*MathLog(g));
|
||||
double g1=g+1.0;
|
||||
double pwr_g1=MathExp(-nu12_half*MathLog(g1));
|
||||
double pwr_lambda=1.0;
|
||||
double fact_mult=1.0;
|
||||
//--- initial value for recurrent calculation
|
||||
double r_beta=MathBeta(nu1_half,nu2_half);
|
||||
//--- direct calculation of the sum
|
||||
int max_terms=100;
|
||||
int j=0;
|
||||
double pdf=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_g*=g;
|
||||
pwr_lambda*=lambda;
|
||||
fact_mult/=j;
|
||||
pwr_g1/=g1;
|
||||
double jm1=j-1;
|
||||
r_beta*=((nu1_half+jm1)/(nu12_half+jm1));
|
||||
}
|
||||
double dp=pwr_g*pwr_g1*coef_lambda*pwr_lambda*fact_mult/r_beta;
|
||||
pdf+=dp;
|
||||
if(dp/(pdf+10E-10)<10E-14)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
return TailLogValue(pdf*nu_coef,true,log_mode);
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral-F probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Noncentral-F distribution with parameters nu1,nu2,sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNoncentralF(const double x,const double nu1,const double nu2,const double sigma,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityNoncentralF(x,nu1,nu2,sigma,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral-F probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Noncentral F distribution with parameters nu1, nu2 and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNoncentralF(const double &x[],const double nu1,const double nu2,const double sigma,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathProbabilityDensityF(x,nu1,nu2,log_mode,result);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
const int max_terms=100;
|
||||
//--- common factors
|
||||
double nu1_half=nu1*0.5;
|
||||
double nu2_half=nu2*0.5;
|
||||
double nu12_half=nu1_half+nu2_half;
|
||||
double lambda=sigma*0.5;
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double nu_coef=nu1/nu2;
|
||||
double r_beta0=MathBeta(nu1_half,nu2_half);
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
double g=x_arg*nu_coef;
|
||||
double g1=g+1.0;
|
||||
//--- initial values for recurrent calculation
|
||||
double pwr_g=MathExp((nu1_half-1)*MathLog(g));
|
||||
double pwr_g1=MathExp(-nu12_half*MathLog(g1));
|
||||
double pwr_lambda=1.0;
|
||||
double fact_mult=1.0;
|
||||
double r_beta=r_beta0;
|
||||
//--- direct calculation of the sum
|
||||
int j=0;
|
||||
double pdf=0;
|
||||
while(j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_g*=g;
|
||||
pwr_lambda*=lambda;
|
||||
fact_mult/=j;
|
||||
pwr_g1/=g1;
|
||||
double jm1=j-1;
|
||||
r_beta*=((nu1_half+jm1)/(nu12_half+jm1));
|
||||
}
|
||||
double dp=pwr_g*pwr_g1*coef_lambda*pwr_lambda*fact_mult/r_beta;
|
||||
pdf+=dp;
|
||||
if(dp/(pdf+10E-10)<10E-14)
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
result[i]=TailLogValue(pdf*nu_coef,true,log_mode);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral-F probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Noncentral F distribution with parameters nu1, nu2 and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNoncentralF(const double &x[],const double nu1,const double nu2,const double sigma,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityNoncentralF(x,nu1,nu2,sigma,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from Noncentral F distribution with parameters nu1,nu2,sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Noncentral F cumulative distribution function |
|
||||
//| with parameters nu1,nu2,sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNoncentralF(const double x,const double nu1,const double nu2,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathCumulativeDistributionF(x,nu1,nu2,error_code);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0 || x<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
if(x<=0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- calculate cdf using Noncentral Beta distribution
|
||||
double arg=(nu1/nu2)*x;
|
||||
return MathCumulativeDistributionNoncentralBeta(arg/(1.0+arg),nu1*0.5,nu2*0.5,sigma,tail,log_mode,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from Noncentral F distribution with parameters nu1,nu2,sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Noncentral F cumulative distribution function |
|
||||
//| with parameters nu1,nu2,sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNoncentralF(const double x,const double nu1,const double nu2,const double sigma,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionNoncentralF(x,nu1,nu2,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Noncentral Fl distribution with parameters nu1,nu2 and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNoncentralF(const double &x[],const double nu1,const double nu2,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathCumulativeDistributionF(x,nu1,nu2,tail,log_mode,result);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
//--- common constants
|
||||
int error_code=0;
|
||||
double nu1_half=nu1*0.5;
|
||||
double nu2_half=nu2*0.5;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate cdf using Noncentral Beta distribution
|
||||
double arg=(nu1/nu2)*x_arg;
|
||||
result[i]=MathCumulativeDistributionNoncentralBeta(arg/(1.0+arg),nu1_half,nu2_half,sigma,tail,log_mode,error_code);
|
||||
//--- check result
|
||||
if(error_code!=ERR_OK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Noncentral Fl distribution with parameters nu1,nu2 and sigma |
|
||||
//| for values in x. |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNoncentralF(const double &x[],const double nu1,const double nu2,const double sigma,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionNoncentralF(x,nu1,nu2,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Noncentral F distribution with parameters nu1,nu2 |
|
||||
//| and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse Noncentral F cumulative distribution |
|
||||
//| function with parameters nu1,nu2,sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNoncentralF(const double probability,const double nu1,const double nu2,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
if(log_mode==true && probability==QNEGINF)
|
||||
return 0.0;
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathQuantileF(probability,nu1,nu2,tail,log_mode,error_code);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
//---
|
||||
int max_iterations=50;
|
||||
int iterations=0;
|
||||
//--- initial values
|
||||
double h=1.0;
|
||||
double h_min=10E-10;
|
||||
double x=0.5;
|
||||
int err_code=0;
|
||||
//--- Newton iterations
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convegence
|
||||
if((MathAbs(h)>h_min && MathAbs(h)>MathAbs(h_min*x))==false)
|
||||
break;
|
||||
//--- calculate pdf and cdf
|
||||
double pdf=MathProbabilityDensityNoncentralF(x,nu1,nu2,sigma,err_code);
|
||||
double cdf=MathCumulativeDistributionNoncentralF(x,nu1,nu2,sigma,err_code);
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
//---
|
||||
double x_new=x-h;
|
||||
//--- check x
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1.0-x)*0.1;
|
||||
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
return x;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Noncentral F distribution with parameters nu1,nu2 |
|
||||
//| and sigma for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse Noncentral F cumulative distribution |
|
||||
//| function with parameters nu1,nu2,sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNoncentralF(const double probability,const double nu1,const double nu2,const double sigma,int &error_code)
|
||||
{
|
||||
return MathQuantileNoncentralF(probability,nu1,nu2,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Noncentral F distribution with parameters nu1,nu2 |
|
||||
//| and sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNoncentralF(const double &probability[],const double nu1,const double nu2,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathQuantileF(probability,nu1,nu2,tail,log_mode,result);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
{
|
||||
int max_iterations=50;
|
||||
int iterations=0;
|
||||
//--- initial values
|
||||
double h=1.0;
|
||||
double h_min=10E-10;
|
||||
double x=0.5;
|
||||
int err_code=0;
|
||||
//--- Newton iterations
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convegence
|
||||
if((MathAbs(h)>h_min && MathAbs(h)>MathAbs(h_min*x))==false)
|
||||
break;
|
||||
//--- calculate pdf and cdf
|
||||
double pdf=MathProbabilityDensityNoncentralF(x,nu1,nu2,sigma,err_code);
|
||||
double cdf=MathCumulativeDistributionNoncentralF(x,nu1,nu2,sigma,err_code);
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
//---
|
||||
double x_new=x-h;
|
||||
//--- check x
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1.0-x)*0.1;
|
||||
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
result[i]=x;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Noncentral F distribution with parameters nu1,nu2 |
|
||||
//| and sigma for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNoncentralF(const double &probability[],const double nu1,const double nu2,const double sigma,double &result[])
|
||||
{
|
||||
return MathQuantileNoncentralF(probability,nu1,nu2,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Noncentral F-distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Noncentral F-distribution |
|
||||
//| with parameters nu1, nu2 and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Noncentral F-distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomNoncentralF(const double nu1,const double nu2,const double sigma,int &error_code)
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathRandomF(nu1,nu2,error_code);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate using noncentral chisquare and chisquare distributions
|
||||
double num=MathRandomNoncentralChiSquare(nu1,sigma,error_code)*nu2;
|
||||
double den=MathRandomGamma(nu2*0.5,2.0,error_code)*nu1;
|
||||
if(den!=0)
|
||||
return num/den;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Noncentral F distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Noncentral F distribution |
|
||||
//| with parameters nu1, nu2 and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomNoncentralF(const double nu1,const double nu2,const double sigma,const int data_count,double &result[])
|
||||
{
|
||||
//--- return F if sigma==0
|
||||
if(sigma==0.0)
|
||||
return MathRandomF(nu1,nu2,data_count,result);
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
return false;
|
||||
int error_code=0;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate using noncentral chisquare and chisquare distributions
|
||||
double num=MathRandomNoncentralChiSquare(nu1,sigma,error_code)*nu2;
|
||||
double den=MathRandomGamma(nu2*0.5,2.0,error_code)*nu1;
|
||||
if(den!=0)
|
||||
result[i]=num/den;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Noncentral F distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Noncental F |
|
||||
//| distribution with parameters nu1,nu2 and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu1 : Numerator degrees of freedom |
|
||||
//| nu2 : Denominator degrees of freedom |
|
||||
//| sigma : Noncentrality parameter |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsNoncentralF(const double nu1,const double nu2,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- if sigma==0, calc moments for F
|
||||
if(sigma==0)
|
||||
return MathMomentsF(nu1,nu2,mean,variance,skewness,kurtosis,error_code);
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu1) || !MathIsValidNumber(nu2) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu1!=MathRound(nu1) || nu2!=MathRound(nu2) || nu1<=0 || nu2<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
if(nu2>2)
|
||||
mean=nu2*(nu1+sigma)/(nu1*(nu2-2));
|
||||
//--- variance
|
||||
if(nu2>4)
|
||||
variance=2*MathPow(nu2/nu1,2)*((nu2-2)*(nu1+2*sigma)+MathPow(nu1+sigma,2))/((nu2-4)*MathPow(nu2-2,2));
|
||||
//--- factors
|
||||
double sigma_sqr=MathPow(sigma,2);
|
||||
double sigma_cube=sigma_sqr*sigma;
|
||||
double nu12m2=(nu1+nu2-2);
|
||||
double nu2p10=(nu2+10);
|
||||
//--- skewness
|
||||
if(nu2>6)
|
||||
{
|
||||
skewness=2*M_SQRT2*MathSqrt(nu2-4);
|
||||
skewness*=(nu12m2*(6*sigma_sqr+(2*nu1+nu2-2)*(3*sigma+nu1))+2*sigma_cube);
|
||||
skewness/=(nu2-6);
|
||||
skewness/=MathPow(nu12m2*(2*sigma+nu1)+sigma_sqr,1.5);
|
||||
}
|
||||
//--- kurtosis
|
||||
if(nu2>8)
|
||||
{
|
||||
double coef=nu2p10*(MathPow(nu1,2)+nu1*(nu2-2))+4*MathPow(nu2-2,2);
|
||||
kurtosis=1;
|
||||
kurtosis=3*(nu2-4);
|
||||
kurtosis*=(nu12m2*(coef*(4*sigma+nu1)+nu2p10*(4*sigma_cube+2*sigma_sqr*(3*nu1+2*nu2-4)))+nu2p10*MathPow(sigma,4));
|
||||
kurtosis/=(nu2-8)*(nu2-6);
|
||||
kurtosis/=MathPow((nu12m2*(2*sigma+nu1)+sigma_sqr),2);
|
||||
kurtosis-=3;
|
||||
}
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,914 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
const static double normal_cdf_a[5]=
|
||||
{
|
||||
2.2352520354606839287E00,1.6102823106855587881E02,
|
||||
1.0676894854603709582E03,1.8154981253343561249E04,
|
||||
6.5682337918207449113E-2
|
||||
};
|
||||
const static double normal_cdf_b[4]=
|
||||
{
|
||||
4.7202581904688241870E01,9.7609855173777669322E02,
|
||||
1.0260932208618978205E04,4.5507789335026729956E04
|
||||
};
|
||||
//--- coefficients for approximation in second interval
|
||||
const static double normal_cdf_c[9]=
|
||||
{
|
||||
3.9894151208813466764E-1,8.8831497943883759412E00,
|
||||
9.3506656132177855979E01,5.9727027639480026226E02,
|
||||
2.4945375852903726711E03,6.8481904505362823326E03,
|
||||
1.1602651437647350124E04,9.8427148383839780218E03,
|
||||
1.0765576773720192317E-8
|
||||
};
|
||||
const static double normal_cdf_d[8]=
|
||||
{
|
||||
2.2266688044328115691E01,2.3538790178262499861E02,
|
||||
1.5193775994075548050E03,6.4855582982667607550E03,
|
||||
1.8615571640885098091E04,3.4900952721145977266E04,
|
||||
3.8912003286093271411E04,1.9685429676859990727E04
|
||||
};
|
||||
//--- coefficients for approximation in third interval
|
||||
const static double normal_cdf_p[6]=
|
||||
{
|
||||
2.1589853405795699E-1,1.274011611602473639E-1,
|
||||
2.2235277870649807E-2,1.421619193227893466E-3,
|
||||
2.9112874951168792E-5,2.307344176494017303E-2
|
||||
};
|
||||
const static double normal_cdf_q[5]=
|
||||
{
|
||||
1.28426009614491121E00,4.68238212480865118E-1,
|
||||
6.59881378689285515E-2,3.78239633202758244E-3,
|
||||
7.29751555083966205E-5
|
||||
};
|
||||
|
||||
//--- coefficients for p close to 0.5
|
||||
const double normal_q_a0 = 3.3871328727963666080;
|
||||
const double normal_q_a1 = 1.3314166789178437745E+2;
|
||||
const double normal_q_a2 = 1.9715909503065514427E+3;
|
||||
const double normal_q_a3 = 1.3731693765509461125E+4;
|
||||
const double normal_q_a4 = 4.5921953931549871457E+4;
|
||||
const double normal_q_a5 = 6.7265770927008700853E+4;
|
||||
const double normal_q_a6 = 3.3430575583588128105E+4;
|
||||
const double normal_q_a7 = 2.5090809287301226727E+3;
|
||||
const double normal_q_b1 = 4.2313330701600911252E+1;
|
||||
const double normal_q_b2 = 6.8718700749205790830E+2;
|
||||
const double normal_q_b3 = 5.3941960214247511077E+3;
|
||||
const double normal_q_b4 = 2.1213794301586595867E+4;
|
||||
const double normal_q_b5 = 3.9307895800092710610E+4;
|
||||
const double normal_q_b6 = 2.8729085735721942674E+4;
|
||||
const double normal_q_b7 = 5.2264952788528545610E+3;
|
||||
//--- coefficients for p not close to 0, 0.5 or 1
|
||||
const double normal_q_c0 = 1.42343711074968357734;
|
||||
const double normal_q_c1 = 4.63033784615654529590;
|
||||
const double normal_q_c2 = 5.76949722146069140550;
|
||||
const double normal_q_c3 = 3.64784832476320460504;
|
||||
const double normal_q_c4 = 1.27045825245236838258;
|
||||
const double normal_q_c5 = 2.41780725177450611770E-1;
|
||||
const double normal_q_c6 = 2.27238449892691845833E-2;
|
||||
const double normal_q_c7 = 7.74545014278341407640E-4;
|
||||
const double normal_q_d1 = 2.05319162663775882187;
|
||||
const double normal_q_d2 = 1.67638483018380384940;
|
||||
const double normal_q_d3 = 6.89767334985100004550E-1;
|
||||
const double normal_q_d4 = 1.48103976427480074590E-1;
|
||||
const double normal_q_d5 = 1.51986665636164571966E-2;
|
||||
const double normal_q_d6 = 5.47593808499534494600E-4;
|
||||
const double normal_q_d7 = 1.05075007164441684324E-9;
|
||||
//--- coefficients for p near 0 or 1.
|
||||
const double normal_q_e0 = 6.65790464350110377720E0;
|
||||
const double normal_q_e1 = 5.46378491116411436990E0;
|
||||
const double normal_q_e2 = 1.78482653991729133580E0;
|
||||
const double normal_q_e3 = 2.96560571828504891230E-1;
|
||||
const double normal_q_e4 = 2.65321895265761230930E-2;
|
||||
const double normal_q_e5 = 1.24266094738807843860E-3;
|
||||
const double normal_q_e6 = 2.71155556874348757815E-5;
|
||||
const double normal_q_e7 = 2.01033439929228813265E-7;
|
||||
const double normal_q_f1 = 5.99832206555887937690E-1;
|
||||
const double normal_q_f2 = 1.36929880922735805310E-1;
|
||||
const double normal_q_f3 = 1.48753612908506148525E-2;
|
||||
const double normal_q_f4 = 7.86869131145613259100E-4;
|
||||
const double normal_q_f5 = 1.84631831751005468180E-5;
|
||||
const double normal_q_f6 = 1.42151175831644588870E-7;
|
||||
const double normal_q_f7 = 2.04426310338993978564E-15;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Normal distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (sigma>0) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNormal(const double x,const double mu,const double sigma,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
|
||||
//--- prepare argument
|
||||
double y=(x-mu)/sigma;
|
||||
//--- check it
|
||||
if(!MathIsValidNumber(y))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check overflow
|
||||
y=MathAbs(y);
|
||||
if(y>=2*MathSqrt(DBL_MAX))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- return density
|
||||
return TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/sigma,true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Normal distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (sigma>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityNormal(const double x,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityNormal(x,mu,sigma,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Normal distribution with parameters mu and sigma |
|
||||
//| for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (sigma>0) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNormal(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- prepare argument and check it
|
||||
double y=(x_arg-mu)/sigma;
|
||||
if(!MathIsValidNumber(y))
|
||||
return false;
|
||||
|
||||
//--- check overflow
|
||||
y=MathAbs(y);
|
||||
if(y>=2*MathSqrt(DBL_MAX))
|
||||
return false;
|
||||
|
||||
//--- calculate density
|
||||
result[i]=TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/sigma,true,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Normal distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (sigma>0) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityNormal(const double &x[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityNormal(x,mu,sigma,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Normal distribution with parameters mu and sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Normal cumulative distribution function with |
|
||||
//| parameters mu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Comment from original FORTRAN code |
|
||||
//| https://www.netlib.org/toms-2014-06-10/639 |
|
||||
//| https://www.netlib.org/toms-2014-06-10/715 |
|
||||
//| |
|
||||
//| This function evaluates the normal distribution function: |
|
||||
//| |
|
||||
//| / x |
|
||||
//| 1 | -t*t/2 |
|
||||
//| P(x) = ----------- | e dt |
|
||||
//| sqrt(2 pi) | |
|
||||
//| /-oo |
|
||||
//| |
|
||||
//| The main computation evaluates near-minimax approximations |
|
||||
//| derived from those in "Rational Chebyshev approximations for |
|
||||
//| the error function" by W. J. Cody, Math. Comp., 1969, 631-637. |
|
||||
//| This transportable program uses rational functions that |
|
||||
//| theoretically approximate the normal distribution function to |
|
||||
//| at least 18 significant decimal digits. The accuracy achieved |
|
||||
//| depends on the arithmetic system, the compiler, the intrinsic |
|
||||
//| functions, and proper selection of the machine-dependent |
|
||||
//| constants. |
|
||||
//| |
|
||||
//| Author: |
|
||||
//| W. J. Cody, Mathematics and Computer Science Division |
|
||||
//| Argonne National Laboratory, Argonne, IL 60439 |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNormal(const double x,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- prepare argument
|
||||
double xx=(x-mu)/sigma;
|
||||
//--- mathematical constants
|
||||
//--- sqrpi = 1 / sqrt(2*pi), root32 = sqrt(32), and
|
||||
//--- thrsh is the argument for which anorm = 0.75.
|
||||
const double sqrpi=1.0/MathSqrt(2*M_PI);
|
||||
const double thrsh = 0.66291e0;
|
||||
const double root32= MathSqrt(32);
|
||||
//--- machine-dependent constants
|
||||
//--- data eps/5.96e-8/,xlow/-12.949e0/,xuppr/5.768e0/
|
||||
const double eps=1.11e-16;
|
||||
const double xlow=-37.519;
|
||||
const double xuppr=8.572;
|
||||
int k;
|
||||
//---
|
||||
double xsq=0.0;
|
||||
double y=MathAbs(xx);
|
||||
double xnum=0.0;
|
||||
double xden=0.0;
|
||||
double cdf=0.0;
|
||||
double del=0.0;
|
||||
//---
|
||||
if(y<=thrsh)
|
||||
{
|
||||
//--- evaluate for |x| <= 0.66291
|
||||
if(y>eps)
|
||||
xsq=xx*xx;
|
||||
|
||||
xnum = normal_cdf_a[4] * xsq;
|
||||
xden = xsq;
|
||||
for(k=0; k<3; k++)
|
||||
{
|
||||
xnum=(xnum+normal_cdf_a[k])*xsq;
|
||||
xden=(xden+normal_cdf_b[k])*xsq;
|
||||
}
|
||||
cdf = xx*(xnum+normal_cdf_a[3])/(xden+normal_cdf_b[3]);
|
||||
cdf = 0.5 + cdf;
|
||||
}
|
||||
else
|
||||
if(y<=root32)
|
||||
{
|
||||
//--- evaluate for 0.66291 <= |x| <= sqrt(32)
|
||||
xnum = normal_cdf_c[8]*y;
|
||||
xden = y;
|
||||
for(k=0; k<7; k++)
|
||||
{
|
||||
xnum=(xnum+normal_cdf_c[k])*y;
|
||||
xden=(xden+normal_cdf_d[k])*y;
|
||||
}
|
||||
cdf=(xnum+normal_cdf_c[7])/(xden+normal_cdf_d[7]);
|
||||
xsq=int(y*16)/16;
|
||||
del=(y-xsq)*(y+xsq);
|
||||
cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf;
|
||||
if(xx>0.0) cdf=1.0-cdf;
|
||||
}
|
||||
//--- evaluate for |x| > sqrt(32)
|
||||
else
|
||||
{
|
||||
cdf=0.0;
|
||||
if((xx>=xlow) && (xx<xuppr))
|
||||
{
|
||||
xsq=1.0/(xx*xx);
|
||||
xnum = normal_cdf_p[5]*xsq;
|
||||
xden = xsq;
|
||||
for(k=0; k<3; k++)
|
||||
{
|
||||
xnum=(xnum+normal_cdf_p[k])*xsq;
|
||||
xden=(xden+normal_cdf_q[k])*xsq;
|
||||
}
|
||||
cdf=xsq*(xnum+normal_cdf_p[4])/(xden+normal_cdf_q[4]);
|
||||
cdf=(sqrpi-cdf)/y;
|
||||
xsq=int(xx*16)/16;
|
||||
del=(xx-xsq)*(xx+xsq);
|
||||
cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf;
|
||||
}
|
||||
if(xx>0.0) cdf=1.0-cdf;
|
||||
}
|
||||
//--- take into account round-off errors for probability
|
||||
return TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Normal distribution with parameters mu and sigma |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Normal cumulative distribution function with |
|
||||
//| parameters mu and sigma, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionNormal(const double x,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionNormal(x,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Normal distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNormal(const double &x[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
//--- prepare argument
|
||||
double xx=(x_arg-mu)/sigma;
|
||||
//--- mathematical constants
|
||||
//--- sqrpi = 1 / sqrt(2*pi), root32 = sqrt(32), and
|
||||
//--- thrsh is the argument for which anorm = 0.75.
|
||||
const double sqrpi=1.0/MathSqrt(2*M_PI);
|
||||
const double thrsh = 0.66291e0;
|
||||
const double root32= MathSqrt(32);
|
||||
//--- machine-dependent constants
|
||||
//--- data eps/5.96e-8/,xlow/-12.949e0/,xuppr/5.768e0/
|
||||
const double eps=1.11e-16;
|
||||
const double xlow=-37.519;
|
||||
const double xuppr=8.572;
|
||||
int k;
|
||||
//---
|
||||
double xsq=0.0;
|
||||
double y=MathAbs(xx);
|
||||
double xnum=0.0;
|
||||
double xden=0.0;
|
||||
double cdf=0.0;
|
||||
double del=0.0;
|
||||
//---
|
||||
if(y<=thrsh)
|
||||
{
|
||||
//--- evaluate for |x| <= 0.66291
|
||||
if(y>eps)
|
||||
xsq=xx*xx;
|
||||
|
||||
xnum = normal_cdf_a[4] * xsq;
|
||||
xden = xsq;
|
||||
for(k=0; k<3; k++)
|
||||
{
|
||||
xnum=(xnum+normal_cdf_a[k])*xsq;
|
||||
xden=(xden+normal_cdf_b[k])*xsq;
|
||||
}
|
||||
cdf = xx*(xnum+normal_cdf_a[3])/(xden+normal_cdf_b[3]);
|
||||
cdf = 0.5 + cdf;
|
||||
}
|
||||
else
|
||||
if(y<=root32)
|
||||
{
|
||||
//--- evaluate for 0.66291 <= |x| <= sqrt(32)
|
||||
xnum = normal_cdf_c[8]*y;
|
||||
xden = y;
|
||||
for(k=0; k<7; k++)
|
||||
{
|
||||
xnum=(xnum+normal_cdf_c[k])*y;
|
||||
xden=(xden+normal_cdf_d[k])*y;
|
||||
}
|
||||
cdf=(xnum+normal_cdf_c[7])/(xden+normal_cdf_d[7]);
|
||||
xsq=int(y*16)/16;
|
||||
del=(y-xsq)*(y+xsq);
|
||||
cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf;
|
||||
if(xx>0.0) cdf=1.0-cdf;
|
||||
}
|
||||
//--- evaluate for |x| > sqrt(32)
|
||||
else
|
||||
{
|
||||
cdf=0.0;
|
||||
if((xx>=xlow) && (xx<xuppr))
|
||||
{
|
||||
xsq=1.0/(xx*xx);
|
||||
xnum = normal_cdf_p[5]*xsq;
|
||||
xden = xsq;
|
||||
for(k=0; k<3; k++)
|
||||
{
|
||||
xnum=(xnum+normal_cdf_p[k])*xsq;
|
||||
xden=(xden+normal_cdf_q[k])*xsq;
|
||||
}
|
||||
cdf=xsq*(xnum+normal_cdf_p[4])/(xden+normal_cdf_q[4]);
|
||||
cdf=(sqrpi-cdf)/y;
|
||||
xsq=int(xx*16)/16;
|
||||
del=(xx-xsq)*(xx+xsq);
|
||||
cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf;
|
||||
}
|
||||
if(xx>0.0) cdf=1.0-cdf;
|
||||
}
|
||||
//--- take into account round-off errors for probability
|
||||
result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Normal distribution with parameters mu and sigma |
|
||||
//| for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionNormal(const double &x[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionNormal(x,mu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Normal distribution with parameters mu and sigma |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Normal distribution with parameters mu and sigma. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Comment from original FORTRAN code |
|
||||
//| https://www1.fpl.fs.fed.us/ni241.f |
|
||||
//| Produces the normal deviate Z corresponding to a given lower |
|
||||
//| tail area of P; Z is accurate to about 1 part in 10**16. |
|
||||
//| Wichura, M.J. (1988). Algorithm AS 241: The Percentage Points of |
|
||||
//| the Normal Distribution. Applied Statistics, v.37, N3, 477-484. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNormal(const double probability,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- f(0)=-infinity
|
||||
if(prob==0.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QNEGINF;
|
||||
}
|
||||
//--- f(1)=+infinity
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
|
||||
double q=prob-0.5;
|
||||
double r=0;
|
||||
double ppnd16=0.0;
|
||||
//---
|
||||
if(MathAbs(q)<=0.425)
|
||||
{
|
||||
r=0.180625-q*q;
|
||||
ppnd16=q*(((((((normal_q_a7*r+normal_q_a6)*r+normal_q_a5)*r+normal_q_a4)*r+normal_q_a3)*r+normal_q_a2)*r+normal_q_a1)*r+normal_q_a0)/
|
||||
(((((((normal_q_b7*r+normal_q_b6)*r+normal_q_b5)*r+normal_q_b4)*r+normal_q_b3)*r+normal_q_b2)*r+normal_q_b1)*r+1.0);
|
||||
//---
|
||||
error_code=ERR_OK;
|
||||
return mu+sigma*ppnd16;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(q<0.0)
|
||||
r=prob;
|
||||
else
|
||||
r=1.0-prob;
|
||||
//---
|
||||
r=MathSqrt(-MathLog(r));
|
||||
//---
|
||||
if(r<=5.0)
|
||||
{
|
||||
r=r-1.6;
|
||||
ppnd16=(((((((normal_q_c7*r+normal_q_c6)*r+normal_q_c5)*r+normal_q_c4)*r+normal_q_c3)*r+normal_q_c2)*r+normal_q_c1)*r+normal_q_c0)/
|
||||
(((((((normal_q_d7*r+normal_q_d6)*r+normal_q_d5)*r+normal_q_d4)*r+normal_q_d3)*r+normal_q_d2)*r+normal_q_d1)*r+1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
r=r-5.0;
|
||||
ppnd16=(((((((normal_q_e7*r+normal_q_e6)*r+normal_q_e5)*r+normal_q_e4)*r+normal_q_e3)*r+normal_q_e2)*r+normal_q_e1)*r+normal_q_e0)/
|
||||
(((((((normal_q_f7*r+normal_q_f6)*r+normal_q_f5)*r+normal_q_f4)*r+normal_q_f3)*r+normal_q_f2)*r+normal_q_f1)*r+1.0);
|
||||
}
|
||||
//---
|
||||
if(q<0.0)
|
||||
ppnd16=-ppnd16;
|
||||
}
|
||||
//--- return rescaled/shifted value
|
||||
return mu+sigma*ppnd16;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Normal distribution with parameters mu and sigma |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Normal distribution with parameters mu and sigma. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileNormal(const double probability,const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
return MathQuantileNormal(probability,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Normal distribution with parameters mu and sigma |
|
||||
//| for the probability values from array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNormal(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
|
||||
//--- case sigma==0
|
||||
if(sigma==0.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=mu;
|
||||
return true;
|
||||
}
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- f(0)=-infinity, f(1)=+infinity
|
||||
if(prob==0.0 || prob==1.0)
|
||||
{
|
||||
if(prob==0.0)
|
||||
result[i]=QNEGINF;
|
||||
else
|
||||
result[i]=QPOSINF;
|
||||
}
|
||||
else
|
||||
{
|
||||
double q=prob-0.5;
|
||||
double r=0;
|
||||
double ppnd16=0.0;
|
||||
//---
|
||||
if(MathAbs(q)<=0.425)
|
||||
{
|
||||
r=0.180625-q*q;
|
||||
ppnd16=q*(((((((normal_q_a7*r+normal_q_a6)*r+normal_q_a5)*r+normal_q_a4)*r+normal_q_a3)*r+normal_q_a2)*r+normal_q_a1)*r+normal_q_a0)/
|
||||
(((((((normal_q_b7*r+normal_q_b6)*r+normal_q_b5)*r+normal_q_b4)*r+normal_q_b3)*r+normal_q_b2)*r+normal_q_b1)*r+1.0);
|
||||
//--- set rescaled/shifted value
|
||||
result[i]=mu+sigma*ppnd16;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(q<0.0)
|
||||
r=prob;
|
||||
else
|
||||
r=1.0-prob;
|
||||
//---
|
||||
r=MathSqrt(-MathLog(r));
|
||||
//---
|
||||
if(r<=5.0)
|
||||
{
|
||||
r=r-1.6;
|
||||
ppnd16=(((((((normal_q_c7*r+normal_q_c6)*r+normal_q_c5)*r+normal_q_c4)*r+normal_q_c3)*r+normal_q_c2)*r+normal_q_c1)*r+normal_q_c0)/
|
||||
(((((((normal_q_d7*r+normal_q_d6)*r+normal_q_d5)*r+normal_q_d4)*r+normal_q_d3)*r+normal_q_d2)*r+normal_q_d1)*r+1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
r=r-5.0;
|
||||
ppnd16=(((((((normal_q_e7*r+normal_q_e6)*r+normal_q_e5)*r+normal_q_e4)*r+normal_q_e3)*r+normal_q_e2)*r+normal_q_e1)*r+normal_q_e0)/
|
||||
(((((((normal_q_f7*r+normal_q_f6)*r+normal_q_f5)*r+normal_q_f4)*r+normal_q_f3)*r+normal_q_f2)*r+normal_q_f1)*r+1.0);
|
||||
}
|
||||
//---
|
||||
if(q<0.0)
|
||||
ppnd16=-ppnd16;
|
||||
}
|
||||
//--- set rescaled/shifted value
|
||||
result[i]=mu+sigma*ppnd16;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Normal distribution with parameters mu and sigma |
|
||||
//| for the probability values from array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileNormal(const double &probability[],const double mu,const double sigma,double &result[])
|
||||
{
|
||||
return MathQuantileNormal(probability,mu,sigma,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Normal distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Normal distribution |
|
||||
//| with given mean mu and standard deviation sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Normal distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomNormal(const double mu,const double sigma,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//---
|
||||
if(sigma==0.0)
|
||||
return mu;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
//--- return normal random using quantile
|
||||
return MathQuantileNormal(rnd,mu,sigma,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Normal distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Normal distribution with |
|
||||
//| parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (must be positive) |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomNormal(const double mu,const double sigma,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
return false;
|
||||
//--- check sigma
|
||||
if(sigma<0)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
if(sigma==0.0)
|
||||
{
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=mu;
|
||||
return true;
|
||||
}
|
||||
int err_code=0;
|
||||
for(int i=0; i<data_count; i++)
|
||||
result[i]=MathRandomNonZero();
|
||||
//--- return normal random array using quantile
|
||||
return MathQuantileNormal(result,mu,sigma,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Normal distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Normal |
|
||||
//| distribution with parameters mu and sigma. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| mu : Mean |
|
||||
//| sigma : Standard deviation (sigma>0) |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsNormal(const double mu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check sigma
|
||||
if(sigma<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =mu;
|
||||
variance=MathPow(sigma,2);
|
||||
skewness=0;
|
||||
kurtosis=0;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,791 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Gamma.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function |
|
||||
//| of the Poisson distribution with parameter lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| lambda : Mean |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityPoisson(const double x,const double lambda,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- lambda must be positive, x must be integer
|
||||
if(lambda<=0.0 || x!=MathRound(x))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<0.0)
|
||||
return TailLog0(true,log_mode);
|
||||
|
||||
//--- calculate log pdf using LogGamma
|
||||
double log_pdf=-lambda+x*MathLog(lambda)-MathGammaLog(x+1.0);
|
||||
if(log_mode)
|
||||
return log_pdf;
|
||||
//--- return density
|
||||
return MathExp(log_pdf);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability mass function |
|
||||
//| of the Poisson distribution with parameter lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| lambda : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability mass evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityPoisson(const double x,const double lambda,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityPoisson(x,lambda,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Poisson distribution with parameter lambda for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| lambda : Mean |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityPoisson(const double &x[],const double lambda,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(lambda))
|
||||
return false;
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg!=MathRound(x_arg))
|
||||
return false;
|
||||
|
||||
//--- check x
|
||||
if(x_arg<0.0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate log pdf using LogGamma
|
||||
double log_pdf=-lambda+x_arg*MathLog(lambda)-MathGammaLog(x_arg+1.0);
|
||||
if(log_mode)
|
||||
result[i]=log_pdf;
|
||||
else
|
||||
result[i]=MathExp(log_pdf);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson probability mass function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the Poisson distribution with parameter lambda for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| lambda : Mean |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityPoisson(const double &x[],const double lambda,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityPoisson(x,lambda,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from Poisson distribution with parameter lambda |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| lambda : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Poisson cumulative distribution function with |
|
||||
//| parameter lambda, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionPoisson(const double x,const double lambda,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- lambda must be positive, x must be integer
|
||||
if(lambda<=0.0 || x!=MathRound(x))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<0.0)
|
||||
return TailLog0(tail,log_mode);
|
||||
int err_code=0;
|
||||
|
||||
int t=(int)MathFloor(x+10e-10);
|
||||
double cdf=MathCumulativeDistributionGamma(lambda,t+1,1,false,false,err_code);
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from Poisson distribution with parameter lambda |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| lambda : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Poisson cumulative distribution function with |
|
||||
//| parameter lambda, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionPoisson(const double x,const double lambda,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionPoisson(x,lambda,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Poisson distribution with parameter lambda for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| lambda : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionPoisson(const double &x[],const double lambda,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(lambda))
|
||||
return false;
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(x_arg!=MathRound(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg<0.0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
int err_code=0;
|
||||
int t=(int)MathFloor(x_arg+10e-10);
|
||||
double cdf=MathCumulativeDistributionGamma(lambda,t+1,1,false,false,err_code);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Poisson distribution with parameter lambda for values in x[].|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| lambda : Mean |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionPoisson(const double &x[],const double lambda,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionPoisson(x,lambda,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the inverse cumulative distribution function of the |
|
||||
//| Poisson distribution with parameter lambda for the desired |
|
||||
//| probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| lambda : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Poisson distribution with parameter lambda. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantilePoisson(const double probability,const double lambda,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
|
||||
prob*=1-1000*DBL_EPSILON;
|
||||
int err_code=0;
|
||||
int j=0;
|
||||
const int max_terms=500;
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
double pwr_lambda=1.0;
|
||||
double inverse_fact=1.0;
|
||||
double sum=0;
|
||||
//--- direct calculation of the quantile
|
||||
while(sum<prob && j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
inverse_fact/=j;
|
||||
}
|
||||
sum+=coef_lambda*pwr_lambda*inverse_fact;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
{
|
||||
if(j==0)
|
||||
return 0;
|
||||
else
|
||||
return j-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the inverse cumulative distribution function of the |
|
||||
//| Poisson distribution with parameter lambda for the desired |
|
||||
//| probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| lambda : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of Poisson distribution with parameter lambda. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantilePoisson(const double probability,const double lambda,int &error_code)
|
||||
{
|
||||
return MathQuantilePoisson(probability,lambda,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Poisson distribution with parameter lambda |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| lambda : Mean |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantilePoisson(const double &probability[],const double lambda,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- NaN
|
||||
if(!MathIsValidNumber(lambda))
|
||||
return false;
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
double coef_lambda=MathExp(-lambda);
|
||||
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
if(prob==0.0)
|
||||
result[i]=0;
|
||||
else
|
||||
{
|
||||
prob*=1-1000*DBL_EPSILON;
|
||||
int err_code=0;
|
||||
int j=0;
|
||||
double sum=0.0;
|
||||
const int max_terms=500;
|
||||
double pwr_lambda=1.0;
|
||||
double inverse_fact=1.0;
|
||||
//--- direct calculation
|
||||
while(sum<prob && j<max_terms)
|
||||
{
|
||||
if(j>0)
|
||||
{
|
||||
pwr_lambda*=lambda;
|
||||
inverse_fact/=j;
|
||||
}
|
||||
sum+=coef_lambda*pwr_lambda*inverse_fact;
|
||||
j++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(j<max_terms)
|
||||
{
|
||||
if(j==0)
|
||||
result[i]=0;
|
||||
else
|
||||
result[i]=j-1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Poisson distribution with parameter lambda |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| lambda : Mean |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantilePoisson(const double &probability[],const double lambda,double &result[])
|
||||
{
|
||||
return MathQuantilePoisson(probability,lambda,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Poisson distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Poisson distribution |
|
||||
//| with parameter lambda. |
|
||||
//| |
|
||||
//| Arguments |
|
||||
//| lambda : Mean |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Poisson distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Original FORTRAN77 version by Barry Brown, James Lovato. |
|
||||
//| C version by John Burkardt. |
|
||||
//| |
|
||||
//| Reference: |
|
||||
//| Joachim Ahrens, Ulrich Dieter, "Computer Generation of Poisson |
|
||||
//| "Deviates From Modified Normal Distributions", |
|
||||
//| ACM Transactions on Mathematical Software, |
|
||||
//| Volume 8, Number 2, June 1982, pages 163-179. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomPoisson(const double lambda)
|
||||
{
|
||||
const double a0 = -0.5;
|
||||
const double a1 = 0.3333333;
|
||||
const double a2 = -0.2500068;
|
||||
const double a3 = 0.2000118;
|
||||
const double a4 = -0.1661269;
|
||||
const double a5 = 0.1421878;
|
||||
const double a6 = -0.1384794;
|
||||
const double a7 = 0.1250060;
|
||||
int kflag;
|
||||
double fk=0,difmuk=0;
|
||||
double e=0,fx,fy,g,p0,px,py,p,q,s,t,u=0,v,x,xx;
|
||||
int value=0;
|
||||
//--- start new table and calculate P0
|
||||
if(lambda<10.0)
|
||||
{
|
||||
int m=MathMax(1,(int)(lambda));
|
||||
p = MathExp(-lambda);
|
||||
q = p;
|
||||
p0= p;
|
||||
//--- uniform sample for inversion method
|
||||
for(;;)
|
||||
{
|
||||
u=MathRandomNonZero();
|
||||
value=0;
|
||||
|
||||
if(u<=p0)
|
||||
return value;
|
||||
//--- creation of new Poisson probabilities
|
||||
for(int k=1; k<=35; k++)
|
||||
{
|
||||
p=p*lambda/double(k);
|
||||
q=q+p;
|
||||
if(u<=q)
|
||||
{
|
||||
value=k;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s=MathSqrt(lambda);
|
||||
double d=6.0*lambda*lambda;
|
||||
int l=(int)(lambda-1.1484);
|
||||
//--- generate normal deviate
|
||||
double f,x1,x2,r2;
|
||||
do
|
||||
{
|
||||
x1=2.0*MathRandomNonZero()-1.0;
|
||||
x2=2.0*MathRandomNonZero()-1.0;
|
||||
r2=x1*x1+x2*x2;
|
||||
}
|
||||
while(r2>=1.0 || r2==0.0);
|
||||
//--- Box-Muller transform
|
||||
f=MathSqrt(-2.0*MathLog(r2)/r2);
|
||||
double snorm=f*x2;
|
||||
//--- normal sample
|
||||
g=lambda+s*snorm;
|
||||
|
||||
if(0.0<=g)
|
||||
{
|
||||
value=(int)(g);
|
||||
//--- immediate acceptance if large enough
|
||||
if(l<=value)
|
||||
return value;
|
||||
//--- squeeze acceptance
|
||||
fk=(double)(value);
|
||||
difmuk=lambda-fk;
|
||||
u=MathRandomNonZero();
|
||||
//---
|
||||
if(difmuk*difmuk*difmuk<=d*u)
|
||||
return value;
|
||||
}
|
||||
//--- preparation for steps P and Q
|
||||
double omega=0.3989423/s;
|
||||
double b1 = 0.04166667/lambda;
|
||||
double b2 = 0.3*b1*b1;
|
||||
double c3 = 0.1428571*b1*b2;
|
||||
double c2 = b2 - 15.0*c3;
|
||||
double c1 = b1 - 6.0*b2 + 45.0*c3;
|
||||
double c0 = 1.0 - b1 + 3.0*b2 - 15.0*c3;
|
||||
double c=0.1069/lambda;
|
||||
double del=0;
|
||||
|
||||
if(0.0<=g)
|
||||
{
|
||||
kflag=0;
|
||||
|
||||
if(value<10)
|
||||
{
|
||||
px = -lambda;
|
||||
py = MathPow(lambda,value)/MathFactorial(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
del = 0.8333333E-01/fk;
|
||||
del = del - 4.8*del*del*del;
|
||||
v=difmuk/fk;
|
||||
|
||||
if(0.25<MathAbs(v))
|
||||
{
|
||||
px=fk*MathLog(1.0+v)-difmuk-del;
|
||||
}
|
||||
else
|
||||
{
|
||||
px=fk*v*v*(((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0)-del;
|
||||
}
|
||||
py=0.3989423/MathSqrt(fk);
|
||||
}
|
||||
x=(0.5-difmuk)/s;
|
||||
xx = x * x;
|
||||
fx = -0.5 * xx;
|
||||
fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);
|
||||
|
||||
if(kflag<=0)
|
||||
{
|
||||
if(fy-u*fy<=py*MathExp(px-fx))
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c*MathAbs(u)<=py*MathExp(px+e)-fy*MathExp(fx+e))
|
||||
return value;
|
||||
}
|
||||
}
|
||||
//--- exponential sample
|
||||
for(;;)
|
||||
{
|
||||
double rnd=MathRandomNonZero();
|
||||
e=-MathLog(1.0-rnd);
|
||||
|
||||
u=2.0*MathRandomNonZero()-1.0;
|
||||
if(u<0.0)
|
||||
t=1.8-MathAbs(e);
|
||||
else
|
||||
t=1.8+MathAbs(e);
|
||||
|
||||
if(t<=-0.6744)
|
||||
continue;
|
||||
|
||||
value=(int)(lambda+s*t);
|
||||
fk=(double)(value);
|
||||
difmuk=lambda-fk;
|
||||
|
||||
kflag=1;
|
||||
//--- calculation of PX, PY, FX, FY
|
||||
if(value<10)
|
||||
{
|
||||
px = -lambda;
|
||||
py = MathPow(lambda,value)/MathFactorial(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
del = 0.8333333E-01/fk;
|
||||
del = del - 4.8*del*del*del;
|
||||
v=difmuk/fk;
|
||||
|
||||
if(0.25<MathAbs(v))
|
||||
px=fk*MathLog(1.0+v)-difmuk-del;
|
||||
else
|
||||
px=fk*v*v*(((((((a7*v+a6)*v+a5)*v+a4)*v+a3)*v+a2)*v+a1)*v+a0)-del;
|
||||
|
||||
py=0.3989423/MathSqrt(fk);
|
||||
}
|
||||
|
||||
x=(0.5-difmuk)/s;
|
||||
xx = x*x;
|
||||
fx = -0.5*xx;
|
||||
fy = omega*(((c3*xx+c2)*xx+c1)*xx+c0);
|
||||
|
||||
if(kflag<=0)
|
||||
{
|
||||
if(fy-u*fy<=py*MathExp(px-fx))
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c*MathAbs(u)<=py*MathExp(px+e)-fy*MathExp(fx+e))
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Poisson distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compute the random variable from the Poisson distribution |
|
||||
//| with parameter lambda. |
|
||||
//| |
|
||||
//| Arguments |
|
||||
//| lambda : Mean |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Poisson distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomPoisson(const double lambda,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
error_code=ERR_OK;
|
||||
return MathRandomPoisson(lambda);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Poisson distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Poisson distribution |
|
||||
//| with parameter lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| lambda : Mean |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomPoisson(const double lambda,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(lambda))
|
||||
return false;
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
result[i]=MathRandomPoisson(lambda);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Poisson distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Poisson |
|
||||
//| distribution with parameter lambda. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| lambda : Mean |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsPoisson(const double lambda,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(lambda))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- lambda must be positive
|
||||
if(lambda<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =lambda;
|
||||
variance=lambda;
|
||||
skewness=MathPow(lambda,-0.5);
|
||||
kurtosis=1.0/lambda;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,27 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stat.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Math\Stat\F.mqh>
|
||||
#include <Math\Stat\Gamma.mqh>
|
||||
#include <Math\Stat\Geometric.mqh>
|
||||
#include <Math\Stat\Hypergeometric.mqh>
|
||||
#include <Math\Stat\Logistic.mqh>
|
||||
#include <Math\Stat\Lognormal.mqh>
|
||||
#include <Math\Stat\Math.mqh>
|
||||
#include <Math\Stat\NegativeBinomial.mqh>
|
||||
#include <Math\Stat\NoncentralBeta.mqh>
|
||||
#include <Math\Stat\NoncentralChiSquare.mqh>
|
||||
#include <Math\Stat\NoncentralF.mqh>
|
||||
#include <Math\Stat\NoncentralT.mqh>
|
||||
#include <Math\Stat\Normal.mqh>
|
||||
#include <Math\Stat\Poisson.mqh>
|
||||
#include <Math\Stat\T.mqh>
|
||||
#include <Math\Stat\Uniform.mqh>
|
||||
#include <Math\Stat\Weibull.mqh>
|
||||
#include <Math\Stat\Beta.mqh>
|
||||
#include <Math\Stat\Binomial.mqh>
|
||||
#include <Math\Stat\Cauchy.mqh>
|
||||
#include <Math\Stat\ChiSquare.mqh>
|
||||
#include <Math\Stat\Exponential.mqh>
|
||||
+654
@@ -0,0 +1,654 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| T.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
#include "Gamma.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| T probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the T-distribution with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu : Degrees of freedom |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityT(const double x,const double nu,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate T density
|
||||
double pdf=MathExp(MathGammaLog((nu+1.0)*0.5)-MathGammaLog(nu*0.5));
|
||||
pdf=pdf/(MathSqrt(nu*M_PI)*MathPow(1+x*x/nu,(nu+1.0)*0.5));
|
||||
//--- return density
|
||||
return TailLogValue(pdf,true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the T-distribution with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityT(const double x,const double nu,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityT(x,nu,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the T distribution with parameter nu for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityT(const double &x[],const double nu,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate T density
|
||||
double pdf=MathExp(MathGammaLog((nu+1.0)*0.5)-MathGammaLog(nu*0.5));
|
||||
pdf=pdf/(MathSqrt(nu*M_PI)*MathPow(1+x_arg*x_arg/nu,(nu+1.0)*0.5));
|
||||
//--- return density
|
||||
result[i]=TailLogValue(pdf,true,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of |
|
||||
//| the T distribution with parameter nu for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityT(const double &x[],const double nu,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityT(x,nu,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation from |
|
||||
//| T-distribution with parameter nu is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the T cumulative distribution function with |
|
||||
//| parameter nu, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionT(const double x,const double nu,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check nu (must be positive integer)
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- special case
|
||||
if(nu==1.0)
|
||||
return TailLogValue(0.5+MathArctan(x)/M_PI,tail,log_mode);
|
||||
//--- otherwise
|
||||
if(x==0)
|
||||
return TailLogValue(0.5,tail,log_mode);
|
||||
//--- calculate pdf using incomplete Beta
|
||||
double cdf=1.0-MathBetaIncomplete(nu/(nu+x*x),nu*0.5,0.5);
|
||||
cdf=(1.0-cdf)*0.5;
|
||||
//--- check x
|
||||
if(x>0.0)
|
||||
cdf=1.0-cdf;
|
||||
//--- take into account round-off errors for probability
|
||||
return TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation from |
|
||||
//| T-distribution with parameter nu is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of T cumulative distribution function with parameter |
|
||||
//| nu, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionT(const double x,const double nu,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionT(x,nu,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the T distribution with parameter nu for values in x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionT(const double &x[],const double nu,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- check nu (must be positive integer)
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
//--- special case
|
||||
if(nu==1.0)
|
||||
result[i]=TailLogValue(0.5+MathArctan(x_arg)/M_PI,tail,log_mode);
|
||||
else
|
||||
//--- otherwise
|
||||
if(x_arg==0)
|
||||
result[i]=TailLogValue(0.5,tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate pdf using incomplete Beta
|
||||
double cdf=1.0-MathBetaIncomplete(nu/(nu+x_arg*x_arg),nu*0.5,0.5);
|
||||
cdf=(1.0-cdf)*0.5;
|
||||
//--- check x
|
||||
if(x_arg>0.0)
|
||||
cdf=1.0-cdf;
|
||||
//--- take into account round-off errors for probability
|
||||
result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the T distribution with parameter nu for values in x[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| nu : Degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionT(const double &x[],const double nu,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionT(x,nu,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the T distribution with parameter nu for the desired |
|
||||
//| probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the T-distribution with parameter nu. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileT(const double probability,const double nu,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(probability) || !MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- check cases when probability==0 or 1
|
||||
if(prob==0.0 || prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
//---
|
||||
if(prob==0.0)
|
||||
return(QNEGINF);
|
||||
else
|
||||
return(QPOSINF);
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- special case nu=1
|
||||
if(nu==1.0)
|
||||
return MathTan(M_PI*(prob-0.5));
|
||||
//--- special case
|
||||
if(prob==0.5)
|
||||
return 0.0;
|
||||
//---
|
||||
int max_iterations=50;
|
||||
int iterations=0;
|
||||
//--- initial values
|
||||
double h=1.0;
|
||||
double h_min=10E-20;
|
||||
double x=0.5;
|
||||
int err_code=0;
|
||||
//--- Newton iterations
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convegence
|
||||
if((MathAbs(h)>h_min && MathAbs(h)>MathAbs(h_min*x))==false)
|
||||
break;
|
||||
//--- calculate pdf and cdf
|
||||
double pdf=MathProbabilityDensityT(x,nu,err_code);
|
||||
double cdf=MathCumulativeDistributionT(x,nu,err_code);
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
//---
|
||||
double x_new=x-h;
|
||||
//--- check x
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1.0-x)*0.1;
|
||||
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
return x;
|
||||
else
|
||||
{
|
||||
error_code=ERR_NON_CONVERGENCE;
|
||||
return QNaN;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the T distribution with parameter nu for the desired |
|
||||
//| probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the T-distribution with parameter nu. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileT(const double probability,const double nu,int &error_code)
|
||||
{
|
||||
return MathQuantileT(probability,nu,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the T distribution with parameter nu for |
|
||||
//| values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu : Degrees of freedom |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileT(const double &probability[],const double nu,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<0.0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- special case p=0.5
|
||||
if(prob==0.5)
|
||||
result[i]=0.0;
|
||||
else
|
||||
if(prob==0.0)
|
||||
result[i]=QNEGINF;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
else
|
||||
{
|
||||
//--- special case nu=1
|
||||
if(nu==1.0)
|
||||
result[i]=MathTan(M_PI*(prob-0.5));
|
||||
else
|
||||
{
|
||||
int max_iterations=50;
|
||||
int iterations=0;
|
||||
//--- initial values
|
||||
double h=1.0;
|
||||
double h_min=10E-18;
|
||||
double x=0.5;
|
||||
int err_code=0;
|
||||
//--- Newton iterations
|
||||
while(iterations<max_iterations)
|
||||
{
|
||||
//--- check convegence
|
||||
if((MathAbs(h)>h_min && MathAbs(h)>MathAbs(h_min*x))==false)
|
||||
break;
|
||||
//--- calculate pdf and cdf
|
||||
double pdf=MathProbabilityDensityT(x,nu,err_code);
|
||||
double cdf=MathCumulativeDistributionT(x,nu,err_code);
|
||||
//--- calculate ratio
|
||||
h=(cdf-prob)/pdf;
|
||||
//---
|
||||
double x_new=x-h;
|
||||
//--- check x
|
||||
if(x_new<0.0)
|
||||
x_new=x*0.1;
|
||||
else
|
||||
if(x_new>1.0)
|
||||
x_new=1.0-(1.0-x)*0.1;
|
||||
|
||||
if (MathAbs(x_new-x)<10E-15)
|
||||
break;
|
||||
|
||||
x=x_new;
|
||||
|
||||
iterations++;
|
||||
}
|
||||
//--- check convergence
|
||||
if(iterations<max_iterations)
|
||||
result[i]=x;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the T distribution with parameter nu for |
|
||||
//| values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| nu : Degrees of freedom |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileT(const double &probability[],const double nu,double &result[])
|
||||
{
|
||||
return MathQuantileT(probability,nu,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the T distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the T distribution |
|
||||
//| with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with T distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomT(const double nu,int error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate normal random variable using Box-Muller transform
|
||||
double x1,x2,r2;
|
||||
do
|
||||
{
|
||||
x1=2.0*MathRandomNonZero()-1.0;
|
||||
x2=2.0*MathRandomNonZero()-1.0;
|
||||
r2=x1*x1+x2*x2;
|
||||
}
|
||||
while(r2>=1.0 || r2==0.0);
|
||||
//--- generate normal and gamma random variables
|
||||
double rnd_normal=x2*MathSqrt(-2.0*MathLog(r2)/r2);
|
||||
double rnd_gamma=MathRandomGamma(nu*0.5,1,error_code);
|
||||
//--- calculate ratio
|
||||
double result=0;
|
||||
if(rnd_gamma!=0)
|
||||
result=MathSqrt(nu*0.5)*rnd_normal/MathSqrt(rnd_gamma);
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the T distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the T distribution with |
|
||||
//| parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomT(const double nu,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
return false;
|
||||
//--- check arguments
|
||||
if(nu!=MathRound(nu) || nu<=0.0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate normal random variable using Box-Muller transform
|
||||
double x1,x2,r2;
|
||||
do
|
||||
{
|
||||
x1=2.0*MathRandomNonZero()-1.0;
|
||||
x2=2.0*MathRandomNonZero()-1.0;
|
||||
r2=x1*x1+x2*x2;
|
||||
}
|
||||
while(r2>=1.0 || r2==0.0);
|
||||
//--- generate normal and gamma random variables
|
||||
double rnd_normal=x2*MathSqrt(-2.0*MathLog(r2)/r2);
|
||||
double rnd_gamma=MathRandomGamma(nu*0.5,1,error_code);
|
||||
//--- calculate ratio
|
||||
double rnd=0;
|
||||
if(rnd_gamma!=0)
|
||||
rnd=MathSqrt(nu*0.5)*rnd_normal/MathSqrt(rnd_gamma);
|
||||
result[i]=rnd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| T distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the T distribution |
|
||||
//| with parameter nu. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| nu : Degrees of freedom |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathMomentsT(const double nu,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(nu))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check nu
|
||||
if(nu!=MathRound(nu) || nu<0.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean=0;
|
||||
if(nu>2)
|
||||
variance=nu/(nu-2);
|
||||
skewness=0;
|
||||
if(nu>4)
|
||||
kurtosis=6/(nu-4);
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,539 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of the |
|
||||
//| Uniform distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityUniform(const double x,const double a,const double b,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check range
|
||||
if(b<=a)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check ranges
|
||||
if(x>=a && x<=b)
|
||||
return TailLogValue(1.0/(b-a),true,log_mode);
|
||||
//--- otherwise 0
|
||||
return TailLog0(true,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function of the |
|
||||
//| Uniform distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityUniform(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityUniform(x,a,b,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| Uniform distribution with parameters a and b for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityUniform(const double &x[],const double a,const double b,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check range
|
||||
if(b<=a)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg>=a && x_arg<=b)
|
||||
result[i]=TailLogValue(1.0/(b-a),true,log_mode);
|
||||
else
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| Uniform distribution with parameters a and b for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| mu : Mean |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityUniform(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityUniform(x,a,b,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function |
|
||||
//| of the Uniform distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Uniform cumulative distribution function with |
|
||||
//| parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionUniform(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check ranges
|
||||
if(b<a)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
|
||||
if(x>=a && x<=b)
|
||||
return TailLogValue(MathMin((x-a)/(b-a),1.0),tail,log_mode);
|
||||
|
||||
if(x>b)
|
||||
return TailLog1(tail,log_mode);
|
||||
return TailLog0(tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the cumulative distribution function of |
|
||||
//| the Uniform distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Uniform cumulative distribution function with |
|
||||
//| parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionUniform(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionUniform(x,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Uniform distribution with parameters a and b for values in x.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode flag,if true it calculates Log values|
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionUniform(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check ranges
|
||||
if(b<a)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
if(!MathIsValidNumber(x_arg))
|
||||
return false;
|
||||
|
||||
if(x_arg>=a && x_arg<=b)
|
||||
result[i]=TailLogValue(MathMin((x_arg-a)/(b-a),1.0),tail,log_mode);
|
||||
else
|
||||
{
|
||||
if(x_arg>b)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Uniform distribution with parameters a and b for values in x.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Mean |
|
||||
//| b : Scale |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionUniform(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionUniform(x,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Uniform distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of Uniform distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileUniform(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
if(log_mode==true)
|
||||
{
|
||||
if(probability==QNEGINF)
|
||||
return 0.0;
|
||||
}
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check bounds
|
||||
if(b<a)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
if(b==a)
|
||||
return a;
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
|
||||
if(prob==0.0)
|
||||
return a;
|
||||
else
|
||||
if(prob==1.0)
|
||||
return b;
|
||||
|
||||
//--- return quantile
|
||||
return a+prob*(b-a);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Uniform distribution with parameters a and b |
|
||||
//| for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of Uniform distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileUniform(const double probability,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathQuantileUniform(probability,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of Uniform distribution with parameters a and b |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileUniform(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check ranges
|
||||
if(b<a)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
if(log_mode==true && probability[i]==QNEGINF)
|
||||
result[i]=0;
|
||||
else
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- check bounds
|
||||
if(b==a)
|
||||
result[i]=a;
|
||||
else
|
||||
if(prob==0.0)
|
||||
result[i]=a;
|
||||
else
|
||||
if(prob==1.0)
|
||||
result[i]=b;
|
||||
else
|
||||
//--- quantile
|
||||
result[i]=(a+prob*(b-a));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of Uniform distribution with parameters a and b |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileUniform(const double &probability[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathQuantileUniform(probability,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Uniform distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the Uniform distribution |
|
||||
//| with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with uniform distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomUniform(const double a,const double b,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- check upper bound
|
||||
if(b<a)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check ranges
|
||||
if(a==b)
|
||||
return a;
|
||||
//---
|
||||
return a+MathRandomNonZero()*(b-a);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Uniform distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Uniform distribution with |
|
||||
//| parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomUniform(const double a,const double b,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- check upper bound
|
||||
if(b<a)
|
||||
return false;
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
result[i]=a+rnd*(b-a);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Uniform distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Uniform |
|
||||
//| distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Lower endpoint (minimum) |
|
||||
//| b : Upper endpoint (maximum) |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsUniform(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- check range
|
||||
if(b<=a)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- calculate moments
|
||||
mean =0.5*(a+b);
|
||||
variance=MathPow(b-a,2)/12;
|
||||
skewness=0;
|
||||
kurtosis=-3+9.0/5.0;
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,574 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull.mqh |
|
||||
//| Copyright 2000-2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Math.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Weibull distribution with parameters a and b. |
|
||||
//| f(x,a,b)=[(a/b)*(x/b)^(a-1)]*exp(-(x/b)^a) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityWeibull(const double x,const double a,const double b,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- f(-infinity)=f(infinity)=0
|
||||
if(x==QPOSINF || x==QNEGINF)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return TailLog0(true,log_mode);
|
||||
}
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0)
|
||||
return TailLog0(true,log_mode);
|
||||
//--- calculate factor
|
||||
double pwr=MathPow(x/b,a-1);
|
||||
double pdf=(a/b)*pwr*MathExp(-(x/b)*pwr);
|
||||
if(log_mode==true)
|
||||
return MathLog(pdf);
|
||||
//--- return density
|
||||
return pdf;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability density function |
|
||||
//| of the Weibull distribution with parameters a and b. |
|
||||
//| f(x,a,b)=[(a/b)*(x/b)^(a-1)]*exp(-(x/b)^a) |
|
||||
//| Arguments: |
|
||||
//| x : Random variable |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The probability density evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathProbabilityDensityWeibull(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathProbabilityDensityWeibull(x,a,b,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| Weibull distribution with parameters a and b for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| log_mode : Logarithm mode flag, if true it returns Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityWeibull(const double &x[],const double a,const double b,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
//--- f(-infinity)=f(infinity)=0
|
||||
if(x_arg==QPOSINF || x_arg==QNEGINF)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(true,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate factor
|
||||
double pwr=MathPow(x_arg/b,a-1);
|
||||
double pdf=(a/b)*pwr*MathExp(-(x_arg/b)*pwr);
|
||||
if(log_mode==true)
|
||||
result[i]=MathLog(pdf);
|
||||
else
|
||||
result[i]=pdf;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull probability density function (PDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the probability density function of the |
|
||||
//| Weibull distribution with parameters a and b for values in x[]. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathProbabilityDensityWeibull(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathProbabilityDensityWeibull(x,a,b,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Weibull distribution with parameters a and b |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Weibull cumulative distribution function |
|
||||
//| F(a,b)=1-exp(-(x/b)^a) |
|
||||
//| with parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionWeibull(const double x,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- f(-infinity)=0
|
||||
if(x==QNEGINF)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return TailLog0(tail,log_mode);
|
||||
}
|
||||
//--- f(+infinity)=1
|
||||
if(x==QPOSINF)
|
||||
{
|
||||
error_code=ERR_OK;
|
||||
return TailLog1(tail,log_mode);
|
||||
}
|
||||
//--- check parameters
|
||||
if(!MathIsValidNumber(x) || !MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- check x
|
||||
if(x<=0)
|
||||
return TailLog0(tail,log_mode);
|
||||
//--- calculate probability and take into account round-off errors
|
||||
double cdf=MathMin(1.0-MathExp(-MathPow(x/b,a)),1.0);
|
||||
return TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the probability that an observation |
|
||||
//| from the Weibull distribution with parameters a and b |
|
||||
//| is less than or equal to x. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : The desired quantile |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the Weibull cumulative distribution function |
|
||||
//| F(a,b)=1-exp(-(x/b)^a) |
|
||||
//| with parameters a and b, evaluated at x. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathCumulativeDistributionWeibull(const double x,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathCumulativeDistributionWeibull(x,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Weibull distribution with parameters a and b for values in x.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionWeibull(const double &x[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(x);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
double x_arg=x[i];
|
||||
|
||||
//--- f(-infinity)=0, f(+infinity)=1
|
||||
if(x_arg==QNEGINF)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
//--- f(+infinity)=1
|
||||
if(x_arg==QPOSINF)
|
||||
result[i]=TailLog1(tail,log_mode);
|
||||
else
|
||||
//--- check x
|
||||
if(x_arg<=0)
|
||||
result[i]=TailLog0(tail,log_mode);
|
||||
else
|
||||
{
|
||||
//--- calculate probability and take into account round-off errors
|
||||
double cdf=MathMin(1.0-MathExp(-MathPow(x_arg/b,a)),1.0);
|
||||
result[i]=TailLogValue(cdf,tail,log_mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull cumulative distribution function (CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the cumulative distribution function of |
|
||||
//| the Weibull distribution with parameters a and b for values in x.|
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| x : Array with random variables |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathCumulativeDistributionWeibull(const double &x[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathCumulativeDistributionWeibull(x,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of Weibull distribution |
|
||||
//| Q(p,a,b)=b*((-ln(1-p)))^(1/a) |
|
||||
//| with parameters a and b for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| tail : Flag to calculate for lower tail |
|
||||
//| log_mode : Logarithm mode,if true it calculates for Log values|
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Weibull distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileWeibull(const double probability,const double a,const double b,const bool tail,const bool log_mode,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability,tail,log_mode);
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
//--- f(1)=+infinity
|
||||
if(prob==1.0)
|
||||
{
|
||||
error_code=ERR_RESULT_INFINITE;
|
||||
return QPOSINF;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- f(0)=0
|
||||
if(prob==0.0)
|
||||
return 0.0;
|
||||
//--- return quantile
|
||||
return b*MathPow(-MathLog(1.0-prob),1.0/a);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function returns the inverse cumulative distribution |
|
||||
//| function of the Weibull distribution |
|
||||
//| Q(p,a,b)=b*((-ln(1-p)))^(1/a) |
|
||||
//| with parameters a and b for the desired probability. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : The desired probability |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The value of the inverse cumulative distribution function |
|
||||
//| of the Weibull distribution with parameters a and b. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathQuantileWeibull(const double probability,const double a,const double b,int &error_code)
|
||||
{
|
||||
return MathQuantileWeibull(probability,a,b,true,false,error_code);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Weibull distribution with parameters a and b |
|
||||
//| for the probability values from array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| tail : Flag to calculate lower tail |
|
||||
//| log_mode : Logarithm mode, if true it calculates Log values |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileWeibull(const double &probability[],const double a,const double b,const bool tail,const bool log_mode,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
int data_count=ArraySize(probability);
|
||||
if(data_count==0)
|
||||
return false;
|
||||
|
||||
int error_code=0;
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- calculate real probability
|
||||
double prob=TailLogProbability(probability[i],tail,log_mode);
|
||||
|
||||
//--- check probability range
|
||||
if(prob<0.0 || prob>1.0)
|
||||
return false;
|
||||
|
||||
//--- f(1)=+infinity
|
||||
if(prob==1.0)
|
||||
result[i]=QPOSINF;
|
||||
//--- f(0)=0
|
||||
if(prob==0.0)
|
||||
result[i]=0.0;
|
||||
else
|
||||
//--- calc quantile
|
||||
result[i]=b*MathPow(-MathLog(1.0-prob),1.0/a);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull distribution quantile function (inverse CDF) |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates the inverse cumulative distribution |
|
||||
//| function of the Weibull distribution with parameters a and b |
|
||||
//| for values from the probability[] array. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| probability : Array with probabilities |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| result : Array with calculated values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathQuantileWeibull(const double &probability[],const double a,const double b,double &result[])
|
||||
{
|
||||
return MathQuantileWeibull(probability,a,b,true,false,result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Weibull distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Computes the random variable from the Weibull distribution |
|
||||
//| with shape a and scale b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| The random value with Weibull distribution. |
|
||||
//+------------------------------------------------------------------+
|
||||
double MathRandomWeibull(const double a,const double b,int &error_code)
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return QNaN;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return QNaN;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
return b*MathPow(-MathLog(rnd),1.0/a);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Random variate from the Weibull distribution |
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generates random variables from the Weibull distribution with |
|
||||
//| parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| data_count : Number of values needed |
|
||||
//| result : Output array with random values |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if successful, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathRandomWeibull(const double a,const double b,const int data_count,double &result[])
|
||||
{
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
return false;
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
return false;
|
||||
|
||||
//--- prepare output array and calculate random values
|
||||
ArrayResize(result,data_count);
|
||||
for(int i=0; i<data_count; i++)
|
||||
{
|
||||
//--- generate random number
|
||||
double rnd=MathRandomNonZero();
|
||||
result[i]=b*MathPow(-MathLog(rnd),1.0/a);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weibull distribution moments |
|
||||
//+------------------------------------------------------------------+
|
||||
//| The function calculates 4 first moments of the Weibull |
|
||||
//| distribution with parameters a and b. |
|
||||
//| |
|
||||
//| Arguments: |
|
||||
//| a : Shape parameter of the distribution (a>0) |
|
||||
//| b : Scale parameter of the distribution (b>0) |
|
||||
//| mean : Variable for mean value (1st moment) |
|
||||
//| variance : Variable for variance value (2nd moment) |
|
||||
//| skewness : Variable for skewness value (3rd moment) |
|
||||
//| kurtosis : Variable for kurtosis value (4th moment) |
|
||||
//| error_code : Variable for error code |
|
||||
//| |
|
||||
//| Return value: |
|
||||
//| true if moments calculated successfully, otherwise false. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool MathMomentsWeibull(const double a,const double b,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code)
|
||||
{
|
||||
//--- default values
|
||||
mean =QNaN;
|
||||
variance=QNaN;
|
||||
skewness=QNaN;
|
||||
kurtosis=QNaN;
|
||||
//--- check NaN
|
||||
if(!MathIsValidNumber(a) || !MathIsValidNumber(b))
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_NAN;
|
||||
return false;
|
||||
}
|
||||
//--- a and b must be positive
|
||||
if(a<=0 || b<=0)
|
||||
{
|
||||
error_code=ERR_ARGUMENTS_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_code=ERR_OK;
|
||||
//--- Gamma function values
|
||||
double g1 = MathGamma(1+1.0/a);
|
||||
double g2 = MathGamma(1+2.0/a);
|
||||
double g3 = MathGamma(1+3.0/a);
|
||||
double g4 = MathGamma(1+4.0/a);
|
||||
//--- calculate moments
|
||||
mean =b*g1;
|
||||
variance=b*b*g2-MathPow(g1,2);
|
||||
skewness=(2*g1*g1*g1-3*g1*g2+g3)*MathPow(g2-g1*g1,-1.5);
|
||||
kurtosis=(-6*MathPow(g1,4)+12*MathPow(g1,2)*g2-3*MathPow(g2,2)-4*g1*g3+g4)*MathPow(g2-g1*g1,-2);
|
||||
//--- successful
|
||||
return true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user