Consolidate Python ignore rules into root gitignore

This commit is contained in:
Hiroaki86
2026-05-27 23:01:28 +09:00
commit fa3394415d
399 changed files with 509103 additions and 0 deletions
+772
View File
@@ -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;
}
//+------------------------------------------------------------------+
+874
View File
@@ -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;
}
//+------------------------------------------------------------------+
+539
View File
@@ -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;
}
//+------------------------------------------------------------------+
+531
View File
@@ -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;
}
//+------------------------------------------------------------------+
+520
View File
@@ -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;
}
//+------------------------------------------------------------------+
+563
View File
@@ -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;
}
//+------------------------------------------------------------------+
+764
View File
@@ -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;
}
//+------------------------------------------------------------------+
+567
View File
@@ -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;
}
//+------------------------------------------------------------------+
+754
View File
@@ -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;
}
//+------------------------------------------------------------------+
+592
View File
@@ -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;
}
//+------------------------------------------------------------------+
+635
View File
@@ -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.
+643
View File
@@ -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;
}
//+------------------------------------------------------------------+
+954
View File
@@ -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;
}
//+------------------------------------------------------------------+
+912
View File
@@ -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;
}
//+------------------------------------------------------------------+
+790
View File
@@ -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
+914
View File
@@ -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;
}
//+------------------------------------------------------------------+
+791
View File
@@ -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;
}
//+------------------------------------------------------------------+
+27
View File
@@ -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>
+654
View File
@@ -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;
}
//+------------------------------------------------------------------+
+539
View File
@@ -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;
}
//+------------------------------------------------------------------+
+574
View File
@@ -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;
}
//+------------------------------------------------------------------+