Consolidate Python ignore rules into root gitignore
This commit is contained in:
@@ -0,0 +1,772 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Beta.mqh |
|
||||
//| Copyright 2000-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,563 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| F.mqh |
|
||||
//| Copyright 2000-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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>
|
||||
@@ -0,0 +1,654 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| T.mqh |
|
||||
//| Copyright 2000-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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-2026, MetaQuotes Ltd. |
|
||||
//| 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;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Reference in New Issue
Block a user